Crossfire Server, Trunk
CREMainWindow.cpp
Go to the documentation of this file.
1 #include <Qt>
2 #include <QtWidgets>
3 #include <CREMainWindow.h>
4 #include <CREResourcesWindow.h>
6 #include "CREExperienceWindow.h"
7 #include "MessageManager.h"
8 #include "CREReportDisplay.h"
9 #include "CREPixmap.h"
10 #include "CRESmoothFaceMaker.h"
11 #include "CREHPBarMaker.h"
12 #include "ResourcesManager.h"
13 #include "CRECombatSimulator.h"
14 #include "CREHPBarMaker.h"
15 #include "ScriptFileManager.h"
16 #include "FaceMakerDialog.h"
17 #include "EditMonstersDialog.h"
18 
19 extern "C" {
20 #include "global.h"
21 #include "sproto.h"
22 #include "image.h"
23 }
24 #include "assets.h"
25 #include "AssetsManager.h"
26 #include "CRESettings.h"
27 #include "LicenseManager.h"
28 
30 {
31  myArea = new QMdiArea();
32  setCentralWidget(myArea);
33  myArea->setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded);
34  myArea->setHorizontalScrollBarPolicy(Qt::ScrollBarAsNeeded);
35 
37 
38  createActions();
39  createMenus();
40 
41  statusBar()->showMessage(tr("Ready"));
42  myMapBrowseStatus = new QLabel(tr("Browsing maps..."));
43  statusBar()->addPermanentWidget(myMapBrowseStatus);
44 
45  setWindowTitle(tr("Crossfire Resource Editor"));
46 
48 
49  fillFacesets();
50 
53 
55 
57  connect(myMapManager, SIGNAL(browsingMap(const QString&)), this, SLOT(browsingMap(const QString&)));
58  connect(myMapManager, SIGNAL(finished()), this, SLOT(browsingFinished()));
60 }
61 
62 void CREMainWindow::closeEvent(QCloseEvent* event)
63 {
65  if (QMessageBox::question(this, "Discard changes?", "You have unsaved changes, really discard them?") != QMessageBox::Yes) {
66  event->ignore();
67  return;
68  }
69  }
70 
72  delete myMapManager;
73  delete myMessageManager;
74  delete myResourcesManager;
75  cleanup();
76  QMainWindow::closeEvent(event);
77 }
78 
79 QAction *CREMainWindow::createAction(const QString &title, const QString &statusTip, QObject *target, const char *slot) {
80  auto action = new QAction(title, this);
81  action->setStatusTip(statusTip);
82  connect(action, SIGNAL(triggered()), target, slot);
83  return action;
84 }
85 
87 {
88  mySaveFormulae = new QAction(tr("Formulae"), this);
89  mySaveFormulae->setEnabled(false);
90  connect(mySaveFormulae, SIGNAL(triggered()), this, SLOT(onSaveFormulae()));
91 
92  myReportPlayer = new QAction(tr("Player vs monsters"), this);
93  myReportPlayer->setStatusTip(tr("Compute statistics related to player vs monster combat."));
94  // can't use that while map browsing is running ; will be enabled in browsingFinished()
95  myReportPlayer->setEnabled(false);
96  connect(myReportPlayer, SIGNAL(triggered()), this, SLOT(onReportPlayer()));
97 
98  myReportShops = new QAction(tr("Shop specialization"), this);
99  myReportShops->setStatusTip(tr("Display the list of shops and their specialization for items."));
100  // can't use that while map browsing is running ; will be enabled in browsingFinished()
101  myReportShops->setEnabled(false);
102  connect(myReportShops, SIGNAL(triggered()), this, SLOT(onReportShops()));
103 
104  myReportQuests = new QAction(tr("Quest solved by players"), this);
105  myReportQuests->setStatusTip(tr("Display quests the players have solved."));
106  // can't use that while map browsing is running ; will be enabled in browsingFinished()
107  myReportQuests->setEnabled(false);
108  connect(myReportQuests, SIGNAL(triggered()), this, SLOT(onReportQuests()));
109 
110  myReportArchetypes = new QAction(tr("Unused archetypes"), this);
111  myReportArchetypes->setStatusTip(tr("Display all archetypes which seem unused."));
112  myReportArchetypes->setEnabled(false);
113  connect(myReportArchetypes, SIGNAL(triggered()), this, SLOT(onReportArchetypes()));
114 
115  myClearMapCache = new QAction(tr("Clear map cache"), this);
116  myClearMapCache->setStatusTip(tr("Force a refresh of all map information at next start."));
117  connect(myClearMapCache, SIGNAL(triggered()), this, SLOT(onClearCache()));
118  /* can't clear map cache while collecting information */
119  myClearMapCache->setEnabled(false);
120 
121  myToolFacesetUseFallback = new QAction("Use set fallback for missing faces", this);
122  connect(myToolFacesetUseFallback, SIGNAL(triggered()), this, SLOT(onToolFacesetUseFallback()));
123  myToolFacesetUseFallback->setCheckable(true);
124  myToolFacesetUseFallback->setChecked(true);
125 }
126 
128  DisplayAll,
134  DisplayFaces,
135  DisplayMaps,
142  DisplayAll,
143 };
144 
145 const char* displayNames[] = {
146  "Resources",
147  "Artifacts",
148  "Archetypes",
149  "Treasures",
150  "Animations",
151  "Formulae",
152  "Faces",
153  "Maps",
154  "Quests",
155  "NPC dialogs",
156  "Scripts",
157  "Random maps",
158  "Messages",
159  "Facesets",
160  nullptr,
161 };
162 
163 const char* displayTips[] = {
164  "List all defined elements, except the experience table.",
165  "List all defined artifacts.",
166  "List all defined archetypes.",
167  "List all defined treasure lists.",
168  "List all defined animations.",
169  "List all defined alchemy recipes.",
170  "List all defined faces.",
171  "List all maps, with their region.",
172  "List all defined quests.",
173  "List all NPC dialogs in files.",
174  "List all scripts references in maps.",
175  "List all random maps.",
176  "Display all general messages.",
177  "Display all facesets.",
178  nullptr,
179 };
180 
182 {
183  myOpenMenu = menuBar()->addMenu(tr("&Open"));
184  for (int i = 0; displayNames[i] != nullptr; i++)
185  {
186  QAction* action = new QAction(tr(displayNames[i]), this);
187  action->setStatusTip(tr(displayTips[i]));
188  action->setData(static_cast<int>(displayModes[i]));
189  connect(action, SIGNAL(triggered()), this, SLOT(onOpenResources()));
190  myOpenMenu->addAction(action);
191  }
192 
193  myOpenMenu->addAction(createAction(tr("Experience"), tr("Display the experience table."), this, SLOT(onOpenExperience())));
194 
195  myOpenMenu->addSeparator();
196  QAction* exit = myOpenMenu->addAction(tr("&Exit"));
197  exit->setStatusTip(tr("Close the application."));
198  connect(exit, SIGNAL(triggered()), this, SLOT(close()));
199 
200  mySaveMenu = menuBar()->addMenu(tr("&Save"));
201  mySaveMenu->addAction(mySaveFormulae);
202  mySaveMenu->addAction(createAction(tr("Quests"), tr("Save all modified quests to disk."), this, SLOT(onSaveQuests())));
203  mySaveMenu->addAction(createAction(tr("Dialogs"), tr("Save all modified NPC dialogs."), this, SLOT(onSaveMessages())));
204  mySaveMenu->addAction(createAction(tr("Archetypes"), tr("Save all modified archetypes."), myResourcesManager, SLOT(saveArchetypes())));
205 
206  QMenu* reportMenu = menuBar()->addMenu("&Reports");
207  reportMenu->addAction(createAction(tr("Faces and animations report"), tr("Show faces and animations which are used by multiple archetypes, or not used."), this, SLOT(onReportDuplicate())));
208  reportMenu->addAction(createAction(tr("Spell damage"), tr("Display spell damage by level (bullet spells only for now)"), this, SLOT(onReportSpellDamage())));
209  reportMenu->addAction(createAction(tr("Alchemy"), tr("Display alchemy formulae, in a table."), this, SLOT(onReportAlchemy())));
210  reportMenu->addAction(createAction(tr("Alchemy graph"), tr("Export alchemy relationship as a DOT file."), this, SLOT(onReportAlchemyGraph())));
211  reportMenu->addAction(createAction(tr("Spells"), tr("Display all spells, in a table."), this, SLOT(onReportSpells())));
212  reportMenu->addAction(myReportPlayer);
213  reportMenu->addAction(createAction(tr("Summoned pets statistics"), tr("Display wc, hp, speed and other statistics for summoned pets."), this, SLOT(onReportSummon())));
214  reportMenu->addAction(myReportShops);
215  reportMenu->addAction(myReportQuests);
216  reportMenu->addAction(createAction(tr("Materials"), tr("Display all materials with their properties."), this, SLOT(onReportMaterials())));
217  reportMenu->addAction(myReportArchetypes);
218  reportMenu->addAction(createAction(tr("Licenses checks"), tr("Check for licenses inconsistencies."), this, SLOT(onReportLicenses())));
219 
220  myToolsMenu = menuBar()->addMenu("&Tools");
221  myToolsMenu->addAction(createAction(tr("Edit monsters"), tr("Edit monsters in a table."), this, SLOT(onToolEditMonsters())));
222  myToolsMenu->addAction(createAction(tr("Generate smooth face base"), tr("Generate the basic smoothed picture for a face."), this, SLOT(onToolSmooth())));
223  myToolsMenu->addAction(createAction(tr("Generate HP bar"), tr("Generate faces for a HP bar."), this, SLOT(onToolBarMaker())));
224  myToolsMenu->addAction(createAction(tr("Combat simulator"), tr("Simulate fighting between two objects."), this, SLOT(onToolCombatSimulator())));
225  myToolsMenu->addAction(createAction(tr("Generate face variants"), tr("Generate faces by changing colors of existing faces."), this, SLOT(onToolFaceMaker())));
226  myToolsMenu->addAction(myClearMapCache);
227  myToolsMenu->addAction(createAction(tr("Reload assets"), tr("Reload all assets from the data directory."), this, SLOT(onToolReloadAssets())));
228 
229  myWindows = menuBar()->addMenu(tr("&Windows"));
230  connect(myWindows, SIGNAL(aboutToShow()), this, SLOT(onWindowsShowing()));
231  myWindows->addAction(createAction(tr("Close current window"), tr("Close the currently focused window"), myArea, SLOT(closeActiveSubWindow())));
232  myWindows->addAction(createAction(tr("Close all windows"), tr("Close all opened windows"), myArea, SLOT(closeAllSubWindows())));
233  myWindows->addAction(createAction(tr("Tile windows"), tr("Tile all windows"), myArea, SLOT(tileSubWindows())));
234  myWindows->addAction(createAction(tr("Cascade windows"), tr("Cascade all windows"), myArea, SLOT(cascadeSubWindows())));
235 
236  auto sep = new QAction(this);
237  sep->setSeparator(true);
238  myWindows->addAction(sep);
239 }
240 
242 {
243  QWidget* resources = new CREResourcesWindow(myMapManager, myMessageManager, myResourcesManager, myScriptManager, this, mode);
244  connect(this, SIGNAL(updateFilters()), resources, SLOT(updateFilters()));
245  connect(resources, SIGNAL(filtersModified()), this, SLOT(onFiltersModified()));
246  connect(this, SIGNAL(updateReports()), resources, SLOT(updateReports()));
247  connect(resources, SIGNAL(reportsModified()), this, SLOT(onReportsModified()));
248  connect(this, SIGNAL(commitData()), resources, SLOT(commitData()));
249  myArea->addSubWindow(resources)->setWindowState(Qt::WindowMaximized);
250  resources->show();
251 }
252 
254 {
255  QWidget* experience = new CREExperienceWindow();
256  myArea->addSubWindow(experience);
257  experience->show();
258 }
259 
261 {
263  const QString select = settings.facesetToDisplay();
264  const bool use = settings.facesetUseFallback();
265 
266  QMenu *fs = myToolsMenu->addMenu("Facesets");
267  myFacesetsGroup = new QActionGroup(this);
268  connect(myFacesetsGroup, SIGNAL(triggered(QAction*)), this, SLOT(onToolFaceset(QAction*)));
269  getManager()->facesets()->each([&fs, &select, this] (face_sets *f)
270  {
271  QAction *a = new QAction(f->fullname, fs);
272  a->setCheckable(true);
273  a->setData(f->prefix);
274  fs->addAction(a);
275  myFacesetsGroup->addAction(a);
276  if (select == f->prefix)
277  a->setChecked(true);
278  });
279  fs->addSeparator();
280  fs->addAction(myToolFacesetUseFallback);
281  myToolFacesetUseFallback->setChecked(use);
282 }
283 
285 {
286  QAction* source = qobject_cast<QAction*>(sender());
287  if (!source)
288  return;
289 
290  doResourceWindow(static_cast<DisplayMode>(source->data().toInt()));
291 }
292 
294 {
295 }
296 
298 {
299  emit commitData();
301 }
302 
304 {
305  emit commitData();
307 }
308 
309 void CREMainWindow::browsingMap(const QString& path)
310 {
311  myMapBrowseStatus->setText(tr("Browsing map %1").arg(path));
312 }
313 
315 {
316  statusBar()->showMessage(tr("Finished browsing maps."), 5000);
317  myMapBrowseStatus->setVisible(false);
318  myReportPlayer->setEnabled(true);
319  myReportShops->setEnabled(true);
320  myReportQuests->setEnabled(true);
321  myReportArchetypes->setEnabled(true);
322  myClearMapCache->setEnabled(true);
323 }
324 
326 {
327  emit updateFilters();
328 }
329 
331 {
332  emit updateReports();
333 }
334 
342 {
343  QHash<QString, QStringList> faces, anims;
344 
345  // browse all archetypes
346  getManager()->archetypes()->each([&faces, &anims] (const auto arch)
347  {
348  if (arch->head)
349  {
350  return;
351  }
352  // if there is an animation, don't consider the face, since it's part of the animation anyway (hopefully, see lower for report on that)
353  if (arch->clone.animation == NULL)
354  {
355  if (arch->clone.face) {
356  faces[QString::fromLatin1(arch->clone.face->name)].append(QString(arch->name) + " (arch)");
357  sstring key = object_get_value(&arch->clone, "identified_face");
358  if (key)
359  {
360  faces[QString(key)].append(QString(arch->name) + " (arch)");
361  }
362  }
363  }
364  else
365  {
366  anims[arch->clone.animation->name].append(QString(arch->name) + " (arch)");
367  sstring key = object_get_value(&arch->clone, "identified_animation");
368  if (key)
369  {
370  anims[QString(key)].append(QString(arch->name) + " (arch)");
371  }
372  }
373  });
374 
375  // list faces in animations
376  getManager()->animations()->each([&faces] (const auto anim)
377  {
378  QStringList done;
379  for (int i = 0; i < anim->num_animations; i++)
380  {
381  // don't list animation twice if they use the same face
382  if (!done.contains(QString::fromLatin1(anim->faces[i]->name)))
383  {
384  faces[QString::fromLatin1(anim->faces[i]->name)].append(QString(anim->name) + " (animation)");
385  done.append(QString::fromLatin1(anim->faces[i]->name));
386  }
387  }
388  });
389 
390  // list faces and animations for artifacts
392  artifact* art;
393  for (list = first_artifactlist; list != NULL; list = list->next)
394  {
395  for (art = list->items; art != NULL; art = art->next)
396  {
397  if (art->item->animation == 0)
398  {
399  if (art->item->face) {
400  faces[QString::fromLatin1(art->item->face->name)].append(QString(art->item->name) + " (art)");
401  sstring key = object_get_value(art->item, "identified_face");
402  if (key)
403  {
404  faces[QString(key)].append(QString(art->item->name) + " (art)");
405  }
406  }
407  }
408  else
409  {
410  anims[art->item->animation->name].append(QString(art->item->name) + " (art)");
411  sstring key = object_get_value(art->item, "identified_animation");
412  if (key)
413  {
414  anims[QString(key)].append(QString(art->item->name) + " (arch)");
415  }
416  }
417  }
418  }
419 
420  getManager()->quests()->each([&] (auto quest) {
421  if (quest->face != nullptr)
422  {
423  faces[quest->face->name].append(QString(quest->quest_code) + " (quest)");
424  }
425  });
426 
428  {
429  if (message->face != nullptr)
430  {
431  faces[message->face->name].append(QString(message->identifier) + " (message)");
432  }
433  });
434 
435  for (const auto map : myMapManager->allMaps())
436  {
437  for (const auto face : map->faces())
438  {
439  faces[face].append(QString(map->path()) + " (map)");
440  }
441  for (const auto animation : map->animations())
442  {
443  anims[animation].append(map->path() + " (map)");
444  }
445  }
446 
447  QString report("<p><strong>Warning:</strong> this list doesn't take into account faces for all artifacts, especially the 'animation_suffix' ones.</p><h1>Faces used multiple times:</h1><ul>");
448 
449  QStringList keys = faces.keys();
450  keys.sort();
451  foreach(QString name, keys)
452  {
453  if (faces[name].size() <= 1 || name.compare("blank.111") == 0)
454  continue;
455 
456  faces[name].sort();
457  report += "<li>" + name + ": ";
458  report += faces[name].join(", ");
459  report += "</li>";
460  }
461 
462  report += "</ul>";
463 
464  report += "<h1>Unused faces:</h1><ul>";
465  getManager()->faces()->each([&faces, &report] (const auto face)
466  {
467  if (faces[face->name].size() > 0)
468  return;
469  report += QString("<li>") + face->name + "</li>";
470  });
471  report += "</ul>";
472 
473  report += "<h1>Animations used multiple times:</h1><ul>";
474  keys = anims.keys();
475  keys.sort();
476  foreach(QString name, keys)
477  {
478  if (anims[name].size() <= 1)
479  continue;
480 
481  anims[name].sort();
482  report += "<li>" + name + ": ";
483  report += anims[name].join(", ");
484  report += "</li>";
485  }
486  report += "</ul>";
487 
488  report += "<h1>Unused animations:</h1><ul>";
489  getManager()->animations()->each([&anims, &report] (const auto anim)
490  {
491  if (anims[anim->name].size() > 0 || !strcmp(anim->name, "###none"))
492  return;
493  report += QString("<li>") + anim->name + "</li>";
494  });
495  report += "</ul>";
496 
497  // Find faces used for an object having an animation not including this face
498  report += "<h1>Objects having a face not part of their animation:</h1><ul>";
499 
501  // if there is an animation, don't consider the face, since it's part of the animation anyway (hopefully)
502  if (arch->clone.animation == NULL || arch->clone.face == NULL) {
503  return;
504  }
505  bool included = false;
506  for (int f = 0; f < arch->clone.animation->num_animations && !included; f++) {
507  if (arch->clone.animation->faces[f] == arch->clone.face) {
508  included = true;
509  }
510  }
511  if (!included) {
512  report += QString("<li>%1 (%2) has face %3 not in animation %4</li>\n").arg(arch->name, arch->clone.name, arch->clone.face->name, arch->clone.animation->name);
513  }
514  });
515 
516  CREReportDisplay show(report, "Faces and animations report");
517  show.exec();
518 }
519 
521 {
522  QStringList spell;
523  QList<QStringList> damage;
524 
525  object* caster = create_archetype("orc");
526 
527  getManager()->archetypes()->each([&caster, &spell, &damage] (archetype *arch)
528  {
529  if (arch->clone.type == SPELL && arch->clone.subtype == SP_BULLET && arch->clone.skill && strcmp(arch->clone.skill, "praying") == 0)
530  {
531  spell.append(arch->clone.name);
532  QStringList dam;
533  for (int l = 0; l < settings.max_level; l++)
534  {
535  caster->level = l;
536  int dm = arch->clone.stats.dam + SP_level_dam_adjust(caster, &arch->clone);
537  int cost = SP_level_spellpoint_cost(caster, &arch->clone, SPELL_GRACE);
538  dam.append(tr("%1 [%2]").arg(dm).arg(cost));
539  }
540  damage.append(dam);
541  }
542  });
543 
545 
546  QString report("<table><thead><tr><th>level</th>");
547 
548  for (int i = 0; i < spell.size(); i++)
549  {
550  report += "<th>" + spell[i] + "</th>";
551  }
552 
553  report += "</tr></thead><tbody>";
554 
555  for (int l = 0; l < settings.max_level; l++)
556  {
557  report += "<tr><td>" + QString::number(l) + "</td>";
558  for (int s = 0; s < spell.size(); s++)
559  report += "<td>" + damage[s][l] + "</td>";
560  report += "</tr>";
561  }
562 
563  report += "</tbody></table>";
564 
565  CREReportDisplay show(report, "Spell damage");
566  show.exec();
567 }
568 
569 static QString alchemyTable(const QString& skill, QStringList& noChance, QStringList& allIngredients)
570 {
571  int count = 0;
572 
573  QHash<int, QStringList> recipes;
574 
575  const recipelist* list;
576  const recipe* recipe;
577 
578  for (int ing = 1; ; ing++)
579  {
580  list = get_formulalist(ing);
581  if (!list)
582  break;
583 
584  for (recipe = list->items; recipe; recipe = recipe->next)
585  {
586  if (skill == recipe->skill)
587  {
588  if (recipe->arch_names == 0)
589  // hu?
590  continue;
591 
593  if (arch == NULL) {
594  continue;
595  }
596 
597  QString name;
598  if (strcmp(recipe->title, "NONE") == 0)
599  {
600  if (arch->clone.title == NULL)
601  name = arch->clone.name;
602  else
603  name = QString("%1 %2").arg(arch->clone.name, arch->clone.title);
604  }
605  else
606  {
607  name = QString("%1 of %2").arg(arch->clone.name, recipe->title);
608  }
609 
610  QStringList ingredients;
611  for (const linked_char* ingred = recipe->ingred; ingred != NULL; ingred = ingred->next)
612  {
613  ingredients.append(ingred->name);
614  const char* name = ingred->name;
615  if (isdigit(ingred->name[0])) {
616  name = strchr(ingred->name, ' ') + 1;
617  }
618  if (!allIngredients.contains(name)) {
619  allIngredients.append(name);
620  }
621  }
622 
623  recipes[recipe->diff].append(QString("<tr><td>%1</td><td>%2</td><td>%3</td><td>%4</td><td>%5</td></tr>").arg(name).arg(recipe->diff).arg(recipe->ingred_count).arg(recipe->exp).arg(ingredients.join(", ")));
624  count++;
625 
626  if (recipe->chance == 0) {
627  noChance.append(name);
628  }
629  }
630  }
631  }
632 
633  if (count == 0)
634  return QString();
635 
636  QString report = QString("<h2>%1 (%2 recipes)</h2><table><thead><tr><th>product</th><th>difficulty</th><th>ingredients count</th><th>experience</th><th>Ingredients</th>").arg(skill).arg(count);
637  report += "</tr></thead><tbody>";
638 
639  QList<int> difficulties = recipes.keys();
640  qSort(difficulties);
641  foreach(int difficulty, difficulties)
642  {
643  QStringList line = recipes[difficulty];
644  qSort(line);
645  report += line.join("\n");
646  }
647 
648  report += "</tbody></table>";
649 
650  return report;
651 }
652 
654 {
655  QStringList skills;
656 
657  getManager()->archetypes()->each([&skills] (const auto arch)
658  {
659  if (arch->clone.type == SKILL)
660  skills.append(arch->clone.name);
661  });
662  skills.sort();
663 
664  QString report("<h1>Alchemy formulae</h1>");
665  QStringList noChance, allIngredients;
666 
667  foreach(const QString skill, skills)
668  {
669  report += alchemyTable(skill, noChance, allIngredients);
670  }
671 
672  qSort(noChance);
673  report += tr("<h1>Formulae with chance of 0</h1>");
674  report += "<table><th>";
675  foreach(const QString& name, noChance) {
676  report += "<tr><td>" + name + "</td></tr>";
677  }
678  report += "</th></table>";
679 
680  qSort(allIngredients.begin(), allIngredients.end(), [] (const QString &s1, const QString &s2) {
681  return s1.toLower() < s2.toLower();
682  });
683  report += tr("<h1>All items used as ingredients</h1>");
684  report += "<ul>";
685  foreach(const QString& name, allIngredients) {
686  report += "<li>" + name + "</li>";
687  }
688  report += "</ul>";
689 
690  CREReportDisplay show(report, "Alchemy formulae");
691  show.exec();
692 }
693 
695 {
696  QString output = QFileDialog::getSaveFileName(this, tr("Destination file"), "", tr("Dot files (*.dot);;All files (*.*)"));
697  if (output.isEmpty()) {
698  return;
699  }
700 
701  QFile file(output);
702  if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) {
703  QMessageBox::critical(this, "Write error", tr("Unable to write to %1").arg(output));
704  return;
705  }
706  QTextStream out(&file);
707 
708  out << "digraph alchemy {\n";
709 
710  QVector<const recipe*> recipes;
711  QHash<const recipe*, QString> names;
712  QHash<QString, QVector<const recipe*> > products;
713 
714  for (int ing = 1; ; ing++)
715  {
716  const recipelist* list = get_formulalist(ing);
717  if (!list)
718  break;
719 
720  for (const recipe* recipe = list->items; recipe; recipe = recipe->next)
721  {
722  QString product("???");
723  for (size_t idx = 0; idx < recipe->arch_names; idx++) {
724  auto arch = getManager()->archetypes()->find(recipe->arch_name[idx]);
725  if (!arch) {
726  continue;
727  }
728  if (recipe->title && strcmp(recipe->title, "NONE")) {
729  product = tr("%1 of %2").arg(arch->clone.name, recipe->title);
730  } else {
731  product = arch->clone.name;
732  }
733  products[product].append(recipe);
734  }
735  names[recipe] = product;
736  recipes.append(recipe);
737  }
738  }
739 
740  QHash<const recipe*, bool> added;
741 
742  foreach (const recipe* rec, recipes) {
743  for (linked_char* ing = rec->ingred; ing; ing = ing->next) {
744  const char* name = ing->name;
745  if (isdigit(name[0]) && strchr(name, ' ')) {
746  name = strchr(name, ' ') + 1;
747  }
748  QHash<QString, QVector<const recipe*> >::iterator item = products.find(name);
749  if (item != products.end()) {
750  if (!added[rec]) {
751  out << tr("alchemy_%1 [label=\"%2\"]\n").arg(recipes.indexOf(rec)).arg(names[rec]);
752  added[rec] = true;
753  }
754  for (auto r = item->begin(); r != item->end(); r++) {
755  if (!added[*r]) {
756  out << tr("alchemy_%1 [label=\"%2\"]\n").arg(recipes.indexOf(*r)).arg(names[*r]);
757  added[*r] = true;
758  }
759  out << tr("alchemy_%1 -> alchemy_%2\n").arg(recipes.indexOf(*r)).arg(recipes.indexOf(rec));
760  }
761  }
762  }
763  }
764 
765  int ignored = 0;
766  foreach (const recipe* rec, recipes) {
767  if (!added[rec]) {
768  ignored++;
769  }
770  }
771  out << "graph [labelloc=\"b\" labeljust=\"c\" label=\"Alchemy graph, formulae producing ingredients of other formulae";
772  if (ignored) {
773  out << tr(" (%1 formulae not displayed)").arg(ignored);
774  }
775  out << "\"]\n";
776 
777  out << "}\n";
778 }
779 
780 static QString spellsTable(const QString& skill)
781 {
782  bool one = false;
783 
784  QString report = QString("<h2>%1</h2><table><thead><tr><th>Spell</th><th>Level</th>").arg(skill);
785  report += "</tr></thead><tbody>";
786 
787  QHash<int, QStringList> spells;
788 
789  getManager()->archetypes()->each([&skill, &spells, &one] (const archetype *spell) {
790  if (spell->clone.type == SPELL && spell->clone.skill == skill)
791  {
792  spells[spell->clone.level].append(QString("<tr><td>%1</td><td>%2</td></tr>").arg(spell->clone.name).arg(spell->clone.level));
793  one = true;
794  }
795  });
796 
797  if (!one)
798  return QString();
799 
800  QList<int> levels = spells.keys();
801  qSort(levels);
802  foreach(int level, levels)
803  {
804  spells[level].sort();
805  report += spells[level].join("\n");
806  }
807 
808  report += "</tbody></table>";
809 
810  return report;
811 }
812 
814 {
815  QStringList skills;
816 
817  getManager()->archetypes()->each([&skills] (const archt *arch)
818  {
819  if (arch->clone.type == SKILL)
820  skills.append(arch->clone.name);
821  });
822 
823  skills.sort();
824 
825  QString report("<h1>Spell list</h1>");
826 
827  foreach(const QString skill, skills)
828  {
829  report += spellsTable(skill);
830  }
831 
832  CREReportDisplay show(report, "Spell list");
833  show.exec();
834 }
835 
845 static int monsterFight(archetype* monster, archetype* skill, int level)
846 {
847  int limit = 50, result = 1;
848  player pl;
849  memset(&pl, 0, sizeof(player));
850  strncpy(pl.savebed_map, "/HallOfSelection", MAX_BUF);
851  pl.bed_x = 5;
852  pl.bed_y = 5;
853  pl.socket.faces_sent = (uint8_t*)calloc(sizeof(uint8_t), get_faces_count());
854 
855  archetype *dwarf_player_arch = find_archetype("dwarf_player");
856  if (dwarf_player_arch == NULL) {
857  free(pl.socket.faces_sent);
858  return 0;
859  }
860  object* obfirst = object_create_arch(dwarf_player_arch);
861  obfirst->level = level;
862  obfirst->contr = &pl;
863  pl.ob = obfirst;
864  object* obskill = object_create_arch(skill);
865  obskill->level = level;
866  SET_FLAG(obskill, FLAG_APPLIED);
867  object_insert_in_ob(obskill, obfirst);
868  archetype *skill_arch = find_archetype((skill->clone.subtype == SK_TWO_HANDED_WEAPON) ? "sword_3" : "sword");
869  if (skill_arch == NULL) {
870  free(pl.socket.faces_sent);
871  return 0;
872  }
873  object* sword = object_create_arch(skill_arch);
874  SET_FLAG(sword, FLAG_APPLIED);
875  object_insert_in_ob(sword, obfirst);
876  fix_object(obfirst);
877  obfirst->stats.hp = obfirst->stats.maxhp;
878 
879  object* obsecond = object_create_arch(monster);
880  tag_t tagfirst = obfirst->count;
881  tag_t tagsecond = obsecond->count;
882 
883  // make a big map so large monsters are ok in map
884  mapstruct* test_map = get_empty_map(50, 50);
885 
886  obfirst = object_insert_in_map_at(obfirst, test_map, NULL, 0, 0, 0);
887  obsecond = object_insert_in_map_at(obsecond, test_map, NULL, 0, 1 + monster->tail_x, monster->tail_y);
888 
889  if (!obsecond || object_was_destroyed(obsecond, tagsecond))
890  {
891  qDebug() << "second removed??";
892  }
893 
894  while (limit-- > 0 && obfirst->stats.hp >= 0 && obsecond->stats.hp >= 0)
895  {
896  if (obfirst->weapon_speed_left > 0) {
897  --obfirst->weapon_speed_left;
898  do_some_living(obfirst);
899 
900  move_player(obfirst, 3);
901  if (object_was_destroyed(obsecond, tagsecond))
902  break;
903 
904  /* the player may have been killed (acid for instance), so check here */
905  if (object_was_destroyed(obfirst, tagfirst) || (obfirst->map != test_map))
906  {
907  result = 0;
908  break;
909  }
910  }
911 
912  if (obsecond->speed_left > 0) {
913  --obsecond->speed_left;
914  monster_do_living(obsecond);
915 
916  attack_ob(obfirst, obsecond);
917  /* when player is killed, she is teleported to bed of reality -> check map */
918  if (object_was_destroyed(obfirst, tagfirst) || (obfirst->map != test_map))
919  {
920  result = 0;
921  break;
922  }
923  }
924 
925  obfirst->weapon_speed_left += obfirst->weapon_speed;
926  if (obfirst->weapon_speed_left > 1.0)
927  obfirst->weapon_speed_left = 1.0;
928  if (obsecond->speed_left <= 0)
929  obsecond->speed_left += FABS(obsecond->speed);
930  }
931 
932  free(pl.socket.faces_sent);
933  if (!object_was_destroyed(obfirst, tagfirst))
934  {
935  object_remove(obfirst);
937  }
938  if (!object_was_destroyed(obsecond, tagsecond))
939  {
940  object_remove(obsecond);
942  }
944 
945  return result;
946 }
947 
958 static int monsterFight(archetype* monster, archetype* skill, int level, int count)
959 {
960  int victory = 0;
961  while (count-- > 0)
962  victory += monsterFight(monster, skill, level);
963 
964  return victory;
965 }
966 
976 static QString monsterFight(archetype* monster, archetype* skill)
977 {
978  qDebug() << "monsterFight:" << monster->clone.name << skill->clone.name;
979  int ret, min = settings.max_level + 1, half = settings.max_level + 1, count = 5, level;
980  int first = 1, max = settings.max_level;
981 
982  while (first != max)
983  {
984  level = (max + first) / 2;
985  if (level < first)
986  level = first;
987  if (first > max)
988  first = max;
989 
990  ret = monsterFight(monster, skill, level, count);
991  if (ret > 0)
992  {
993  if (level < min)
994  min = level;
995  if (ret > (count / 2) && (level < half))
996  half = level;
997 
998  max = level;
999  }
1000  else
1001  {
1002  if (first == level)
1003  break;
1004  first = level;
1005  }
1006  }
1007 
1008  //qDebug() << " result:" << min << half;
1009 
1010  // if player was killed, then HallOfSelection was loaded, so clean it now.
1011  // This speeds up various checks, like in free_all_objects().
1012  mapstruct* hos = has_been_loaded("/HallOfSelection");
1013  if (hos)
1014  {
1015  hos->reset_time = 1;
1016  hos->in_memory = MAP_IN_MEMORY;
1017  delete_map(hos);
1018  }
1019  /*
1020  extern int nroffreeobjects;
1021  extern int nrofallocobjects;
1022  qDebug() << "free: " << nroffreeobjects << ", all: " << nrofallocobjects;
1023  */
1024 
1025  if (min == settings.max_level + 1)
1026  return "<td colspan=\"2\">-</td>";
1027  return "<td>" + QString::number(min) + "</td><td>" + ((half != 0) ? QString::number(half) : "") + "</td>";
1028 }
1029 
1036 static QString monsterTable(archetype* monster, QList<archetype*> skills)
1037 {
1038  QString line = "<tr>";
1039 
1040  line += "<td>" + QString(monster->clone.name) + "</td>";
1041  line += "<td>" + QString::number(monster->clone.level) + "</td>";
1042  line += "<td>" + QString::number(monster->clone.speed) + "</td>";
1043  line += "<td>" + QString::number(monster->clone.stats.wc) + "</td>";
1044  line += "<td>" + QString::number(monster->clone.stats.dam) + "</td>";
1045  line += "<td>" + QString::number(monster->clone.stats.ac) + "</td>";
1046  line += "<td>" + QString::number(monster->clone.stats.hp) + "</td>";
1047  line += "<td>" + QString::number(monster->clone.stats.Con) + "</td>";
1048 
1049  foreach(archetype* skill, skills)
1050  {
1051  line += monsterFight(monster, skill);
1052  }
1053  line += "</tr>\n";
1054 
1055  return line;
1056 }
1057 
1063 {
1064  QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
1065 
1066  QStringList names;
1067  QMap<QString, archetype*> monsters;
1068  QList<archetype*> skills;
1069 
1070  getManager()->archetypes()->each([&names, &monsters, &skills] (archetype *arch)
1071  {
1072  if (QUERY_FLAG(&arch->clone, FLAG_MONSTER) && arch->clone.stats.hp > 0 && arch->head == NULL)
1073  {
1074  QString name(QString(arch->clone.name).toLower());
1075  if (monsters.contains(name))
1076  {
1077  int suffix = 1;
1078  do
1079  {
1080  name = QString(arch->clone.name).toLower() + "_" + QString::number(suffix);
1081  suffix++;
1082  } while (monsters.contains(name));
1083  }
1084 
1085  monsters[name] = arch;
1086  }
1087  if (arch->clone.type == SKILL && IS_COMBAT_SKILL(arch->clone.subtype))
1088  {
1089  if (strcmp(arch->name, "skill_missile_weapon") == 0 || strcmp(arch->name, "skill_throwing") == 0)
1090  return;
1091  skills.append(arch);
1092  }
1093  });
1094 
1095  names = monsters.keys();
1096  names.sort();
1097 
1098  QString report(tr("<h1>Player vs monsters</h1><p><strong>fv</strong> is the level at which the first victory happened, <strong>hv</strong> is the level at which at least 50% of fights were victorious.</p>\n")), line;
1099  report += "<table border=\"1\"><tbody>\n";
1100  report += "<tr>";
1101  report += "<th rowspan=\"2\">Monster</th>";
1102  report += "<th rowspan=\"2\">level</th>";
1103  report += "<th rowspan=\"2\">speed</th>";
1104  report += "<th rowspan=\"2\">wc</th>";
1105  report += "<th rowspan=\"2\">dam</th>";
1106  report += "<th rowspan=\"2\">ac</th>";
1107  report += "<th rowspan=\"2\">hp</th>";
1108  report += "<th rowspan=\"2\">regen</th>";
1109 
1110  line = "<tr>";
1111  foreach(archetype* skill, skills)
1112  {
1113  report += "<th colspan=\"2\">" + QString(skill->clone.name) + "</th>";
1114  line += "<th>fv</th><th>hv</th>";
1115  }
1116  report += "</tr>\n" + line + "</tr>\n";
1117 
1118  int limit = 500;
1119  foreach(const QString name, names)
1120  {
1121  report += monsterTable(monsters[name], skills);
1122  if (limit-- <= 0)
1123  break;
1124  }
1125 
1126  report += "</tbody></table>\n";
1127 
1128  CREReportDisplay show(report, "Player vs monsters (hand to hand)");
1129  QApplication::restoreOverrideCursor();
1130  show.exec();
1131 }
1132 
1133 static QString reportSummon(const archetype* summon, const object* other, QString name)
1134 {
1135  QString report;
1136  int level, wc_adj = 0;
1137 
1138  const object* spell = &summon->clone;
1139  sstring rate = object_get_value(spell, "wc_increase_rate");
1140  if (rate != NULL) {
1141  wc_adj = atoi(rate);
1142  }
1143 
1144  // hp, dam, speed, wc
1145 
1146  QString ac("<tr><td>ac</td>");
1147  QString hp("<tr><td>hp</td>");
1148  QString dam("<tr><td>dam</td>");
1149  QString speed("<tr><td>speed</td>");
1150  QString wc("<tr><td>wc</td>");
1151  int ihp, idam, iwc, diff;
1152  float fspeed;
1153 
1154  for (level = 1; level < 120; level += 10)
1155  {
1156  if (level < spell->level)
1157  {
1158  ac += "<td></td>";
1159  hp += "<td></td>";
1160  dam += "<td></td>";
1161  speed += "<td></td>";
1162  wc += "<td></td>";
1163  continue;
1164  }
1165 
1166  diff = level - spell->level;
1167 
1168  ihp = other->stats.hp + spell->duration + (spell->duration_modifier != 0 ? (diff / spell->duration_modifier) : 0);
1169  idam = (spell->stats.dam ? spell->stats.dam : other->stats.dam) + (spell->dam_modifier != 0 ? (diff / spell->dam_modifier) : 0);
1170  fspeed = MIN(1.0, FABS(other->speed) + .02 * (spell->range_modifier != 0 ? (diff / spell->range_modifier) : 0));
1171  iwc = other->stats.wc;
1172  if (wc_adj > 0)
1173  iwc -= (diff / wc_adj);
1174 
1175  ac += "<td>" + QString::number(other->stats.ac) + "</td>";
1176  hp += "<td>" + QString::number(ihp) + "</td>";
1177  dam += "<td>" + QString::number(idam) + "</td>";
1178  speed += "<td>" + QString::number(fspeed) + "</td>";
1179  wc += "<td>" + QString::number(iwc) + "</td>";
1180  }
1181 
1182  report += "<tr><td colspan=\"13\"><strong>" + name + "</strong></td></tr>\n";
1183 
1184  report += ac + "</tr>\n" + hp + "</tr>\n" + dam + "</tr>\n" + speed + "</tr>\n" + wc + "</tr>\n\n";
1185 
1186  return report;
1187 }
1188 
1190 {
1191  QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
1192 
1193  int level;
1194 
1195  QString report(tr("<h1>Summoned pet statistics</h1>\n")), line;
1196  report += "<table border=\"1\">\n<thead>\n";
1197  report += "<tr>";
1198  report += "<th rowspan=\"2\">Spell</th>";
1199  report += "<th colspan=\"12\">Level</th>";
1200  report += "</tr>\n";
1201  report += "<tr>";
1202 
1203  for (level = 1; level < 120; level += 10)
1204  {
1205  report += "<th>" + QString::number(level) + "</th>";
1206  }
1207  report += "</tr>\n</thead>\n<tbody>\n";
1208 
1209  QMap<QString, QString> spells;
1210 
1211  getManager()->archetypes()->each([&spells] (archetype *summon)
1212  {
1213  if (summon->clone.type != SPELL || summon->clone.subtype != SP_SUMMON_GOLEM)
1214  return;
1215  if (summon->clone.other_arch != NULL)
1216  {
1217  spells[summon->clone.name] = reportSummon(summon, &summon->clone.other_arch->clone, QString(summon->clone.name));
1218  return;
1219  }
1220 
1221  // god-based summoning
1222  getManager()->archetypes()->each([&summon, &spells] (archetype *god)
1223  {
1224  if (god->clone.type != GOD)
1225  return;
1226 
1227  QString name(QString(summon->clone.name) + " (" + QString(god->name) + ")");
1228  archetype* holy = determine_holy_arch(&god->clone, summon->clone.race);
1229  if (holy == NULL)
1230  return;
1231 
1232  spells[name] = reportSummon(summon, &holy->clone, name);
1233  });
1234  });
1235 
1236  QStringList keys = spells.keys();
1237  keys.sort();
1238  foreach(QString key, keys)
1239  {
1240  report += spells[key];
1241  }
1242 
1243  report += "</tbody>\n</table>\n";
1244 
1245  CREReportDisplay show(report, "Summoned pet statistics");
1246  QApplication::restoreOverrideCursor();
1247  show.exec();
1248 }
1249 
1250 static QString buildShopReport(const QString& title, const QStringList& types, const QList<CREMapInformation*>& maps, QStringList& items)
1251 {
1252  QString report("<h2>" + title + "</h2>");
1253  report += "<table border=\"1\">\n<thead>\n";
1254  report += "<tr>";
1255  report += "<th>Shop</th>";
1256  report += "<th>Greed</th>";
1257  report += "<th>Race</th>";
1258  report += "<th>Min</th>";
1259  report += "<th>Max</th>";
1260  foreach (QString item, types)
1261  {
1262  report += "<th>" + item + "</th>";
1263  items.removeAll(item);
1264  }
1265  report += "</tr>\n</thead><tbody>";
1266 
1267  foreach(const CREMapInformation* map, maps)
1268  {
1269  QString line;
1270  bool keep = false;
1271 
1272  if (map->shopItems().size() == 0)
1273  continue;
1274 
1275  line += "<tr>";
1276 
1277  line += "<td>" + map->name() + " " + map->path() + "</td>";
1278  line += "<td>" + QString::number(map->shopGreed()) + "</td>";
1279  line += "<td>" + map->shopRace() + "</td>";
1280  line += "<td>" + (map->shopMin() != 0 ? QString::number(map->shopMin()) : "") + "</td>";
1281  line += "<td>" + (map->shopMax() != 0 ? QString::number(map->shopMax()) : "") + "</td>";
1282 
1283  foreach(const QString item, types)
1284  {
1285  if (map->shopItems()[item] == 0)
1286  {
1287  if (map->shopItems()["*"] == 0)
1288  line += "<td></td>";
1289  else
1290  line += "<td>" + QString::number(map->shopItems()["*"]) + "</td>";
1291  continue;
1292  }
1293  keep = true;
1294  line += "<td>" + QString::number(map->shopItems()[item]) + "</td>";
1295  }
1296 
1297  line += "</tr>";
1298  if (keep)
1299  report += line;
1300  }
1301 
1302  report += "</tbody></table>";
1303  return report;
1304 }
1305 
1307 {
1308  QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
1309 
1310  QString report(tr("<h1>Shop information</h1>\n"));
1311 
1312  QList<CREMapInformation*> maps = myMapManager->allMaps();
1313  QStringList items;
1314  foreach(const CREMapInformation* map, maps)
1315  {
1316  QStringList add = map->shopItems().keys();
1317  foreach(const QString item, add)
1318  {
1319  if (!items.contains(item))
1320  items.append(item);
1321  }
1322  }
1323  qSort(items);
1324 
1325  QStringList part;
1326 
1327  part << "weapon" << "weapon improver" << "bow" << "arrow";
1328  report += buildShopReport("Weapons", part, maps, items);
1329 
1330  part.clear();
1331  part << "armour" << "armour improver" << "boots" << "bracers" << "cloak" << "girdle" << "gloves" << "helmet" << "shield";
1332  report += buildShopReport("Armour", part, maps, items);
1333 
1334  part.clear();
1335  part << "amulet" << "potion" << "power_crystal" << "ring" << "rod" << "scroll" << "skillscroll" << "spellbook" << "wand";
1336  report += buildShopReport("Magical", part, maps, items);
1337 
1338  part.clear();
1339  part << "container" << "food" << "key" << "lamp" << "skill tool" << "special key";
1340  report += buildShopReport("Equipment", part, maps, items);
1341 
1342  if (!items.isEmpty())
1343  {
1344 
1345  part = items;
1346  report += buildShopReport("Others", part, maps, items);
1347  }
1348 
1349  CREReportDisplay show(report, "Shop information");
1350  QApplication::restoreOverrideCursor();
1351  show.exec();
1352 }
1353 
1354 void readDirectory(const QString& path, QHash<QString, QHash<QString, bool> >& states)
1355 {
1356  QDir dir(path);
1357  QStringList subdirs = dir.entryList(QStringList("*"), QDir::Dirs | QDir::NoDotAndDotDot);
1358  foreach(QString subdir, subdirs)
1359  {
1360  readDirectory(path + QDir::separator() + subdir, states);
1361  }
1362 
1363  QStringList quests = dir.entryList(QStringList("*.quest"), QDir::Files);
1364  foreach(QString file, quests)
1365  {
1366  qDebug() << "read quest:" << path << file;
1367  QString name = file.left(file.length() - 6);
1368  QFile read(path + QDir::separator() + file);
1369  read.open(QFile::ReadOnly);
1370  QTextStream stream(&read);
1371  QString line, code;
1372  bool completed;
1373  while (!(line = stream.readLine(0)).isNull())
1374  {
1375  if (line.startsWith("quest "))
1376  {
1377  code = line.mid(6);
1378  completed = false;
1379  continue;
1380  }
1381  if (code.isEmpty())
1382  continue;
1383  if (line == "end_quest")
1384  {
1385  states[code][name] = completed;
1386  code.clear();
1387  continue;
1388  }
1389  if (line.startsWith("state "))
1390  continue;
1391  if (line == "completed 1")
1392  completed = true;
1393  }
1394  }
1395 }
1396 
1398 {
1399  QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
1400 
1401  QHash<QString, QHash<QString, bool> > states;
1402  QString directory(settings.localdir);
1403  directory += QDir::separator();
1404  directory += settings.playerdir;
1405  readDirectory(directory, states);
1406 
1407  QStringList codes;
1408  getManager()->quests()->each([&] (const auto quest) {
1409  codes.append(quest->quest_code);
1410  });
1411 
1412  QString report("<html><body>\n<h1>Quests</h1>\n");
1413 
1414  QStringList keys = states.keys();
1415  keys.sort();
1416 
1417  foreach(QString key, keys)
1418  {
1419  codes.removeAll(key);
1420  const auto quest = getManager()->quests()->get(key.toStdString());
1421  report += "<h2>Quest: " + (quest != NULL ? quest->quest_title : (key + " ???")) + "</h2>\n";
1422  report += "<p>";
1423  QHash<QString, bool> done = states[key];
1424  QStringList players = done.keys();
1425  players.sort();
1426  int completed = 0;
1427  QString sep;
1428  foreach(QString player, players)
1429  {
1430  report += sep;
1431  sep = ", ";
1432  if (done[player])
1433  {
1434  completed++;
1435  report += "<strong>" + player + "</strong>";
1436  }
1437  else
1438  {
1439  report += player;
1440  }
1441  }
1442  report += "</p>\n";
1443  report += "<p>" + tr("%1 completed out of %2 (%3%)").arg(completed).arg(players.size()).arg(completed * 100 / players.size()) + "</p>\n";
1444  }
1445 
1446  if (codes.length() > 0)
1447  {
1448  codes.sort();
1449  QString sep;
1450  report += "<h2>Quests never done</h2>\n<p>\n";
1451  foreach(QString code, codes)
1452  {
1453  report += sep;
1454  sep = ", ";
1455  const auto quest = getManager()->quests()->find(code.toStdString());
1456  report += (quest != NULL ? quest->quest_title : (code + " ???"));
1457  }
1458  report += "</p>\n";
1459  }
1460 
1461  report += "</body>\n</html>\n";
1462 
1463  CREReportDisplay show(report, "Quests report");
1464  QApplication::restoreOverrideCursor();
1465  show.exec();
1466 }
1467 
1469 {
1470  QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
1471 
1472  QString report;
1473  report += "<html>";
1474 
1475  report += "<h1>Materials</h1>";
1476  report += "<table><tr><th>Name</th><th>Description</th></tr>";
1477  auto mat = materialt;
1478  while (mat) {
1479  report += tr("<tr><td>%1</td><td>%2</td></tr>").arg(mat->name, mat->description);
1480  mat = mat->next;
1481  }
1482  report += "</table>";
1483 
1484  for (int s = 0; s < 2; s++) {
1485  QString name(s == 0 ? "Saves" : "Resistances");
1486  report += tr("<h1>%1</h1>").arg(name);
1487  report += tr("<tr><th rowspan='2'>Name</th><th colspan='%1'>%2</th></tr>").arg(NROFATTACKS).arg(name);
1488  report += "<tr>";
1489  for (int r = 0; r < NROFATTACKS; r++) {
1490  report += "<th>" + QString(attacktype_desc[r]) + "</th>";
1491  }
1492  report += "</tr>";
1493 
1494  mat = materialt;
1495  while (mat) {
1496  report += tr("<tr><td>%1</td>").arg(mat->name);
1497  for (int r = 0; r < NROFATTACKS; r++) {
1498  report += tr("<td>%1</td>").arg(s == 0 ? mat->save[r] : mat->mod[r]);
1499  }
1500  report += "</tr>";
1501  mat = mat->next;
1502  }
1503  report += "</table>";
1504  }
1505 
1506  report += "</html>";
1507 
1508  CREReportDisplay show(report, "Materials report");
1509  QApplication::restoreOverrideCursor();
1510  show.exec();
1511 }
1512 
1514 {
1515  QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
1516 
1517  QString report;
1518  report += "<html>";
1519 
1520  report += "<h1>Apparently unused archetypes</h1>";
1521  report += "<h3>Warning: this list contains skills, items on style maps, and other things which are actually used.</h3>";
1522  report += "<table>";
1523  report += "<tr><th>Image</th><th>Archetype name</th><th>Item name</th><th>Type</th></tr>";
1524 
1525  getManager()->archetypes()->each([this, &report] (const archt* arch)
1526  {
1527  if (arch->head || arch->clone.type == PLAYER || arch->clone.type == MAP || arch->clone.type == EVENT_CONNECTOR)
1528  return;
1529  if (strstr(arch->name, "hpbar") != nullptr)
1530  return;
1531 
1532  bool used = false;
1534  (ArchetypeUse, const archt*, const treasurelist*, const CREMapInformation*, const recipe*) -> bool
1535  {
1536  used = true;
1537  return false;
1538  });
1539 
1540  if (!used)
1541  {
1542  QImage image(CREPixmap::getIcon(arch->clone.face->number).pixmap(32,32).toImage());
1543  QByteArray byteArray;
1544  QBuffer buffer(&byteArray);
1545  image.save(&buffer, "PNG");
1546  QString iconBase64 = QString::fromLatin1(byteArray.toBase64().data());
1547  auto td = get_typedata(arch->clone.type);
1548  report += tr("<tr><td><img src='data:image/png;base64,%1'></td><td>%2</td><td>%3</td><td>%4</td></tr>")
1549  .arg(iconBase64, arch->name, arch->clone.name, td ? td->name : tr("unknown: %1").arg(arch->clone.type));
1550  }
1551  });
1552 
1553  report += "</table>";
1554  report += "</html>";
1555 
1556  CREReportDisplay show(report, "Unused archetypes report");
1557  QApplication::restoreOverrideCursor();
1558  show.exec();
1559 }
1560 
1562 {
1563  QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
1564 
1565  QString report;
1566  report += "<html>";
1567 
1568  auto all = LicenseManager::get()->getAll();
1569  std::set<std::string> faces, facesets;
1570 
1571  for (auto item : all)
1572  {
1573  faces.insert(item.first);
1574  for (auto fs : item.second)
1575  {
1576  facesets.insert(fs.first);
1577  }
1578  }
1579 
1580  getManager()->facesets()->each([&facesets] (const face_sets *fs)
1581  {
1582  facesets.erase(fs->prefix);
1583  });
1584  getManager()->faces()->each([&faces] (const Face *face)
1585  {
1587  });
1588 
1589  if (facesets.empty())
1590  {
1591  report += "<h1>No invalid faceset</h1>\n";
1592  }
1593  else
1594  {
1595  report += "<h1>Invalid faceset found</h1>\n";
1596  report += "<p>The faceset of the license file doesn't match any defined facesets.</p>";
1597  report += "<ul>\n";
1598  for (auto fs : facesets)
1599  {
1600  report += "<li>" + QString(fs.c_str()) + "</li>\n";
1601  }
1602  report += "</ul>\n";
1603  }
1604 
1605  if (faces.empty())
1606  {
1607  report += "<h1>No invalid face name</h1>\n";
1608  }
1609  else
1610  {
1611  report += "<h1>Invalid face names found</h1>\n";
1612  report += "<p>The face name from the license file doesn't match any defined face.</p>";
1613  report += "<ul>\n";
1614  for (auto f : faces)
1615  {
1616  report += "<li>" + QString(f.c_str()) + "</li>\n";
1617  }
1618  report += "</ul>\n";
1619  }
1620 
1621  report += "</html>";
1622  CREReportDisplay show(report, "Licenses checks");
1623  QApplication::restoreOverrideCursor();
1624  show.exec();
1625 }
1626 
1628 {
1630  edit.exec();
1631 }
1632 
1634 {
1635  CRESmoothFaceMaker smooth;
1636  smooth.exec();
1637 }
1638 
1640 {
1641  CRECombatSimulator simulator;
1642  simulator.exec();
1643 }
1644 
1646 {
1647  CREHPBarMaker maker;
1648  maker.exec();
1649 }
1650 
1652 {
1653  FaceMakerDialog maker(this, myResourcesManager);
1654  maker.exec();
1655 }
1656 
1658 {
1659  QMessageBox confirm;
1660  confirm.setWindowTitle(tr("Crossfire Resource Editor"));
1661  confirm.setText("Really clear map cache?");
1662  confirm.setInformativeText("This will force cache rebuild at next application start.");
1663  confirm.setStandardButtons(QMessageBox::Yes | QMessageBox::No);
1664  confirm.setDefaultButton(QMessageBox::No);
1665  confirm.setIcon(QMessageBox::Question);
1666  if (confirm.exec() == QMessageBox::Yes)
1667  {
1669  }
1670 }
1671 
1673 {
1674  CREPixmap::setFaceset(action->data().toString());
1675 }
1676 
1678 {
1680 }
1681 
1683 {
1684  QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
1688  QApplication::restoreOverrideCursor();
1689  QMessageBox::information(this, "Reload complete", "Assets reload complete, you may need to change the selected item to see updated versions.");
1690 }
1691 
1693  auto windows = myArea->subWindowList();
1694  bool hasWindows = !windows.empty();
1695 
1696  while (myWindows->actions().size() > 5) {
1697  myWindows->removeAction(myWindows->actions()[5]);
1698  }
1699  for (auto a : myWindows->actions()) {
1700  if (a->isSeparator()) {
1701  a->setVisible(hasWindows);
1702  } else {
1703  a->setEnabled(hasWindows);
1704  }
1705  }
1706 
1707  for (int i = 0; i < windows.size(); ++i) {
1708  QMdiSubWindow *mdiSubWindow = windows.at(i);
1709 
1710  QString title(mdiSubWindow->widget()->windowTitle());
1711  if (i < 9) {
1712  title = tr("&%1 %2").arg(i + 1).arg(title);
1713  } else {
1714  title = tr("%1 %2").arg(i + 1).arg(title);
1715  }
1716  QAction *action = myWindows->addAction(title, mdiSubWindow, [this, mdiSubWindow] () {
1717  myArea->setActiveSubWindow(mdiSubWindow);
1718  });
1719  action->setCheckable(true);
1720  action ->setChecked(mdiSubWindow == myArea->activeSubWindow());
1721  }
1722 }
object_was_destroyed
#define object_was_destroyed(op, old_tag)
Definition: object.h:68
DisplayMaps
@ DisplayMaps
Definition: CREResourcesWindow.h:26
obj::weapon_speed
float weapon_speed
Definition: object.h:332
recipestruct::arch_names
size_t arch_names
Definition: recipe.h:12
Face::name
sstring name
Definition: face.h:19
ScriptFileManager
Definition: ScriptFileManager.h:10
CREPixmap::setFaceset
static void setFaceset(const QString &prefix)
Definition: CREPixmap.cpp:34
Face
Definition: face.h:14
PLAYER
@ PLAYER
Definition: object.h:107
CREMainWindow::onSaveFormulae
void onSaveFormulae()
Definition: CREMainWindow.cpp:293
global.h
make_face_from_files.anims
list anims
Definition: make_face_from_files.py:52
displayNames
const char * displayNames[]
Definition: CREMainWindow.cpp:145
CREMainWindow::browsingMap
void browsingMap(const QString &path)
Definition: CREMainWindow.cpp:309
get_formulalist
recipelist * get_formulalist(int i)
Definition: recipe.c:96
liv::dam
int16_t dam
Definition: living.h:46
object_free
void object_free(object *ob, int flags)
Definition: object.c:1565
DisplayQuests
@ DisplayQuests
Definition: CREResourcesWindow.h:27
banquet.l
l
Definition: banquet.py:164
GeneralMessage
Definition: book.h:44
object_remove
void object_remove(object *op)
Definition: object.c:1806
MAP
@ MAP
Definition: object.h:125
CREMainWindow::closeEvent
void closeEvent(QCloseEvent *event)
Definition: CREMainWindow.cpp:62
CREMainWindow::onReportAlchemyGraph
void onReportAlchemyGraph()
Definition: CREMainWindow.cpp:694
Settings::max_level
int16_t max_level
Definition: global.h:298
CREMainWindow::myClearMapCache
QAction * myClearMapCache
Definition: CREMainWindow.h:51
obj::face
const Face * face
Definition: object.h:334
FABS
#define FABS(x)
Definition: define.h:22
CREMainWindow::onFiltersModified
void onFiltersModified()
Definition: CREMainWindow.cpp:325
maps
static std::unordered_map< std::string, mapzone * > maps
Definition: citylife.cpp:93
EVENT_CONNECTOR
@ EVENT_CONNECTOR
Definition: object.h:227
monsterFight
static int monsterFight(archetype *monster, archetype *skill, int level)
Definition: CREMainWindow.cpp:845
CREMainWindow::myReportQuests
QAction * myReportQuests
Definition: CREMainWindow.h:46
ResourcesManager::archetypeUse
static void archetypeUse(const archt *item, CREMapInformationManager *store, AssetUseCallback callback)
Definition: ResourcesManager.cpp:93
SET_FLAG
#define SET_FLAG(xyz, p)
Definition: define.h:224
AssetsManager::messages
Messages * messages()
Definition: AssetsManager.h:59
CREResourcesWindow
Definition: CREResourcesWindow.h:35
spellsTable
static QString spellsTable(const QString &skill)
Definition: CREMainWindow.cpp:780
ScriptFileManager.h
obj::count
tag_t count
Definition: object.h:300
obj::map
struct mapdef * map
Definition: object.h:298
CREPixmap::setUseFacesetFallback
static void setUseFacesetFallback(bool use)
Definition: CREPixmap.cpp:42
QUERY_FLAG
#define QUERY_FLAG(xyz, p)
Definition: define.h:226
MessageManager.h
ResourcesManager
Definition: ResourcesManager.h:28
archininventory.arch
arch
DIALOGCHECK MINARGS 1 MAXARGS 1
Definition: archininventory.py:16
obj::race
sstring race
Definition: object.h:319
AssetsManager.h
archt::tail_x
int8_t tail_x
Definition: object.h:473
types
type_definition ** types
Definition: gridarta-types-convert.c:56
liv::wc
int8_t wc
Definition: living.h:37
CREMainWindow::onOpenExperience
void onOpenExperience()
Definition: CREMainWindow.cpp:253
CREMapInformationManager::start
void start()
Definition: CREMapInformationManager.cpp:73
Settings::datadir
const char * datadir
Definition: global.h:244
DisplayAll
@ DisplayAll
Definition: CREResourcesWindow.h:19
MessageManager::loadMessages
void loadMessages()
Definition: MessageManager.cpp:23
disinfect.a
a
Definition: disinfect.py:13
FaceMakerDialog.h
liv::maxhp
int16_t maxhp
Definition: living.h:41
pl::socket
socket_struct socket
Definition: player.h:94
pl
Definition: player.h:92
cleanup
void cleanup(void)
Definition: server.c:1230
CREMapInformationManager::clearCache
void clearCache()
Definition: CREMapInformationManager.cpp:777
guildoracle.list
list
Definition: guildoracle.py:87
report.report
def report(pl)
Definition: report.py:6
AssetsManager::animations
AllAnimations * animations()
Definition: AssetsManager.h:49
python_event.path
path
Definition: python_event.py:11
liv::hp
int16_t hp
Definition: living.h:40
CREPixmap::getIcon
static QIcon getIcon(uint16_t faceNumber)
Definition: CREPixmap.cpp:55
CREMainWindow::createMenus
void createMenus()
Definition: CREMainWindow.cpp:181
DisplayAnimations
@ DisplayAnimations
Definition: CREResourcesWindow.h:21
ArchetypeUse
ArchetypeUse
Definition: ResourcesManager.h:17
obj::range_modifier
uint8_t range_modifier
Definition: object.h:410
mapdef::in_memory
uint32_t in_memory
Definition: map.h:344
CREMainWindow::myReportPlayer
QAction * myReportPlayer
Definition: CREMainWindow.h:44
mad_mage_user.file
file
Definition: mad_mage_user.py:15
recipestruct::title
sstring title
Definition: recipe.h:11
MIN
#define MIN(x, y)
Definition: compat.h:21
first_artifactlist
EXTERN artifactlist * first_artifactlist
Definition: global.h:118
move_player
int move_player(object *op, int dir)
Definition: player.c:2912
pl::ob
object * ob
Definition: player.h:162
hall_of_fame.keys
keys
Definition: hall_of_fame.py:43
archt::tail_y
int8_t tail_y
Definition: object.h:473
SKILL
@ SKILL
Definition: object.h:143
monster_do_living
void monster_do_living(object *op)
Definition: monster.c:688
DisplayScripts
@ DisplayScripts
Definition: CREResourcesWindow.h:29
CREMapInformationManager::allMaps
QList< CREMapInformation * > allMaps()
Definition: CREMapInformationManager.cpp:353
LicenseManager::get
static LicenseManager * get()
Definition: LicenseManager.cpp:29
LicenseManager::reset
void reset()
Definition: LicenseManager.h:52
guildbuy.players
list players
Definition: guildbuy.py:17
done
int done
Definition: readable.c:1607
CREMainWindow::onSaveQuests
void onSaveQuests()
Definition: CREMainWindow.cpp:297
materialt
EXTERN materialtype_t * materialt
Definition: material.h:42
levels
int64_t * levels
Definition: exp.c:26
NROFATTACKS
#define NROFATTACKS
Definition: attack.h:17
curse_on_apply.ac
ac
Definition: curse_on_apply.py:4
ResourcesManager::saveQuests
void saveQuests()
Definition: ResourcesManager.cpp:181
CREMainWindow::onReportMaterials
void onReportMaterials()
Definition: CREMainWindow.cpp:1468
recipestruct::ingred_count
int ingred_count
Definition: recipe.h:23
FLAG_APPLIED
#define FLAG_APPLIED
Definition: define.h:235
DisplayTreasures
@ DisplayTreasures
Definition: CREResourcesWindow.h:22
DisplayGeneralMessages
@ DisplayGeneralMessages
Definition: CREResourcesWindow.h:31
getManager
AssetsManager * getManager()
Definition: assets.cpp:329
recipestruct::chance
int chance
Definition: recipe.h:14
face_sets::prefix
char * prefix
Definition: image.h:19
DisplayArtifacts
@ DisplayArtifacts
Definition: CREResourcesWindow.h:24
AssetsCollection::find
T * find(const Key &name)
Definition: AssetsCollection.h:85
CREMainWindow::myMapBrowseStatus
QLabel * myMapBrowseStatus
Definition: CREMainWindow.h:53
CREMainWindow::onReportLicenses
void onReportLicenses()
Definition: CREMainWindow.cpp:1561
obj::duration_modifier
uint8_t duration_modifier
Definition: object.h:408
obj::duration
int16_t duration
Definition: object.h:407
LicenseManager.h
CREMainWindow::onReportSpellDamage
void onReportSpellDamage()
Definition: CREMainWindow.cpp:520
linked_char
Definition: global.h:86
CREMainWindow::myResourcesManager
ResourcesManager * myResourcesManager
Definition: CREMainWindow.h:56
archt
Definition: object.h:468
settings
struct Settings settings
Definition: init.c:39
object_get_value
const char * object_get_value(const object *op, const char *const key)
Definition: object.c:4354
displayTips
const char * displayTips[]
Definition: CREMainWindow.cpp:163
CREMapInformation
Definition: CREMapInformation.h:13
quest
Definition: quest.py:1
CREMainWindow::onSaveMessages
void onSaveMessages()
Definition: CREMainWindow.cpp:303
recipestruct
Definition: recipe.h:10
pl::savebed_map
char savebed_map[MAX_BUF]
Definition: player.h:97
MAP_IN_MEMORY
#define MAP_IN_MEMORY
Definition: map.h:131
CREMainWindow::onToolCombatSimulator
void onToolCombatSimulator()
Definition: CREMainWindow.cpp:1639
CREHPBarMaker
Definition: CREHPBarMaker.h:10
CREMainWindow::updateReports
void updateReports()
is_valid_types_gen.line
line
Definition: is_valid_types_gen.py:34
SP_BULLET
#define SP_BULLET
Definition: spells.h:79
disinfect.map
map
Definition: disinfect.py:4
titlestruct
Definition: readable.c:107
obj::name
sstring name
Definition: object.h:312
EditMonstersDialog.h
SK_TWO_HANDED_WEAPON
@ SK_TWO_HANDED_WEAPON
Definition: skills.h:56
CREExperienceWindow.h
buildShopReport
static QString buildShopReport(const QString &title, const QStringList &types, const QList< CREMapInformation * > &maps, QStringList &items)
Definition: CREMainWindow.cpp:1250
DisplayMessage
@ DisplayMessage
Definition: CREResourcesWindow.h:28
DisplayMode
DisplayMode
Definition: CREResourcesWindow.h:18
CREMainWindow::onToolFaceset
void onToolFaceset(QAction *action)
Definition: CREMainWindow.cpp:1672
ResourcesManager::load
void load()
Definition: ResourcesManager.cpp:36
artifactstruct::next
struct artifactstruct * next
Definition: artifact.h:18
CRECombatSimulator.h
CREMainWindow::onWindowsShowing
void onWindowsShowing()
Definition: CREMainWindow.cpp:1692
recipestruct::arch_name
char ** arch_name
Definition: recipe.h:13
CRESettings.h
obj::speed_left
float speed_left
Definition: object.h:331
CREMainWindow::onToolFacesetUseFallback
void onToolFacesetUseFallback()
Definition: CREMainWindow.cpp:1677
convert.action
action
Definition: convert.py:25
DisplayArchetypes
@ DisplayArchetypes
Definition: CREResourcesWindow.h:20
AssetsManager::quests
Quests * quests()
Definition: AssetsManager.h:71
AssetsManager::faces
Faces * faces()
Definition: AssetsManager.h:39
CREMainWindow::browsingFinished
void browsingFinished()
Definition: CREMainWindow.cpp:314
CREMainWindow::fillFacesets
void fillFacesets()
Definition: CREMainWindow.cpp:260
LicenseManager::licenseNameFromFaceName
static std::string licenseNameFromFaceName(const std::string &face)
Definition: LicenseManager.cpp:90
fix_object
void fix_object(object *op)
Definition: living.c:1126
recipestruct::exp
int exp
Definition: recipe.h:17
object_create_arch
object * object_create_arch(archetype *at)
Definition: arch.cpp:301
CREReportDisplay.h
linked_char::next
struct linked_char * next
Definition: global.h:88
artifactliststruct
Definition: artifact.h:26
obj::other_arch
struct archt * other_arch
Definition: object.h:417
CREMainWindow::onToolReloadAssets
void onToolReloadAssets()
Definition: CREMainWindow.cpp:1682
CREMainWindow::createActions
void createActions()
Definition: CREMainWindow.cpp:86
player
struct pl player
sstring
const typedef char * sstring
Definition: global.h:40
disinfect.count
int count
Definition: disinfect.py:7
obj::speed
float speed
Definition: object.h:330
say.max
dictionary max
Definition: say.py:148
MessageManager
Definition: MessageManager.h:12
tag_t
uint32_t tag_t
Definition: object.h:12
liv::Con
int8_t Con
Definition: living.h:36
CREMainWindow::myScriptManager
ScriptFileManager * myScriptManager
Definition: CREMainWindow.h:57
AssetsCollection::get
T * get(const Key &name)
Definition: AssetsCollection.h:66
sproto.h
recipeliststruct
Definition: recipe.h:37
AssetsCollection::each
void each(std::function< void(T *)> op)
Definition: AssetsCollection.h:135
animate.anim
string anim
Definition: animate.py:20
IS_COMBAT_SKILL
#define IS_COMBAT_SKILL(num)
Definition: skills.h:91
displayModes
const DisplayMode displayModes[]
Definition: CREMainWindow.cpp:127
mapdef
Definition: map.h:324
AssetsManager::facesets
Facesets * facesets()
Definition: AssetsManager.h:65
CREMainWindow::mySaveMenu
QMenu * mySaveMenu
Definition: CREMainWindow.h:41
delete_map
void delete_map(mapstruct *m)
Definition: map.c:1716
CREMainWindow::myMapManager
CREMapInformationManager * myMapManager
Definition: CREMainWindow.h:54
obj::animation
const Animations * animation
Definition: object.h:420
CREMainWindow::onToolEditMonsters
void onToolEditMonsters()
Definition: CREMainWindow.cpp:1627
image.h
pl::bed_x
int16_t bed_x
Definition: player.h:98
ASSETS_ALL
#define ASSETS_ALL
Definition: assets.h:35
FLAG_MONSTER
#define FLAG_MONSTER
Definition: define.h:245
recipestruct::ingred
linked_char * ingred
Definition: recipe.h:22
AssetsManager::archetypes
Archetypes * archetypes()
Definition: AssetsManager.h:44
MAX_BUF
#define MAX_BUF
Definition: define.h:35
artifactstruct
Definition: artifact.h:14
CREMapInformationManager.h
CREMainWindow::onReportSpells
void onReportSpells()
Definition: CREMainWindow.cpp:813
CREMainWindow::onReportAlchemy
void onReportAlchemy()
Definition: CREMainWindow.cpp:653
ResourcesManager.h
CREMainWindow::myArea
QMdiArea * myArea
Definition: CREMainWindow.h:35
alchemyTable
static QString alchemyTable(const QString &skill, QStringList &noChance, QStringList &allIngredients)
Definition: CREMainWindow.cpp:569
CREMainWindow::onReportDuplicate
void onReportDuplicate()
Definition: CREMainWindow.cpp:341
create_archetype
object * create_archetype(const char *name)
Definition: arch.cpp:281
CREMainWindow::onOpenResources
void onOpenResources()
Definition: CREMainWindow.cpp:284
CREMainWindow::myFacesetsGroup
QActionGroup * myFacesetsGroup
Definition: CREMainWindow.h:49
CREMainWindow::mySaveFormulae
QAction * mySaveFormulae
Definition: CREMainWindow.h:43
title
struct titlestruct title
Settings::playerdir
const char * playerdir
Definition: global.h:246
CREMainWindow::onReportsModified
void onReportsModified()
Definition: CREMainWindow.cpp:330
CREMainWindow::myToolsMenu
QMenu * myToolsMenu
Definition: CREMainWindow.h:48
recipestruct::skill
sstring skill
Definition: recipe.h:26
test_map
mapstruct * test_map
Definition: comet_perf.c:74
animations_struct::name
sstring name
Definition: face.h:26
pl::bed_y
int16_t bed_y
Definition: player.h:98
diamondslots.message
string message
Definition: diamondslots.py:57
CRESmoothFaceMaker
Definition: CRESmoothFaceMaker.h:11
make_face_from_files.out
out
Definition: make_face_from_files.py:74
obj::type
uint8_t type
Definition: object.h:341
DisplayFacesets
@ DisplayFacesets
Definition: CREResourcesWindow.h:32
obj::stats
living stats
Definition: object.h:371
report
Definition: report.py:1
archt::clone
object clone
Definition: object.h:472
obj::contr
struct pl * contr
Definition: object.h:277
DisplayFormulae
@ DisplayFormulae
Definition: CREResourcesWindow.h:23
item
Definition: item.py:1
DisplayRandomMaps
@ DisplayRandomMaps
Definition: CREResourcesWindow.h:30
readDirectory
void readDirectory(const QString &path, QHash< QString, QHash< QString, bool > > &states)
Definition: CREMainWindow.cpp:1354
CREMainWindow::onReportSummon
void onReportSummon()
Definition: CREMainWindow.cpp:1189
guildbuy.names
list names
Definition: guildbuy.py:18
CRESettings
Definition: CRESettings.h:9
CREExperienceWindow
Definition: CREExperienceWindow.h:6
find_archetype
archetype * find_archetype(const char *name)
Definition: assets.cpp:278
CREMainWindow::commitData
void commitData()
obj::weapon_speed_left
float weapon_speed_left
Definition: object.h:333
CREMainWindow::onReportShops
void onReportShops()
Definition: CREMainWindow.cpp:1306
EditMonstersDialog
Definition: EditMonstersDialog.h:10
attacktype_desc
const EXTERN char *const attacktype_desc[NROFATTACKS]
Definition: attack.h:138
CREMainWindow::myMessageManager
MessageManager * myMessageManager
Definition: CREMainWindow.h:55
assets.h
mapdef::reset_time
uint32_t reset_time
Definition: map.h:331
CREMapInformationManager::cancel
void cancel()
Definition: CREMapInformationManager.cpp:347
recipestruct::next
struct recipestruct * next
Definition: recipe.h:24
object_insert_in_ob
object * object_insert_in_ob(object *op, object *where)
Definition: object.c:2820
get_typedata
const typedata * get_typedata(int itemtype)
Definition: item.c:319
dragon_attune.faces
dictionary faces
Definition: dragon_attune.py:31
CREMainWindow::updateFilters
void updateFilters()
obj::subtype
uint8_t subtype
Definition: object.h:342
socket_struct::faces_sent
uint8_t * faces_sent
Definition: newserver.h:96
recipestruct::diff
int diff
Definition: recipe.h:16
CREHPBarMaker.h
artifactstruct::item
object * item
Definition: artifact.h:15
castle_read.key
key
Definition: castle_read.py:64
CREMainWindow::CREMainWindow
CREMainWindow()
Definition: CREMainWindow.cpp:29
liv::ac
int8_t ac
Definition: living.h:38
obj::skill
sstring skill
Definition: object.h:322
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.c:2067
object_free_drop_inventory
void object_free_drop_inventory(object *ob)
Definition: object.c:1533
CREMainWindow::myReportArchetypes
QAction * myReportArchetypes
Definition: CREMainWindow.h:47
animate.event
event
DIALOGCHECK MINARGS 1 MAXARGS 2
Definition: animate.py:17
CREMainWindow::myOpenMenu
QMenu * myOpenMenu
Definition: CREMainWindow.h:40
monsterTable
static QString monsterTable(archetype *monster, QList< archetype * > skills)
Definition: CREMainWindow.cpp:1036
CREMainWindow::myToolFacesetUseFallback
QAction * myToolFacesetUseFallback
Definition: CREMainWindow.h:50
CREMainWindow::onReportArchetypes
void onReportArchetypes()
Definition: CREMainWindow.cpp:1513
face_sets::fullname
char * fullname
Definition: image.h:20
do_some_living
void do_some_living(object *op)
Definition: player.c:3236
SP_SUMMON_GOLEM
#define SP_SUMMON_GOLEM
Definition: spells.h:86
level
int level
Definition: readable.c:1604
CREMainWindow::onReportPlayer
void onReportPlayer()
Definition: CREMainWindow.cpp:1062
FREE_OBJ_FREE_INVENTORY
#define FREE_OBJ_FREE_INVENTORY
Definition: object.h:531
archt::name
sstring name
Definition: object.h:469
CREMainWindow.h
CREMainWindow::doResourceWindow
void doResourceWindow(DisplayMode mode)
Definition: CREMainWindow.cpp:241
assets_collect
void assets_collect(const char *datadir, int what)
Definition: assets.cpp:116
say.item
dictionary item
Definition: say.py:149
reportSummon
static QString reportSummon(const archetype *summon, const object *other, QString name)
Definition: CREMainWindow.cpp:1133
attack_ob
int attack_ob(object *op, object *hitter)
Definition: attack.c:912
connect
Definition: connect.py:1
CREPixmap::clearFaceCache
static void clearFaceCache()
Definition: CREPixmap.cpp:50
get_faces_count
size_t get_faces_count()
Definition: assets.cpp:313
CRESmoothFaceMaker.h
CREMainWindow::onToolBarMaker
void onToolBarMaker()
Definition: CREMainWindow.cpp:1645
CREMapInformationManager
Definition: CREMapInformationManager.h:16
face_sets
Definition: image.h:17
FaceMakerDialog
Definition: FaceMakerDialog.h:11
CREResourcesWindow.h
SPELL
@ SPELL
Definition: object.h:214
CREMainWindow::createAction
QAction * createAction(const QString &title, const QString &statusTip, QObject *target, const char *slot)
Definition: CREMainWindow.cpp:79
quests
static struct_quest ** quests
Definition: mapper.cpp:915
ResourcesManager::hasPendingChanges
bool hasPendingChanges() const
Definition: ResourcesManager.h:53
CREPixmap.h
altar_valkyrie.pl
pl
Definition: altar_valkyrie.py:28
get_empty_map
mapstruct * get_empty_map(int sizex, int sizey)
Definition: map.c:867
DisplayFaces
@ DisplayFaces
Definition: CREResourcesWindow.h:25
CREReportDisplay
Definition: CREReportDisplay.h:7
CREMainWindow::myWindows
QMenu * myWindows
Definition: CREMainWindow.h:52
if
if(!(yy_init))
Definition: loader.c:2589
LicenseManager::getAll
std::map< std::string, LicenseItems > getAll() const
Definition: LicenseManager.h:47
CREMainWindow::onReportQuests
void onReportQuests()
Definition: CREMainWindow.cpp:1397
CRECombatSimulator
Definition: CRECombatSimulator.h:16
ring_occidental_mages.r
r
Definition: ring_occidental_mages.py:6
CREMainWindow::onClearCache
void onClearCache()
Definition: CREMainWindow.cpp:1657
MessageManager::saveMessages
void saveMessages()
Definition: MessageManager.cpp:32
obj::level
int16_t level
Definition: object.h:354
GOD
@ GOD
Definition: object.h:148
treasureliststruct
Definition: treasure.h:82
spell_arrow.spells
spells
Definition: spell_arrow.py:6
determine_holy_arch
archetype * determine_holy_arch(const object *god, const char *type)
Definition: gods.c:739
give.name
name
Definition: give.py:27
has_been_loaded
mapstruct * has_been_loaded(const char *name)
Definition: map.c:88
CREMainWindow::onToolSmooth
void onToolSmooth()
Definition: CREMainWindow.cpp:1633
obj::dam_modifier
uint8_t dam_modifier
Definition: object.h:411
CREMainWindow::myReportShops
QAction * myReportShops
Definition: CREMainWindow.h:45
CREMainWindow::onToolFaceMaker
void onToolFaceMaker()
Definition: CREMainWindow.cpp:1651
recipe
struct recipestruct recipe
level
Definition: level.py:1
Settings::localdir
const char * localdir
Definition: global.h:245