Crossfire Server, Trunk
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 
150 #include <ctype.h>
151 #include <errno.h>
152 #include <stdio.h>
153 #include <stdlib.h>
154 #include <string.h>
155 #include <strings.h>
156 #include <sys/stat.h>
157 #include <sys/types.h>
158 #include <time.h>
159 
160 #include "global.h"
161 #include "sproto.h"
162 #include "image.h"
163 #include "quest.h"
164 
165 extern "C" {
166 #include <gd.h>
167 #include <gdfonts.h>
168 #include <gdfontl.h>
169 #include <gdfontg.h>
170 }
171 
172 #include "inja.hpp"
173 #include <map>
174 #include <set>
175 
176 static gdImagePtr *gdfaces;
177 
180  const char *name;
181  const char *message;
182  int x, y;
183 };
184 
186 typedef std::vector<struct_npc_info *> npc_list;
187 
190  struct struct_race **races;
191  size_t count;
192  size_t allocated;
193 };
194 
198  size_t count;
199  size_t allocated;
200 };
201 
205  size_t count;
206  size_t allocated;
207 };
208 
211  char *path;
212  char *name;
213  char *filename;
214  char *lore;
221 
223 
225 
228 
230  int height, width;
232  struct struct_map_info *tiles[4];
233 };
234 
237 
240 
243  char *name;
244  int power;
246  char *diff;
248 };
249 
250 static std::vector<struct_equipment *> special_equipment;
254 struct struct_race {
255  char *name;
256  int count;
258 };
259 
262 static std::set<std::string> reset_groups;
270  list->races = NULL;
271  list->count = 0;
272  list->allocated = 0;
273 }
274 
286  if (check) {
287  size_t test;
288 
289  for (test = 0; test < list->count; test++) {
290  if (list->races[test] == race)
291  return;
292  }
293  }
294 
295  if (list->allocated == list->count) {
296  list->allocated += 50;
297  list->races = (struct_race **)realloc(list->races, sizeof(struct_race *)*list->allocated);
298  }
299  list->races[list->count] = race;
300  list->count++;
301 }
302 
304 static char root[500];
305 
307 static int pics_allocated;
308 
309 /* Options */
310 static int generate_pics = 1;
311 static int force_pics = 0;
312 static int sizes[] = {32, 16, 8, 4, 2};
313 static const int num_sizes = sizeof(sizes)/sizeof(int);
314 #define size_large sizes[0]
315 #define size_small sizes[1]
316 static int map_limit = -1;
317 static int show_maps = 0;
318 static int world_map = 1;
319 static int world_exit_info = 1;
320 static int tileset = 0;
321 static bool detail_quests = false;
322 static bool list_system_quests = false;
323 static bool display_rendered_template = false;
326 static int created_pics = 0;
327 static int cached_pics = 0;
331  OF_PNG = 0,
332  OF_JPG = 1
333 };
334 
336 static const char *output_extensions[] = {
337  ".png",
338  ".jpg"
339 };
340 
343 
345 static int jpeg_quality = -1;
346 
348 static int rawmaps = 0;
349 
351 static int warn_no_path = 0;
352 
357  int sum_x, sum_y, sum;
358  int is_world;
359 };
360 
361 static struct struct_region_info **regions = NULL;
362 static size_t region_count = 0;
363 static size_t region_allocated = 0;
365 static int list_unused_maps = 0;
366 static std::vector<char *> found_maps;
368 /* Path/exit info */
369 static gdImagePtr infomap;
371 static int color_linked_exit;
372 static int color_road;
373 static int color_blocking;
374 static int color_slowing;
376 static int **elevation_info;
377 static int elevation_min;
378 static int elevation_max;
380 /* Whether to compute links between regions or not (expensive). */
381 static bool do_regions_link = false;
382 /* Links between regions, key is source, value are destinations. */
383 static std::map<region *, std::set<region *>> region_links;
384 
386 #define S_DOOR 0
387 #define S_KEY 1
388 #define S_CONTAINER 2
389 #define S_DETECTOR 3
390 #define S_CONNECT 4
391 #define S_MAX 5
392 
395  char *slaying;
397 };
398 
400 static size_t slaying_count = 0;
401 static size_t slaying_allocated = 0;
409  list->maps = NULL;
410  list->count = 0;
411  list->allocated = 0;
412 }
413 
414 static void add_map(struct_map_info *info, struct_map_list *list);
415 
416 static int is_special_equipment(object *item) {
417  if (item->name == item->arch->clone.name && item->title == item->arch->clone.title)
418  return 0;
420  return 0;
421  if (item->move_block == MOVE_ALL)
422  return 0;
423 
424  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))
425  return 1;
426 
427  return 0;
428 }
429 
436  struct_equipment *add = (struct_equipment *)calloc(1, sizeof(struct_equipment));
437 
438  init_map_list(&add->origin);
439  return add;
440 }
441 
448 static void free_equipment(struct_equipment *equip) {
449  free(equip->diff);
450  free(equip->name);
451  free(equip);
452 }
453 
462 static bool sort_equipment(const struct_equipment *l, const struct_equipment *r) {
463  int cmp = strcasecmp(l->name, r->name);
464  if (cmp)
465  return cmp < 0;
466  if (l->power != r->power)
467  return l->power < r->power;
468  if (l->calc_power != r->calc_power)
469  return l->calc_power < r->calc_power;
470 
471  return strcasecmp(l->diff, r->diff) < 0;
472 }
473 
483  assert(item);
484  auto existing = std::find_if(special_equipment.begin(), special_equipment.end(),
485  [&] (const auto *e) { return !sort_equipment(e, item) && !sort_equipment(item, e); });
486 
487  if (existing != special_equipment.end()) {
489  return *existing;
490  }
491 
492  special_equipment.push_back(item);
493 
494  return item;
495 }
496 
506 static void add_one_item(object *item, struct_map_info *map) {
509  int x, y;
510  sstring name, namepl;
511  uint32_t nrof;
512  object *base;
513 
514  x = item->x;
515  y = item->y;
516  name = item->name;
517  namepl = item->name_pl;
518  nrof = item->nrof;
519 
520  if (item->artifact != NULL) {
521  const artifact *artifact;
522 
523  artifact = find_artifact(item, item->artifact);
524  if (artifact == NULL) {
525  LOG(llevError, "could not find artifact %s [%d] to save data\n", item->artifact, item->type);
526  base = arch_to_object(item->arch);
527  } else {
528  base = arch_to_object(item->arch);
530  }
531  }
532  else {
533  base = arch_to_object(item->arch);
534  }
535 
536  item->x = base->x;
537  item->y = base->y;
538  item->name = base->name;
539  item->name_pl = base->name_pl;
540  item->nrof = base->nrof;
541 
544  SET_FLAG(base, FLAG_IDENTIFIED);
545  }
547  SET_FLAG(base, FLAG_UNPAID);
548  get_ob_diff(bf, item, base);
550 
551  add->diff = stringbuffer_finish(bf);
552 
553  item->x = x;
554  item->y = y;
555  item->name = name;
556  item->name_pl = namepl;
557  item->nrof = nrof;
558 
559  if (add->diff == NULL || strcmp(add->diff, "") == 0) {
560  free_equipment(add);
561  return;
562  }
563 
564  add->name = strdup(item->name);
565  add->power = item->item_power;
567 
568  add = ensure_unique(add);
569  add_map(map, &add->origin);
570 }
571 
580 static void check_equipment(object *item, struct_map_info *map) {
583 
586  FOR_INV_FINISH();
587 }
588 
597 static struct_race *get_race(const char *name) {
598  size_t test;
599  struct_race *item;
600 
601  for (test = 0; test < races.count; test++) {
602  if (strcmp(races.races[test]->name, name) == 0) {
603  races.races[test]->count++;
604  return races.races[test];
605  }
606  }
607 
608  item = (struct_race *)calloc(1, sizeof(struct_race));
609  item->name = strdup(name);
610  item->count = 1;
611  init_map_list(&item->origin);
612 
614 
615  return item;
616 }
617 
626 static void add_monster(object *monster, struct_map_info *map) {
627  struct_race *race;
628 
629  if (monster->head && monster != monster->head)
630  return;
631 
632  map->min_monster = MIN(monster->level, map->min_monster);
633  map->max_monster = MAX(monster->level, map->max_monster);
634 
635  race = get_race(monster->name);
636  add_map(map, &race->origin);
637  add_race_to_list(race, &map->monsters, 1);
638 }
639 
648 static int sort_race(const void *a, const void *b) {
649  const struct_race *l = *(const struct_race **)a;
650  const struct_race *r = *(const struct_race **)b;
651  return strcasecmp(l->name, r->name);
652 }
653 
661 static int is_road(object *item) {
662  int test;
663  /* Archetypes used as roads. */
664  const char *roads[] = {
665  "cobblestones",
666  "flagstone",
667  "ice_stone",
668  "snow",
669  NULL };
670  const char *partial[] = {
671  "dirtroad_",
672  NULL };
673 
674  for (test = 0; partial[test] != NULL; test++) {
675  if (strstr(item->arch->name, partial[test]) != NULL)
676  return 1;
677  }
678 
680  return 0;
681 
682  for (test = 0; roads[test] != NULL; test++) {
683  if (strcmp(item->arch->name, roads[test]) == 0)
684  return 1;
685  }
686 
687  return 0;
688 }
689 
697 static int is_blocking(object *item) {
698  return item->move_block == MOVE_ALL ? 1 : 0;
699 }
700 
711 static int get_elevation_color(int elevation, gdImagePtr elevationmap) {
712  if (elevation > 0)
713  return gdImageColorResolve(elevationmap, 200*elevation/elevation_max, 0, 0);
714  else
715  return gdImageColorResolve(elevationmap, 0, 0, 200*elevation/elevation_min);
716 }
717 
726 static void do_exit_map(mapstruct *map) {
727  int tx, ty, x, y;
728  object *test;
729  sstring selevation;
730 
731  if (sscanf(map->path, "/world/world_%d_%d", &x, &y) != 2)
732  return;
733 
734  x -= 100;
735  y -= 100;
736 
737  for (tx = 0; tx < MAP_WIDTH(map); tx++) {
738  for (ty = 0; ty < MAP_HEIGHT(map); ty++) {
739  FOR_MAP_PREPARE(map, tx, ty, item) {
740  test = HEAD(item);
741 
742  // Do this before we check for blocked tiles,
743  // otherwise we don't receive elevation data for blocked tiles.
744  selevation = object_get_value(item, "elevation");
745  if (selevation) {
746  int32_t elevation = atoi(selevation);
747  elevation_min = MIN(elevation_min, elevation);
748  elevation_max = MAX(elevation_max, elevation);
749  elevation_info[x*50+tx][y*50+ty] = elevation;
750  }
751 
752  if (test->type == EXIT || test->type == TELEPORTER) {
753  if (!test->slaying)
754  gdImageSetPixel(infomap, x*50+tx, y*50+ty, color_unlinked_exit);
755  else
756  gdImageSetPixel(infomap, x*50+tx, y*50+ty, color_linked_exit);
757  } else if (is_road(test))
758  gdImageSetPixel(infomap, x*50+tx, y*50+ty, color_road);
759  else if (is_blocking(test)) {
760  gdImageSetPixel(infomap, x*50+tx, y*50+ty, color_blocking);
761  /* can't get on the spot, so no need to go on. */
762  break;
763  } else if (test->move_slow != 0)
764  gdImageSetPixel(infomap, x*50+tx, y*50+ty, color_slowing);
765 
766  } FOR_MAP_FINISH();
767  }
768  }
769 }
770 
771 void do_auto_apply(mapstruct *m);
772 
785 static void relative_path(const char *from, const char *to, char *result) {
786  const char *fslash;
787  const char *rslash;
788 
789  result[0] = '\0';
790 
791  fslash = strchr(from+1, '/');
792  if (!fslash) {
793  strcpy(result, to+1);
794  return;
795  }
796 
797  rslash = strchr(to+1, '/');
798  while (fslash && rslash && (fslash-from == rslash-to) && strncmp(from, to, fslash-from+1) == 0) {
799  from = fslash+1;
800  to = rslash+1;
801  fslash = strchr(fslash+1, '/');
802  rslash = strchr(rslash+1, '/');
803  }
804 
805  while (fslash) {
806  strcat(result, "../");
807  fslash = strchr(fslash+1, '/');
808  }
809  if (strlen(result) && result[strlen(result)-1] == '/' && *to == '/')
810  result[strlen(result)-1] = '\0';
811  strcat(result, to);
812 }
813 
824 static int compare_map_info(const struct_map_info *left, const struct_map_info *right) {
825  int c;
826 
827  if (left->tiled_group)
828  left = left->tiled_group;
829  if (right->tiled_group)
830  right = right->tiled_group;
831 
832  // Shortcut -- if both are the same pointer, return 0.
833  // This occurs when tiled maps of the same set are compared to each other.
834  if (left == right)
835  return 0;
836 
837  c = strcasecmp(left->name, right->name);
838  if (c)
839  return c;
840 
841  return strcasecmp(left->path, right->path);
842 }
843 
854 static int sort_map_info(const void *left, const void *right) {
855  const struct_map_info *l = *(const struct_map_info **)left;
856  const struct_map_info *r = *(const struct_map_info **)right;
857  return compare_map_info(l, r);
858 }
859 
870 static int sort_region(const void *left, const void *right) {
871  return strcmp((*((struct_region_info **)left))->reg->name, (*((struct_region_info **)right))->reg->name);
872 }
873 
874 /************************************
875  Start of quest-related definitions.
876 ************************************/
877 
881  char *description;
882  struct struct_quest *quest;
883 };
884 
886 struct struct_quest {
887  char *name;
888  char *description;
889  int number;
892 };
893 
894 static struct_quest **quests = NULL;
896 static int quests_count = 0;
898 static int quests_allocated = 0;
901  list->list = NULL;
902  list->count = 0;
903  list->allocated = 0;
904 }
905 
907  if (list->count == list->allocated) {
908  list->allocated += 10;
909  list->list = (struct_map_in_quest **)realloc(list->list, sizeof(struct_map_in_quest *)*list->allocated);
910  }
911  list->list[list->count++] = item;
912 }
913 
919 static struct_quest *find_quest_info(const char *name) {
920  int test;
921  for (test = 0; test < quests_count; test++) {
922  if (strcmp(quests[test]->name, name) == 0)
923  return quests[test];
924  }
925  return NULL;
926 }
927 
936 static struct_quest *get_quest_info(const char *name) {
938  if (add) {
939  return add;
940  }
941 
943  quests_allocated += 10;
944  quests = (struct_quest **)realloc(quests, sizeof(struct_quest *)*quests_allocated);
945  }
946  add = (struct_quest *)calloc(1, sizeof(struct_quest));
947  add->name = strdup(name);
948  add->number = quests_count;
950  quests[quests_count] = add;
951  quests_count++;
952  return add;
953 }
954 
965 static void add_map_to_quest(struct_map_info *map, const char *name, const char *description) {
966  struct_map_in_quest *add;
968 
969  add = (struct_map_in_quest *)calloc(1, sizeof(struct_map_in_quest));
970  add->map = map;
971  add->quest = quest;
972  add->description = strdup(description);
973  while (strlen(add->description) && add->description[strlen(add->description)-1] == '\n')
974  add->description[strlen(add->description)-1] = '\0';
976  add_to_struct_map_in_quest_list(&map->quests, add);
977 }
978 
987 static int sort_struct_map_in_quest(const void *left, const void *right) {
988  int c;
989 
990  const struct_map_in_quest *l = *(const struct_map_in_quest **)left;
991  const struct_map_in_quest *r = *(const struct_map_in_quest **)right;
992  const struct_map_info *ml = l->map;
993  const struct_map_info *mr = r->map;
994 
995  if (ml->tiled_group)
996  ml = ml->tiled_group;
997  if (mr->tiled_group)
998  mr = mr->tiled_group;
999 
1000  c = strcasecmp(ml->name, mr->name);
1001  if (c)
1002  return c;
1003 
1004  return strcasecmp(ml->path, mr->path);
1005 }
1006 
1015 static int sort_struct_quest(const void *left, const void *right) {
1016  const struct_quest *l = *(const struct_quest **)left;
1017  const struct_quest *r = *(const struct_quest **)right;
1018  return strcasecmp(l->name, r->name);
1019 }
1020 
1031 static void define_quest(const char *name, struct_map_info *mainmap, const char *description) {
1033 
1034  if (quest->description || quest->mainmap) {
1035  printf("warning, multiple quest definition for %s, found in %s and %s.\n", quest->name, quest->mainmap ? quest->mainmap->path : "(unknown map)", mainmap->path);
1036  return;
1037  }
1038  quest->description = strdup(description);
1039  while (strlen(quest->description) && quest->description[strlen(quest->description)-1] == '\n')
1040  quest->description[strlen(quest->description)-1] = '\0';
1041  quest->mainmap = mainmap;
1042 }
1043 
1051  char *start, *end, *next;
1052  char name[500];
1053  char description[500];
1054 
1055  start = strstr(map->lore, "@def");
1056  while (start) {
1057  description[0] = '\0';
1058  /* find name */
1059  end = strstr(start, "\n");
1060  if (end) {
1061  strncpy(name, start+5, end-start-5);
1062  name[end-start-5] = '\0';
1063  next = end+1;
1064  end = strstr(next, "@end");
1065  if (end) {
1066  strncpy(description, next, end-next);
1067  description[end-next] = '\0';
1068  /* need to erase the text. */
1069  memmove(start, end+4, strlen(map->lore)-(end-start+3));
1070  end = start;
1071  }
1072  else {
1073  strcpy(description, next);
1074  *start = '\0';
1075  end = NULL;
1076  }
1077  } else {
1078  strcpy(name, start);
1079  *start = '\0';
1080  end = NULL;
1081  }
1082 
1084  start = end ? strstr(end, "@def") : NULL;
1085  }
1086 
1087  start = strstr(map->lore, "@quest");
1088  while (start) {
1089  description[0] = '\0';
1090  /* find name */
1091  end = strstr(start, "\n");
1092  if (end) {
1093  strncpy(name, start+7, end-start-7);
1094  name[end-start-7] = '\0';
1095  next = end+1;
1096  end = strstr(next, "@end");
1097  if (end) {
1098  strncpy(description, next, end-next);
1099  description[end-next] = '\0';
1100  /* need to erase the text. */
1101  memmove(start, end+4, strlen(map->lore)-(end-start+3));
1102  end = start;
1103  }
1104  else {
1105  strcpy(description, next);
1106  *start = '\0';
1107  end = NULL;
1108  }
1109  } else {
1110  strcpy(name, start);
1111  *start = '\0';
1112  end = NULL;
1113  }
1114 
1116  start = end ? strstr(end, "@quest") : NULL;
1117  }
1118 }
1119 
1120 /************************************
1121  End of quest-related definitions.
1122 ************************************/
1123 
1124 /*********
1125 NPC-related stuff
1126 ********/
1127 
1135 static struct_npc_info *create_npc_info(const object *npc) {
1136  struct_npc_info *info = (struct_npc_info *)calloc(1, sizeof(struct_npc_info));
1137 
1138  info->name = strdup(npc->name);
1139  info->message = strdup(npc->msg);
1140  info->x = npc->x;
1141  info->y = npc->y;
1142 
1143  return info;
1144 }
1145 
1153 static void add_npc_to_map(npc_list *list, const object *npc) {
1154  list->push_back(create_npc_info(npc));
1155 }
1156 /* end of NPC stuff */
1157 
1170  size_t map;
1171 
1172  for (map = 0; map < list->count; map++)
1173  if (list->maps[map] == info)
1174  return;
1175 
1176  if (list->count == list->allocated) {
1177  list->allocated += 50;
1178  list->maps = (struct_map_info **)realloc(list->maps, list->allocated*sizeof(struct_map_info *));
1179  }
1180  list->maps[list->count] = info;
1181  list->count++;
1182 }
1183 
1191  struct_map_info *add = (struct_map_info *)calloc(1, sizeof(struct_map_info));
1192 
1193  add->min_monster = 2000;
1194  init_map_list(&add->exits_to);
1195  init_map_list(&add->exits_from);
1196  init_map_list(&add->tiled_maps);
1198  init_race_list(&add->monsters);
1199  add->npcs = new npc_list();
1200  add->readable = new npc_list();
1201  add->tiled_group = NULL;
1202 
1203  return add;
1204 }
1205 
1214 
1215  add_map(add, &tiled_map_list);
1216  return add;
1217 }
1218 
1229  size_t g;
1230  struct_map_info *group = tiled_map->tiled_group;
1231  struct_map_info *change;
1232 
1233  while (group->tiled_maps.count > 0) {
1234  change = group->tiled_maps.maps[group->tiled_maps.count-1];
1235  change->tiled_group = map->tiled_group;
1236  add_map(change, &map->tiled_group->tiled_maps);
1237  group->tiled_maps.count--;
1238  }
1239 
1240  for (g = 0; g < tiled_map_list.count; g++) {
1241  if (tiled_map_list.maps[g] == group) {
1242  if (g < tiled_map_list.count-1)
1245  free(group);
1246  return;
1247  }
1248  }
1249  printf("tiled_map not in tiled_map_list!");
1250  abort();
1251 
1252 }
1253 
1262 static struct_map_info *get_map_info(const char *path) {
1263  struct_map_info *add;
1264  char *tmp;
1265 
1266  for (size_t map = 0; map < maps_list.count; map++) {
1267  if (strcmp(maps_list.maps[map]->path, path) == 0)
1268  return maps_list.maps[map];
1269  }
1270 
1271  add = create_map_info();
1272  add->path = strdup(path);
1273  tmp = strrchr((char *)path, '/');
1274  if (tmp)
1275  add->filename = strdup(tmp+1);
1276  else
1277  add->filename = strdup(path);
1278 
1279  add_map(add, &maps_list);
1280  return add;
1281 }
1282 
1289 static void list_map(const char *path) {
1290  for (auto map = found_maps.begin(); map != found_maps.end(); ++map) {
1291  if (strcmp(path, *map) == 0) {
1292  free(*map);
1293  found_maps.erase(map);
1294  return;
1295  }
1296  }
1297  printf("Map processed but not found in directory reading? %s\n", path);
1298 }
1299 
1311  size_t test;
1312  int x, y;
1313 
1314  for (test = 0; test < region_count; test++) {
1315  if (regions[test]->reg == reg)
1316  break;
1317  }
1318  if (test == region_count) {
1319  if (test == region_allocated) {
1320  region_allocated++;
1322  regions[test] = (struct_region_info *)calloc(1, sizeof(struct_region_info));
1323  }
1324  region_count++;
1325  regions[test]->reg = reg;
1326  }
1327  add_map(map, &regions[test]->maps_list);
1328  if (sscanf(map->path, "/world/world_%d_%d", &x, &y) == 2) {
1329  regions[test]->sum_x += (x-100);
1330  regions[test]->sum_y += (y-100);
1331  regions[test]->sum++;
1332  regions[test]->is_world = 1;
1333  }
1334 }
1335 
1344 static void save_picture(FILE *file, gdImagePtr pic) {
1345  if (output_format == OF_PNG)
1346  gdImagePng(pic, file);
1347  else
1348  gdImageJpeg(pic, file, jpeg_quality);
1349 }
1350 
1359  region *s, *d;
1360 
1363  if (s == d)
1364  return;
1365 
1366  region_links[s].insert(d);
1367 }
1368 
1377 static int is_slaying(object *item) {
1378  return (item->type == LOCKED_DOOR || item->type == SPECIAL_KEY || item->type == CONTAINER || item->type == CHECK_INV);
1379 }
1380 
1381 
1390 static struct_slaying_info *get_slaying_struct(const char *slaying) {
1391  for (size_t l = 0; l < slaying_count; l++) {
1392  if (!strcmp(slaying_info[l]->slaying, slaying))
1393  return slaying_info[l];
1394  }
1396  slaying_allocated += 10;
1398  }
1399 
1400  struct_slaying_info *add = (struct_slaying_info *)calloc(1, sizeof(struct_slaying_info));
1401  add->slaying = strdup(slaying);
1402  for (size_t l = 0; l < S_MAX; l++)
1403  init_map_list(&add->maps[l]);
1404 
1405  slaying_info[slaying_count] = add;
1406  slaying_count++;
1407 
1408  return add;
1409 }
1410 
1422  add_map(map, &info->maps[item]);
1423 }
1424 
1433 static void add_slaying(struct_map_info *map, object *item) {
1434  struct_slaying_info *info;
1435 
1436  if (!item->slaying)
1437  /* can be undefined */
1438  return;
1439 
1440  info = get_slaying_struct(item->slaying);
1441  if (item->type == LOCKED_DOOR)
1442  add_map_to_slaying(info, S_DOOR, map);
1443  else if (item->type == SPECIAL_KEY)
1444  add_map_to_slaying(info, S_KEY, map);
1445  else if (item->type == CONTAINER)
1447  else if (item->type == DETECTOR)
1449  else
1451 }
1452 
1463  if (is_slaying(inv))
1464  add_slaying(map, inv);
1466  } FOR_INV_FINISH();
1467 }
1468 
1469 static void generate_picture_path(const char *path, size_t pic_size, char *out, size_t len) {
1470  snprintf(out, len, "%s%s.x%zu%s", root, path, pic_size + 1, output_extensions[output_format]);
1471 }
1472 
1473 static void write_pictures_from_real_size(const char *path, gdImagePtr real, int width, int height) {
1474  char picpath[MAX_BUF];
1475 
1476  generate_picture_path(path, 0, picpath, sizeof(picpath));
1477  make_path_to_file(picpath);
1478  FILE *out = fopen(picpath, "wb+");
1479  save_picture(out, real);
1480  fclose(out);
1481 
1482  for (size_t i = 1; i < num_sizes; i++) {
1483  generate_picture_path(path, i, picpath, sizeof(picpath));
1484  gdImagePtr small = gdImageCreateTrueColor(width*sizes[i], height*sizes[i]);
1485  gdImageCopyResampled(small, real, 0, 0, 0, 0, width*sizes[i], height*sizes[i], width*size_large, height*size_large);
1486  out = fopen(picpath, "wb+");
1487  save_picture(out, small);
1488  fclose(out);
1489  gdImageDestroy(small);
1490  }
1491 }
1492 
1501 static void process_map(struct_map_info *info) {
1502  mapstruct *m;
1503  int x, y, isworld;
1504  gdImagePtr pic = nullptr;
1505  struct stat stats;
1506  struct stat statspic;
1507  char exit_path[500];
1508  char tmppath[MAX_BUF];
1509  char picpath[num_sizes][MAX_BUF];
1510  int needpic = 0;
1511  struct_map_info *link;
1512 
1513  if (list_unused_maps)
1514  list_map(info->path);
1515 
1516  if (show_maps)
1517  printf(" processing map %s\n", info->path);
1518 
1519  m = ready_map_name(info->path, 0);
1520  if (!m) {
1521  printf("couldn't load map %s\n", info->path);
1522  return;
1523  }
1524 
1525  do_exit_map(m);
1526 
1527  if (!rawmaps)
1528  do_auto_apply(m);
1529 
1530  info->level = m->difficulty;
1531  if (m->maplore) {
1532  info->lore = strdup(m->maplore);
1533  process_map_lore(info);
1534  }
1535  if (m->reset_group) {
1536  info->reset_group = add_string(m->reset_group);
1537  reset_groups.insert(m->reset_group);
1538  }
1539 
1540  isworld = (sscanf(info->path, "/world/world_%d_%d", &x, &y) == 2);
1541 
1542  if (m->name)
1543  info->name = strdup(m->name);
1544  else
1545  info->name = strdup(info->filename);
1546 
1547  info->cfregion = get_region_by_map(m);
1548  add_map_to_region(info, info->cfregion);
1549 
1550  for (int i = 0; i < num_sizes; i++) {
1551  generate_picture_path(info->path, i, picpath[i], sizeof(picpath[i]));
1552  }
1553 
1554  if (force_pics)
1555  needpic = 1;
1556  else if (generate_pics) {
1557  create_pathname(info->path, tmppath, MAX_BUF);
1558  stat(tmppath, &stats);
1559  if (stat(picpath[0], &statspic) || (statspic.st_mtime < stats.st_mtime))
1560  needpic = 1;
1561  }
1562  else
1563  needpic = 0;
1564 
1565  if (needpic) {
1566  pic = gdImageCreateTrueColor(MAP_WIDTH(m)*size_large, MAP_HEIGHT(m)*size_large);
1567  created_pics++;
1568  }
1569  else
1570  cached_pics++;
1571 
1572  for (x = 0; x < 4; x++)
1573  if (m->tile_path[x] != NULL) {
1574  path_combine_and_normalize(m->path, m->tile_path[x], exit_path, sizeof(exit_path));
1575  create_pathname(exit_path, tmppath, MAX_BUF);
1576  if (stat(tmppath, &stats)) {
1577  printf(" map %s doesn't exist in map %s, for tile %d.\n", exit_path, info->path, x);
1578  }
1579 
1580  if (isworld) {
1581  link = get_map_info(exit_path);
1582  add_map(link, &info->exits_from);
1583  add_map(info, &link->exits_to);
1584 
1585  if (do_regions_link) {
1586  mapstruct *link = ready_map_name(exit_path, 0);
1587 
1588  if (link && link != m) {
1589  /* no need to link a map with itself. Also, if the exit points to the same map, we don't
1590  * want to reset it. */
1591  add_region_link(m, link);
1592  link->reset_time = 1;
1593  link->in_memory = MAP_IN_MEMORY;
1594  delete_map(link);
1595  }
1596  }
1597  } else {
1598  link = get_map_info(exit_path);
1599  info->tiles[x] = link;
1600  if (link->tiled_group) {
1601  if (info->tiled_group && link->tiled_group != info->tiled_group) {
1602  merge_tiled_maps(info, link);
1603  continue;
1604  }
1605  if (link->tiled_group == info->tiled_group) {
1606  continue;
1607  }
1608  if (!info->tiled_group) {
1609  add_map(info, &link->tiled_group->tiled_maps);
1610  continue;
1611  }
1612  }
1613 
1614  if (!info->tiled_group) {
1615  info->tiled_group = create_tiled_map();
1616  add_map(info, &info->tiled_group->tiled_maps);
1617  }
1618  link->tiled_group = info->tiled_group;
1619  add_map(link, &info->tiled_group->tiled_maps);
1620  }
1621  }
1622 
1623  info->width = MAP_WIDTH(m);
1624  info->height = MAP_HEIGHT(m);
1625 
1626  for (x = MAP_WIDTH(m)-1; x >= 0; x--)
1627  for (y = MAP_HEIGHT(m)-1; y >= 0; y--) {
1628  FOR_MAP_PREPARE(m, x, y, item) {
1629  if (item->type == EXIT || item->type == TELEPORTER || item->type == PLAYER_CHANGER) {
1630  char ep[500];
1631  const char *start;
1632 
1633  if (!item->slaying) {
1634  ep[0] = '\0';
1635  if (warn_no_path)
1636  printf(" exit without any path at %d, %d on %s\n", item->x, item->y, info->path);
1637  } else {
1638  memset(ep, 0, 500);
1639  if (strcmp(item->slaying, "/!"))
1640  strcpy(ep, EXIT_PATH(item));
1641  else {
1642  if (!item->msg) {
1643  printf(" random map without message in %s at %d, %d\n", info->path, item->x, item->y);
1644  } else {
1645  /* Some maps have a 'exit_on_final_map' flag, ignore it. */
1646  start = strstr(item->msg, "\nfinal_map ");
1647  if (!start && strncmp(item->msg, "final_map", strlen("final_map")) == 0)
1648  /* Message start is final_map, nice */
1649  start = item->msg;
1650  if (start) {
1651  char *end = strchr((char *)start+1, '\n');
1652 
1653  start += strlen("final_map")+2;
1654  strncpy(ep, start, end-start);
1655  }
1656  }
1657  }
1658 
1659  if (strlen(ep)) {
1660  path_combine_and_normalize(m->path, ep, exit_path, 500);
1661  create_pathname(exit_path, tmppath, MAX_BUF);
1662  if (stat(tmppath, &stats)) {
1663  printf(" map %s doesn't exist in map %s, at %d, %d.\n", ep, info->path, item->x, item->y);
1664  } else {
1665  link = get_map_info(exit_path);
1666  add_map(link, &info->exits_from);
1667  add_map(info, &link->exits_to);
1668 
1669  if (do_regions_link) {
1670  mapstruct *link = ready_map_name(exit_path, 0);
1671 
1672  if (link && link != m) {
1673  /* no need to link a map with itself. Also, if the exit points to the same map, we don't
1674  * want to reset it. */
1675  add_region_link(m, link);
1676  link->reset_time = 1;
1677  link->in_memory = MAP_IN_MEMORY;
1678  delete_map(link);
1679  }
1680  }
1681  }
1682  }
1683  }
1684  } else if (is_slaying(item))
1685  add_slaying(info, item);
1686 
1687  check_equipment(item, info);
1688 
1690 
1691  if (QUERY_FLAG(item, FLAG_MONSTER)) {
1692  /* need to get the "real" archetype, as the item's archetype can certainly be a temporary one. */
1693  archetype *arch = find_archetype(item->arch->name);
1694 
1695  add_monster(item, info);
1696  if (arch != NULL && (QUERY_FLAG(item, FLAG_UNAGGRESSIVE) || QUERY_FLAG(item, FLAG_FRIENDLY)) && (item->msg != arch->clone.msg) && (item->msg != NULL))
1697  add_npc_to_map(info->npcs, item);
1698  } else if ((item->type == SIGN || item->type == BOOK) && (item->msg != item->arch->clone.msg) && (item->msg != NULL)) {
1699  add_npc_to_map(info->readable, item);
1700  }
1701 
1702  if (item->invisible)
1703  continue;
1704 
1705  if (needpic) {
1706  int sx, sy, hx, hy;
1707 
1708  if (gdfaces[item->face->number] == NULL) {
1709  face_sets *fs = find_faceset(get_face_fallback(tileset, item->face->number));
1710 
1711  gdfaces[item->face->number] = gdImageCreateFromPngPtr(fs->faces[item->face->number].datalen, fs->faces[item->face->number].data);
1712  pics_allocated++;
1713  }
1714  if (item->head || item->more) {
1715  object_get_multi_size(item, &sx, &sy, &hx, &hy);
1716  } else {
1717  hx = 0;
1718  hy = 0;
1719  }
1720  if (gdfaces[item->face->number] != NULL && ((!item->head && !item->more) || (item->arch->clone.x+hx == 0 && item->arch->clone.y+hy == 0))) {
1721  gdImageCopy(pic, gdfaces[item->face->number], x*size_large, y*size_large, 0, 0, gdfaces[item->face->number]->sx, gdfaces[item->face->number]->sy);
1722  }
1723  }
1724  } FOR_MAP_FINISH();
1725  }
1726 
1727  if (needpic) {
1729  gdImageDestroy(pic);
1730  info->pic_was_done = 1;
1731  }
1732 
1733  m->reset_time = 1;
1734  m->in_memory = MAP_IN_MEMORY;
1735  delete_map(m);
1736 }
1737 
1741 static void write_world_map(void) {
1742 #define SIZE 50
1743  int x, y;
1744  FILE *out;
1745  int wx, wy;
1746  char file[500];
1747  char mapleft[10], maptop[10], mapright[10], mapbottom[10], mappath[5000];
1748  char name[100];
1749  gdImagePtr pic;
1750  gdImagePtr small;
1751  gdFontPtr font;
1752  int color;
1753 
1754  if (!world_map)
1755  return;
1756 
1757  printf("Generating world map in world.html...");
1758  fflush(stdout);
1759 
1760  pic = gdImageCreateTrueColor(SIZE*30, SIZE*30);
1761 
1762  strcpy(file, root);
1763  strcat(file, "/world.html");
1764 
1765  wx = 100;
1766  wy = 100;
1767 
1768  for (y = 0; y < 30; y++) {
1769  for (x = 0; x < 30; x++) {
1770  snprintf(name, sizeof(name), "world_%d_%d", wx, wy);
1771  snprintf(mapleft, sizeof(mapleft), "%d", SIZE*x);
1772  snprintf(maptop, sizeof(maptop), "%d", SIZE*y);
1773  snprintf(mapright, sizeof(mapright), "%d", SIZE*(x+1)-1);
1774  snprintf(mapbottom, sizeof(mapbottom), "%d", SIZE*(y+1)-1);
1775 
1776  snprintf(mappath, sizeof(mappath), "%s/world/%s.x1%s", root, name, output_extensions[output_format]);
1777 
1778  out = fopen(mappath, "rb");
1779  if (!out) {
1780  printf("\n warning: large pic not found for world_%d_%d", wx, wy);
1781  wx++;
1782  continue;
1783  }
1784  if (output_format == OF_PNG)
1785  small = gdImageCreateFromPng(out);
1786  else
1787  small = gdImageCreateFromJpeg(out);
1788  fclose(out);
1789  if (!small) {
1790  printf("\n warning: pic not found for world_%d_%d", wx, wy);
1791  wx++;
1792  continue;
1793  }
1794  gdImageCopyResized(pic, small, SIZE*x, SIZE*y, 0, 0, SIZE, SIZE, small->sx, small->sy);
1795  gdImageDestroy(small);
1796 
1797  wx++;
1798  }
1799  wy++;
1800  wx = 100;
1801  }
1802 
1803  snprintf(mappath, sizeof(mappath), "%s/world_raw%s", root, output_extensions[output_format]);
1804  out = fopen(mappath, "wb+");
1805  save_picture(out, pic);
1806  fclose(out);
1807 
1808  /* Write region names. */
1809  small = gdImageCreateTrueColor(SIZE*30, SIZE*30);
1810  font = gdFontGetGiant();
1811  color = gdImageColorAllocateAlpha(pic, 255, 0, 0, 20);
1812  for (size_t region = 0; region < region_allocated; region++) {
1813  if (!regions[region]->is_world || regions[region]->sum == 0)
1814  continue;
1815 
1816  x = regions[region]->sum_x*SIZE/regions[region]->sum+SIZE/2-strlen(regions[region]->reg->name)*font->w/2;
1817  y = regions[region]->sum_y*SIZE/regions[region]->sum+SIZE/2-font->h/2;
1818  gdImageString(small, font, x, y, (unsigned char *)regions[region]->reg->name, color);
1819  gdImageString(pic, font, x, y, (unsigned char *)regions[region]->reg->name, color);
1820 
1821  /* For exit/road map, size isn't the same. */
1822  x = regions[region]->sum_x*50/regions[region]->sum+50/2-strlen(regions[region]->reg->name)*font->w/2;
1823  y = regions[region]->sum_y*50/regions[region]->sum+50/2-font->h/2;
1824  gdImageString(infomap, font, x, y, (unsigned char *)regions[region]->reg->name, color);
1825  }
1826 
1827  snprintf(mappath, sizeof(mappath), "%s/world_regions%s", root, output_extensions[output_format]);
1828  out = fopen(mappath, "wb+");
1829  save_picture(out, small);
1830  fclose(out);
1831  gdImageDestroy(small);
1832 
1833  snprintf(mappath, sizeof(mappath), "%s/world%s", root, output_extensions[output_format]);
1834  out = fopen(mappath, "wb+");
1835  save_picture(out, pic);
1836  fclose(out);
1837  gdImageDestroy(pic);
1838 
1839  printf(" done.\n");
1840 #undef SIZE
1841 }
1842 
1844 static void fix_map_names(void) {
1845  for (size_t map = 0; map < maps_list.count; map++) {
1846  if (maps_list.maps[map]->name)
1847  continue;
1848  if (!maps_list.maps[map]->filename) {
1849  printf("map without path!\n");
1850  abort();
1851  }
1852  maps_list.maps[map]->name = strdup(maps_list.maps[map]->filename);
1853  }
1854 }
1855 
1862 static void fix_tiled_map(void) {
1863  size_t map, tile;
1864  char name[500];
1865  char *slash, *test;
1866  region *cfregion;
1867 
1868  for (map = 0; map < tiled_map_list.count; map++) {
1869  if (tiled_map_list.maps[map]->tiled_maps.count == 0) {
1870  printf("empty tiled map group!");
1871  abort();
1872  }
1873 
1874  snprintf(name, sizeof(name), "tiled_map_group_%zu", map);
1875  tiled_map_list.maps[map]->filename = strdup(name);
1876 
1877  cfregion = NULL;
1878  test = NULL;
1879 
1880  for (tile = 0; tile < tiled_map_list.maps[map]->tiled_maps.count; tile++) {
1882  /* map not processed, ignore it. */
1883  continue;
1884 
1885  if (!cfregion)
1887  else if (cfregion != tiled_map_list.maps[map]->tiled_maps.maps[tile]->cfregion) {
1888  printf("*** warning: tiled maps %s and %s not in same region (%s and %s).\n",
1891  cfregion = NULL;
1892  }
1893 
1895  /* map has a custom name, use it */
1896  if (!test)
1898  }
1899  }
1900 
1901  if (!test) {
1902  /* this can happen of course if only partial maps were processed, but well... */
1903  printf("*** warning: tiled map without any name. First map path %s\n", tiled_map_list.maps[map]->tiled_maps.maps[0]->path);
1904  test = name;
1905  }
1906 
1907  tiled_map_list.maps[map]->name = strdup(test);
1908  tiled_map_list.maps[map]->cfregion = cfregion;
1909 
1910  strncpy(name, tiled_map_list.maps[map]->tiled_maps.maps[0]->path, sizeof(name));
1911  slash = strrchr(name, '/');
1912  if (!slash)
1913  snprintf(name, sizeof(name), "/");
1914  else
1915  *(slash+1) = '\0';
1916  strncat(name, tiled_map_list.maps[map]->filename, sizeof(name) - strlen(name) - 1);
1917  tiled_map_list.maps[map]->path = strdup(name);
1918  }
1919 }
1920 
1931 static void fix_exits_for_map(struct_map_info *current, struct_map_list *from, int is_from) {
1932  int map, max;
1933  struct_map_info *group;
1934 
1935  max = from->count-1;
1936  for (map = max; map >= 0; map--) {
1937  if (from->maps[map]->tiled_group) {
1938  group = from->maps[map]->tiled_group;
1939  if (map != max)
1940  from->maps[map] = from->maps[max];
1941  from->count--;
1942  max--;
1943  add_map(group, from);
1944  add_map(current->tiled_group ? current->tiled_group : current, is_from ? &group->exits_to : &group->exits_from);
1945  }
1946  }
1947 }
1948 
1950 static void fix_exits_to_tiled_maps(void) {
1951  int map, max;
1952  struct_map_info *group;
1953 
1954  for (map = 0; static_cast<size_t>(map) < maps_list.count; map++) {
1957  }
1958 
1959  for (size_t region = 0; region < region_count; region++) {
1961  for (map = max; map >= 0; map--) {
1964  if (map != max)
1967  max--;
1968  add_map(group, &regions[region]->maps_list);
1969  }
1970  }
1971  }
1972 }
1973 
1978 static void fix_tiled_map_monsters(void) {
1979  int map, max;
1980  struct_map_info *group;
1981 
1982  for (size_t race = 0; race < races.count; race++) {
1983  max = races.races[race]->origin.count-1;
1984  for (map = max; map >= 0; map--) {
1985  if (races.races[race]->origin.maps[map]->tiled_group) {
1986  group = races.races[race]->origin.maps[map]->tiled_group;
1987  if (map != max)
1988  races.races[race]->origin.maps[map] = races.races[race]->origin.maps[max];
1989  races.races[race]->origin.count--;
1990  max--;
1991  add_map(group, &races.races[race]->origin);
1992  }
1993  }
1994  }
1995 
1996  for (map = 0; static_cast<size_t>(map) < maps_list.count; map++) {
1997  if (maps_list.maps[map]->tiled_group) {
1998  for (size_t race = 0; race < maps_list.maps[map]->monsters.count; race++) {
2000  }
2001  }
2002  }
2003 }
2004 
2006  size_t test;
2007  char picpath[500];
2008  struct stat stats;
2009 
2010  for (size_t size = 0; size < num_sizes; size++) {
2011  generate_picture_path(map->path, size, picpath, sizeof(picpath));
2012  if (stat(picpath, &stats))
2013  return 1;
2014  }
2015 
2016  for (test = 0; test < map->tiled_maps.count; test++) {
2017  if (map->tiled_maps.maps[test]->pic_was_done)
2018  return 1;
2019  }
2020 
2021  return 0;
2022 }
2023 
2036  int xmin = 0, xmax = 0, ymin = 0, ymax = 0, count, last;
2037  size_t tiled;
2038  char picpath[500];
2039  gdImagePtr large, load;
2040  FILE *out;
2042 
2043  if (!generate_pics)
2044  return;
2045 
2046  printf(" Generating composite map for %s...", map->name);
2047  fflush(stdout);
2048 
2049  if (!tiled_map_need_pic(map)) {
2050  printf(" already uptodate.\n");
2051  return;
2052  }
2053 
2054  count = map->tiled_maps.count;
2055  if (count == 0) {
2056  printf("Tiled map without tiled maps?\n");
2057  abort();
2058  }
2059  map->tiled_maps.maps[0]->processed = 1;
2060  map->tiled_maps.maps[0]->tiled_x_from = 0;
2061  map->tiled_maps.maps[0]->tiled_y_from = 0;
2062 
2063  while (count > 0) {
2064  last = count;
2065 
2066  for (tiled = 0; tiled < map->tiled_maps.count; tiled++) {
2067  current = map->tiled_maps.maps[tiled];
2068  if (current->processed != 1)
2069  continue;
2070 
2071  count--;
2072 
2073  if ((current->tiles[0]) && (current->tiles[0]->processed == 0)) {
2074  current->tiles[0]->processed = 1;
2075  current->tiles[0]->tiled_x_from = current->tiled_x_from;
2076  current->tiles[0]->tiled_y_from = current->tiled_y_from-current->tiles[0]->height;
2077  }
2078  if ((current->tiles[1]) && (current->tiles[1]->processed == 0)) {
2079  current->tiles[1]->processed = 1;
2080  current->tiles[1]->tiled_x_from = current->tiled_x_from+current->width;
2081  current->tiles[1]->tiled_y_from = current->tiled_y_from;
2082  }
2083  if ((current->tiles[2]) && (current->tiles[2]->processed == 0)) {
2084  current->tiles[2]->processed = 1;
2085  current->tiles[2]->tiled_x_from = current->tiled_x_from;
2086  current->tiles[2]->tiled_y_from = current->tiled_y_from+current->height;
2087  }
2088  if ((current->tiles[3]) && (current->tiles[3]->processed == 0)) {
2089  current->tiles[3]->processed = 1;
2090  current->tiles[3]->tiled_x_from = current->tiled_x_from-current->tiles[3]->width;
2091  current->tiles[3]->tiled_y_from = current->tiled_y_from;
2092  }
2093  }
2094 
2095  if (last == count) {
2096  printf("do_tiled_map_picture: didn't process any map in %s (%d left)??\n", map->path, last);
2097  abort();
2098  }
2099  }
2100 
2101  for (tiled = 0; tiled < map->tiled_maps.count; tiled++) {
2102  if (map->tiled_maps.maps[tiled]->tiled_x_from < xmin)
2103  xmin = map->tiled_maps.maps[tiled]->tiled_x_from;
2104  if (map->tiled_maps.maps[tiled]->tiled_y_from < ymin)
2105  ymin = map->tiled_maps.maps[tiled]->tiled_y_from;
2106  if (map->tiled_maps.maps[tiled]->tiled_x_from+map->tiled_maps.maps[tiled]->width > xmax)
2107  xmax = map->tiled_maps.maps[tiled]->tiled_x_from+map->tiled_maps.maps[tiled]->width;
2108  if (map->tiled_maps.maps[tiled]->tiled_y_from+map->tiled_maps.maps[tiled]->height > ymax)
2109  ymax = map->tiled_maps.maps[tiled]->tiled_y_from+map->tiled_maps.maps[tiled]->height;
2110  }
2111 
2112  large = gdImageCreateTrueColor(size_large*(xmax-xmin), size_large*(ymax-ymin));
2113 
2114  for (tiled = 0; tiled < map->tiled_maps.count; tiled++) {
2115  generate_picture_path(map->tiled_maps.maps[tiled]->path, 0, picpath, sizeof(picpath));
2116 
2117  out = fopen(picpath, "rb");
2118  if (!out) {
2119  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);
2120  continue;
2121  }
2122  if (output_format == OF_PNG)
2123  load = gdImageCreateFromPng(out);
2124  else
2125  load = gdImageCreateFromJpeg(out);
2126  fclose(out);
2127  if (!load) {
2128  printf("\n do_tiled_map_picture: warning: pic not found for %s\n", map->tiled_maps.maps[tiled]->path);
2129  continue;
2130  }
2131  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);
2132  gdImageDestroy(load);
2133  }
2134 
2135  write_pictures_from_real_size(map->path, large, xmax-xmin, ymax-ymin);
2136 
2137  gdImageDestroy(large);
2138 
2139  printf(" done.\n");
2140 }
2141 
2144 
2146 
2149 // write_map_page(map);
2150 }
2151 
2153 static void write_tiled_maps(void) {
2154  printf("Writing tiled map information...\n");
2155 
2156  for (size_t map = 0; map < tiled_map_list.count; map++)
2158 
2159  printf(" done.\n");
2160 }
2161 
2162 static std::vector<quest_definition *> system_quests;
2163 
2164 static void quest_callback(const quest_definition *quest, void *) {
2165  if (list_system_quests || !quest->quest_is_system) {
2166  system_quests.push_back(const_cast<quest_definition *>(quest));
2167  }
2168 }
2169 
2170 static std::shared_ptr<inja::Environment> env;
2172 static std::set<std::string> rendered_templates;
2173 static std::map<struct_map_info *, std::string> reverse_maps;
2174 static std::map<region *, std::string> reverse_regions;
2181 static struct_map_info *find_map_by_key(const std::string &key) {
2182  auto found = std::find_if(reverse_maps.cbegin(), reverse_maps.cend(), [&key] (auto c) { return c.second == key; });
2183  if (found != reverse_maps.cend())
2184  return found->first;
2185  return nullptr;
2186 }
2187 
2193 static region *find_region_by_key(const std::string &key) {
2194  auto found = std::find_if(reverse_regions.cbegin(), reverse_regions.cend(), [&key] (auto c) { return c.second == key; });
2195  if (found != reverse_regions.cend())
2196  return found->first;
2197  return nullptr;
2198 }
2199 
2207  for (size_t m = 0; m < maps.count; m++) {
2208  auto map = reverse_maps.find(maps.maps[m]);
2209  if (map != reverse_maps.end()) {
2210  result.push_back(map->second);
2211  }
2212  }
2213  return result;
2214 }
2215 
2223  for (size_t n = 0; n < list.size(); n++) {
2224  auto npc = list[n];
2225  result.push_back({
2226  { "name", npc->name },
2227  { "x", npc->x },
2228  { "y", npc->y },
2229  { "message", npc->message },
2230  });
2231  }
2232  return result;
2233 }
2234 
2242  for (size_t n = 0; n < list.count; n++) {
2243  auto race = list.races[n];
2244  result.push_back({
2245  { "name", race->name },
2246  { "count", race->count },
2247  });
2248  }
2249  return result;
2250 }
2251 
2259  for (size_t m = 0; m < list.count; m++) {
2260  auto q = list.list[m];
2261  if (!q->map || !q->description)
2262  continue;
2263  ret.push_back({
2264  { "map", reverse_maps.find(q->map)->second },
2265  { "description", q->description },
2266  { "quest", q->quest->name },
2267  { "number", q->quest->number },
2268  });
2269  }
2270 
2271  return ret;
2272 }
2273 
2281  return {
2282  { "_key", key },
2283  { "name", map->name },
2284  { "path", map->path },
2285  { "region", map->cfregion ? reverse_regions[map->cfregion] : "reg_ffff" },
2286  { "level", map->level },
2287  { "reset_group", map->reset_group ? map->reset_group : "" },
2288  { "lore", map->lore && map->lore[0] ? map->lore : "" },
2289  { "exits_to", create_maps_array(map->exits_to) },
2290  { "exits_from", create_maps_array(map->exits_from) },
2291  { "npcs", create_npc_array(*map->npcs) },
2292  { "readables", create_npc_array(*map->readable) },
2293  { "monsters", create_race_array(map->monsters) },
2294  { "quests", create_map_in_quest_array(map->quests) },
2295  };
2296 }
2297 
2305  return {
2306  { "_key", key },
2307  { "number", quest->number },
2308  { "name", quest->name ? quest->name : "" },
2309  { "description", quest->description ? quest->description : "" },
2310  { "main_map", quest->mainmap ? reverse_maps.find(quest->mainmap)->second : "" },
2311  { "maps", create_map_in_quest_array(quest->maps) },
2312  };
2313 }
2314 
2320  char buf[50];
2321  for (size_t map = 0; map < list.count; map++) {
2322  auto cur = list.maps[map];
2323  if (cur->tiled_group)
2324  continue;
2325  snprintf(buf, sizeof(buf), "map_%04lu", map);
2326  reverse_maps.insert(std::make_pair(cur, buf));
2327  qsort(cur->exits_to.maps, cur->exits_to.count, sizeof(struct_map_info *), sort_map_info);
2328  qsort(cur->exits_from.maps, cur->exits_from.count, sizeof(struct_map_info *), sort_map_info);
2329  qsort(cur->monsters.races, cur->monsters.count, sizeof(struct_race *), sort_race);
2330  }
2331 }
2332 
2339  for (size_t map = 0; map < src.count; map++)
2340  add_map(src.maps[map], &dest);
2341 }
2342 
2348 static nlohmann::json create_region_array(const std::set<region *> &regions) {
2350  for (auto reg : regions) {
2351  auto r = reverse_regions.find(reg);
2352  if (r != reverse_regions.end()) {
2353  ret.push_back((*r).second);
2354  }
2355  }
2356  return ret;
2357 }
2358 
2365  char buf[10];
2366  struct_map_list all_maps;
2367  bool need_unknown_region = false;
2368 
2369  init_map_list(&all_maps);
2370  append_map_list(all_maps, maps_list);
2371  append_map_list(all_maps, tiled_map_list);
2372  qsort(all_maps.maps, all_maps.count, sizeof(struct_map_info *), sort_map_info);
2373 
2374  fill_reverse_maps(all_maps);
2375 
2376  for (size_t reg = 0; reg < region_count; reg++) {
2377  auto region = regions[reg];
2378  snprintf(buf, sizeof(buf), "reg_%04lu", reg);
2379  reverse_regions.insert(std::make_pair(region->reg, buf));
2380  }
2381 
2382  for (size_t reg = 0; reg < region_count; reg++) {
2383  auto region = regions[reg];
2384  qsort(region->maps_list.maps, region->maps_list.count, sizeof(struct_map_info *), sort_map_info);
2385 
2386  json["regions"].push_back({
2387  { "_key", reverse_regions[region->reg] },
2388  { "name", region->reg->name },
2389  { "longname", region->reg->longname },
2390  { "description", region->reg->msg ? region->reg->msg : "" },
2391  { "maps", create_maps_array(region->maps_list) },
2392  { "links", create_region_array(region_links[region->reg]) },
2393  });
2394  }
2395 
2396  for (auto map : reverse_maps) {
2397  auto cur = map.first;
2398  if (cur->tiled_group)
2399  continue;
2400  if (cur->cfregion == nullptr)
2401  need_unknown_region = true;
2402  json["maps"].push_back(create_map_object(cur, map.second));
2403  }
2404 
2405  if (need_unknown_region) {
2406  json["regions"].push_back({
2407  { "_key", "reg_ffff" },
2408  { "name", "unknown" },
2409  { "longname", "unknown" },
2410  { "description", "unknown" },
2411  { "maps", nlohmann::json::array() },
2412  { "links", nlohmann::json::array() },
2413  });
2414  }
2415 
2416  json["reset_groups"] = nlohmann::json::array();
2417  for (const auto &rg : reset_groups) {
2418  json["reset_groups"].push_back(rg);
2419  }
2420 
2421  json["items"] = nlohmann::json::array();
2422  for (size_t idx = 0; idx < special_equipment.size(); idx++) {
2423  auto eq = special_equipment[idx];
2424  json["items"][idx] = {
2425  { "name", eq->name },
2426  { "power", eq->power },
2427  { "calc_power", eq->calc_power },
2428  { "diff", eq->diff },
2429  { "maps", create_maps_array(eq->origin) },
2430  };
2431  }
2432 
2433  json["monsters"] = nlohmann::json::array();
2434  for (size_t item = 0; item < races.count; item++) {
2435  auto race = races.races[item];
2436  qsort(race->origin.maps, race->origin.count, sizeof(struct_map_info *), sort_map_info);
2437  json["monsters"].push_back({
2438  { "name", race->name },
2439  { "count", race->count },
2440  { "maps", create_maps_array(race->origin) },
2441  });
2442  }
2443 
2444  json["system_quests"] = nlohmann::json::array();
2445  for (size_t q = 0; q < system_quests.size(); q++) {
2446  auto quest = system_quests[q];
2447  nlohmann::json j({
2448  { "code", quest->quest_code },
2449  { "title", quest->quest_title },
2450  { "description", quest->quest_description ? quest->quest_description : "" },
2451  { "replayable", quest->quest_restart },
2452  { "steps", nlohmann::json::array() },
2453  { "maps", nlohmann::json::array() },
2454  });
2455 
2456  if (detail_quests) {
2457  std::sort(quest->steps.begin(), quest->steps.end(), [] (auto left, auto right) { return left->step < right->step; });
2458  for (size_t s = 0; s < quest->steps.size(); s++) {
2459  j["steps"].push_back({
2460  { "description", quest->steps[s]->step_description ? quest->steps[s]->step_description : "" },
2461  { "is_completion", quest->steps[s]->is_completion_step ? true : false },
2462  });
2463  }
2464 
2465  auto qim = find_quest_info(quest->quest_code);
2466  if (qim) {
2467  for (size_t m = 0; m < qim->maps.count; m++) {
2468  auto map = reverse_maps.find(qim->maps.list[m]->map);
2469  assert(map != reverse_maps.end());
2470  j["maps"].push_back({
2471  { "description", qim->maps.list[m]->description },
2472  { "map", map->second },
2473  });
2474  }
2475  }
2476  }
2477  json["system_quests"].push_back(j);
2478  }
2479 
2480  json["slaying"] = nlohmann::json::array();
2481  for (size_t s = 0; s < slaying_count; s++) {
2482  auto info = slaying_info[s];
2483  json["slaying"].push_back({
2484  { "slaying", info->slaying },
2485  { "doors", create_maps_array(info->maps[S_DOOR]) },
2486  { "keys", create_maps_array(info->maps[S_KEY]) },
2487  { "containers", create_maps_array(info->maps[S_CONTAINER]) },
2488  { "detectors", create_maps_array(info->maps[S_DETECTOR]) },
2489  { "connections", create_maps_array(info->maps[S_CONNECT]) },
2490  });
2491  }
2492 
2493  json["quests"] = nlohmann::json::array();
2494  for (int quest = 0; quest < quests_count; quest++) {
2496  char buf[100];
2497  snprintf(buf, sizeof(buf), "quest_%d", quests[quest]->number);
2499  }
2500 }
2501 
2503 static std::vector<std::string> path_stack;
2504 
2505 void add_template_to_render(const std::string &template_name, const std::string &output_name, const std::string &param);
2506 
2512 static std::string path_from_current(const std::string &path) {
2513  auto p(path);
2514  char rel[1000];
2515  if (p[0] != '/')
2516  p = '/' + p;
2517  auto current(path_stack.back());
2518  if (current[0] != '/')
2519  current = '/' + current;
2520  relative_path(current.c_str(), p.c_str(), rel);
2521  return rel;
2522 }
2523 
2530  auto template_name = args.at(0)->get<std::string>();
2531  auto output_name(template_name);
2532  auto param = (args.size() > 1 ? args.at(1)->get<std::string>() : "");
2533 
2534  if (!param.empty()) {
2535  output_name = param + "_" + output_name;
2536  if (param.substr(0, 4) == "map_") {
2537  auto map = find_map_by_key(param);
2538  if (map != nullptr) {
2539  output_name = std::string(map->path + 1) + ".html";
2540  }
2541  }
2542  if (param.substr(0, 4) == "reg_") {
2543  auto reg = find_region_by_key(param);
2544  if (reg != nullptr) {
2545  output_name = std::string(reg->name) + ".html";
2546  }
2547  }
2548  }
2549 
2550  add_template_to_render(template_name, output_name, param);
2551  return path_from_current(output_name);
2552 }
2553 
2560  auto what = args.at(0)->get<std::string>();
2561  if (what.substr(0, 4) == "map_") {
2562  auto map = find_map_by_key(what);
2563  if (map == nullptr)
2564  return "";
2565  int size = 0;
2566  if (args.size() > 1) {
2567  size = args.at(1)->get<int>() - 1;
2568  }
2569  char picpath[1000];
2570  snprintf(picpath, sizeof(picpath), "%s.x%d%s", map->path, size + 1, output_extensions[output_format]);
2571  return path_from_current(picpath);
2572  }
2573  return "";
2574 }
2575 
2580 public:
2581  std::string template_name;
2582  std::string output_name;
2583  std::string param;
2584 };
2585 static std::vector<pageToRender> pages;
2593 void add_template_to_render(const std::string &template_name, const std::string &output_name, const std::string &param) {
2594  auto on(output_name);
2595  if (on[0] != '/')
2596  on = '/' + on;
2597  if (rendered_templates.find(on) != rendered_templates.end())
2598  return;
2599 
2600  rendered_templates.insert(on);
2601  pageToRender r;
2602  r.template_name = template_name;
2603  r.output_name = on;
2604  r.param = param;
2605  pages.push_back(r);
2606 }
2607 
2608 static std::vector<std::string> split(const std::string &field, const std::string &by) {
2609  std::vector<std::string> result;
2610  size_t start = 0, found;
2611  while ((found = field.find(by, start)) != std::string::npos) {
2612  result.push_back(field.substr(start, found - start));
2613  start = found + 1;
2614  }
2615  result.push_back(field.substr(start));
2616  return result;
2617 }
2618 
2619 static std::string templates_root("templates/");
2620 static std::vector<std::string> templates;
2625 static void init_renderer_env() {
2626  env = std::make_shared<inja::Environment>(templates_root, std::string(root) + "/");
2627  env->add_callback("link_to_page", generate_page_and_link);
2628  env->add_callback("substr", [] (inja::Arguments &args) {
2629  std::string str = args.at(0)->get<std::string>();
2630  size_t start = args.at(1)->get<size_t>();
2631  size_t len = args.size() > 2 ? args.at(2)->get<size_t>() : std::string::npos;
2632  return str.substr(start, len);
2633  });
2634  env->add_callback("picture", generate_picture_link);
2635  env->add_callback("pad", [] (inja::Arguments &args) {
2636  char buf[50];
2637  int val = args.at(0)->get<int>(), digits = args.at(1)->get<int>();
2638  snprintf(buf, sizeof(buf), "%0*d", digits, val);
2639  return std::string(buf);
2640  });
2641  env->add_callback("path_to_root", 0, [] (inja::Arguments &) {
2642  std::string r(root);
2643  char rel[1000];
2644  auto current(path_stack.back() + '/');
2645  if (current[0] != '/')
2646  current = '/' + current;
2647  relative_path(current.c_str(), r.c_str(), rel);
2648  return std::string(rel);
2649  });
2650  env->add_callback("get_by_field", 3, [] (inja::Arguments &args) {
2651  const auto &src = args.at(0);
2652  auto field = args.at(1)->get<std::string>();
2653  const auto &value = args.at(2);
2654  auto found = std::find_if(src->begin(), src->end(), [&field, &value] (auto item) {
2655  return item[field] == *value;
2656  });
2657  if (found == src->end()) {
2658  return nlohmann::json();
2659  }
2660  return *found;
2661  });
2662  env->add_callback("get_list_by_field", 3, [] (inja::Arguments &args) {
2664  const auto &src = args.at(0);
2665  auto field = args.at(1)->get<std::string>();
2666  const auto filter = args.at(2);
2667  if (filter->is_array()) {
2668  std::copy_if(src->begin(), src->end(), std::back_inserter(ret), [&] (auto &item) {
2669  auto val = item[field];
2670  return std::find_if(filter->begin(), filter->end(), [&] (auto li) { return val == li; }) != filter->end();
2671  });
2672  } else {
2673  std::copy_if(src->begin(), src->end(), std::back_inserter(ret), [&] (auto &item) {
2674  return filter->get<std::string>() == item[field];
2675  });
2676  }
2677  return ret;
2678  });
2679  env->add_callback("sort", [] (inja::Arguments &args) {
2680  const auto &src = args.at(0);
2681  std::vector<nlohmann::json> ret;
2682  for (auto i : *src) {
2683  ret.push_back(i);
2684  }
2685  auto fields = split(args.at(1)->get<std::string>(), ",");
2686  bool invert = args.size() > 2 ? args.at(2)->get<bool>() : false;
2687  bool ignore_case = args.size() > 3 ? args.at(3)->get<bool>() : true;
2688  std::sort(ret.begin(), ret.end(), [&] (auto left, auto right) {
2689  for (auto field : fields) {
2690  nlohmann::json l = left[field], r = right[field];
2691  if (ignore_case && l.is_string() && r.is_string()) {
2692  std::string ls(l.get<std::string>()), rs(r.get<std::string>());
2693  std::transform(ls.begin(), ls.end(), ls.begin(), [](unsigned char c){ return std::tolower(c); });
2694  std::transform(rs.begin(), rs.end(), rs.begin(), [](unsigned char c){ return std::tolower(c); });
2695  if (ls == rs) {
2696  continue;
2697  }
2698  return invert ? (rs < ls) : (ls < rs);
2699  }
2700  if (r == l) {
2701  continue;
2702  }
2703  return invert ? (r < l) : (l < r);
2704  }
2705  return false;
2706  });
2707  return ret;
2708  });
2709 
2710  env->set_trim_blocks(true);
2711  env->set_lstrip_blocks(true);
2712 }
2713 
2715 static const char *ignore_path[] = {
2716  "/Info",
2717  "/editor",
2718  "/python",
2719  "/styles",
2720  "/templates",
2721  "/test",
2722  "/unlinked",
2723  NULL };
2724 
2726 static const char *ignore_name[] = {
2727  ".",
2728  "..",
2729  ".git",
2730  ".svn",
2731  "README",
2732  NULL };
2733 
2740 static void find_maps(const char *from) {
2741  struct dirent *file;
2742  struct stat statbuf;
2743  int status, ignore;
2744  char path[1024], full[1024];
2745  DIR *dir;
2746 
2747  for (ignore = 0; ignore_path[ignore] != NULL; ignore++) {
2748  if (strcmp(from, ignore_path[ignore]) == 0)
2749  return;
2750  }
2751 
2752  snprintf(path, sizeof(path), "%s/%s%s", settings.datadir, settings.mapdir, from);
2753  dir = opendir(path);
2754 
2755  if (dir) {
2756  for (file = readdir(dir); file; file = readdir(dir)) {
2757 
2758  for (ignore = 0; ignore_name[ignore] != NULL; ignore++) {
2759  if (strcmp(file->d_name, ignore_name[ignore]) == 0)
2760  break;
2761  }
2762  if (ignore_name[ignore] != NULL)
2763  continue;
2764 
2765  snprintf(full, sizeof(full), "%s/%s", path, file->d_name);
2766 
2767  status = stat(full, &statbuf);
2768  snprintf(full, sizeof(full), "%s/%s", from, file->d_name);
2769  if ((status != -1) && (S_ISDIR(statbuf.st_mode))) {
2770  find_maps(full);
2771  continue;
2772  }
2773  found_maps.push_back(strdup(full));
2774  }
2775  closedir(dir);
2776  }
2777 }
2778 
2780 static void dump_unused_maps(void) {
2781  FILE *dump;
2782  char path[1024];
2783 
2784  snprintf(path, sizeof(path), "%s/%s", root, "maps.unused");
2785  dump = fopen(path, "w+");
2786  if (dump == NULL) {
2787  printf("Unable to open file maps.unused!\n");
2788  return;
2789  }
2790  for (auto map = found_maps.cbegin(); map != found_maps.cend(); ++map) {
2791  fprintf(dump, "%s\n", *map);
2792  }
2793  fclose(dump);
2794  printf("%ld unused maps.\n", found_maps.size());
2795 }
2796 
2798 static void write_world_info(void) {
2799  FILE *file;
2800  char path[MAX_BUF];
2801  int x, y;
2802  gdImagePtr elevationmap;
2803 
2804  if (!world_exit_info)
2805  return;
2806 
2807  printf("Saving exit/blocking/road information...");
2808  snprintf(path, sizeof(path), "%s/%s%s", root, "world_info", output_extensions[output_format]);
2809  file = fopen(path, "wb+");
2811  fclose(file);
2812  printf("done.\n");
2813  gdImageDestroy(infomap);
2814  infomap = NULL;
2815 
2816  if (elevation_min == 0 || elevation_max == 0) {
2817  puts("Error: Could not save elevation world map due to not finding any minimum or maximum elevation.");
2818  return;
2819  }
2820 
2821  elevationmap = gdImageCreateTrueColor(30*50, 30*50);;
2822 
2823  for (x = 0; x < 30*50; x++) {
2824  for (y = 0; y < 30*50; y++) {
2825  gdImageSetPixel(elevationmap, x, y, get_elevation_color(elevation_info[x][y], elevationmap));
2826  }
2827  }
2828 
2829  printf("Saving elevation world map...");
2830  snprintf(path, sizeof(path), "%s/%s%s", root, "world_elevation", output_extensions[output_format]);
2831  file = fopen(path, "wb+");
2832  save_picture(file, elevationmap);
2833  fclose(file);
2834  printf("done.\n");
2835  gdImageDestroy(elevationmap);
2836  elevationmap = NULL;
2837 }
2838 
2849 static int sort_slaying(const void *left, const void *right) {
2852 
2853  return strcasecmp(l->slaying, r->slaying);
2854 }
2855 
2862 static void do_help(const char *program) {
2863  printf("Crossfire Mapper will generate pictures of maps, and create indexes for all maps and regions.\n\n");
2864  printf("Syntax: %s\n\n", program);
2865  printf("Optional arguments:\n");
2866  printf(" -nopics don't generate pictures.\n");
2867  printf(" -root=<path> destination path. Default 'html'.\n");
2868  printf(" -limit=<number> stop processing after this number of maps, -1 to do all maps (default).\n");
2869  printf(" -showmaps outputs the name of maps as they are processed.\n");
2870  printf(" -jpg[=quality] generate jpg pictures, instead of default png. Quality should be 0-95, -1 for automatic.\n");
2871  printf(" -forcepics force to regenerate pics, even if pics's date is after map's.\n");
2872  printf(" -addmap=<map> adds a map to process. Path is relative to map's directory root.\n");
2873  printf(" -rawmaps generates maps pics without items on random (shop, treasure) tiles.\n");
2874  printf(" -warnnopath inform when an exit has no path set.\n");
2875  printf(" -listunusedmaps finds all unused maps in the maps directory.\n");
2876  printf(" -noworldmap don't write the world map in world.png.\n");
2877  printf(" -noregionslink don't generate regions relation file.\n");
2878  printf(" -regionslink generate regions relation file.\n");
2879  printf(" -noexitmap don't generate map of exits.\n");
2880  printf(" -exitmap generate map of exits.\n");
2881  printf(" -tileset=<number> use specified tileset to generate the pictures. Default 0 (standard).\n");
2882  printf(" -details-quests list all quests steps. Default no.\n");
2883  printf(" -list-system-quests include 'system' quests in quest list. Default no.\n");
2884  printf(" -templates-dir=[dir] set the directory to get templates from. Default 'templates/'.\n");
2885  printf(" -add-template=[file] add a template to process. May be specified multiple times. If empty, 'index.html' is used.\n");
2886  printf(" -list-template-to-process display the name of the template about to be rendered. Useful for debugging.");
2887  printf("\n\n");
2888  exit(0);
2889 }
2890 
2899 static void do_parameters(int argc, char **argv) {
2900  int arg = 1;
2901  char path[500];
2902 
2903  root[0] = '\0';
2904 
2905  while (arg < argc) {
2906  if (strcmp(argv[arg], "-nopics") == 0)
2907  generate_pics = 0;
2908  else if (strncmp(argv[arg], "-root=", 6) == 0)
2909  strncpy(root, argv[arg]+6, 500);
2910  else if (strncmp(argv[arg], "-limit=", 7) == 0)
2911  map_limit = atoi(argv[arg]+7);
2912  else if (strcmp(argv[arg], "-showmaps") == 0)
2913  show_maps = 1;
2914  else if (strcmp(argv[arg], "-jpg") == 0) {
2916  if (argv[arg][4] == '=') {
2917  jpeg_quality = atoi(argv[arg]+5);
2918  if (jpeg_quality < 0)
2919  jpeg_quality = -1;
2920  }
2921  }
2922  else if (strcmp(argv[arg], "-forcepics") == 0)
2923  force_pics = 1;
2924  else if (strncmp(argv[arg], "-addmap=", 8) == 0) {
2925  if (*(argv[arg]+8) == '/')
2926  strncpy(path, argv[arg]+8, 500);
2927  else
2928  snprintf(path, 500, "/%s", argv[arg]+8);
2930  }
2931  else if (strcmp(argv[arg], "-rawmaps") == 0)
2932  rawmaps = 1;
2933  else if (strcmp(argv[arg], "-warnnopath") == 0)
2934  warn_no_path = 1;
2935  else if (strcmp(argv[arg], "-listunusedmaps") == 0)
2936  list_unused_maps = 1;
2937  else if (strcmp(argv[arg], "-noworldmap") == 0)
2938  world_map = 0;
2939  else if (strcmp(argv[arg], "-noregionslink") == 0)
2940  do_regions_link = false;
2941  else if (strcmp(argv[arg], "-regionslink") == 0)
2942  do_regions_link = true;
2943  else if (strcmp(argv[arg], "-noexitmap") == 0)
2944  world_exit_info = 0;
2945  else if (strcmp(argv[arg], "-exitmap") == 0)
2946  world_exit_info = 1;
2947  else if (strncmp(argv[arg], "-tileset=", 9) == 0) {
2948  tileset = atoi(argv[arg]+9);
2949  /* check of validity is done in main() as we need to actually have the sets loaded. */
2950  } else if (strcmp(argv[arg], "-detail-quests") == 0) {
2951  detail_quests = 1;
2952  } else if (strcmp(argv[arg], "-list-system-quests") == 0) {
2953  list_system_quests = 1;
2954  } else if (strncmp(argv[arg], "-templates-dir=", 15) == 0) {
2955  templates_root = argv[arg] + 15;
2956  } else if (strncmp(argv[arg], "-add-template=", 14) == 0) {
2957  templates.push_back(argv[arg] + 14);
2958  } else if (strcmp(argv[arg], "-list-template-to-process") == 0) {
2960  } else
2961  do_help(argv[0]);
2962  arg++;
2963  }
2964  if (!strlen(root))
2965  strcpy(root, "html");
2966  if (root[strlen(root)-1] == '/')
2967  root[strlen(root)-1] = '\0';
2968  if (map_limit < -1)
2969  map_limit = -1;
2970 
2971  if (templates_root.empty()) {
2972  templates_root = "templates/";
2973  } else if (templates_root[templates_root.length() - 1] != '/') {
2974  templates_root.append("/");
2975  }
2976 }
2977 
2981 static void create_destination(void) {
2982  char dummy[502];
2983 
2984  strcpy(dummy, root);
2985  strcat(dummy, "/a");
2986  make_path_to_file(dummy);
2987 }
2988 
2997 static const char *yesno(int value) {
2998  return (value ? "yes" : "no");
2999 }
3000 
3002 static inja::Template get_template(const std::string &filename) {
3003  auto find = templateCache.find(filename);
3004  if (find != templateCache.end()) {
3005  return find->second;
3006  }
3007  inja::Template parsed = env->parse_template(filename);
3008  templateCache[filename] = parsed;
3009  return parsed;
3010 }
3011 
3012 int main(int argc, char **argv) {
3013  size_t current_map = 0, i;
3014  char max[50];
3015  region *dummy;
3016 
3020  pics_allocated = 0;
3021 
3022  do_parameters(argc, argv);
3023 
3024  printf("Initializing Crossfire data...\n");
3025 
3027 
3028  init_globals();
3029  init_library();
3030  init_readable();
3031 
3032  init_gods();
3033 
3034  /* Add a dummy region so unlinked maps can be identified. */
3035  dummy = get_region_struct();
3036  dummy->fallback = 1;
3037  dummy->name = strdup_local("unlinked");
3038  dummy->longname = strdup_local("This dummy region contains all maps without a region set.");
3039  dummy->longname = strdup_local("This dummy region contains all maps without a region set.");
3040  all_regions.push_back(dummy);
3041 
3042  printf("\n\n done.\n\n");
3043 
3044  if (!is_valid_faceset(tileset)) {
3045  printf("Erreor: invalid tileset %d!\n", tileset);
3046  exit(1);
3047  }
3048 
3049  if (templates.empty()) {
3050  templates.push_back("index.html");
3051  }
3052 
3054  gdfaces = (gdImagePtr *)calloc(get_faces_count(), sizeof(gdImagePtr));
3055 
3056  if (map_limit != -1)
3057  snprintf(max, sizeof(max), "%d", map_limit);
3058  else
3059  strcpy(max, "(none)");
3060  printf("Crossfire map browser generator\n");
3061  printf("-------------------------------\n\n");
3062  printf("Parameters:\n");
3063  printf(" path to write files: %s\n", root);
3064  printf(" maximum number of maps to process: %s\n", max);
3065  printf(" will generate map picture: %s\n", yesno(generate_pics));
3066  printf(" will always generate map picture: %s\n", yesno(force_pics));
3067  printf(" picture output format: %s\n", output_extensions[output_format]);
3068  if (output_format == OF_JPG)
3069  printf(" JPEG quality: %d\n", jpeg_quality);
3070  printf(" show map being processed: %s\n", yesno(show_maps));
3071  printf(" generate raw maps: %s\n", yesno(rawmaps));
3072  printf(" warn of exit without path: %s\n", yesno(warn_no_path));
3073  printf(" list unused maps: %s\n", yesno(list_unused_maps));
3074  printf(" generate world map: %s\n", yesno(world_map));
3075  printf(" generate exit map: %s\n", yesno(world_exit_info));
3076  printf(" generate regions link file: %s\n", yesno(do_regions_link));
3077  printf(" tileset: %s\n", find_faceset(tileset)->fullname);
3078  printf(" detail quest steps: %s\n", yesno(detail_quests));
3079  printf(" list system quests: %s\n", yesno(list_system_quests));
3080  printf(" templates directory: %s\n", templates_root.c_str());
3081  printf(" templates to process: ");
3082  const char *sep = "";
3083  for (auto f : templates) {
3084  printf("%s%s", sep, f.c_str());
3085  sep = ", ";
3086  }
3087  printf("\n");
3088  printf(" display template to process: %s\n", yesno(display_rendered_template));
3089  printf("\n");
3090 
3091  if (list_unused_maps) {
3092  printf("listing all maps...");
3093  find_maps("");
3094  printf("done, %ld maps found.\n", found_maps.size());
3095  }
3096 
3097  /* exit/blocking information. */
3098  infomap = gdImageCreateTrueColor(30*50, 30*50);
3099  color_unlinked_exit = gdImageColorResolve(infomap, 255, 0, 0);
3100  color_linked_exit = gdImageColorResolve(infomap, 255, 255, 255);
3101  color_road = gdImageColorResolve(infomap, 0, 255, 0);
3102  color_blocking = gdImageColorResolve(infomap, 0, 0, 255);
3103  color_slowing = gdImageColorResolve(infomap, 0, 0, 127);
3104  elevation_info = (int **)calloc(50*30, sizeof(int *));
3105  for (i = 0; i < 50*30; i++)
3106  elevation_info[i] = (int *)calloc(50*30, sizeof(int));
3107  elevation_min = 0;
3108  elevation_max = 0;
3109 
3110  printf("browsing maps...\n");
3111 
3113 
3114  while (current_map < maps_list.count) {
3116  if (current_map%100 == 0) {
3117  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);
3118  }
3119  if ((map_limit != -1) && (current_map == static_cast<size_t>(map_limit))) {
3120  printf(" --- map limit reached, stopping ---\n");
3121  break;
3122  }
3123  }
3124 
3125  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);
3126 
3127  if (list_unused_maps)
3128  dump_unused_maps();
3129 
3131  fix_map_names();
3132  fix_tiled_map();
3134  write_tiled_maps();
3135 
3136  write_world_map();
3137  write_world_info();
3138 
3140  qsort(regions, region_count, sizeof(struct_region_info *), sort_region);
3141  std::sort(special_equipment.begin(), special_equipment.end(), sort_equipment);
3143  qsort(races.races, races.count, sizeof(struct_race *), sort_race);
3144  qsort(quests, quests_count, sizeof(struct_quest *), sort_struct_quest);
3145 
3147  std::sort(system_quests.begin(), system_quests.end(), [] (const auto &left, const auto &right) { return strcmp(left->quest_code, right->quest_code) < 0; });
3148 
3150 
3152 
3153  for (auto file : templates) {
3154  if (!file.empty()) {
3156  }
3157  }
3158 
3159  const auto fullStart = time(nullptr);
3160  printf("rendering pages...");
3162  printf("\n");
3163  fflush(stdout);
3164 
3165  while (!pages.empty()) {
3166  auto p = pages.back();
3167  pages.pop_back();
3168  if (p.param.empty())
3169  all_data.erase("param");
3170  else
3171  all_data["param"] = p.param;
3172  const auto start = time(nullptr);
3174  printf(" rendering page %s (%s)... ", p.template_name.c_str(), p.param.c_str());
3175  fflush(stdout);
3176  }
3177  path_stack.push_back(p.output_name);
3178  inja::Template temp = get_template(p.template_name);
3179  env->write(temp, all_data, p.output_name);
3180  path_stack.pop_back();
3181  const auto elapsed = time(nullptr) - start;
3183  printf("took %ld seconds\n", elapsed);
3184  }
3185  }
3186 
3187  const auto elapsed = time(nullptr) - fullStart;
3188  printf(" done, took %ld seconds\n", elapsed);
3189 
3190  return 0;
3191 }
3192 
3194  int x, y;
3195 
3196  if (m == NULL)
3197  return;
3198 
3199  for (x = 0; x < MAP_WIDTH(m); x++)
3200  for (y = 0; y < MAP_HEIGHT(m); y++)
3201  FOR_MAP_PREPARE(m, x, y, tmp) {
3202  if (tmp->inv) {
3203  FOR_INV_PREPARE(tmp, invtmp) {
3204  if (QUERY_FLAG(invtmp, FLAG_AUTO_APPLY))
3205  apply_auto(invtmp);
3206  else if (invtmp->type == TREASURE && HAS_RANDOM_ITEMS(invtmp)) {
3207  while ((invtmp->stats.hp--) > 0)
3208  create_treasure(invtmp->randomitems, invtmp, 0, m->difficulty, 0);
3209  invtmp->randomitems = NULL;
3210  } else if (invtmp
3211  && invtmp->arch
3212  && invtmp->type != TREASURE
3213  && invtmp->type != SPELL
3214  && invtmp->type != CLASS
3215  && HAS_RANDOM_ITEMS(invtmp)) {
3216  create_treasure(invtmp->randomitems, invtmp, 0, m->difficulty, 0);
3217  /* Need to clear this so that we never try to create
3218  * treasure again for this object
3219  */
3220  invtmp->randomitems = NULL;
3221  }
3222  } FOR_INV_FINISH();
3223  /* This is really temporary - the code at the bottom will
3224  * also set randomitems to null. The problem is there are bunches
3225  * of maps/players already out there with items that have spells
3226  * which haven't had the randomitems set to null yet.
3227  * MSW 2004-05-13
3228  *
3229  * And if it's a spellbook, it's better to set randomitems to NULL too,
3230  * else you get two spells in the book ^_-
3231  * Ryo 2004-08-16
3232  */
3233  if (tmp->type == WAND
3234  || tmp->type == ROD
3235  || tmp->type == SCROLL
3236  || tmp->type == FIREWALL
3237  || tmp->type == POTION
3238  || tmp->type == ALTAR
3239  || tmp->type == SPELLBOOK)
3240  tmp->randomitems = NULL;
3241  }
3242 
3244  apply_auto(tmp);
3245  else if ((tmp->type == TREASURE || (tmp->type == CONTAINER)) && HAS_RANDOM_ITEMS(tmp)) {
3246  while ((tmp->stats.hp--) > 0)
3247  create_treasure(tmp->randomitems, tmp, 0, m->difficulty, 0);
3248  tmp->randomitems = NULL;
3249  } else if (tmp->type == TIMED_GATE) {
3250  object *head = HEAD(tmp);
3251 
3252  if (QUERY_FLAG(head, FLAG_IS_LINKED)) {
3253  tmp->speed = 0;
3255  }
3256  /* This function can be called everytime a map is loaded, even when
3257  * swapping back in. As such, we don't want to create the treasure
3258  * over and ove again, so after we generate the treasure, blank out
3259  * randomitems so if it is swapped in again, it won't make anything.
3260  * This is a problem for the above objects, because they have counters
3261  * which say how many times to make the treasure.
3262  */
3263  } else if (tmp
3264  && tmp->arch
3265  && tmp->type != PLAYER
3266  && tmp->type != TREASURE
3267  && tmp->type != SPELL
3268  && tmp->type != PLAYER_CHANGER
3269  && tmp->type != CLASS
3270  && HAS_RANDOM_ITEMS(tmp)) {
3271  create_treasure(tmp->randomitems, tmp, 0, m->difficulty, 0);
3272  tmp->randomitems = NULL;
3273  }
3274  } FOR_MAP_FINISH();
3275 
3276  for (x = 0; x < MAP_WIDTH(m); x++)
3277  for (y = 0; y < MAP_HEIGHT(m); y++)
3278  FOR_MAP_PREPARE(m, x, y, tmp) {
3279  if (tmp->above
3280  && (tmp->type == TRIGGER_BUTTON || tmp->type == TRIGGER_PEDESTAL))
3281  check_trigger(tmp, tmp->above);
3282  } FOR_MAP_FINISH();
3283 }
3284 
3285 #ifndef DOXYGEN_SHOULD_SKIP_THIS
3286 
3291 void draw_ext_info(int, int, const object *, uint8_t, uint8_t, const char *txt) {
3292  fprintf(logfile, "%s\n", txt);
3293 }
3294 
3295 void draw_ext_info_format(int, int, const object *, uint8_t, uint8_t, const char *format, ...) {
3296  va_list ap;
3297 
3298  va_start(ap, format);
3299  vfprintf(logfile, format, ap);
3300  va_end(ap);
3301 }
3302 
3303 void ext_info_map(int, const mapstruct *, uint8_t, uint8_t, const char *str1) {
3304  fprintf(logfile, "ext_info_map: %s\n", str1);
3305 }
3306 
3307 void move_firewall(object *) {
3308 }
3309 
3310 void emergency_save(int) {
3311 }
3312 
3313 void clean_tmp_files(void) {
3314 }
3315 
3316 void esrv_send_item(object *, object *) {
3317 }
3318 
3319 void dragon_ability_gain(object *, int, int) {
3320 }
3321 
3323 }
3324 
3325 object *find_skill_by_number(object *, int) {
3326  return NULL;
3327 }
3328 
3329 void esrv_del_item(player *, object *) {
3330 }
3331 
3332 void esrv_update_item(int, object *, object *) {
3333 }
3334 
3336 }
3337 
3338 void rod_adjust(object *) {
3339 }
3340 
3341 /*
3342  * This a modified version of apply_auto: BOOK are not generated, so they don't pollute
3343  * the readable list.
3344  */
3345 int apply_auto(object *op) {
3346  object *tmp = NULL;
3347  int i;
3348 
3349  switch (op->type) {
3350  case SHOP_FLOOR:
3351  if (!HAS_RANDOM_ITEMS(op))
3352  return 0;
3353  do {
3354  i = 10; /* let's give it 10 tries */
3355  while ((tmp = generate_treasure(op->randomitems, op->stats.exp ? (int)op->stats.exp : MAX(op->map->difficulty, 5))) == NULL && --i)
3356  ;
3357  if (tmp == NULL)
3358  return 0;
3359  if (QUERY_FLAG(tmp, FLAG_CURSED) || QUERY_FLAG(tmp, FLAG_DAMNED) || tmp->type == BOOK) {
3361  tmp = NULL;
3362  }
3363  } while (!tmp);
3365  object_insert_in_map_at(tmp, op->map, NULL, 0, op->x, op->y);
3367  tmp = identify(tmp);
3368  break;
3369 
3370  case TREASURE:
3372  return 0;
3373 
3374  while ((op->stats.hp--) > 0)
3375  create_treasure(op->randomitems, op, 0, op->stats.exp ? (int)op->stats.exp : op->map == NULL ? 14 : op->map->difficulty, 0);
3376 
3377  /* If we generated an object and put it in this object inventory,
3378  * move it to the parent object as the current object is about
3379  * to disappear. An example of this item is the random_ *stuff
3380  * that is put inside other objects.
3381  */
3382  FOR_INV_PREPARE(op, tmp) {
3383  object_remove(tmp);
3384  if (op->env && tmp->type != BOOK)
3385  object_insert_in_ob(tmp, op->env);
3386  else
3388  }
3389  FOR_INV_FINISH();
3390  object_remove(op);
3392  break;
3393  }
3394  return tmp ? 1 : 0;
3395 }
3396 
3398 }
3399 
3401  return NULL;
3402 }
3403 
3405  return NULL;
3406 }
3407 
3409  return NULL;
3410 }
3411 
3413 }
3414 
3416 }
3417 
3418 void command_help(object *, const char *) {
3419 }
3420 
3421 void account_logout(const char *) {
3422 }
3423 
3424 #endif /* dummy DOXYGEN_SHOULD_SKIP_THIS */
get_race
static struct_race * get_race(const char *name)
Definition: mapper.cpp:597
struct_map_info::tiles
struct struct_map_info * tiles[4]
Definition: mapper.cpp:232
CLASS
@ CLASS
Definition: object.h:143
object::name_pl
sstring name_pl
Definition: object.h:323
struct_region_info::sum_x
int sum_x
Definition: mapper.cpp:357
give.next
def next
Definition: give.py:44
move_firewall
void move_firewall(object *)
Definition: mapper.cpp:3307
init_globals
void init_globals(void)
Definition: init.cpp:395
write_tiled_map_page
static void write_tiled_map_page(struct_map_info *map)
Definition: mapper.cpp:2143
fix_tiled_map_monsters
static void fix_tiled_map_monsters(void)
Definition: mapper.cpp:1978
do_auto_apply
void do_auto_apply(mapstruct *m)
Definition: mapper.cpp:3193
add_map
static void add_map(struct_map_info *info, struct_map_list *list)
Definition: mapper.cpp:1169
HAS_RANDOM_ITEMS
#define HAS_RANDOM_ITEMS(op)
Definition: define.h:184
PLAYER
@ PLAYER
Definition: object.h:112
global.h
FREE_OBJ_NO_DESTROY_CALLBACK
#define FREE_OBJ_NO_DESTROY_CALLBACK
Definition: object.h:536
settings
struct Settings settings
Definition: init.cpp:139
pageToRender::param
std::string param
Definition: mapper.cpp:2583
ignore_name
static const char * ignore_name[]
Definition: mapper.cpp:2726
struct_equipment::diff
char * diff
Definition: mapper.cpp:246
banquet.l
l
Definition: banquet.py:164
get_quest_info
static struct_quest * get_quest_info(const char *name)
Definition: mapper.cpp:936
find_region_by_key
static region * find_region_by_key(const std::string &key)
Definition: mapper.cpp:2193
FOR_MAP_FINISH
#define FOR_MAP_FINISH()
Definition: define.h:730
process_map_lore
static void process_map_lore(struct_map_info *map)
Definition: mapper.cpp:1050
find_artifact
const artifact * find_artifact(const object *op, const char *name)
Definition: artifact.cpp:589
llevError
@ llevError
Definition: logger.h:11
get_region_struct
region * get_region_struct(void)
Definition: region.cpp:294
region::fallback
int8_t fallback
Definition: map.h:284
compare_map_info
static int compare_map_info(const struct_map_info *left, const struct_map_info *right)
Definition: mapper.cpp:824
path_from_current
static std::string path_from_current(const std::string &path)
Definition: mapper.cpp:2512
MOVE_ALL
#define MOVE_ALL
Definition: define.h:398
WAND
@ WAND
Definition: object.h:225
quest_for_each
void quest_for_each(quest_op op, void *user)
Definition: assets.cpp:539
LOG
void LOG(LogLevel logLevel, const char *format,...)
Definition: logger.cpp:51
struct_region_info::is_world
int is_world
Definition: mapper.cpp:358
SET_FLAG
#define SET_FLAG(xyz, p)
Definition: define.h:224
generate_picture_link
static nlohmann::json generate_picture_link(inja::Arguments &args)
Definition: mapper.cpp:2559
struct_map_info::tiled_group
struct struct_map_info * tiled_group
Definition: mapper.cpp:229
struct_map_info::filename
char * filename
Definition: mapper.cpp:213
num_sizes
static const int num_sizes
Definition: mapper.cpp:313
player
Definition: player.h:105
add_slaying
static void add_slaying(struct_map_info *map, object *item)
Definition: mapper.cpp:1433
strdup_local
#define strdup_local
Definition: compat.h:29
diamondslots.x
x
Definition: diamondslots.py:15
n
based on the size of the this randomly makes land number of spaces randomly lower or higher The default is Note that this is run also based on the the altitude amount will likely be less So if you do something like l and n
Definition: land.6.txt:25
ready_map_name
mapstruct * ready_map_name(const char *name, int flags)
Definition: map.cpp:1759
write_tiled_maps
static void write_tiled_maps(void)
Definition: mapper.cpp:2153
first_map_path
char first_map_path[MAX_BUF]
Definition: init.cpp:120
QUERY_FLAG
#define QUERY_FLAG(xyz, p)
Definition: define.h:226
struct_quest::maps
struct_map_in_quest_list maps
Definition: mapper.cpp:891
archininventory.arch
arch
DIALOGCHECK MINARGS 1 MAXARGS 1
Definition: archininventory.py:16
create_quest_object
static nlohmann::json create_quest_object(struct_quest *quest, const std::string &key)
Definition: mapper.cpp:2304
create_map_info
static struct_map_info * create_map_info(void)
Definition: mapper.cpp:1190
struct_race::count
int count
Definition: mapper.cpp:256
TRIGGER_PEDESTAL
@ TRIGGER_PEDESTAL
Definition: object.h:139
nlohmann::json
basic_json<> json
default JSON class
Definition: json.hpp:3404
struct_map_in_quest::map
struct_map_info * map
Definition: mapper.cpp:882
pageToRender::output_name
std::string output_name
Definition: mapper.cpp:2582
esrv_del_item
void esrv_del_item(player *, object *)
Definition: mapper.cpp:3329
S_CONNECT
#define S_CONNECT
Definition: mapper.cpp:390
write_pictures_from_real_size
static void write_pictures_from_real_size(const char *path, gdImagePtr real, int width, int height)
Definition: mapper.cpp:1473
region_links
static std::map< region *, std::set< region * > > region_links
Definition: mapper.cpp:383
get_face_fallback
int get_face_fallback(int faceset, uint16_t imageno)
Definition: image.cpp:133
c
static event_registration c
Definition: citylife.cpp:425
filter
Definition: filter.py:1
output_format
static enum output_format_type output_format
Definition: mapper.cpp:342
stringbuffer_new
StringBuffer * stringbuffer_new(void)
Definition: stringbuffer.cpp:57
quests_count
static int quests_count
Definition: mapper.cpp:896
SHOP_FLOOR
@ SHOP_FLOOR
Definition: object.h:188
create_npc_array
static nlohmann::json create_npc_array(npc_list &list)
Definition: mapper.cpp:2221
get_map_info
static struct_map_info * get_map_info(const char *path)
Definition: mapper.cpp:1262
EXIT_PATH
#define EXIT_PATH(xyz)
Definition: define.h:439
fix_exits_to_tiled_maps
static void fix_exits_to_tiled_maps(void)
Definition: mapper.cpp:1950
object::x
int16_t x
Definition: object.h:335
reverse_maps
static std::map< struct_map_info *, std::string > reverse_maps
Definition: mapper.cpp:2173
Settings::debug
LogLevel debug
Definition: global.h:243
guildoracle.list
list
Definition: guildoracle.py:87
Account_Chars
Definition: account_char.h:27
struct_map_in_quest
Definition: mapper.cpp:879
slaying_allocated
static size_t slaying_allocated
Definition: mapper.cpp:401
give_artifact_abilities
void give_artifact_abilities(object *op, const object *artifact)
Definition: artifact.cpp:230
get_equipment
static struct_equipment * get_equipment(void)
Definition: mapper.cpp:435
is_special_equipment
static int is_special_equipment(object *item)
Definition: mapper.cpp:416
TIMED_GATE
@ TIMED_GATE
Definition: object.h:133
region_allocated
static size_t region_allocated
Definition: mapper.cpp:363
struct_map_list
Definition: mapper.cpp:203
generate_page_and_link
static nlohmann::json generate_page_and_link(inja::Arguments &args)
Definition: mapper.cpp:2529
struct_equipment::origin
struct_map_list origin
Definition: mapper.cpp:247
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:328
artifact::item
object * item
Definition: artifact.h:15
commongive.inv
inv
Definition: commongive.py:29
root
static char root[500]
Definition: mapper.cpp:304
create_map_in_quest_array
static nlohmann::json create_map_in_quest_array(struct_map_in_quest_list &list)
Definition: mapper.cpp:2257
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)
Definition: mapper.cpp:2997
AMULET
@ AMULET
Definition: object.h:144
CHECK_INV
@ CHECK_INV
Definition: object.h:174
struct_map_info::name
char * name
Definition: mapper.cpp:212
fix_map_names
static void fix_map_names(void)
Definition: mapper.cpp:1844
mad_mage_user.file
file
Definition: mad_mage_user.py:15
struct_slaying_info::maps
struct_map_list maps[S_MAX]
Definition: mapper.cpp:396
MIN
#define MIN(x, y)
Definition: compat.h:21
SIZE
#define SIZE
maps_list
static struct_map_list maps_list
Definition: mapper.cpp:236
TREASURE
@ TREASURE
Definition: object.h:115
color_unlinked_exit
static int color_unlinked_exit
Definition: mapper.cpp:370
struct_region_info::sum_y
int sum_y
Definition: mapper.cpp:357
pages
static std::vector< pageToRender > pages
Definition: mapper.cpp:2585
Ice.tmp
int tmp
Definition: Ice.py:207
list_unused_maps
static int list_unused_maps
Definition: mapper.cpp:365
struct_map_info
Definition: mapper.cpp:210
draw_ext_info_format
void draw_ext_info_format(int, int, const object *, uint8_t, uint8_t, const char *format,...)
Definition: mapper.cpp:3295
esrv_send_item
void esrv_send_item(object *, object *)
Definition: mapper.cpp:3316
struct_map_info::min_monster
int min_monster
Definition: mapper.cpp:216
nlohmann::basic_json::push_back
void push_back(basic_json &&val)
add an object to an array
Definition: json.hpp:22807
dump
static int dump(const std::set< std::string > &items, const char *name)
Definition: AssetsManager.cpp:42
create_region_array
static nlohmann::json create_region_array(const std::set< region * > &regions)
Definition: mapper.cpp:2348
struct_region_info
Definition: mapper.cpp:354
clean_tmp_files
void clean_tmp_files(void)
Definition: mapper.cpp:3313
add_npc_to_map
static void add_npc_to_map(npc_list *list, const object *npc)
Definition: mapper.cpp:1153
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
Definition: map.h:274
nlohmann::basic_json::diff
static JSON_HEDLEY_WARN_UNUSED_RESULT basic_json diff(const basic_json &source, const basic_json &target, const std::string &path="")
creates a diff as a JSON patch
Definition: json.hpp:26097
SIGN
@ SIGN
Definition: object.h:216
struct_equipment::name
char * name
Definition: mapper.cpp:243
TRIGGER_BUTTON
@ TRIGGER_BUTTON
Definition: object.h:137
source
Almost all the spell_ *base png files are taken from JXClient s source
Definition: readme-icons.txt:1
npc_dialog.filename
filename
Definition: npc_dialog.py:99
smoking_pipe.color
color
Definition: smoking_pipe.py:5
object_get_value
const char * object_get_value(const object *op, const char *const key)
Definition: object.cpp:4337
create_treasure
void create_treasure(treasurelist *t, object *op, int flag, int difficulty, int tries)
Definition: treasure.cpp:263
struct_map_info::max_monster
int max_monster
Definition: mapper.cpp:216
struct_slaying_info
Definition: mapper.cpp:394
buf
StringBuffer * buf
Definition: readable.cpp:1552
struct_equipment::calc_power
int calc_power
Definition: mapper.cpp:245
object_insert_in_ob
object * object_insert_in_ob(object *op, object *where)
Definition: object.cpp:2848
MAX
#define MAX(x, y)
Definition: compat.h:24
apply_auto_fix
void apply_auto_fix(mapstruct *)
Definition: mapper.cpp:3397
account_char_save
void account_char_save(Account_Chars *)
Definition: mapper.cpp:3412
FLAG_NO_PICK
#define FLAG_NO_PICK
Definition: define.h:239
name
Plugin animator file specs[Config] name
Definition: animfiles.txt:4
force_pics
static int force_pics
Definition: mapper.cpp:311
pageToRender::template_name
std::string template_name
Definition: mapper.cpp:2581
world_exit_info
static int world_exit_info
Definition: mapper.cpp:319
sort_struct_quest
static int sort_struct_quest(const void *left, const void *right)
Definition: mapper.cpp:1015
struct_quest
Definition: mapper.cpp:886
struct_map_in_quest_list
Definition: mapper.cpp:196
region::longname
char * longname
Definition: map.h:280
struct_region_info::reg
region * reg
Definition: mapper.cpp:355
SockList
Definition: newclient.h:670
pageToRender
Definition: mapper.cpp:2579
struct_map_in_quest::quest
struct struct_quest * quest
Definition: mapper.cpp:884
FLAG_IS_A_TEMPLATE
#define FLAG_IS_A_TEMPLATE
Definition: define.h:366
init_renderer_env
static void init_renderer_env()
Definition: mapper.cpp:2625
struct_quest::description
char * description
Definition: mapper.cpp:888
init_gods
void init_gods(void)
Definition: holy.cpp:59
object::y
int16_t y
Definition: object.h:335
m
static event_registration m
Definition: citylife.cpp:425
quest
Definition: quest.py:1
MAP_IN_MEMORY
#define MAP_IN_MEMORY
Definition: map.h:127
stringbuffer_finish
char * stringbuffer_finish(StringBuffer *sb)
Definition: stringbuffer.cpp:76
S_CONTAINER
#define S_CONTAINER
Definition: mapper.cpp:388
object_free_drop_inventory
void object_free_drop_inventory(object *ob)
Definition: object.cpp:1555
item.q
q
Definition: item.py:32
opendir
DIR * opendir(const char *)
struct_map_info::reset_group
sstring reset_group
Definition: mapper.cpp:220
templateCache
static inja::TemplateStorage templateCache
Definition: mapper.cpp:3001
disinfect.map
map
Definition: disinfect.py:4
regions
static struct struct_region_info ** regions
Definition: mapper.cpp:361
struct_npc_info::y
int y
Definition: mapper.cpp:182
struct_map_info::exits_from
struct_map_list exits_from
Definition: mapper.cpp:217
detail_quests
static bool detail_quests
Definition: mapper.cpp:321
ensure_unique
static struct_equipment * ensure_unique(struct_equipment *item)
Definition: mapper.cpp:482
struct_npc_info::message
const char * message
Definition: mapper.cpp:181
get_slaying_struct
static struct_slaying_info * get_slaying_struct(const char *slaying)
Definition: mapper.cpp:1390
generate_picture_path
static void generate_picture_path(const char *path, size_t pic_size, char *out, size_t len)
Definition: mapper.cpp:1469
make_face_from_files.args
args
Definition: make_face_from_files.py:37
OF_JPG
@ OF_JPG
Definition: mapper.cpp:332
rotate-tower.result
bool result
Definition: rotate-tower.py:13
elevation_max
static int elevation_max
Definition: mapper.cpp:378
struct_map_info::pic_was_done
int pic_was_done
Definition: mapper.cpp:216
set_darkness_map
void set_darkness_map(mapstruct *)
Definition: mapper.cpp:3322
POTION
@ POTION
Definition: object.h:116
struct_npc_info
Definition: mapper.cpp:179
define_quest
static void define_quest(const char *name, struct_map_info *mainmap, const char *description)
Definition: mapper.cpp:1031
path_combine_and_normalize
char * path_combine_and_normalize(const char *src, const char *dst, char *path, size_t size)
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:906
do_tiled_map_picture
static void do_tiled_map_picture(struct_map_info *map)
Definition: mapper.cpp:2035
slaying_info
static struct_slaying_info ** slaying_info
Definition: mapper.cpp:399
add_string
sstring add_string(const char *str)
Definition: shstr.cpp:124
races
static struct_race_list races
Definition: mapper.cpp:260
npc_list
std::vector< struct_npc_info * > npc_list
Definition: mapper.cpp:186
object_get_multi_size
void object_get_multi_size(const object *ob, int *sx, int *sy, int *hx, int *hy)
Definition: object.cpp:4735
main
int main(int argc, char **argv)
Definition: mapper.cpp:3012
HEAD
#define HEAD(op)
Definition: object.h:598
output_extensions
static const char * output_extensions[]
Definition: mapper.cpp:336
create_maps_array
static nlohmann::json create_maps_array(struct_map_list &maps)
Definition: mapper.cpp:2205
ROD
@ ROD
Definition: object.h:114
show_maps
static int show_maps
Definition: mapper.cpp:317
CONTAINER
@ CONTAINER
Definition: object.h:236
system_quests
static std::vector< quest_definition * > system_quests
Definition: mapper.cpp:2162
get_elevation_color
static int get_elevation_color(int elevation, gdImagePtr elevationmap)
Definition: mapper.cpp:711
reset_groups
static std::set< std::string > reset_groups
Definition: mapper.cpp:262
region::msg
char * msg
Definition: map.h:282
init_readable
void init_readable(void)
Definition: readable.cpp:895
make_face_from_files.str
str
Definition: make_face_from_files.py:30
S_MAX
#define S_MAX
Definition: mapper.cpp:391
quest_callback
static void quest_callback(const quest_definition *quest, void *)
Definition: mapper.cpp:2164
readdir
struct dirent * readdir(DIR *)
LOCKED_DOOR
@ LOCKED_DOOR
Definition: object.h:128
struct_race::name
char * name
Definition: mapper.cpp:255
dump
Definition: quest.cpp:847
is_slaying
static int is_slaying(object *item)
Definition: mapper.cpp:1377
struct_equipment::power
int power
Definition: mapper.cpp:244
create_race_array
static nlohmann::json create_race_array(struct_race_list &list)
Definition: mapper.cpp:2240
account_char_load
Account_Chars * account_char_load(const char *)
Definition: mapper.cpp:3408
dragon_ability_gain
void dragon_ability_gain(object *, int, int)
Definition: mapper.cpp:3319
description
spell prayer lvl t sp speed range duration short description
Definition: spell-summary.txt:2
nlohmann::basic_json::array
array_t * array
array (stored with pointer to save storage)
Definition: json.hpp:18360
SPECIAL_KEY
@ SPECIAL_KEY
Definition: object.h:129
inja::json
nlohmann::json json
Definition: inja.hpp:1565
object_update_speed
void object_update_speed(object *op)
Definition: object.cpp:1344
Ice.b
b
Definition: Ice.py:48
struct_race::origin
struct_map_list origin
Definition: mapper.cpp:257
color_slowing
static int color_slowing
Definition: mapper.cpp:374
object::type
uint8_t type
Definition: object.h:348
struct_map_info::quests
struct_map_in_quest_list quests
Definition: mapper.cpp:219
write_world_map
static void write_world_map(void)
Definition: mapper.cpp:1741
FLAG_DAMNED
#define FLAG_DAMNED
Definition: define.h:317
struct_map_info::width
int width
Definition: mapper.cpp:230
add_map_to_quest
static void add_map_to_quest(struct_map_info *map, const char *name, const char *description)
Definition: mapper.cpp:965
create_npc_info
static struct_npc_info * create_npc_info(const object *npc)
Definition: mapper.cpp:1135
face_info::data
uint8_t * data
Definition: image.h:11
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
color_road
static int color_road
Definition: mapper.cpp:372
tileset
static int tileset
Definition: mapper.cpp:320
esrv_update_item
void esrv_update_item(int, object *, object *)
Definition: mapper.cpp:3332
object_free
void object_free(object *ob, int flags)
Definition: object.cpp:1587
FOR_INV_FINISH
#define FOR_INV_FINISH()
Definition: define.h:677
is_blocking
static int is_blocking(object *item)
Definition: mapper.cpp:697
do_exit_map
static void do_exit_map(mapstruct *map)
Definition: mapper.cpp:726
create_destination
static void create_destination(void)
Definition: mapper.cpp:2981
struct_map_info::tiled_y_from
int tiled_y_from
Definition: mapper.cpp:231
struct_race_list::races
struct struct_race ** races
Definition: mapper.cpp:190
disinfect.count
int count
Definition: disinfect.py:7
FLAG_UNAGGRESSIVE
#define FLAG_UNAGGRESSIVE
Definition: define.h:272
check_slaying_inventory
static void check_slaying_inventory(struct_map_info *map, object *item)
Definition: mapper.cpp:1461
say.max
dictionary max
Definition: say.py:148
archetype
Definition: object.h:474
jpeg_quality
static int jpeg_quality
Definition: mapper.cpp:345
sproto.h
append_map_list
static void append_map_list(struct_map_list &dest, struct_map_list &src)
Definition: mapper.cpp:2338
struct_map_info::npcs
npc_list * npcs
Definition: mapper.cpp:226
IS_SHIELD
#define IS_SHIELD(op)
Definition: define.h:170
logfile
FILE * logfile
Definition: init.cpp:114
BOOK
@ BOOK
Definition: object.h:119
rawmaps
static int rawmaps
Definition: mapper.cpp:348
init_struct_map_in_quest_list
static void init_struct_map_in_quest_list(struct_map_in_quest_list *list)
Definition: mapper.cpp:900
struct_race_list
Definition: mapper.cpp:189
struct_race
Definition: mapper.cpp:254
emergency_save
void emergency_save(int)
Definition: mapper.cpp:3310
delete_map
void delete_map(mapstruct *m)
Definition: map.cpp:1696
struct_race_list::allocated
size_t allocated
Definition: mapper.cpp:192
struct_map_list::maps
struct struct_map_info ** maps
Definition: mapper.cpp:204
RING
@ RING
Definition: object.h:190
struct_race_list::count
size_t count
Definition: mapper.cpp:191
fill_json
static void fill_json(nlohmann::json &json)
Definition: mapper.cpp:2363
add_map_to_region
static void add_map_to_region(struct_map_info *map, region *reg)
Definition: mapper.cpp:1310
image.h
struct_map_info::level
int level
Definition: mapper.cpp:216
object_insert_in_map_at
object * object_insert_in_map_at(object *op, mapstruct *m, object *originator, int flag, int x, int y)
Definition: object.cpp:2095
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
FLAG_MONSTER
#define FLAG_MONSTER
Definition: define.h:245
list_system_quests
static bool list_system_quests
Definition: mapper.cpp:322
generate_pics
static int generate_pics
Definition: mapper.cpp:310
MAP_WIDTH
#define MAP_WIDTH(m)
Definition: map.h:74
create_map_object
static nlohmann::json create_map_object(struct_map_info *map, const std::string &key)
Definition: mapper.cpp:2280
struct_quest::mainmap
struct_map_info * mainmap
Definition: mapper.cpp:890
env
static std::shared_ptr< inja::Environment > env
Definition: mapper.cpp:2170
MAX_BUF
#define MAX_BUF
Definition: define.h:35
S_KEY
#define S_KEY
Definition: mapper.cpp:387
sort_map_info
static int sort_map_info(const void *left, const void *right)
Definition: mapper.cpp:854
fill_reverse_maps
static void fill_reverse_maps(struct_map_list &list)
Definition: mapper.cpp:2319
is_valid_faceset
int is_valid_faceset(int fsn)
Definition: image.cpp:117
struct_map_info::tiled_x_from
int tiled_x_from
Definition: mapper.cpp:231
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
Definition: object.h:439
sort_slaying
static int sort_slaying(const void *left, const void *right)
Definition: mapper.cpp:2849
tiled_map_list
static struct_map_list tiled_map_list
Definition: mapper.cpp:239
add_race_to_list
static void add_race_to_list(struct_race *race, struct_race_list *list, int check)
Definition: mapper.cpp:285
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)
Definition: mapper.cpp:580
FOR_MAP_PREPARE
#define FOR_MAP_PREPARE(map_, mx_, my_, it_)
Definition: define.h:723
EXIT
@ EXIT
Definition: object.h:186
path_stack
static std::vector< std::string > path_stack
Definition: mapper.cpp:2503
merge_tiled_maps
static void merge_tiled_maps(struct_map_info *map, struct_map_info *tiled_map)
Definition: mapper.cpp:1228
cached_pics
static int cached_pics
Definition: mapper.cpp:327
struct_map_list::allocated
size_t allocated
Definition: mapper.cpp:206
list_map
static void list_map(const char *path)
Definition: mapper.cpp:1289
struct_map_info::exits_to
struct_map_list exits_to
Definition: mapper.cpp:218
region
Definition: map.h:273
struct_map_info::lore
char * lore
Definition: mapper.cpp:214
rendered_templates
static std::set< std::string > rendered_templates
Definition: mapper.cpp:2172
apply_auto
int apply_auto(object *op)
Definition: mapper.cpp:3345
check_trigger
int check_trigger(object *op, object *cause)
Definition: button.cpp:518
make_face_from_files.out
out
Definition: make_face_from_files.py:81
quest.h
S_DETECTOR
#define S_DETECTOR
Definition: mapper.cpp:389
struct_map_info::path
char * path
Definition: mapper.cpp:211
struct_map_in_quest_list::count
size_t count
Definition: mapper.cpp:198
object::slaying
sstring slaying
Definition: object.h:327
init_map_list
static void init_map_list(struct_map_list *list)
Definition: mapper.cpp:408
all_regions
std::vector< region * > all_regions
Definition: init.cpp:108
add_region_link
static void add_region_link(mapstruct *source, mapstruct *dest)
Definition: mapper.cpp:1358
FLAG_FRIENDLY
#define FLAG_FRIENDLY
Definition: define.h:246
init_library
void init_library(void)
Definition: init.cpp:323
object::name
sstring name
Definition: object.h:319
free_equipment
static void free_equipment(struct_equipment *equip)
Definition: mapper.cpp:448
esrv_update_spells
void esrv_update_spells(player *)
Definition: mapper.cpp:3335
created_pics
static int created_pics
Definition: mapper.cpp:326
bigchest.check
check
Definition: bigchest.py:10
size_large
#define size_large
Definition: mapper.cpp:314
add_map_to_slaying
static void add_map_to_slaying(struct_slaying_info *info, int item, struct_map_info *map)
Definition: mapper.cpp:1421
struct_region_info::sum
int sum
Definition: mapper.cpp:357
inja::TemplateStorage
std::map< std::string, Template > TemplateStorage
Definition: inja.hpp:2852
struct_map_info::readable
npc_list * readable
Definition: mapper.cpp:227
IS_ARMOR
#define IS_ARMOR(op)
Definition: define.h:166
OF_PNG
@ OF_PNG
Definition: mapper.cpp:331
account_char_free
void account_char_free(Account_Chars *)
Definition: mapper.cpp:3415
struct_region_info::maps_list
struct_map_list maps_list
Definition: mapper.cpp:356
item
Definition: item.py:1
struct_map_info::processed
int processed
Definition: mapper.cpp:231
FIREWALL
@ FIREWALL
Definition: object.h:173
PLAYER_CHANGER
@ PLAYER_CHANGER
Definition: object.h:167
mapstruct
Definition: map.h:314
inja::Arguments
std::vector< const json * > Arguments
Definition: inja.hpp:1567
create_pathname
char * create_pathname(const char *name, char *buf, size_t size)
Definition: map.cpp:103
sstring
const typedef char * sstring
Definition: sstring.h:2
nlohmann::basic_json
a class to store JSON values
Definition: json.hpp:3380
give.op
op
Definition: give.py:33
autojail.value
value
Definition: autojail.py:6
save_picture
static void save_picture(FILE *file, gdImagePtr pic)
Definition: mapper.cpp:1344
create-tower.current_map
current_map
Definition: create-tower.py:7
display_rendered_template
static bool display_rendered_template
Definition: mapper.cpp:323
templates_root
static std::string templates_root("templates/")
FLAG_AUTO_APPLY
#define FLAG_AUTO_APPLY
Definition: define.h:250
quest_definition
Definition: quest.h:37
struct_map_info::monsters
struct_race_list monsters
Definition: mapper.cpp:224
find_archetype
archetype * find_archetype(const char *name)
Definition: assets.cpp:266
elevation_info
static int ** elevation_info
Definition: mapper.cpp:376
color_blocking
static int color_blocking
Definition: mapper.cpp:373
struct_map_in_quest::description
char * description
Definition: mapper.cpp:883
format
Python Guilds Quick outline Add a guild(mapmakers) this is still a problem *after dropping the token to gain access to the stove a woodfloor now appears which is Toolshed Token(found in Guild_HQ) *Note also have multiple gates in place to protect players and items from the mana explosion drop x for Jewelers room *Jewelers room works just need to determine what x is drop x for Thaumaturgy room *Thaumaturgy room works just need to determine what x is drop gold dropping the Firestar named fearless allows access to but I suspect that the drop location of the chest is not as intended because the player is in the way once you enter the chest the exit back to the basement is things such as the message et al reside on teleporters which then transport items to the map as they are when the map is already purchased items reappear in that area From my this does not cause any problems at the moment But this should be corrected fixed Major it s now possible to buy guilds Ryo Update Uploaded guild package to CVS Changes the cauldrons and the charging room I spent a while agonizing over They were natural guild enhancements but much too much value for any reasonable expense to buy them Then I thought that they should be pay access but at a greatly reduced rate SO when you buy a forge or whatever for your guild it is available on a perplayer daily rate but it will be accessable for testing and to DMs to play with Like I said lots still to do with the especially comingt up with quest items for buying things like the new workshops and stuff One of the things I would like some input on would be proposals for additional fields for either the guildhouses or guild datafiles to play with Currently the Guildhouse but there is no reason we can t have more than one measure of a guild perhaps have dues relate to Dues and use points for some other suspended or inactive or when a guild is founded inactive active Guilds have the format
Definition: README.txt:140
get_template
static inja::Template get_template(const std::string &filename)
Definition: mapper.cpp:3002
mapstruct::in_memory
uint32_t in_memory
Definition: map.h:335
convert.dest
dest
Definition: convert.py:25
struct_map_info::tiled_maps
struct_map_list tiled_maps
Definition: mapper.cpp:222
inja.hpp
exit
Install Bug reporting Credits but rather whatever guild name you are using *With the current map and server there are three they and GreenGoblin *Whatever name you give the folder should but it will still use GUILD_TEMPLATE *You can change what guild it uses by editing the map files Modify Map or objects if you want to use the optional Python based Guild Storage hall The first three are on the main the next two are in the guild_hq and the final one is in hallofjoining Withe the Storage three objects are found on the main floor and the last two are in the basement It s not that but you will need a map editor You find the object that has the click edit and change the line script options(which currently is "GUILD_TEMPALTE") to the guild you wish to use. And make sure you use the same one for all of them or it won 't work. Here 's a quick HOWTO for using the map editor to make these changes edit the mainfloor map exit(x15, y29 - set to/Edit/This/Exit/Path in the template) back to the world map as well. If you are using the Storage Hall map(storage_hall)
diamondslots.y
y
Definition: diamondslots.py:16
ext_info_map
void ext_info_map(int, const mapstruct *, uint8_t, uint8_t, const char *str1)
Definition: mapper.cpp:3303
region_count
static size_t region_count
Definition: mapper.cpp:362
command_help
void command_help(object *, const char *)
Definition: mapper.cpp:3418
do_parameters
static void do_parameters(int argc, char **argv)
Definition: mapper.cpp:2899
CLEAR_FLAG
#define CLEAR_FLAG(xyz, p)
Definition: define.h:225
all_data
static nlohmann::json all_data
Definition: mapper.cpp:2171
face_info::datalen
uint16_t datalen
Definition: image.h:12
add_monster
static void add_monster(object *monster, struct_map_info *map)
Definition: mapper.cpp:626
struct_map_in_quest_list::list
struct struct_map_in_quest ** list
Definition: mapper.cpp:197
MAP_HEIGHT
#define MAP_HEIGHT(m)
Definition: map.h:76
struct_quest::number
int number
Definition: mapper.cpp:889
struct_map_info::cfregion
region * cfregion
Definition: mapper.cpp:215
get_ob_diff
void get_ob_diff(StringBuffer *sb, const object *op, const object *op2)
Definition: object.cpp:4977
Settings::mapdir
const char * mapdir
Definition: global.h:251
sort_race
static int sort_race(const void *a, const void *b)
Definition: mapper.cpp:648
do_regions_link
static bool do_regions_link
Definition: mapper.cpp:381
arch_to_object
object * arch_to_object(archetype *at)
Definition: arch.cpp:229
object_give_identified_properties
void object_give_identified_properties(object *op)
Definition: item.cpp:1360
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)
Definition: mapper.cpp:269
create-tower.tile
tile
Definition: create-tower.py:8
process_map
static void process_map(struct_map_info *info)
Definition: mapper.cpp:1501
quests_allocated
static int quests_allocated
Definition: mapper.cpp:898
strcasecmp
int strcasecmp(const char *s1, const char *s2)
castle_read.key
key
Definition: castle_read.py:64
npc_dialog.npc
npc
Definition: npc_dialog.py:95
find_skill_by_number
object * find_skill_by_number(object *, int)
Definition: mapper.cpp:3325
sizes
static int sizes[]
Definition: mapper.cpp:312
account_logout
void account_logout(const char *)
Definition: mapper.cpp:3421
reverse_regions
static std::map< region *, std::string > reverse_regions
Definition: mapper.cpp:2174
get_region_by_map
region * get_region_by_map(mapstruct *m)
Definition: region.cpp:72
S_DOOR
#define S_DOOR
Definition: mapper.cpp:386
Settings::datadir
const char * datadir
Definition: global.h:248
create_tiled_map
static struct_map_info * create_tiled_map(void)
Definition: mapper.cpp:1212
world_map
static int world_map
Definition: mapper.cpp:318
templates
static std::vector< std::string > templates
Definition: mapper.cpp:2620
ignore_path
static const char * ignore_path[]
Definition: mapper.cpp:2715
struct_map_list::count
size_t count
Definition: mapper.cpp:205
slaying_count
static size_t slaying_count
Definition: mapper.cpp:400
player_get_delayed_buffer
SockList * player_get_delayed_buffer(player *)
Definition: mapper.cpp:3400
add_template_to_render
void add_template_to_render(const std::string &template_name, const std::string &output_name, const std::string &param)
Definition: mapper.cpp:2593
object_remove
void object_remove(object *op)
Definition: object.cpp:1828
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
Definition: mapper.cpp:369
sort_struct_map_in_quest
static int sort_struct_map_in_quest(const void *left, const void *right)
Definition: mapper.cpp:987
struct_map_info::height
int height
Definition: mapper.cpp:230
ALTAR
@ ALTAR
Definition: object.h:127
struct_npc_info::x
int x
Definition: mapper.cpp:182
relative_path
static void relative_path(const char *from, const char *to, char *result)
Definition: mapper.cpp:785
FLAG_UNPAID
#define FLAG_UNPAID
Definition: define.h:236
dump_unused_maps
static void dump_unused_maps(void)
Definition: mapper.cpp:2780
rod_adjust
void rod_adjust(object *)
Definition: mapper.cpp:3338
sort_region
static int sort_region(const void *left, const void *right)
Definition: mapper.cpp:870
special_equipment
static std::vector< struct_equipment * > special_equipment
Definition: mapper.cpp:250
generate_treasure
object * generate_treasure(treasurelist *t, int difficulty)
Definition: treasure.cpp:295
make_path_to_file
void make_path_to_file(const char *filename)
Definition: porting.cpp:164
FREE_OBJ_FREE_INVENTORY
#define FREE_OBJ_FREE_INVENTORY
Definition: object.h:535
fix_exits_for_map
static void fix_exits_for_map(struct_map_info *current, struct_map_list *from, int is_from)
Definition: mapper.cpp:1931
SCROLL
@ SCROLL
Definition: object.h:226
FLAG_IS_LINKED
#define FLAG_IS_LINKED
Definition: define.h:315
struct_npc_info::name
const char * name
Definition: mapper.cpp:180
object::nrof
uint32_t nrof
Definition: object.h:342
draw_ext_info
void draw_ext_info(int, int, const object *, uint8_t, uint8_t, const char *txt)
Definition: mapper.cpp:3291
split
static std::vector< std::string > split(const std::string &field, const std::string &by)
Definition: mapper.cpp:2608
param
No space after the left no space before the right paren Comma right after the formal param
Definition: style-guide.txt:215
mapstruct::reset_time
uint32_t reset_time
Definition: map.h:321
say.item
dictionary item
Definition: say.py:149
do_help
static void do_help(const char *program)
Definition: mapper.cpp:2862
artifact
Definition: artifact.h:14
struct_quest::name
char * name
Definition: mapper.cpp:887
nlohmann::basic_json::erase
IteratorType erase(IteratorType pos)
remove element given an iterator
Definition: json.hpp:21582
get_faces_count
size_t get_faces_count()
Definition: assets.cpp:293
calc_item_power
int calc_item_power(const object *op)
Definition: item.cpp:239
write_world_info
static void write_world_info(void)
Definition: mapper.cpp:2798
struct_map_in_quest_list::allocated
size_t allocated
Definition: mapper.cpp:199
tiled_map_need_pic
static int tiled_map_need_pic(struct_map_info *map)
Definition: mapper.cpp:2005
StringBuffer
Definition: stringbuffer.cpp:25
face_sets
Definition: image.h:17
SPELL
@ SPELL
Definition: object.h:219
map_limit
static int map_limit
Definition: mapper.cpp:316
replace.current
current
Definition: replace.py:64
closedir
int closedir(DIR *)
quests
static struct_quest ** quests
Definition: mapper.cpp:894
guildbuy.temp
def temp
Definition: guildbuy.py:26
fix_tiled_map
static void fix_tiled_map(void)
Definition: mapper.cpp:1862
FLAG_CURSED
#define FLAG_CURSED
Definition: define.h:316
output_format_type
output_format_type
Definition: mapper.cpp:330
TELEPORTER
@ TELEPORTER
Definition: object.h:146
gdfaces
static gdImagePtr * gdfaces
Definition: mapper.cpp:176
pics_allocated
static int pics_allocated
Definition: mapper.cpp:307
struct_equipment
Definition: mapper.cpp:242
face_sets::faces
face_info * faces
Definition: image.h:26
IS_ARROW
#define IS_ARROW(op)
Definition: define.h:178
SPELLBOOK
@ SPELLBOOK
Definition: object.h:208
found_maps
static std::vector< char * > found_maps
Definition: mapper.cpp:366
FOR_INV_PREPARE
#define FOR_INV_PREPARE(op_, it_)
Definition: define.h:670
takeitem.status
status
Definition: takeitem.py:38
find_player_partial_name
player * find_player_partial_name(const char *)
Definition: mapper.cpp:3404
find_map_by_key
static struct_map_info * find_map_by_key(const std::string &key)
Definition: mapper.cpp:2181
warn_no_path
static int warn_no_path
Definition: mapper.cpp:351
find_quest_info
static struct_quest * find_quest_info(const char *name)
Definition: mapper.cpp:919
DETECTOR
@ DETECTOR
Definition: object.h:154
find_maps
static void find_maps(const char *from)
Definition: mapper.cpp:2740
struct_slaying_info::slaying
char * slaying
Definition: mapper.cpp:395
ring_occidental_mages.r
r
Definition: ring_occidental_mages.py:6
is_road
static int is_road(object *item)
Definition: mapper.cpp:661
Ice.g
def g
Definition: Ice.py:63
elevation_min
static int elevation_min
Definition: mapper.cpp:377
color_linked_exit
static int color_linked_exit
Definition: mapper.cpp:371
FLAG_IS_FLOOR
#define FLAG_IS_FLOOR
Definition: define.h:302
sort_equipment
static bool sort_equipment(const struct_equipment *l, const struct_equipment *r)
Definition: mapper.cpp:462
inja::Template
The main inja Template.
Definition: inja.hpp:2836
add_one_item
static void add_one_item(object *item, struct_map_info *map)
Definition: mapper.cpp:506
FLAG_IDENTIFIED
#define FLAG_IDENTIFIED
Definition: define.h:261
identify
object * identify(object *op)
Definition: item.cpp:1425