troop_profile_service.cpp 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152
  1. #include "troop_profile_service.h"
  2. #include "nation_registry.h"
  3. #include "units/troop_catalog.h"
  4. namespace Game::Systems {
  5. auto TroopProfileService::instance() -> TroopProfileService & {
  6. static TroopProfileService inst;
  7. return inst;
  8. }
  9. void TroopProfileService::clear() { m_cache.clear(); }
  10. auto TroopProfileService::get_profile(
  11. NationID nation_id, Game::Units::TroopType type) -> TroopProfile {
  12. auto &nationCache = m_cache[nation_id];
  13. auto cached = nationCache.find(type);
  14. if (cached != nationCache.end()) {
  15. return cached->second;
  16. }
  17. const Nation *nation = NationRegistry::instance().get_nation(nation_id);
  18. if (nation == nullptr) {
  19. const auto fallback_id = NationRegistry::instance().default_nation_id();
  20. nation = NationRegistry::instance().get_nation(fallback_id);
  21. if (nation == nullptr) {
  22. const auto &all = NationRegistry::instance().get_all_nations();
  23. if (all.empty()) {
  24. const auto &catalog_class =
  25. Game::Units::TroopCatalog::instance().get_class_or_fallback(type);
  26. TroopProfile fallback{};
  27. fallback.display_name = catalog_class.display_name;
  28. fallback.production = catalog_class.production;
  29. fallback.combat = catalog_class.combat;
  30. fallback.visuals = catalog_class.visuals;
  31. fallback.individuals_per_unit = catalog_class.individuals_per_unit;
  32. fallback.max_units_per_row = catalog_class.max_units_per_row;
  33. fallback.formation_type = FormationType::Roman;
  34. return fallback;
  35. }
  36. nation = &all.front();
  37. }
  38. }
  39. TroopProfile profile = build_profile(*nation, type);
  40. nationCache.emplace(type, profile);
  41. return profile;
  42. }
  43. auto TroopProfileService::build_profile(
  44. const Nation &nation, Game::Units::TroopType type) -> TroopProfile {
  45. const auto &catalogClass =
  46. Game::Units::TroopCatalog::instance().get_class_or_fallback(type);
  47. TroopProfile profile{};
  48. profile.display_name = catalogClass.display_name;
  49. profile.production = catalogClass.production;
  50. profile.combat = catalogClass.combat;
  51. profile.visuals = catalogClass.visuals;
  52. profile.individuals_per_unit = catalogClass.individuals_per_unit;
  53. profile.max_units_per_row = catalogClass.max_units_per_row;
  54. profile.formation_type = nation.formation_type;
  55. if (const auto *nationTroop = nation.get_troop(type)) {
  56. profile.display_name = nationTroop->display_name;
  57. profile.production.cost = nationTroop->cost;
  58. profile.production.build_time = nationTroop->build_time;
  59. profile.production.priority = nationTroop->priority;
  60. profile.production.is_melee = nationTroop->is_melee;
  61. }
  62. auto variantIt = nation.troop_variants.find(type);
  63. if (variantIt != nation.troop_variants.end()) {
  64. const auto &variant = variantIt->second;
  65. if (variant.health) {
  66. profile.combat.health = *variant.health;
  67. }
  68. if (variant.max_health) {
  69. profile.combat.max_health = *variant.max_health;
  70. }
  71. if (variant.speed) {
  72. profile.combat.speed = *variant.speed;
  73. }
  74. if (variant.vision_range) {
  75. profile.combat.vision_range = *variant.vision_range;
  76. }
  77. if (variant.attack_damage) {
  78. profile.combat.ranged_damage = *variant.attack_damage;
  79. }
  80. if (variant.attack_range) {
  81. profile.combat.ranged_range = *variant.attack_range;
  82. }
  83. if (variant.attack_cooldown) {
  84. profile.combat.ranged_cooldown = *variant.attack_cooldown;
  85. }
  86. if (variant.melee_damage) {
  87. profile.combat.melee_damage = *variant.melee_damage;
  88. }
  89. if (variant.melee_range) {
  90. profile.combat.melee_range = *variant.melee_range;
  91. }
  92. if (variant.melee_cooldown) {
  93. profile.combat.melee_cooldown = *variant.melee_cooldown;
  94. }
  95. if (variant.individuals_per_unit) {
  96. profile.individuals_per_unit = *variant.individuals_per_unit;
  97. }
  98. if (variant.max_units_per_row) {
  99. profile.max_units_per_row = *variant.max_units_per_row;
  100. }
  101. if (variant.selection_ring_size) {
  102. profile.visuals.selection_ring_size = *variant.selection_ring_size;
  103. }
  104. if (variant.selection_ring_y_offset) {
  105. profile.visuals.selection_ring_y_offset =
  106. *variant.selection_ring_y_offset;
  107. }
  108. if (variant.selection_ring_ground_offset) {
  109. profile.visuals.selection_ring_ground_offset =
  110. *variant.selection_ring_ground_offset;
  111. }
  112. if (variant.renderer_id) {
  113. profile.visuals.renderer_id = *variant.renderer_id;
  114. }
  115. if (variant.render_scale) {
  116. profile.visuals.render_scale = *variant.render_scale;
  117. }
  118. if (variant.formation_type) {
  119. profile.formation_type = *variant.formation_type;
  120. }
  121. if (variant.can_ranged) {
  122. profile.combat.can_ranged = *variant.can_ranged;
  123. }
  124. if (variant.can_melee) {
  125. profile.combat.can_melee = *variant.can_melee;
  126. }
  127. if (variant.max_stamina) {
  128. profile.combat.max_stamina = *variant.max_stamina;
  129. }
  130. if (variant.stamina_regen_rate) {
  131. profile.combat.stamina_regen_rate = *variant.stamina_regen_rate;
  132. }
  133. if (variant.stamina_depletion_rate) {
  134. profile.combat.stamina_depletion_rate = *variant.stamina_depletion_rate;
  135. }
  136. }
  137. return profile;
  138. }
  139. } // namespace Game::Systems