Crossfire Server, Trunk  R20513
CREMainWindow.cpp
Go to the documentation of this file.
1 #include <Qt>
2 #include <QtGui>
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 
566  QString name;
567  if (strcmp(recipe->title, "NONE") == 0)
568  {
569  if (arch->clone.title == NULL)
570  name = arch->clone.name;
571  else
572  name = QString("%1 %2").arg(arch->clone.name, arch->clone.title);
573  }
574  else
575  {
576  name = QString("%1 of %2").arg(arch->clone.name, recipe->title);
577  }
578 
579  QStringList ingredients;
580  for (const linked_char* ingred = recipe->ingred; ingred != NULL; ingred = ingred->next)
581  {
582  ingredients.append(ingred->name);
583  }
584 
585  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(", ")));
586  count++;
587  }
588  }
589  }
590 
591  if (count == 0)
592  return QString();
593 
594  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);
595  report += "</tr></thead><tbody>";
596 
597  QList<int> difficulties = recipes.keys();
598  qSort(difficulties);
599  foreach(int difficulty, difficulties)
600  {
601  QStringList line = recipes[difficulty];
602  qSort(line);
603  report += line.join("\n");
604  }
605 
606  report += "</tbody></table>";
607 
608  return report;
609 }
610 
612 {
613  QStringList skills;
614 
615  const archt* arch = first_archetype;
616  for (; arch; arch = arch->next)
617  {
618  if (arch->clone.type == SKILL)
619  skills.append(arch->clone.name);
620  }
621 
622  skills.sort();
623 
624  QString report("<h1>Alchemy formulae</h1>");
625 
626  foreach(const QString skill, skills)
627  {
628  report += alchemyTable(skill);
629  }
630 
631  CREReportDisplay show(report, "Alchemy formulae");
632  show.exec();
633 }
634 
635 static QString spellsTable(const QString& skill)
636 {
637  bool one = false;
638 
639  QString report = QString("<h2>%1</h2><table><thead><tr><th>Spell</th><th>Level</th>").arg(skill);
640  report += "</tr></thead><tbody>";
641 
642  QHash<int, QStringList> spells;
643 
644  const archetype* spell;
645 
646  for (spell = first_archetype; spell; spell = spell->next)
647  {
648  if (spell->clone.type == SPELL && spell->clone.skill == skill)
649  {
650  spells[spell->clone.level].append(QString("<tr><td>%1</td><td>%2</td></tr>").arg(spell->clone.name).arg(spell->clone.level));
651  one = true;
652  }
653  }
654 
655  if (!one)
656  return QString();
657 
658  QList<int> levels = spells.keys();
659  qSort(levels);
660  foreach(int level, levels)
661  {
662  report += spells[level].join("\n");
663  }
664 
665  report += "</tbody></table>";
666 
667  return report;
668 }
669 
671 {
672  QStringList skills;
673 
674  const archt* arch = first_archetype;
675  for (; arch; arch = arch->next)
676  {
677  if (arch->clone.type == SKILL)
678  skills.append(arch->clone.name);
679  }
680 
681  skills.sort();
682 
683  QString report("<h1>Spell list</h1>");
684 
685  foreach(const QString skill, skills)
686  {
687  report += spellsTable(skill);
688  }
689 
690  CREReportDisplay show(report, "Spell list");
691  show.exec();
692 }
693 
703 static int monsterFight(archetype* monster, archetype* skill, int level)
704 {
705  int limit = 50, result = 1;
706  player pl;
707  memset(&pl, 0, sizeof(player));
708  strncpy(pl.savebed_map, "/HallOfSelection", MAX_BUF);
709  pl.bed_x = 5;
710  pl.bed_y = 5;
711  pl.socket.faces_sent = (uint8_t*)calloc(sizeof(uint8_t), nrofpixmaps);
712 
713  object* obfirst = object_create_arch(find_archetype("dwarf_player"));
714  obfirst->level = level;
715  obfirst->contr = &pl;
716  pl.ob = obfirst;
717  object* obskill = object_create_arch(skill);
718  obskill->level = level;
719  SET_FLAG(obskill, FLAG_APPLIED);
720  object_insert_in_ob(obskill, obfirst);
721  object* sword = object_create_arch(find_archetype((skill->clone.subtype == SK_TWO_HANDED_WEAPON) ? "sword_3" : "sword"));
722  SET_FLAG(sword, FLAG_APPLIED);
723  object_insert_in_ob(sword, obfirst);
724  fix_object(obfirst);
725  obfirst->stats.hp = obfirst->stats.maxhp;
726 
727  object* obsecond = object_create_arch(monster);
728  tag_t tagfirst = obfirst->count;
729  tag_t tagsecond = obsecond->count;
730 
731  // make a big map so large monsters are ok in map
732  mapstruct* test_map = get_empty_map(50, 50);
733 
734  obfirst = object_insert_in_map_at(obfirst, test_map, NULL, 0, 0, 0);
735  obsecond = object_insert_in_map_at(obsecond, test_map, NULL, 0, 1 + monster->tail_x, monster->tail_y);
736 
737  if (!obsecond || object_was_destroyed(obsecond, tagsecond))
738  {
739  qDebug() << "second removed??";
740  }
741 
742  while (limit-- > 0 && obfirst->stats.hp >= 0 && obsecond->stats.hp >= 0)
743  {
744  if (obfirst->weapon_speed_left > 0) {
745  --obfirst->weapon_speed_left;
746  do_some_living(obfirst);
747 
748  move_player(obfirst, 3);
749  if (object_was_destroyed(obsecond, tagsecond))
750  break;
751 
752  /* the player may have been killed (acid for instance), so check here */
753  if (object_was_destroyed(obfirst, tagfirst) || (obfirst->map != test_map))
754  {
755  result = 0;
756  break;
757  }
758  }
759 
760  if (obsecond->speed_left > 0) {
761  --obsecond->speed_left;
762  monster_do_living(obsecond);
763 
764  attack_ob(obfirst, obsecond);
765  /* when player is killed, she is teleported to bed of reality -> check map */
766  if (object_was_destroyed(obfirst, tagfirst) || (obfirst->map != test_map))
767  {
768  result = 0;
769  break;
770  }
771  }
772 
773  obfirst->weapon_speed_left += obfirst->weapon_speed;
774  if (obfirst->weapon_speed_left > 1.0)
775  obfirst->weapon_speed_left = 1.0;
776  if (obsecond->speed_left <= 0)
777  obsecond->speed_left += FABS(obsecond->speed);
778  }
779 
780  free(pl.socket.faces_sent);
781  if (!object_was_destroyed(obfirst, tagfirst))
782  {
783  object_remove(obfirst);
785  }
786  if (!object_was_destroyed(obsecond, tagsecond))
787  {
788  object_remove(obsecond);
790  }
791  delete_map(test_map);
792 
793  return result;
794 }
795 
806 static int monsterFight(archetype* monster, archetype* skill, int level, int count)
807 {
808  int victory = 0;
809  while (count-- > 0)
810  victory += monsterFight(monster, skill, level);
811 
812  return victory;
813 }
814 
824 static QString monsterFight(archetype* monster, archetype* skill)
825 {
826  qDebug() << "monsterFight:" << monster->clone.name << skill->clone.name;
827  int ret, min = settings.max_level + 1, half = settings.max_level + 1, count = 5, level;
828  int first = 1, max = settings.max_level;
829 
830  while (first != max)
831  {
832  level = (max + first) / 2;
833  if (level < first)
834  level = first;
835  if (first > max)
836  first = max;
837 
838  ret = monsterFight(monster, skill, level, count);
839  if (ret > 0)
840  {
841  if (level < min)
842  min = level;
843  if (ret > (count / 2) && (level < half))
844  half = level;
845 
846  max = level;
847  }
848  else
849  {
850  if (first == level)
851  break;
852  first = level;
853  }
854  }
855 
856  //qDebug() << " result:" << min << half;
857 
858  // if player was killed, then HallOfSelection was loaded, so clean it now.
859  // This speeds up various checks, like in free_all_objects().
860  mapstruct* hos = has_been_loaded("/HallOfSelection");
861  if (hos)
862  {
863  hos->reset_time = 1;
864  hos->in_memory = MAP_IN_MEMORY;
865  delete_map(hos);
866  }
867  /*
868  extern int nroffreeobjects;
869  extern int nrofallocobjects;
870  qDebug() << "free: " << nroffreeobjects << ", all: " << nrofallocobjects;
871  */
872 
873  if (min == settings.max_level + 1)
874  return "<td colspan=\"2\">-</td>";
875  return "<td>" + QString::number(min) + "</td><td>" + ((half != 0) ? QString::number(half) : "") + "</td>";
876 }
877 
884 static QString monsterTable(archetype* monster, QList<archetype*> skills)
885 {
886  QString line = "<tr>";
887 
888  line += "<td>" + QString(monster->clone.name) + "</td>";
889  line += "<td>" + QString::number(monster->clone.level) + "</td>";
890  line += "<td>" + QString::number(monster->clone.speed) + "</td>";
891  line += "<td>" + QString::number(monster->clone.stats.wc) + "</td>";
892  line += "<td>" + QString::number(monster->clone.stats.dam) + "</td>";
893  line += "<td>" + QString::number(monster->clone.stats.ac) + "</td>";
894  line += "<td>" + QString::number(monster->clone.stats.hp) + "</td>";
895  line += "<td>" + QString::number(monster->clone.stats.Con) + "</td>";
896 
897  foreach(archetype* skill, skills)
898  {
899  line += monsterFight(monster, skill);
900  }
901  line += "</tr>\n";
902 
903  return line;
904 }
905 
911 {
912  QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
913 
914  QStringList names;
915  QMap<QString, archetype*> monsters;
916  QList<archetype*> skills;
917 
918  archt* arch = first_archetype;
919  for (; arch; arch = arch->next)
920  {
921  if (QUERY_FLAG(&arch->clone, FLAG_MONSTER) && arch->clone.stats.hp > 0 && arch->head == NULL)
922  {
923  QString name(QString(arch->clone.name).toLower());
924  if (monsters.contains(name))
925  {
926  int suffix = 1;
927  do
928  {
929  name = QString(arch->clone.name).toLower() + "_" + QString::number(suffix);
930  suffix++;
931  } while (monsters.contains(name));
932  }
933 
934  monsters[name] = arch;
935  }
936  if (arch->clone.type == SKILL && IS_COMBAT_SKILL(arch->clone.subtype))
937  {
938  if (strcmp(arch->name, "skill_missile_weapon") == 0 || strcmp(arch->name, "skill_throwing") == 0)
939  continue;
940  skills.append(arch);
941  }
942  }
943 
944  names = monsters.keys();
945  names.sort();
946 
947  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;
948  report += "<table border=\"1\"><tbody>\n";
949  report += "<tr>";
950  report += "<th rowspan=\"2\">Monster</th>";
951  report += "<th rowspan=\"2\">level</th>";
952  report += "<th rowspan=\"2\">speed</th>";
953  report += "<th rowspan=\"2\">wc</th>";
954  report += "<th rowspan=\"2\">dam</th>";
955  report += "<th rowspan=\"2\">ac</th>";
956  report += "<th rowspan=\"2\">hp</th>";
957  report += "<th rowspan=\"2\">regen</th>";
958 
959  line = "<tr>";
960  foreach(archetype* skill, skills)
961  {
962  report += "<th colspan=\"2\">" + QString(skill->clone.name) + "</th>";
963  line += "<th>fv</th><th>hv</th>";
964  }
965  report += "</tr>\n" + line + "</tr>\n";
966 
967  int limit = 500;
968  foreach(const QString name, names)
969  {
970  report += monsterTable(monsters[name], skills);
971  if (limit-- <= 0)
972  break;
973  }
974 
975  report += "</tbody></table>\n";
976 
977  CREReportDisplay show(report, "Player vs monsters (hand to hand)");
978  QApplication::restoreOverrideCursor();
979  show.exec();
980 }
981 
982 static QString reportSummon(const archetype* summon, const object* other, QString name)
983 {
984  QString report;
985  int level, wc_adj = 0;
986 
987  const object* spell = &summon->clone;
988  sstring rate = object_get_value(spell, "wc_increase_rate");
989  if (rate != NULL) {
990  wc_adj = atoi(rate);
991  }
992 
993  // hp, dam, speed, wc
994 
995  QString ac("<tr><td>ac</td>");
996  QString hp("<tr><td>hp</td>");
997  QString dam("<tr><td>dam</td>");
998  QString speed("<tr><td>speed</td>");
999  QString wc("<tr><td>wc</td>");
1000  int ihp, idam, iwc, diff;
1001  float fspeed;
1002 
1003  for (level = 1; level < 120; level += 10)
1004  {
1005  if (level < spell->level)
1006  {
1007  ac += "<td></td>";
1008  hp += "<td></td>";
1009  dam += "<td></td>";
1010  speed += "<td></td>";
1011  wc += "<td></td>";
1012  continue;
1013  }
1014 
1015  diff = level - spell->level;
1016 
1017  ihp = other->stats.hp + spell->duration + (spell->duration_modifier != 0 ? (diff / spell->duration_modifier) : 0);
1018  idam = (spell->stats.dam ? spell->stats.dam : other->stats.dam) + (spell->dam_modifier != 0 ? (diff / spell->dam_modifier) : 0);
1019  fspeed = MIN(1.0, FABS(other->speed) + .02 * (spell->range_modifier != 0 ? (diff / spell->range_modifier) : 0));
1020  iwc = other->stats.wc;
1021  if (wc_adj > 0)
1022  iwc -= (diff / wc_adj);
1023 
1024  ac += "<td>" + QString::number(other->stats.ac) + "</td>";
1025  hp += "<td>" + QString::number(ihp) + "</td>";
1026  dam += "<td>" + QString::number(idam) + "</td>";
1027  speed += "<td>" + QString::number(fspeed) + "</td>";
1028  wc += "<td>" + QString::number(iwc) + "</td>";
1029  }
1030 
1031  report += "<tr><td colspan=\"13\"><strong>" + name + "</strong></td></tr>\n";
1032 
1033  report += ac + "</tr>\n" + hp + "</tr>\n" + dam + "</tr>\n" + speed + "</tr>\n" + wc + "</tr>\n\n";
1034 
1035  return report;
1036 }
1037 
1039 {
1040  QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
1041 
1042  int level;
1043 
1044  QString report(tr("<h1>Summoned pet statistics</h1>\n")), line;
1045  report += "<table border=\"1\">\n<thead>\n";
1046  report += "<tr>";
1047  report += "<th rowspan=\"2\">Spell</th>";
1048  report += "<th colspan=\"12\">Level</th>";
1049  report += "</tr>\n";
1050  report += "<tr>";
1051 
1052  for (level = 1; level < 120; level += 10)
1053  {
1054  report += "<th>" + QString::number(level) + "</th>";
1055  }
1056  report += "</tr>\n</thead>\n<tbody>\n";
1057 
1058  QMap<QString, QString> spells;
1059 
1060  for (const archetype* summon = first_archetype; summon; summon = summon->next)
1061  {
1062  if (summon->clone.type != SPELL || summon->clone.subtype != SP_SUMMON_GOLEM)
1063  continue;
1064  if (summon->clone.other_arch != NULL)
1065  {
1066  spells[summon->clone.name] = reportSummon(summon, &summon->clone.other_arch->clone, QString(summon->clone.name));
1067  continue;
1068  }
1069 
1070  // god-based summoning
1071  for (const archetype* god = first_archetype; god; god = god->next)
1072  {
1073  if (god->clone.type != GOD)
1074  continue;
1075 
1076  QString name(QString(summon->clone.name) + " (" + QString(god->name) + ")");
1077  archetype* holy = determine_holy_arch(&god->clone, summon->clone.race);
1078  if (holy == NULL)
1079  continue;
1080 
1081  spells[name] = reportSummon(summon, &holy->clone, name);
1082  }
1083  }
1084 
1085  QStringList keys = spells.keys();
1086  keys.sort();
1087  foreach(QString key, keys)
1088  {
1089  report += spells[key];
1090  }
1091 
1092  report += "</tbody>\n</table>\n";
1093 
1094  CREReportDisplay show(report, "Summoned pet statistics");
1095  QApplication::restoreOverrideCursor();
1096  show.exec();
1097 }
1098 
1099 static QString buildShopReport(const QString& title, const QStringList& types, const QList<CREMapInformation*>& maps, QStringList& items)
1100 {
1101  QString report("<h2>" + title + "</h2>");
1102  report += "<table border=\"1\">\n<thead>\n";
1103  report += "<tr>";
1104  report += "<th>Shop</th>";
1105  report += "<th>Greed</th>";
1106  report += "<th>Race</th>";
1107  report += "<th>Min</th>";
1108  report += "<th>Max</th>";
1109  foreach (QString item, types)
1110  {
1111  report += "<th>" + item + "</th>";
1112  items.removeAll(item);
1113  }
1114  report += "</tr>\n</thead><tbody>";
1115 
1116  foreach(const CREMapInformation* map, maps)
1117  {
1118  QString line;
1119  bool keep = false;
1120 
1121  if (map->shopItems().size() == 0)
1122  continue;
1123 
1124  line += "<tr>";
1125 
1126  line += "<td>" + map->name() + " " + map->path() + "</td>";
1127  line += "<td>" + QString::number(map->shopGreed()) + "</td>";
1128  line += "<td>" + map->shopRace() + "</td>";
1129  line += "<td>" + (map->shopMin() != 0 ? QString::number(map->shopMin()) : "") + "</td>";
1130  line += "<td>" + (map->shopMax() != 0 ? QString::number(map->shopMax()) : "") + "</td>";
1131 
1132  foreach(const QString item, types)
1133  {
1134  if (map->shopItems()[item] == 0)
1135  {
1136  if (map->shopItems()["*"] == 0)
1137  line += "<td></td>";
1138  else
1139  line += "<td>" + QString::number(map->shopItems()["*"]) + "</td>";
1140  continue;
1141  }
1142  keep = true;
1143  line += "<td>" + QString::number(map->shopItems()[item]) + "</td>";
1144  }
1145 
1146  line += "</tr>";
1147  if (keep)
1148  report += line;
1149  }
1150 
1151  report += "</tbody></table>";
1152  return report;
1153 }
1154 
1156 {
1157  QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
1158 
1159  QString report(tr("<h1>Shop information</h1>\n"));
1160 
1161  QList<CREMapInformation*> maps = myMapManager->allMaps();
1162  QStringList items;
1163  foreach(const CREMapInformation* map, maps)
1164  {
1165  QStringList add = map->shopItems().keys();
1166  foreach(const QString item, add)
1167  {
1168  if (!items.contains(item))
1169  items.append(item);
1170  }
1171  }
1172  qSort(items);
1173 
1174  QStringList part;
1175 
1176  part << "weapon" << "weapon improver" << "bow" << "arrow";
1177  report += buildShopReport("Weapons", part, maps, items);
1178 
1179  part.clear();
1180  part << "armour" << "armour improver" << "boots" << "bracers" << "cloak" << "girdle" << "gloves" << "helmet" << "shield";
1181  report += buildShopReport("Armour", part, maps, items);
1182 
1183  part.clear();
1184  part << "amulet" << "potion" << "power_crystal" << "ring" << "rod" << "scroll" << "skillscroll" << "spellbook" << "wand";
1185  report += buildShopReport("Magical", part, maps, items);
1186 
1187  part.clear();
1188  part << "container" << "food" << "key" << "lamp" << "skill tool" << "special key";
1189  report += buildShopReport("Equipment", part, maps, items);
1190 
1191  if (!items.isEmpty())
1192  {
1193 
1194  part = items;
1195  report += buildShopReport("Others", part, maps, items);
1196  }
1197 
1198  CREReportDisplay show(report, "Shop information");
1199  QApplication::restoreOverrideCursor();
1200  show.exec();
1201 }
1202 
1203 void readDirectory(const QString& path, QHash<QString, QHash<QString, bool> >& states)
1204 {
1205  QDir dir(path);
1206  QStringList subdirs = dir.entryList(QStringList("*"), QDir::Dirs | QDir::NoDotAndDotDot);
1207  foreach(QString subdir, subdirs)
1208  {
1209  readDirectory(path + QDir::separator() + subdir, states);
1210  }
1211 
1212  QStringList quests = dir.entryList(QStringList("*.quest"), QDir::Files);
1213  foreach(QString file, quests)
1214  {
1215  qDebug() << "read quest:" << path << file;
1216  QString name = file.left(file.length() - 6);
1217  QFile read(path + QDir::separator() + file);
1218  read.open(QFile::ReadOnly);
1219  QTextStream stream(&read);
1220  QString line, code;
1221  bool completed;
1222  while (!(line = stream.readLine(0)).isNull())
1223  {
1224  if (line.startsWith("quest "))
1225  {
1226  code = line.mid(6);
1227  completed = false;
1228  continue;
1229  }
1230  if (code.isEmpty())
1231  continue;
1232  if (line == "end_quest")
1233  {
1234  states[code][name] = completed;
1235  code.clear();
1236  continue;
1237  }
1238  if (line.startsWith("state "))
1239  continue;
1240  if (line == "completed 1")
1241  completed = true;
1242  }
1243  }
1244 }
1245 
1247 {
1248  QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
1249 
1250  QHash<QString, QHash<QString, bool> > states;
1251  QString directory(settings.localdir);
1252  directory += QDir::separator();
1253  directory += settings.playerdir;
1254  readDirectory(directory, states);
1255 
1256  QStringList codes;
1257  foreach(const Quest* quest, myQuestManager->quests())
1258  {
1259  codes.append(quest->code());
1260  }
1261 
1262  QString report("<html><body>\n<h1>Quests</h1>\n");
1263 
1264  QStringList keys = states.keys();
1265  keys.sort();
1266 
1267  foreach(QString key, keys)
1268  {
1269  codes.removeAll(key);
1270  Quest* quest = myQuestManager->findByCode(key);
1271  report += "<h2>Quest: " + (quest != NULL ? quest->title() : (key + " ???")) + "</h2>\n";
1272  report += "<p>";
1273  QHash<QString, bool> done = states[key];
1274  QStringList players = done.keys();
1275  players.sort();
1276  int completed = 0;
1277  QString sep;
1278  foreach(QString player, players)
1279  {
1280  report += sep;
1281  sep = ", ";
1282  if (done[player])
1283  {
1284  completed++;
1285  report += "<strong>" + player + "</strong>";
1286  }
1287  else
1288  {
1289  report += player;
1290  }
1291  }
1292  report += "</p>\n";
1293  report += "<p>" + tr("%1 completed out of %2 (%3%)").arg(completed).arg(players.size()).arg(completed * 100 / players.size()) + "</p>\n";
1294  }
1295 
1296  if (codes.length() > 0)
1297  {
1298  codes.sort();
1299  QString sep;
1300  report += "<h2>Quests never done</h2>\n<p>\n";
1301  foreach(QString code, codes)
1302  {
1303  report += sep;
1304  sep = ", ";
1305  Quest* quest = myQuestManager->findByCode(code);
1306  report += (quest != NULL ? quest->title() : (code + " ???"));
1307  }
1308  report += "</p>\n";
1309  }
1310 
1311  report += "</body>\n</html>\n";
1312 
1313  CREReportDisplay show(report, "Quests report");
1314  QApplication::restoreOverrideCursor();
1315  show.exec();
1316 }
1317 
1319 {
1320  CRESmoothFaceMaker smooth;
1321  smooth.exec();
1322 }
1323 
1325 {
1326  CRECombatSimulator simulator;
1327  simulator.exec();
1328 }
1329 
1331 {
1332  CREHPBarMaker maker;
1333  maker.exec();
1334 }
1335 
1337 {
1338  QMessageBox confirm;
1339  confirm.setWindowTitle(tr("Crossfire Resource Editor"));
1340  confirm.setText("Really clear map cache?");
1341  confirm.setInformativeText("This will force cache rebuild at next application start.");
1342  confirm.setStandardButtons(QMessageBox::Yes | QMessageBox::No);
1343  confirm.setDefaultButton(QMessageBox::No);
1344  confirm.setIcon(QMessageBox::Question);
1345  if (confirm.exec() == QMessageBox::Yes)
1346  {
1348  }
1349 }
float weapon_speed_left
How much speed is left to spend this round.
Definition: object.h:331
QAction * myOpenScripts
Definition: CREMainWindow.h:54
One player.
Definition: player.h:92
archetype * find_archetype(const char *name)
Finds, using the hashtable, which archetype matches the given name.
Definition: arch.c:695
int8_t ac
Armour Class, how hard to hit, the lower the better.
Definition: living.h:37
List of recipes with a certain number of ingredients.
Definition: recipe.h:37
int diff
Alchemical dfficulty level.
Definition: recipe.h:16
int move_player(object *op, int dir)
Player gave us a direction, check whether to move or fire.
Definition: player.c:3007
uint8_t dam_modifier
How going up in level affects damage.
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)
Creates and returns a map of the specific size.
Definition: map.c:874
#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)
Decstations have trouble with fabs()...
Definition: define.h:22
unsigned char uint8_t
Definition: win32.h:161
Definition: Quest.h:32
uint16_t animation_id
An index into the animation array.
Definition: object.h:416
const char * name
Name of the animation sequence.
Definition: face.h:27
void do_some_living(object *op)
Regenerate hp/sp/gr, decreases food.
Definition: player.c:3286
const QString & code() const
Definition: Quest.cpp:63
void onFiltersModified()
const animations_struct * animation(const QString &name) const
Information on one title.
Definition: readable.c:106
int attack_ob(object *op, object *hitter)
Simple wrapper for attack_ob_simple(), will use hitter&#39;s values.
Definition: attack.c:903
struct artifactstruct * items
Artifacts for this type.
Definition: artifact.h:30
#define SPELL_GRACE
Definition: spells.h:59
Manage scripts for items.
uint32_t in_memory
Combination of IN_MEMORY_xxx flags.
Definition: map.h:345
QMenu * myOpenMenu
Definition: CREMainWindow.h:40
const char * playerdir
Where the player files are.
Definition: global.h:246
int16_t max_level
This is read out of exp_table.
Definition: global.h:300
const char * object_get_value(const object *op, const char *const key)
Get an extra value by key.
Definition: object.c:4246
static QString buildShopReport(const QString &title, const QStringList &types, const QList< CREMapInformation * > &maps, QStringList &items)
struct pl player
One player.
QAction * myReportQuests
Definition: CREMainWindow.h:66
object clone
An object from which to do object_copy()
Definition: object.h:470
void onOpenExperience()
int16_t duration
How long the spell lasts.
Definition: object.h:403
socket_struct socket
Socket information for this player.
Definition: player.h:94
linked_char * ingred
List of ingredients.
Definition: recipe.h:22
uint32_t reset_time
When this map should reset.
Definition: map.h:332
uint8_t duration_modifier
how level modifies duration
Definition: object.h:404
int16_t SP_level_spellpoint_cost(object *caster, object *spell, int flags)
Scales the spellpoint cost of a spell by it&#39;s increased effectiveness.
Definition: spell_util.c:277
QAction * myOpenFormulae
Definition: CREMainWindow.h:47
static QString reportSummon(const archetype *summon, const object *other, QString name)
uint8_t subtype
Subtype of object.
Definition: object.h:339
void commitData()
int SP_level_dam_adjust(const object *caster, const object *spob)
Returns adjusted damage based on the caster.
Definition: spell_util.c:328
void onOpenTreasures()
QAction * mySaveMessages
Definition: CREMainWindow.h:58
#define object_was_destroyed(op, old_tag)
Checks if an object still exists.
Definition: object.h:68
static QString monsterTable(archetype *monster, QList< archetype * > skills)
Generate an HTML table line for a player versus monster fight statistics.
static QString spellsTable(const QString &skill)
mapstruct * test_map
Definition: comet_perf.c:73
void onToolCombatSimulator()
Global type definitions and header inclusions.
void onReportsModified()
QStringList allAnimations() const
void loadQuests()
QAction * myToolHPBar
Definition: CREMainWindow.h:68
The archetype structure is a set of rules on how to generate and manipulate objects which point to ar...
Definition: object.h:465
char savebed_map[MAX_BUF]
Map where player will respawn after death.
Definition: player.h:97
int8_t tail_y
Where the lower right most portion of the object is in comparison to the head.
Definition: object.h:471
#define MIN(x, y)
Definition: compat.h:17
int8_t Con
Definition: living.h:35
unsigned int nrofpixmaps
Number of bitmaps loaded from the "bmaps" file.
Definition: image.c:45
int16_t hp
Hit Points.
Definition: living.h:39
void cleanup(void)
Clean up everything and exit.
Definition: server.c:1137
QAction * myOpenTreasures
Definition: CREMainWindow.h:45
int ingred_count
Number of items in ingred.
Definition: recipe.h:23
void closeEvent(QCloseEvent *event)
void onReportPlayer()
Generate and display a table reporting for each monster and skill at what level approximately the pla...
void onOpenArtifacts()
QAction * myOpenRandomMaps
Definition: CREMainWindow.h:55
QAction * myToolSmooth
Definition: CREMainWindow.h:67
#define MAP_IN_MEMORY
Map is fully loaded.
Definition: map.h:130
void object_free_drop_inventory(object *ob)
Frees everything allocated by an object, removes it from the list of used objects, and puts it on the list of free objects.
Definition: object.c:1368
const char * name
Face name, as used by archetypes and such.
Definition: face.h:20
const char * title
Of foo, etc.
Definition: object.h:317
object * object_insert_in_map_at(object *op, mapstruct *m, object *originator, int flag, int x, int y)
Same as object_insert_in_map() except it handle separate coordinates and do a clean job preparing mul...
Definition: object.c:1921
int16_t maxhp
Max hit points.
Definition: living.h:40
QAction * myOpenMessages
Definition: CREMainWindow.h:53
const QString & title() const
Definition: Quest.cpp:76
#define FREE_OBJ_FREE_INVENTORY
Free inventory objects; if not set, drop inventory.
Definition: object.h:532
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
Next list of artifacts.
Definition: artifact.h:29
sstring title
Distinguishing name of product.
Definition: recipe.h:11
object * create_archetype(const char *name)
Finds which archetype matches the given name, and returns a new object containing a copy of the arche...
Definition: arch.c:620
Image-related structures.
char ** arch_name
Possible archetypes of the final product made.
Definition: recipe.h:13
object * object_insert_in_ob(object *op, object *where)
This function inserts the object op in the linked list inside the object environment.
Definition: object.c:2690
float speed_left
How much speed is left to spend this round.
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
How going up in level affects range.
Definition: object.h:406
double shopGreed() const
struct mapdef * map
Pointer to the map in which this object is present.
Definition: object.h:297
void onReportAlchemy()
QAction * myReportShops
Definition: CREMainWindow.h:65
struct linked_char * next
Definition: global.h:88
struct recipestruct recipe
One alchemy recipe.
QuestManager * myQuestManager
Definition: CREMainWindow.h:73
type_definition ** types
Defined types.
int16_t dam
How much damage this object does when hitting.
Definition: living.h:45
const char * name
The name of the object, obviously...
Definition: object.h:311
int16_t bed_y
x,y - coordinates of respawn (savebed).
Definition: player.h:98
QAction * myOpenResources
Definition: CREMainWindow.h:50
const QString & shopRace() const
This represents one animation.
Definition: face.h:26
QAction * myOpenExperience
Definition: CREMainWindow.h:51
uint8_t num_animations
How many different faces to animate, size of the faces array.
Definition: face.h:28
QAction * myOpenArchetypes
Definition: CREMainWindow.h:44
struct archt * head
The main part of a linked object.
Definition: object.h:468
QAction * mySaveQuests
Definition: CREMainWindow.h:57
EXTERN Animations * animations
Definition: global.h:165
struct pl * contr
Pointer to the player which control this object.
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)
Simulates a fight between a player and a monster.
This represents all archetypes for one particular object type.
Definition: artifact.h:26
uint32_t tag_t
Object tag, unique during the whole game.
Definition: object.h:12
sstring skill
Skill name used to make this recipe.
Definition: recipe.h:26
float speed
The overall speed of this object.
Definition: object.h:328
See Spell.
Definition: object.h:214
#define QUERY_FLAG(xyz, p)
Definition: define.h:225
QAction * myToolCombatSimulator
Definition: CREMainWindow.h:69
EXTERN artifactlist * first_artifactlist
First artifact.
Definition: global.h:121
#define MAX_BUF
Used for all kinds of things.
Definition: define.h:35
This is one artifact, ie one special item.
Definition: artifact.h:14
object * object_create_arch(archetype *at)
Create a full object using the given archetype.
Definition: arch.c:736
QAction * myReportAlchemy
Definition: CREMainWindow.h:61
const char * skill
Name of the skill this object uses/grants.
Definition: object.h:321
QAction * myReportSpells
Definition: CREMainWindow.h:62
void updateReports()
int8_t wc
Weapon Class, how skilled, the lower the better.
Definition: living.h:36
QMenu * mySaveMenu
Definition: CREMainWindow.h:41
CREMapInformationManager * myMapManager
Definition: CREMainWindow.h:72
object * ob
The object representing the player.
Definition: player.h:158
const char * sstring
Strings that should be manipulated through add_string() and free_string().
Definition: global.h:40
const New_Face ** faces
The actual faces for the animation.
Definition: face.h:31
int exp
How much exp to give for this formulae.
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)
Determines the archetype for holy servant and god avatar.
Definition: gods.c:735
Also see SKILL_TOOL (74) below.
Definition: object.h:143
const char * localdir
Read/write data files.
Definition: global.h:245
QList< const Quest * > quests() const
tag_t count
Unique object number for this object.
Definition: object.h:299
living stats
Str, Con, Dex, etc.
Definition: object.h:368
mapstruct * has_been_loaded(const char *name)
Checks whether map has been loaded.
Definition: map.c:79
size_t arch_names
Size of the arch_name[] array.
Definition: recipe.h:12
DisplayMode
uint8_t type
PLAYER, BULLET, etc.
Definition: object.h:338
struct Settings settings
Server settings.
Definition: init.c:40
void object_free2(object *ob, int flags)
Frees everything allocated by an object, removes it from the list of used objects, and puts it on the list of free objects.
Definition: object.c:1391
QAction * myOpenMaps
Definition: CREMainWindow.h:49
struct archt * next
Next archetype in a linked list.
Definition: object.h:467
#define FLAG_APPLIED
Object is ready for use by living.
Definition: define.h:235
void browsingFinished()
Two handed weapons.
Definition: skills.h:56
struct recipestruct * next
Next recipe with the same number of ingredients.
Definition: recipe.h:24
void delete_map(mapstruct *m)
Frees the map, including the mapstruct.
Definition: map.c:1741
QAction * myOpenQuests
Definition: CREMainWindow.h:52
QStringList faces() const
int64_t * levels
Number of levels for which we have experience.
Definition: exp.c:26
static quest_definition * quests
All known quests.
Definition: quest.c:93
quint64 shopMin() const
#define FLAG_MONSTER
Will attack players.
Definition: define.h:245
quint64 shopMax() const
void monster_do_living(object *op)
For a monster, regenerate hp and sp, potentially clear scared status.
Definition: monster.c:500
ScriptFileManager * myScriptManager
Definition: CREMainWindow.h:76
QAction * myOpenFaces
Definition: CREMainWindow.h:48
object * item
Special values of the artifact.
Definition: artifact.h:15
#define IS_COMBAT_SKILL(num)
This macro is used in fix_object() to define if this is a sill that should be used to calculate wc&#39;s ...
Definition: skills.h:92
This is a game-map.
Definition: map.h:325
const New_Face * face
Face with colors.
Definition: object.h:332
static QString alchemyTable(const QString &skill)
void onOpenResources()
QAction * mySaveFormulae
Definition: CREMainWindow.h:56
int16_t level
Level of creature or object.
Definition: object.h:351
void fix_object(object *op)
Updates all abilities given by applied objects in the inventory of the given object.
Definition: living.c:1120
float weapon_speed
The overall speed of this object.
Definition: object.h:330
#define SP_SUMMON_GOLEM
Definition: spells.h:86
Definition: object.h:148
EXTERN archetype * first_archetype
First archetype.
Definition: global.h:122
uint8_t * faces_sent
This is a bitmap on sent face status.
Definition: newserver.h:106
const char * name
More definite name, like "generate_kobold".
Definition: object.h:466
struct recipestruct * items
Pointer to first recipe in this list.
Definition: recipe.h:40
recipelist * get_formulalist(int i)
Gets a formula list by ingredients count.
Definition: recipe.c:114
void object_remove(object *op)
This function removes the object op from the linked list of objects which it is currently tied to...
Definition: object.c:1654
struct artifactstruct * next
Next artifact in the list.
Definition: artifact.h:18
One alchemy recipe.
Definition: recipe.h:10
QHash< QString, int > & shopItems()
void onOpenRandomMaps()
void onReportSpellDamage()
void createActions()
void readDirectory(const QString &path, QHash< QString, QHash< QString, bool > > &states)