Crossfire Server, Trunk  R21246
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 "QuestManager.h"
8 #include "MessageManager.h"
9 #include "CREReportDisplay.h"
10 #include "CREPixmap.h"
11 #include "CRESmoothFaceMaker.h"
12 #include "CREHPBarMaker.h"
13 #include "ResourcesManager.h"
14 #include "CRECombatSimulator.h"
15 #include "Quest.h"
16 #include "CREHPBarMaker.h"
17 #include "ScriptFileManager.h"
18 
19 extern "C" {
20 #include "global.h"
21 #include "sproto.h"
22 #include "image.h"
23 }
24 
26 {
27  myArea = new QMdiArea();
28  setCentralWidget(myArea);
29 
30  createActions();
31  createMenus();
32 
33  statusBar()->showMessage(tr("Ready"));
34  myMapBrowseStatus = new QLabel(tr("Browsing maps..."));
35  statusBar()->addPermanentWidget(myMapBrowseStatus);
36 
37  setWindowTitle(tr("Crossfire Resource Editor"));
38 
41 
44 
47 
49 
51  connect(myMapManager, SIGNAL(browsingMap(const QString&)), this, SLOT(browsingMap(const QString&)));
52  connect(myMapManager, SIGNAL(finished()), this, SLOT(browsingFinished()));
54 }
55 
56 void CREMainWindow::closeEvent(QCloseEvent* event)
57 {
59  delete myMapManager;
60  delete myQuestManager;
61  delete myMessageManager;
62  delete myResourcesManager;
63  cleanup();
64  QMainWindow::closeEvent(event);
65 }
66 
68 {
69  myOpenArtifacts = new QAction(tr("Artifacts"), this);
70  myOpenArtifacts->setStatusTip(tr("List all defined artifacts."));
71  connect(myOpenArtifacts, SIGNAL(triggered()), this, SLOT(onOpenArtifacts()));
72 
73  myOpenArchetypes = new QAction(tr("Archetypes"), this);
74  myOpenArchetypes->setStatusTip(tr("List all defined archetypes."));
75  connect(myOpenArchetypes, SIGNAL(triggered()), this, SLOT(onOpenArchetypes()));
76 
77  myOpenTreasures = new QAction(tr("Treasures"), this);
78  myOpenTreasures->setStatusTip(tr("List all defined treasure lists."));
79  connect(myOpenTreasures, SIGNAL(triggered()), this, SLOT(onOpenTreasures()));
80 
81  myOpenAnimations = new QAction(tr("Animations"), this);
82  myOpenAnimations->setStatusTip(tr("List all defined animations."));
83  connect(myOpenAnimations, SIGNAL(triggered()), this, SLOT(onOpenAnimations()));
84 
85  myOpenFormulae = new QAction(tr("Formulae"), this);
86  myOpenFormulae->setStatusTip(tr("List all defined alchemy recipes."));
87  connect(myOpenFormulae, SIGNAL(triggered()), this, SLOT(onOpenFormulae()));
88 
89  myOpenResources = new QAction(tr("Resources"), this);
90  myOpenResources->setStatusTip(tr("List all defined elements, except experience table."));
91  connect(myOpenResources, SIGNAL(triggered()), this, SLOT(onOpenResources()));
92 
93  myOpenFaces = new QAction(tr("Faces"), this);
94  myOpenFaces->setStatusTip(tr("List all defined faces."));
95  connect(myOpenFaces, SIGNAL(triggered()), this, SLOT(onOpenFaces()));
96 
97  myOpenMaps = new QAction(tr("Maps"), this);
98  myOpenMaps->setStatusTip(tr("List all maps, with their region."));
99  connect(myOpenMaps, SIGNAL(triggered()), this, SLOT(onOpenMaps()));
100 
101  myOpenQuests = new QAction(tr("Quests"), this);
102  myOpenQuests->setStatusTip(tr("List all defined quests."));
103  connect(myOpenQuests, SIGNAL(triggered()), this, SLOT(onOpenQuests()));
104 
105  myOpenMessages = new QAction(tr("NPC dialogs"), this);
106  myOpenMessages->setStatusTip(tr("List all NPC dialogs in files."));
107  connect(myOpenMessages, SIGNAL(triggered()), this, SLOT(onOpenMessages()));
108 
109  myOpenExperience = new QAction(tr("Experience"), this);
110  myOpenExperience->setStatusTip(tr("Display the experience table."));
111  connect(myOpenExperience, SIGNAL(triggered()), this, SLOT(onOpenExperience()));
112 
113  myOpenScripts = new QAction(tr("Scripts"), this);
114  myOpenExperience->setStatusTip(tr("List all scripts references in maps."));
115  connect(myOpenScripts, SIGNAL(triggered()), this, SLOT(onOpenScripts()));
116 
117  myOpenRandomMaps = new QAction(tr("Random maps"), this);
118  myOpenRandomMaps->setStatusTip(tr("List all random maps."));
119  connect(myOpenRandomMaps, SIGNAL(triggered()), this, SLOT(onOpenRandomMaps()));
120 
121  mySaveFormulae = new QAction(tr("Formulae"), this);
122  mySaveFormulae->setEnabled(false);
123  connect(mySaveFormulae, SIGNAL(triggered()), this, SLOT(onSaveFormulae()));
124 
125  mySaveQuests = new QAction(tr("Quests"), this);
126  mySaveQuests->setStatusTip(tr("Save all modified quests to disk."));
127  connect(mySaveQuests, SIGNAL(triggered()), this, SLOT(onSaveQuests()));
128 
129  mySaveMessages = new QAction(tr("Dialogs"), this);
130  mySaveMessages->setStatusTip(tr("Save all modified NPC dialogs."));
131  connect(mySaveMessages, SIGNAL(triggered()), this, SLOT(onSaveMessages()));
132 
133  myReportDuplicate = new QAction(tr("Faces and animations report"), this);
134  myReportDuplicate->setStatusTip(tr("Show faces and animations which are used by multiple archetypes, or not used."));
135  connect(myReportDuplicate, SIGNAL(triggered()), this, SLOT(onReportDuplicate()));
136 
137  myReportSpellDamage = new QAction(tr("Spell damage"), this);
138  myReportSpellDamage->setStatusTip(tr("Display spell damage by level (bullet spells only for now)"));
139  connect(myReportSpellDamage, SIGNAL(triggered()), this, SLOT(onReportSpellDamage()));
140 
141  myReportAlchemy = new QAction(tr("Alchemy"), this);
142  myReportAlchemy->setStatusTip(tr("Display alchemy formulae, in a table."));
143  connect(myReportAlchemy, SIGNAL(triggered()), this, SLOT(onReportAlchemy()));
144 
145  myReportSpells = new QAction(tr("Spells"), this);
146  myReportSpells->setStatusTip(tr("Display all spells, in a table."));
147  connect(myReportSpells, SIGNAL(triggered()), this, SLOT(onReportSpells()));
148 
149  myReportPlayer = new QAction(tr("Player vs monsters"), this);
150  myReportPlayer->setStatusTip(tr("Compute statistics related to player vs monster combat."));
151  // can't use that while map browsing is running ; will be enabled in browsingFinished()
152  myReportPlayer->setEnabled(false);
153  connect(myReportPlayer, SIGNAL(triggered()), this, SLOT(onReportPlayer()));
154 
155  myReportSummon = new QAction(tr("Summoned pets statistics"), this);
156  myReportSummon->setStatusTip(tr("Display wc, hp, speed and other statistics for summoned pets."));
157  connect(myReportSummon, SIGNAL(triggered()), this, SLOT(onReportSummon()));
158 
159  myReportShops = new QAction(tr("Shop specialization"), this);
160  myReportShops->setStatusTip(tr("Display the list of shops and their specialization for items."));
161  // can't use that while map browsing is running ; will be enabled in browsingFinished()
162  myReportShops->setEnabled(false);
163  connect(myReportShops, SIGNAL(triggered()), this, SLOT(onReportShops()));
164 
165  myReportQuests = new QAction(tr("Quest solved by players"), this);
166  myReportQuests->setStatusTip(tr("Display quests the players have solved."));
167  // can't use that while map browsing is running ; will be enabled in browsingFinished()
168  myReportQuests->setEnabled(false);
169  connect(myReportQuests, SIGNAL(triggered()), this, SLOT(onReportQuests()));
170 
171  myToolSmooth = new QAction(tr("Generate smooth face base"), this);
172  myToolSmooth->setStatusTip(tr("Generate the basic smoothed picture for a face."));
173  connect(myToolSmooth, SIGNAL(triggered()), this, SLOT(onToolSmooth()));
174 
175  myToolHPBar = new QAction(tr("Generate HP bar"), this);
176  myToolHPBar->setStatusTip(tr("Generate faces for a HP bar."));
177  connect(myToolHPBar, SIGNAL(triggered()), this, SLOT(onToolBarMaker()));
178 
179  myToolCombatSimulator = new QAction(tr("Combat simulator"), this);
180  myToolCombatSimulator->setStatusTip(tr("Simulate fighting between two objects."));
181  connect(myToolCombatSimulator, SIGNAL(triggered()), this, SLOT(onToolCombatSimulator()));
182 
183  myClearMapCache = new QAction(tr("Clear map cache"), this);
184  myClearMapCache->setStatusTip(tr("Force a refresh of all map information at next start."));
185  connect(myClearMapCache, SIGNAL(triggered()), this, SLOT(onClearCache()));
186  /* can't clear map cache while collecting information */
187  myClearMapCache->setEnabled(false);
188 }
189 
191 {
192  myOpenMenu = menuBar()->addMenu(tr("&Open"));
193  myOpenMenu->addAction(myOpenResources);
194  myOpenMenu->addAction(myOpenArtifacts);
195  myOpenMenu->addAction(myOpenArchetypes);
196  myOpenMenu->addAction(myOpenTreasures);
197  myOpenMenu->addAction(myOpenAnimations);
198  myOpenMenu->addAction(myOpenFormulae);
199  myOpenMenu->addAction(myOpenFaces);
200  myOpenMenu->addAction(myOpenMaps);
201  myOpenMenu->addAction(myOpenQuests);
202  myOpenMenu->addAction(myOpenMessages);
203  myOpenMenu->addAction(myOpenExperience);
204  myOpenMenu->addAction(myOpenScripts);
205  myOpenMenu->addAction(myOpenRandomMaps);
206  myOpenMenu->addSeparator();
207  QAction* exit = myOpenMenu->addAction(tr("&Exit"));
208  exit->setStatusTip(tr("Close the application."));
209  connect(exit, SIGNAL(triggered()), this, SLOT(close()));
210 
211  mySaveMenu = menuBar()->addMenu(tr("&Save"));
212  mySaveMenu->addAction(mySaveFormulae);
213  mySaveMenu->addAction(mySaveQuests);
214  mySaveMenu->addAction(mySaveMessages);
215 
216  QMenu* reportMenu = menuBar()->addMenu("&Reports");
217  reportMenu->addAction(myReportDuplicate);
218  reportMenu->addAction(myReportSpellDamage);
219  reportMenu->addAction(myReportAlchemy);
220  reportMenu->addAction(myReportSpells);
221  reportMenu->addAction(myReportPlayer);
222  reportMenu->addAction(myReportSummon);
223  reportMenu->addAction(myReportShops);
224  reportMenu->addAction(myReportQuests);
225 
226  QMenu* toolsMenu = menuBar()->addMenu("&Tools");
227  toolsMenu->addAction(myToolSmooth);
228  toolsMenu->addAction(myToolHPBar);
229  toolsMenu->addAction(myToolCombatSimulator);
230  toolsMenu->addAction(myClearMapCache);
231 }
232 
234 {
236  connect(this, SIGNAL(updateFilters()), resources, SLOT(updateFilters()));
237  connect(resources, SIGNAL(filtersModified()), this, SLOT(onFiltersModified()));
238  connect(this, SIGNAL(updateReports()), resources, SLOT(updateReports()));
239  connect(resources, SIGNAL(reportsModified()), this, SLOT(onReportsModified()));
240  connect(this, SIGNAL(commitData()), resources, SLOT(commitData()));
241  myArea->addSubWindow(resources);
242  resources->show();
243 }
244 
246 {
248 }
249 
251 {
253 }
254 
256 {
258 }
259 
261 {
263 }
264 
266 {
268 }
269 
271 {
273 }
274 
276 {
278 }
279 
281 {
283 }
284 
286 {
288 }
289 
291 {
293 }
294 
296 {
297  QWidget* experience = new CREExperienceWindow();
298  myArea->addSubWindow(experience);
299  experience->show();
300 }
301 
303 {
305 }
306 
308 {
310 }
311 
313 {
314 }
315 
317 {
318  emit commitData();
320 }
321 
323 {
324  emit commitData();
326 }
327 
328 void CREMainWindow::browsingMap(const QString& path)
329 {
330  myMapBrowseStatus->setText(tr("Browsing map %1").arg(path));
331 }
332 
334 {
335  statusBar()->showMessage(tr("Finished browsing maps."), 5000);
336  myMapBrowseStatus->setVisible(false);
337  myReportPlayer->setEnabled(true);
338  myReportShops->setEnabled(true);
339  myReportQuests->setEnabled(true);
340  myClearMapCache->setEnabled(true);
341 }
342 
344 {
345  emit updateFilters();
346 }
347 
349 {
350  emit updateReports();
351 }
352 
360 {
361  QHash<QString, QStringList> faces, anims;
362 
363  // browse all archetypes
364  archetype* arch = first_archetype;
365 
366  while (arch != NULL)
367  {
368  // if there is an animation, don't consider the face, since it's part of the animation anyway (hopefully)
369  if (arch->clone.animation_id == 0)
370  {
371  faces[QString::fromLatin1(arch->clone.face->name)].append(QString(arch->name) + " (arch)");
372  sstring key = object_get_value(&arch->clone, "identified_face");
373  if (key)
374  {
375  faces[QString(key)].append(QString(arch->name) + " (arch)");
376  }
377  }
378  else
379  {
380  anims[animations[arch->clone.animation_id].name].append(QString(arch->name) + " (arch)");
381  sstring key = object_get_value(&arch->clone, "identified_animation");
382  if (key)
383  {
384  anims[QString(key)].append(QString(arch->name) + " (arch)");
385  }
386  }
387  arch = arch->next;
388  }
389 
390  // list faces in animations
391  QStringList allAnims = myResourcesManager->allAnimations();
392  foreach(QString name, allAnims)
393  {
394  QStringList done;
395  const animations_struct* anim = myResourcesManager->animation(name);
396  for (int i = 0; i < anim->num_animations; i++)
397  {
398  // don't list animation twice if they use the same face
399  if (!done.contains(QString::fromLatin1(anim->faces[i]->name)))
400  {
401  faces[QString::fromLatin1(anim->faces[i]->name)].append(QString(anim->name) + " (animation)");
402  done.append(QString::fromLatin1(anim->faces[i]->name));
403  }
404  }
405  }
406 
407  // list faces and animations for artifacts
408  artifactlist* list;
409  artifact* art;
410  for (list = first_artifactlist; list != NULL; list = list->next)
411  {
412  for (art = list->items; art != NULL; art = art->next)
413  {
414  if (art->item->animation_id == 0)
415  {
416  faces[QString::fromLatin1(art->item->face->name)].append(QString(art->item->name) + " (art)");
417  sstring key = object_get_value(art->item, "identified_face");
418  if (key)
419  {
420  faces[QString(key)].append(QString(art->item->name) + " (art)");
421  }
422  }
423  else
424  {
425  anims[animations[art->item->animation_id].name].append(QString(art->item->name) + " (art)");
426  sstring key = object_get_value(art->item, "identified_animation");
427  if (key)
428  {
429  anims[QString(key)].append(QString(art->item->name) + " (arch)");
430  }
431  }
432  }
433  }
434 
435  QString report("<p><strong>Warning:</strong> this list doesn't take into account faces for all artifacts, especially the 'animation_suffix' ones. Also, faces and archetypes defined in maps will not be taken into account in this list.</p><h1>Faces used multiple times:</h1><ul>");
436 
437  QStringList keys = faces.keys();
438  keys.sort();
439  foreach(QString name, keys)
440  {
441  if (faces[name].size() <= 1 || name.compare("blank.111") == 0)
442  continue;
443 
444  faces[name].sort();
445  report += "<li>" + name + ": ";
446  report += faces[name].join(", ");
447  report += "</li>";
448  }
449 
450  report += "</ul>";
451 
452  report += "<h1>Unused faces:</h1><ul>";
453  foreach(QString face, myResourcesManager->faces())
454  {
455  if (faces[face].size() > 0)
456  continue;
457  report += "<li>" + face + "</li>";
458  }
459  report += "</ul>";
460 
461  report += "<h1>Animations used multiple times:</h1><ul>";
462  keys = anims.keys();
463  keys.sort();
464  foreach(QString name, keys)
465  {
466  if (anims[name].size() <= 1)
467  continue;
468 
469  anims[name].sort();
470  report += "<li>" + name + ": ";
471  report += anims[name].join(", ");
472  report += "</li>";
473  }
474  report += "</ul>";
475 
476  report += "<h1>Unused animations:</h1><ul>";
477  foreach(QString anim, myResourcesManager->allAnimations())
478  {
479  if (anims[anim].size() > 0 || anim == "###none")
480  continue;
481  report += "<li>" + anim + "</li>";
482  }
483  report += "</ul>";
484 
485  CREReportDisplay show(report, "Duplicate and unused faces and animations");
486  show.exec();
487 }
488 
490 {
491  QStringList spell;
492  QList<QStringList> damage;
493 
494  archetype* arch = first_archetype;
495  object* caster = create_archetype("orc");
496  int dm, cost;
497 
498  while (arch != NULL)
499  {
500  if (arch->clone.type == SPELL && arch->clone.subtype == SP_BULLET && arch->clone.skill && strcmp(arch->clone.skill, "praying") == 0)
501  {
502  spell.append(arch->clone.name);
503  QStringList dam;
504  for (int l = 0; l < settings.max_level; l++)
505  {
506  caster->level = l;
507  dm = arch->clone.stats.dam + SP_level_dam_adjust(caster, &arch->clone);
508  cost = SP_level_spellpoint_cost(caster, &arch->clone, SPELL_GRACE);
509  dam.append(tr("%1 [%2]").arg(dm).arg(cost));
510  }
511  damage.append(dam);
512  }
513 
514  arch = arch->next;
515  }
517 
518  QString report("<table><thead><tr><th>level</th>");
519 
520  for (int i = 0; i < spell.size(); i++)
521  {
522  report += "<th>" + spell[i] + "</th>";
523  }
524 
525  report += "</tr></thead><tbody>";
526 
527  for (int l = 0; l < settings.max_level; l++)
528  {
529  report += "<tr><td>" + QString::number(l) + "</td>";
530  for (int s = 0; s < spell.size(); s++)
531  report += "<td>" + damage[s][l] + "</td>";
532  report += "</tr>";
533  }
534 
535  report += "</tbody></table>";
536 
537  CREReportDisplay show(report, "Spell damage");
538  show.exec();
539 }
540 
541 static QString alchemyTable(const QString& skill)
542 {
543  int count = 0;
544 
545  QHash<int, QStringList> recipes;
546 
547  const recipelist* list;
548  const recipe* recipe;
549 
550  for (int ing = 1; ; ing++)
551  {
552  list = get_formulalist(ing);
553  if (!list)
554  break;
555 
556  for (recipe = list->items; recipe; recipe = recipe->next)
557  {
558  if (skill == recipe->skill)
559  {
560  if (recipe->arch_names == 0)
561  // hu?
562  continue;
563 
564  const archetype* arch = find_archetype(recipe->arch_name[0]);
565  if (arch == NULL) {
566  continue;
567  }
568 
569  QString name;
570  if (strcmp(recipe->title, "NONE") == 0)
571  {
572  if (arch->clone.title == NULL)
573  name = arch->clone.name;
574  else
575  name = QString("%1 %2").arg(arch->clone.name, arch->clone.title);
576  }
577  else
578  {
579  name = QString("%1 of %2").arg(arch->clone.name, recipe->title);
580  }
581 
582  QStringList ingredients;
583  for (const linked_char* ingred = recipe->ingred; ingred != NULL; ingred = ingred->next)
584  {
585  ingredients.append(ingred->name);
586  }
587 
588  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(", ")));
589  count++;
590  }
591  }
592  }
593 
594  if (count == 0)
595  return QString();
596 
597  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);
598  report += "</tr></thead><tbody>";
599 
600  QList<int> difficulties = recipes.keys();
601  qSort(difficulties);
602  foreach(int difficulty, difficulties)
603  {
604  QStringList line = recipes[difficulty];
605  qSort(line);
606  report += line.join("\n");
607  }
608 
609  report += "</tbody></table>";
610 
611  return report;
612 }
613 
615 {
616  QStringList skills;
617 
618  const archt* arch = first_archetype;
619  for (; arch; arch = arch->next)
620  {
621  if (arch->clone.type == SKILL)
622  skills.append(arch->clone.name);
623  }
624 
625  skills.sort();
626 
627  QString report("<h1>Alchemy formulae</h1>");
628 
629  foreach(const QString skill, skills)
630  {
631  report += alchemyTable(skill);
632  }
633 
634  CREReportDisplay show(report, "Alchemy formulae");
635  show.exec();
636 }
637 
638 static QString spellsTable(const QString& skill)
639 {
640  bool one = false;
641 
642  QString report = QString("<h2>%1</h2><table><thead><tr><th>Spell</th><th>Level</th>").arg(skill);
643  report += "</tr></thead><tbody>";
644 
645  QHash<int, QStringList> spells;
646 
647  const archetype* spell;
648 
649  for (spell = first_archetype; spell; spell = spell->next)
650  {
651  if (spell->clone.type == SPELL && spell->clone.skill == skill)
652  {
653  spells[spell->clone.level].append(QString("<tr><td>%1</td><td>%2</td></tr>").arg(spell->clone.name).arg(spell->clone.level));
654  one = true;
655  }
656  }
657 
658  if (!one)
659  return QString();
660 
661  QList<int> levels = spells.keys();
662  qSort(levels);
663  foreach(int level, levels)
664  {
665  report += spells[level].join("\n");
666  }
667 
668  report += "</tbody></table>";
669 
670  return report;
671 }
672 
674 {
675  QStringList skills;
676 
677  const archt* arch = first_archetype;
678  for (; arch; arch = arch->next)
679  {
680  if (arch->clone.type == SKILL)
681  skills.append(arch->clone.name);
682  }
683 
684  skills.sort();
685 
686  QString report("<h1>Spell list</h1>");
687 
688  foreach(const QString skill, skills)
689  {
690  report += spellsTable(skill);
691  }
692 
693  CREReportDisplay show(report, "Spell list");
694  show.exec();
695 }
696 
706 static int monsterFight(archetype* monster, archetype* skill, int level)
707 {
708  int limit = 50, result = 1;
709  player pl;
710  memset(&pl, 0, sizeof(player));
711  strncpy(pl.savebed_map, "/HallOfSelection", MAX_BUF);
712  pl.bed_x = 5;
713  pl.bed_y = 5;
714  pl.socket.faces_sent = (uint8_t*)calloc(sizeof(uint8_t), nrofpixmaps);
715 
716  archetype *dwarf_player_arch = find_archetype("dwarf_player");
717  if (dwarf_player_arch == NULL) {
718  free(pl.socket.faces_sent);
719  return 0;
720  }
721  object* obfirst = object_create_arch(dwarf_player_arch);
722  obfirst->level = level;
723  obfirst->contr = &pl;
724  pl.ob = obfirst;
725  object* obskill = object_create_arch(skill);
726  obskill->level = level;
727  SET_FLAG(obskill, FLAG_APPLIED);
728  object_insert_in_ob(obskill, obfirst);
729  archetype *skill_arch = find_archetype((skill->clone.subtype == SK_TWO_HANDED_WEAPON) ? "sword_3" : "sword");
730  if (skill_arch == NULL) {
731  free(pl.socket.faces_sent);
732  return 0;
733  }
734  object* sword = object_create_arch(skill_arch);
735  SET_FLAG(sword, FLAG_APPLIED);
736  object_insert_in_ob(sword, obfirst);
737  fix_object(obfirst);
738  obfirst->stats.hp = obfirst->stats.maxhp;
739 
740  object* obsecond = object_create_arch(monster);
741  tag_t tagfirst = obfirst->count;
742  tag_t tagsecond = obsecond->count;
743 
744  // make a big map so large monsters are ok in map
745  mapstruct* test_map = get_empty_map(50, 50);
746 
747  obfirst = object_insert_in_map_at(obfirst, test_map, NULL, 0, 0, 0);
748  obsecond = object_insert_in_map_at(obsecond, test_map, NULL, 0, 1 + monster->tail_x, monster->tail_y);
749 
750  if (!obsecond || object_was_destroyed(obsecond, tagsecond))
751  {
752  qDebug() << "second removed??";
753  }
754 
755  while (limit-- > 0 && obfirst->stats.hp >= 0 && obsecond->stats.hp >= 0)
756  {
757  if (obfirst->weapon_speed_left > 0) {
758  --obfirst->weapon_speed_left;
759  do_some_living(obfirst);
760 
761  move_player(obfirst, 3);
762  if (object_was_destroyed(obsecond, tagsecond))
763  break;
764 
765  /* the player may have been killed (acid for instance), so check here */
766  if (object_was_destroyed(obfirst, tagfirst) || (obfirst->map != test_map))
767  {
768  result = 0;
769  break;
770  }
771  }
772 
773  if (obsecond->speed_left > 0) {
774  --obsecond->speed_left;
775  monster_do_living(obsecond);
776 
777  attack_ob(obfirst, obsecond);
778  /* when player is killed, she is teleported to bed of reality -> check map */
779  if (object_was_destroyed(obfirst, tagfirst) || (obfirst->map != test_map))
780  {
781  result = 0;
782  break;
783  }
784  }
785 
786  obfirst->weapon_speed_left += obfirst->weapon_speed;
787  if (obfirst->weapon_speed_left > 1.0)
788  obfirst->weapon_speed_left = 1.0;
789  if (obsecond->speed_left <= 0)
790  obsecond->speed_left += FABS(obsecond->speed);
791  }
792 
793  free(pl.socket.faces_sent);
794  if (!object_was_destroyed(obfirst, tagfirst))
795  {
796  object_remove(obfirst);
798  }
799  if (!object_was_destroyed(obsecond, tagsecond))
800  {
801  object_remove(obsecond);
803  }
804  delete_map(test_map);
805 
806  return result;
807 }
808 
819 static int monsterFight(archetype* monster, archetype* skill, int level, int count)
820 {
821  int victory = 0;
822  while (count-- > 0)
823  victory += monsterFight(monster, skill, level);
824 
825  return victory;
826 }
827 
837 static QString monsterFight(archetype* monster, archetype* skill)
838 {
839  qDebug() << "monsterFight:" << monster->clone.name << skill->clone.name;
840  int ret, min = settings.max_level + 1, half = settings.max_level + 1, count = 5, level;
841  int first = 1, max = settings.max_level;
842 
843  while (first != max)
844  {
845  level = (max + first) / 2;
846  if (level < first)
847  level = first;
848  if (first > max)
849  first = max;
850 
851  ret = monsterFight(monster, skill, level, count);
852  if (ret > 0)
853  {
854  if (level < min)
855  min = level;
856  if (ret > (count / 2) && (level < half))
857  half = level;
858 
859  max = level;
860  }
861  else
862  {
863  if (first == level)
864  break;
865  first = level;
866  }
867  }
868 
869  //qDebug() << " result:" << min << half;
870 
871  // if player was killed, then HallOfSelection was loaded, so clean it now.
872  // This speeds up various checks, like in free_all_objects().
873  mapstruct* hos = has_been_loaded("/HallOfSelection");
874  if (hos)
875  {
876  hos->reset_time = 1;
877  hos->in_memory = MAP_IN_MEMORY;
878  delete_map(hos);
879  }
880  /*
881  extern int nroffreeobjects;
882  extern int nrofallocobjects;
883  qDebug() << "free: " << nroffreeobjects << ", all: " << nrofallocobjects;
884  */
885 
886  if (min == settings.max_level + 1)
887  return "<td colspan=\"2\">-</td>";
888  return "<td>" + QString::number(min) + "</td><td>" + ((half != 0) ? QString::number(half) : "") + "</td>";
889 }
890 
897 static QString monsterTable(archetype* monster, QList<archetype*> skills)
898 {
899  QString line = "<tr>";
900 
901  line += "<td>" + QString(monster->clone.name) + "</td>";
902  line += "<td>" + QString::number(monster->clone.level) + "</td>";
903  line += "<td>" + QString::number(monster->clone.speed) + "</td>";
904  line += "<td>" + QString::number(monster->clone.stats.wc) + "</td>";
905  line += "<td>" + QString::number(monster->clone.stats.dam) + "</td>";
906  line += "<td>" + QString::number(monster->clone.stats.ac) + "</td>";
907  line += "<td>" + QString::number(monster->clone.stats.hp) + "</td>";
908  line += "<td>" + QString::number(monster->clone.stats.Con) + "</td>";
909 
910  foreach(archetype* skill, skills)
911  {
912  line += monsterFight(monster, skill);
913  }
914  line += "</tr>\n";
915 
916  return line;
917 }
918 
924 {
925  QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
926 
927  QStringList names;
928  QMap<QString, archetype*> monsters;
929  QList<archetype*> skills;
930 
931  archt* arch = first_archetype;
932  for (; arch; arch = arch->next)
933  {
934  if (QUERY_FLAG(&arch->clone, FLAG_MONSTER) && arch->clone.stats.hp > 0 && arch->head == NULL)
935  {
936  QString name(QString(arch->clone.name).toLower());
937  if (monsters.contains(name))
938  {
939  int suffix = 1;
940  do
941  {
942  name = QString(arch->clone.name).toLower() + "_" + QString::number(suffix);
943  suffix++;
944  } while (monsters.contains(name));
945  }
946 
947  monsters[name] = arch;
948  }
949  if (arch->clone.type == SKILL && IS_COMBAT_SKILL(arch->clone.subtype))
950  {
951  if (strcmp(arch->name, "skill_missile_weapon") == 0 || strcmp(arch->name, "skill_throwing") == 0)
952  continue;
953  skills.append(arch);
954  }
955  }
956 
957  names = monsters.keys();
958  names.sort();
959 
960  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;
961  report += "<table border=\"1\"><tbody>\n";
962  report += "<tr>";
963  report += "<th rowspan=\"2\">Monster</th>";
964  report += "<th rowspan=\"2\">level</th>";
965  report += "<th rowspan=\"2\">speed</th>";
966  report += "<th rowspan=\"2\">wc</th>";
967  report += "<th rowspan=\"2\">dam</th>";
968  report += "<th rowspan=\"2\">ac</th>";
969  report += "<th rowspan=\"2\">hp</th>";
970  report += "<th rowspan=\"2\">regen</th>";
971 
972  line = "<tr>";
973  foreach(archetype* skill, skills)
974  {
975  report += "<th colspan=\"2\">" + QString(skill->clone.name) + "</th>";
976  line += "<th>fv</th><th>hv</th>";
977  }
978  report += "</tr>\n" + line + "</tr>\n";
979 
980  int limit = 500;
981  foreach(const QString name, names)
982  {
983  report += monsterTable(monsters[name], skills);
984  if (limit-- <= 0)
985  break;
986  }
987 
988  report += "</tbody></table>\n";
989 
990  CREReportDisplay show(report, "Player vs monsters (hand to hand)");
991  QApplication::restoreOverrideCursor();
992  show.exec();
993 }
994 
995 static QString reportSummon(const archetype* summon, const object* other, QString name)
996 {
997  QString report;
998  int level, wc_adj = 0;
999 
1000  const object* spell = &summon->clone;
1001  sstring rate = object_get_value(spell, "wc_increase_rate");
1002  if (rate != NULL) {
1003  wc_adj = atoi(rate);
1004  }
1005 
1006  // hp, dam, speed, wc
1007 
1008  QString ac("<tr><td>ac</td>");
1009  QString hp("<tr><td>hp</td>");
1010  QString dam("<tr><td>dam</td>");
1011  QString speed("<tr><td>speed</td>");
1012  QString wc("<tr><td>wc</td>");
1013  int ihp, idam, iwc, diff;
1014  float fspeed;
1015 
1016  for (level = 1; level < 120; level += 10)
1017  {
1018  if (level < spell->level)
1019  {
1020  ac += "<td></td>";
1021  hp += "<td></td>";
1022  dam += "<td></td>";
1023  speed += "<td></td>";
1024  wc += "<td></td>";
1025  continue;
1026  }
1027 
1028  diff = level - spell->level;
1029 
1030  ihp = other->stats.hp + spell->duration + (spell->duration_modifier != 0 ? (diff / spell->duration_modifier) : 0);
1031  idam = (spell->stats.dam ? spell->stats.dam : other->stats.dam) + (spell->dam_modifier != 0 ? (diff / spell->dam_modifier) : 0);
1032  fspeed = MIN(1.0, FABS(other->speed) + .02 * (spell->range_modifier != 0 ? (diff / spell->range_modifier) : 0));
1033  iwc = other->stats.wc;
1034  if (wc_adj > 0)
1035  iwc -= (diff / wc_adj);
1036 
1037  ac += "<td>" + QString::number(other->stats.ac) + "</td>";
1038  hp += "<td>" + QString::number(ihp) + "</td>";
1039  dam += "<td>" + QString::number(idam) + "</td>";
1040  speed += "<td>" + QString::number(fspeed) + "</td>";
1041  wc += "<td>" + QString::number(iwc) + "</td>";
1042  }
1043 
1044  report += "<tr><td colspan=\"13\"><strong>" + name + "</strong></td></tr>\n";
1045 
1046  report += ac + "</tr>\n" + hp + "</tr>\n" + dam + "</tr>\n" + speed + "</tr>\n" + wc + "</tr>\n\n";
1047 
1048  return report;
1049 }
1050 
1052 {
1053  QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
1054 
1055  int level;
1056 
1057  QString report(tr("<h1>Summoned pet statistics</h1>\n")), line;
1058  report += "<table border=\"1\">\n<thead>\n";
1059  report += "<tr>";
1060  report += "<th rowspan=\"2\">Spell</th>";
1061  report += "<th colspan=\"12\">Level</th>";
1062  report += "</tr>\n";
1063  report += "<tr>";
1064 
1065  for (level = 1; level < 120; level += 10)
1066  {
1067  report += "<th>" + QString::number(level) + "</th>";
1068  }
1069  report += "</tr>\n</thead>\n<tbody>\n";
1070 
1071  QMap<QString, QString> spells;
1072 
1073  for (const archetype* summon = first_archetype; summon; summon = summon->next)
1074  {
1075  if (summon->clone.type != SPELL || summon->clone.subtype != SP_SUMMON_GOLEM)
1076  continue;
1077  if (summon->clone.other_arch != NULL)
1078  {
1079  spells[summon->clone.name] = reportSummon(summon, &summon->clone.other_arch->clone, QString(summon->clone.name));
1080  continue;
1081  }
1082 
1083  // god-based summoning
1084  for (const archetype* god = first_archetype; god; god = god->next)
1085  {
1086  if (god->clone.type != GOD)
1087  continue;
1088 
1089  QString name(QString(summon->clone.name) + " (" + QString(god->name) + ")");
1090  archetype* holy = determine_holy_arch(&god->clone, summon->clone.race);
1091  if (holy == NULL)
1092  continue;
1093 
1094  spells[name] = reportSummon(summon, &holy->clone, name);
1095  }
1096  }
1097 
1098  QStringList keys = spells.keys();
1099  keys.sort();
1100  foreach(QString key, keys)
1101  {
1102  report += spells[key];
1103  }
1104 
1105  report += "</tbody>\n</table>\n";
1106 
1107  CREReportDisplay show(report, "Summoned pet statistics");
1108  QApplication::restoreOverrideCursor();
1109  show.exec();
1110 }
1111 
1112 static QString buildShopReport(const QString& title, const QStringList& types, const QList<CREMapInformation*>& maps, QStringList& items)
1113 {
1114  QString report("<h2>" + title + "</h2>");
1115  report += "<table border=\"1\">\n<thead>\n";
1116  report += "<tr>";
1117  report += "<th>Shop</th>";
1118  report += "<th>Greed</th>";
1119  report += "<th>Race</th>";
1120  report += "<th>Min</th>";
1121  report += "<th>Max</th>";
1122  foreach (QString item, types)
1123  {
1124  report += "<th>" + item + "</th>";
1125  items.removeAll(item);
1126  }
1127  report += "</tr>\n</thead><tbody>";
1128 
1129  foreach(const CREMapInformation* map, maps)
1130  {
1131  QString line;
1132  bool keep = false;
1133 
1134  if (map->shopItems().size() == 0)
1135  continue;
1136 
1137  line += "<tr>";
1138 
1139  line += "<td>" + map->name() + " " + map->path() + "</td>";
1140  line += "<td>" + QString::number(map->shopGreed()) + "</td>";
1141  line += "<td>" + map->shopRace() + "</td>";
1142  line += "<td>" + (map->shopMin() != 0 ? QString::number(map->shopMin()) : "") + "</td>";
1143  line += "<td>" + (map->shopMax() != 0 ? QString::number(map->shopMax()) : "") + "</td>";
1144 
1145  foreach(const QString item, types)
1146  {
1147  if (map->shopItems()[item] == 0)
1148  {
1149  if (map->shopItems()["*"] == 0)
1150  line += "<td></td>";
1151  else
1152  line += "<td>" + QString::number(map->shopItems()["*"]) + "</td>";
1153  continue;
1154  }
1155  keep = true;
1156  line += "<td>" + QString::number(map->shopItems()[item]) + "</td>";
1157  }
1158 
1159  line += "</tr>";
1160  if (keep)
1161  report += line;
1162  }
1163 
1164  report += "</tbody></table>";
1165  return report;
1166 }
1167 
1169 {
1170  QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
1171 
1172  QString report(tr("<h1>Shop information</h1>\n"));
1173 
1174  QList<CREMapInformation*> maps = myMapManager->allMaps();
1175  QStringList items;
1176  foreach(const CREMapInformation* map, maps)
1177  {
1178  QStringList add = map->shopItems().keys();
1179  foreach(const QString item, add)
1180  {
1181  if (!items.contains(item))
1182  items.append(item);
1183  }
1184  }
1185  qSort(items);
1186 
1187  QStringList part;
1188 
1189  part << "weapon" << "weapon improver" << "bow" << "arrow";
1190  report += buildShopReport("Weapons", part, maps, items);
1191 
1192  part.clear();
1193  part << "armour" << "armour improver" << "boots" << "bracers" << "cloak" << "girdle" << "gloves" << "helmet" << "shield";
1194  report += buildShopReport("Armour", part, maps, items);
1195 
1196  part.clear();
1197  part << "amulet" << "potion" << "power_crystal" << "ring" << "rod" << "scroll" << "skillscroll" << "spellbook" << "wand";
1198  report += buildShopReport("Magical", part, maps, items);
1199 
1200  part.clear();
1201  part << "container" << "food" << "key" << "lamp" << "skill tool" << "special key";
1202  report += buildShopReport("Equipment", part, maps, items);
1203 
1204  if (!items.isEmpty())
1205  {
1206 
1207  part = items;
1208  report += buildShopReport("Others", part, maps, items);
1209  }
1210 
1211  CREReportDisplay show(report, "Shop information");
1212  QApplication::restoreOverrideCursor();
1213  show.exec();
1214 }
1215 
1216 void readDirectory(const QString& path, QHash<QString, QHash<QString, bool> >& states)
1217 {
1218  QDir dir(path);
1219  QStringList subdirs = dir.entryList(QStringList("*"), QDir::Dirs | QDir::NoDotAndDotDot);
1220  foreach(QString subdir, subdirs)
1221  {
1222  readDirectory(path + QDir::separator() + subdir, states);
1223  }
1224 
1225  QStringList quests = dir.entryList(QStringList("*.quest"), QDir::Files);
1226  foreach(QString file, quests)
1227  {
1228  qDebug() << "read quest:" << path << file;
1229  QString name = file.left(file.length() - 6);
1230  QFile read(path + QDir::separator() + file);
1231  read.open(QFile::ReadOnly);
1232  QTextStream stream(&read);
1233  QString line, code;
1234  bool completed;
1235  while (!(line = stream.readLine(0)).isNull())
1236  {
1237  if (line.startsWith("quest "))
1238  {
1239  code = line.mid(6);
1240  completed = false;
1241  continue;
1242  }
1243  if (code.isEmpty())
1244  continue;
1245  if (line == "end_quest")
1246  {
1247  states[code][name] = completed;
1248  code.clear();
1249  continue;
1250  }
1251  if (line.startsWith("state "))
1252  continue;
1253  if (line == "completed 1")
1254  completed = true;
1255  }
1256  }
1257 }
1258 
1260 {
1261  QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
1262 
1263  QHash<QString, QHash<QString, bool> > states;
1264  QString directory(settings.localdir);
1265  directory += QDir::separator();
1266  directory += settings.playerdir;
1267  readDirectory(directory, states);
1268 
1269  QStringList codes;
1270  foreach(const Quest* quest, myQuestManager->quests())
1271  {
1272  codes.append(quest->code());
1273  }
1274 
1275  QString report("<html><body>\n<h1>Quests</h1>\n");
1276 
1277  QStringList keys = states.keys();
1278  keys.sort();
1279 
1280  foreach(QString key, keys)
1281  {
1282  codes.removeAll(key);
1283  Quest* quest = myQuestManager->findByCode(key);
1284  report += "<h2>Quest: " + (quest != NULL ? quest->title() : (key + " ???")) + "</h2>\n";
1285  report += "<p>";
1286  QHash<QString, bool> done = states[key];
1287  QStringList players = done.keys();
1288  players.sort();
1289  int completed = 0;
1290  QString sep;
1291  foreach(QString player, players)
1292  {
1293  report += sep;
1294  sep = ", ";
1295  if (done[player])
1296  {
1297  completed++;
1298  report += "<strong>" + player + "</strong>";
1299  }
1300  else
1301  {
1302  report += player;
1303  }
1304  }
1305  report += "</p>\n";
1306  report += "<p>" + tr("%1 completed out of %2 (%3%)").arg(completed).arg(players.size()).arg(completed * 100 / players.size()) + "</p>\n";
1307  }
1308 
1309  if (codes.length() > 0)
1310  {
1311  codes.sort();
1312  QString sep;
1313  report += "<h2>Quests never done</h2>\n<p>\n";
1314  foreach(QString code, codes)
1315  {
1316  report += sep;
1317  sep = ", ";
1318  Quest* quest = myQuestManager->findByCode(code);
1319  report += (quest != NULL ? quest->title() : (code + " ???"));
1320  }
1321  report += "</p>\n";
1322  }
1323 
1324  report += "</body>\n</html>\n";
1325 
1326  CREReportDisplay show(report, "Quests report");
1327  QApplication::restoreOverrideCursor();
1328  show.exec();
1329 }
1330 
1332 {
1333  CRESmoothFaceMaker smooth;
1334  smooth.exec();
1335 }
1336 
1338 {
1339  CRECombatSimulator simulator;
1340  simulator.exec();
1341 }
1342 
1344 {
1345  CREHPBarMaker maker;
1346  maker.exec();
1347 }
1348 
1350 {
1351  QMessageBox confirm;
1352  confirm.setWindowTitle(tr("Crossfire Resource Editor"));
1353  confirm.setText("Really clear map cache?");
1354  confirm.setInformativeText("This will force cache rebuild at next application start.");
1355  confirm.setStandardButtons(QMessageBox::Yes | QMessageBox::No);
1356  confirm.setDefaultButton(QMessageBox::No);
1357  confirm.setIcon(QMessageBox::Question);
1358  if (confirm.exec() == QMessageBox::Yes)
1359  {
1361  }
1362 }
float weapon_speed_left
Definition: object.h:331
QAction * myOpenScripts
Definition: CREMainWindow.h:54
Definition: player.h:92
archetype * find_archetype(const char *name)
Definition: arch.c:695
int8_t ac
Definition: living.h:38
quint64 shopMax() const
int diff
Definition: recipe.h:16
void object_free(object *ob, int flags)
Definition: object.c:1409
int move_player(object *op, int dir)
Definition: player.c:3009
uint8_t dam_modifier
Definition: object.h:407
int8_t tail_x
Definition: object.h:471
void onOpenArchetypes()
QAction * myReportDuplicate
Definition: CREMainWindow.h:59
QList< CREMapInformation * > allMaps()
void onReportDuplicate()
QAction * myReportSpellDamage
Definition: CREMainWindow.h:60
mapstruct * get_empty_map(int sizex, int sizey)
Definition: map.c:863
#define SET_FLAG(xyz, p)
Definition: define.h:223
void updateFilters()
QMdiArea * myArea
Definition: CREMainWindow.h:35
QAction * myOpenAnimations
Definition: CREMainWindow.h:46
int16_t bed_x
Definition: player.h:98
#define FABS(x)
Definition: define.h:22
unsigned char uint8_t
Definition: win32.h:161
Definition: Quest.h:32
uint16_t animation_id
Definition: object.h:416
const char * name
Definition: face.h:27
void do_some_living(object *op)
Definition: player.c:3277
void onFiltersModified()
int attack_ob(object *op, object *hitter)
Definition: attack.c:905
struct artifactstruct * items
Definition: artifact.h:30
double shopGreed() const
#define SPELL_GRACE
Definition: spells.h:59
uint32_t in_memory
Definition: map.h:345
QMenu * myOpenMenu
Definition: CREMainWindow.h:40
const char * playerdir
Definition: global.h:244
int16_t max_level
Definition: global.h:299
const char * object_get_value(const object *op, const char *const key)
Definition: object.c:4266
const animations_struct * animation(const QString &name) const
struct pl player
QAction * myReportQuests
Definition: CREMainWindow.h:66
object clone
Definition: object.h:470
void onOpenExperience()
int16_t duration
Definition: object.h:403
socket_struct socket
Definition: player.h:94
linked_char * ingred
Definition: recipe.h:22
uint32_t reset_time
Definition: map.h:332
uint8_t duration_modifier
Definition: object.h:404
int16_t SP_level_spellpoint_cost(object *caster, object *spell, int flags)
Definition: spell_util.c:275
QAction * myOpenFormulae
Definition: CREMainWindow.h:47
const QString & code() const
Definition: Quest.cpp:63
static QString reportSummon(const archetype *summon, const object *other, QString name)
uint8_t subtype
Definition: object.h:339
void commitData()
const QString & shopRace() const
int SP_level_dam_adjust(const object *caster, const object *spob)
Definition: spell_util.c:326
void onOpenTreasures()
QAction * mySaveMessages
Definition: CREMainWindow.h:58
static QString buildShopReport(const QString &title, const QStringList &types, const QList< CREMapInformation *> &maps, QStringList &items)
#define object_was_destroyed(op, old_tag)
Definition: object.h:68
static QString spellsTable(const QString &skill)
mapstruct * test_map
Definition: comet_perf.c:73
void onToolCombatSimulator()
void onReportsModified()
void loadQuests()
QAction * myToolHPBar
Definition: CREMainWindow.h:68
Definition: object.h:465
char savebed_map[MAX_BUF]
Definition: player.h:97
int8_t tail_y
Definition: object.h:471
#define MIN(x, y)
Definition: compat.h:17
int8_t Con
Definition: living.h:36
unsigned int nrofpixmaps
Definition: image.c:45
quint64 shopMin() const
int16_t hp
Definition: living.h:40
void cleanup(void)
Definition: server.c:1164
QStringList allAnimations() const
QAction * myOpenTreasures
Definition: CREMainWindow.h:45
int ingred_count
Definition: recipe.h:23
void closeEvent(QCloseEvent *event)
void onOpenArtifacts()
const QString & title() const
Definition: Quest.cpp:76
QAction * myOpenRandomMaps
Definition: CREMainWindow.h:55
QAction * myToolSmooth
Definition: CREMainWindow.h:67
#define MAP_IN_MEMORY
Definition: map.h:130
void object_free_drop_inventory(object *ob)
Definition: object.c:1389
const char * name
Definition: face.h:20
const char * title
Definition: object.h:317
object * object_insert_in_map_at(object *op, mapstruct *m, object *originator, int flag, int x, int y)
Definition: object.c:1933
int16_t maxhp
Definition: living.h:41
QAction * myOpenMessages
Definition: CREMainWindow.h:53
#define FREE_OBJ_FREE_INVENTORY
Definition: object.h:530
ResourcesManager * myResourcesManager
Definition: CREMainWindow.h:75
void doResourceWindow(DisplayMode mode)
Quest * findByCode(const QString &code)
#define SP_BULLET
Definition: spells.h:79
struct artifactliststruct * next
Definition: artifact.h:29
sstring title
Definition: recipe.h:11
object * create_archetype(const char *name)
Definition: arch.c:620
char ** arch_name
Definition: recipe.h:13
object * object_insert_in_ob(object *op, object *where)
Definition: object.c:2707
float speed_left
Definition: object.h:329
void onOpenAnimations()
QAction * myOpenArtifacts
Definition: CREMainWindow.h:43
MessageManager * myMessageManager
Definition: CREMainWindow.h:74
QLabel * myMapBrowseStatus
Definition: CREMainWindow.h:71
uint8_t range_modifier
Definition: object.h:406
struct mapdef * map
Definition: object.h:297
void onReportAlchemy()
QAction * myReportShops
Definition: CREMainWindow.h:65
struct linked_char * next
Definition: global.h:88
struct recipestruct recipe
QuestManager * myQuestManager
Definition: CREMainWindow.h:73
type_definition ** types
int16_t dam
Definition: living.h:46
QStringList faces() const
const char * name
Definition: object.h:311
int16_t bed_y
Definition: player.h:98
QAction * myOpenResources
Definition: CREMainWindow.h:50
QAction * myOpenExperience
Definition: CREMainWindow.h:51
uint8_t num_animations
Definition: face.h:28
QAction * myOpenArchetypes
Definition: CREMainWindow.h:44
struct archt * head
Definition: object.h:468
QAction * mySaveQuests
Definition: CREMainWindow.h:57
EXTERN Animations * animations
Definition: global.h:163
struct pl * contr
Definition: object.h:276
QAction * myClearMapCache
Definition: CREMainWindow.h:70
QAction * myReportSummon
Definition: CREMainWindow.h:64
static int monsterFight(archetype *monster, archetype *skill, int level)
uint32_t tag_t
Definition: object.h:12
sstring skill
Definition: recipe.h:26
float speed
Definition: object.h:328
Definition: object.h:214
#define QUERY_FLAG(xyz, p)
Definition: define.h:225
QAction * myToolCombatSimulator
Definition: CREMainWindow.h:69
EXTERN artifactlist * first_artifactlist
Definition: global.h:121
#define MAX_BUF
Definition: define.h:35
object * object_create_arch(archetype *at)
Definition: arch.c:736
QAction * myReportAlchemy
Definition: CREMainWindow.h:61
const char * skill
Definition: object.h:321
QAction * myReportSpells
Definition: CREMainWindow.h:62
void updateReports()
int8_t wc
Definition: living.h:37
QMenu * mySaveMenu
Definition: CREMainWindow.h:41
CREMapInformationManager * myMapManager
Definition: CREMainWindow.h:72
object * ob
Definition: player.h:158
const char * sstring
Definition: global.h:40
const New_Face ** faces
Definition: face.h:31
int exp
Definition: recipe.h:17
QAction * myReportPlayer
Definition: CREMainWindow.h:63
void browsingMap(const QString &path)
archetype * determine_holy_arch(const object *god, const char *type)
Definition: gods.c:741
Definition: object.h:143
const char * localdir
Definition: global.h:243
tag_t count
Definition: object.h:299
living stats
Definition: object.h:368
mapstruct * has_been_loaded(const char *name)
Definition: map.c:87
size_t arch_names
Definition: recipe.h:12
DisplayMode
uint8_t type
Definition: object.h:338
struct Settings settings
Definition: init.c:40
QAction * myOpenMaps
Definition: CREMainWindow.h:49
struct archt * next
Definition: object.h:467
#define FLAG_APPLIED
Definition: define.h:235
void browsingFinished()
struct recipestruct * next
Definition: recipe.h:24
void delete_map(mapstruct *m)
Definition: map.c:1753
QAction * myOpenQuests
Definition: CREMainWindow.h:52
int64_t * levels
Definition: exp.c:26
static quest_definition * quests
Definition: quest.c:93
#define FLAG_MONSTER
Definition: define.h:245
void monster_do_living(object *op)
Definition: monster.c:564
ScriptFileManager * myScriptManager
Definition: CREMainWindow.h:76
QAction * myOpenFaces
Definition: CREMainWindow.h:48
object * item
Definition: artifact.h:15
#define IS_COMBAT_SKILL(num)
Definition: skills.h:91
Definition: map.h:325
const New_Face * face
Definition: object.h:332
static QString alchemyTable(const QString &skill)
void onOpenResources()
QList< const Quest * > quests() const
QAction * mySaveFormulae
Definition: CREMainWindow.h:56
int16_t level
Definition: object.h:351
static QString monsterTable(archetype *monster, QList< archetype *> skills)
void fix_object(object *op)
Definition: living.c:1119
float weapon_speed
Definition: object.h:330
#define SP_SUMMON_GOLEM
Definition: spells.h:86
Definition: object.h:148
EXTERN archetype * first_archetype
Definition: global.h:122
uint8_t * faces_sent
Definition: newserver.h:96
const char * name
Definition: object.h:466
struct recipestruct * items
Definition: recipe.h:40
recipelist * get_formulalist(int i)
Definition: recipe.c:96
void object_remove(object *op)
Definition: object.c:1666
struct artifactstruct * next
Definition: artifact.h:18
QHash< QString, int > & shopItems()
void onOpenRandomMaps()
void onReportSpellDamage()
void createActions()
void readDirectory(const QString &path, QHash< QString, QHash< QString, bool > > &states)