@hytopia.com/examples 1.0.14 → 1.0.17

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (180) hide show
  1. package/frontiers-rpg-game/assets/blocks/Brown_dirt_with_splatters_of_light_green_grass/+x.png +0 -0
  2. package/frontiers-rpg-game/assets/blocks/Brown_dirt_with_splatters_of_light_green_grass/+y.png +0 -0
  3. package/frontiers-rpg-game/assets/blocks/Brown_dirt_with_splatters_of_light_green_grass/+z.png +0 -0
  4. package/frontiers-rpg-game/assets/blocks/Brown_dirt_with_splatters_of_light_green_grass/-x.png +0 -0
  5. package/frontiers-rpg-game/assets/blocks/Brown_dirt_with_splatters_of_light_green_grass/-y.png +0 -0
  6. package/frontiers-rpg-game/assets/blocks/Brown_dirt_with_splatters_of_light_green_grass/-z.png +0 -0
  7. package/frontiers-rpg-game/assets/blocks/carved_stone_face/+x.png +0 -0
  8. package/frontiers-rpg-game/assets/blocks/carved_stone_face/+y.png +0 -0
  9. package/frontiers-rpg-game/assets/blocks/carved_stone_face/+z.png +0 -0
  10. package/frontiers-rpg-game/assets/blocks/carved_stone_face/-x.png +0 -0
  11. package/frontiers-rpg-game/assets/blocks/carved_stone_face/-y.png +0 -0
  12. package/frontiers-rpg-game/assets/blocks/carved_stone_face/-z.png +0 -0
  13. package/frontiers-rpg-game/assets/blocks/coral/+x.png +0 -0
  14. package/frontiers-rpg-game/assets/blocks/coral/+y.png +0 -0
  15. package/frontiers-rpg-game/assets/blocks/coral/+z.png +0 -0
  16. package/frontiers-rpg-game/assets/blocks/coral/-x.png +0 -0
  17. package/frontiers-rpg-game/assets/blocks/coral/-y.png +0 -0
  18. package/frontiers-rpg-game/assets/blocks/coral/-z.png +0 -0
  19. package/frontiers-rpg-game/assets/blocks/square_single_stone_brick/+x.png +0 -0
  20. package/frontiers-rpg-game/assets/blocks/square_single_stone_brick/+y.png +0 -0
  21. package/frontiers-rpg-game/assets/blocks/square_single_stone_brick/+z.png +0 -0
  22. package/frontiers-rpg-game/assets/blocks/square_single_stone_brick/-x.png +0 -0
  23. package/frontiers-rpg-game/assets/blocks/square_single_stone_brick/-y.png +0 -0
  24. package/frontiers-rpg-game/assets/blocks/square_single_stone_brick/-z.png +0 -0
  25. package/frontiers-rpg-game/assets/maps/hearthwilds.json +287978 -0
  26. package/frontiers-rpg-game/assets/models/environment/.optimized/barrel-wood-1/barrel-wood-1-named-nodes.bin +0 -0
  27. package/frontiers-rpg-game/assets/models/environment/.optimized/barrel-wood-1/barrel-wood-1-named-nodes.gltf +294 -0
  28. package/frontiers-rpg-game/assets/models/environment/.optimized/barrel-wood-1/barrel-wood-1.bin +0 -0
  29. package/frontiers-rpg-game/assets/models/environment/.optimized/barrel-wood-1/barrel-wood-1.gltf +136 -0
  30. package/frontiers-rpg-game/assets/models/environment/.optimized/barrel-wood-1/barrel-wood-1.gltf.md5 +1 -0
  31. package/frontiers-rpg-game/assets/models/environment/.optimized/barrel-wood-1/baseColor.png +0 -0
  32. package/frontiers-rpg-game/assets/models/environment/.optimized/barrel-wood-2/barrel-wood-2-named-nodes.bin +0 -0
  33. package/frontiers-rpg-game/assets/models/environment/.optimized/barrel-wood-2/barrel-wood-2-named-nodes.gltf +410 -0
  34. package/frontiers-rpg-game/assets/models/environment/.optimized/barrel-wood-2/barrel-wood-2.bin +0 -0
  35. package/frontiers-rpg-game/assets/models/environment/.optimized/barrel-wood-2/barrel-wood-2.gltf +142 -0
  36. package/frontiers-rpg-game/assets/models/environment/.optimized/barrel-wood-2/barrel-wood-2.gltf.md5 +1 -0
  37. package/frontiers-rpg-game/assets/models/environment/.optimized/barrel-wood-2/baseColor.png +0 -0
  38. package/frontiers-rpg-game/assets/models/environment/.optimized/bush-berry/baseColor.png +0 -0
  39. package/frontiers-rpg-game/assets/models/environment/.optimized/bush-berry/bush-berry-named-nodes.bin +0 -0
  40. package/frontiers-rpg-game/assets/models/environment/.optimized/bush-berry/bush-berry-named-nodes.gltf +621 -0
  41. package/frontiers-rpg-game/assets/models/environment/.optimized/bush-berry/bush-berry.bin +0 -0
  42. package/frontiers-rpg-game/assets/models/environment/.optimized/bush-berry/bush-berry.gltf +629 -0
  43. package/frontiers-rpg-game/assets/models/environment/.optimized/bush-berry/bush-berry.gltf.md5 +1 -0
  44. package/frontiers-rpg-game/assets/models/environment/.optimized/cat-statue/baseColor.png +0 -0
  45. package/frontiers-rpg-game/assets/models/environment/.optimized/cat-statue/cat-statue-named-nodes.bin +0 -0
  46. package/frontiers-rpg-game/assets/models/environment/.optimized/cat-statue/cat-statue-named-nodes.gltf +889 -0
  47. package/frontiers-rpg-game/assets/models/environment/.optimized/cat-statue/cat-statue.bin +0 -0
  48. package/frontiers-rpg-game/assets/models/environment/.optimized/cat-statue/cat-statue.gltf +136 -0
  49. package/frontiers-rpg-game/assets/models/environment/.optimized/cat-statue/cat-statue.gltf.md5 +1 -0
  50. package/frontiers-rpg-game/assets/models/environment/.optimized/dead-tree-big/baseColor.png +0 -0
  51. package/frontiers-rpg-game/assets/models/environment/.optimized/dead-tree-big/dead-tree-big-named-nodes.bin +0 -0
  52. package/frontiers-rpg-game/assets/models/environment/.optimized/dead-tree-big/dead-tree-big-named-nodes.gltf +5292 -0
  53. package/frontiers-rpg-game/assets/models/environment/.optimized/dead-tree-big/dead-tree-big.bin +0 -0
  54. package/frontiers-rpg-game/assets/models/environment/.optimized/dead-tree-big/dead-tree-big.gltf +2623 -0
  55. package/frontiers-rpg-game/assets/models/environment/.optimized/dead-tree-big/dead-tree-big.gltf.md5 +1 -0
  56. package/frontiers-rpg-game/assets/models/environment/.optimized/dead-tree-medium/baseColor.png +0 -0
  57. package/frontiers-rpg-game/assets/models/environment/.optimized/dead-tree-medium/dead-tree-medium-named-nodes.bin +0 -0
  58. package/frontiers-rpg-game/assets/models/environment/.optimized/dead-tree-medium/dead-tree-medium-named-nodes.gltf +2763 -0
  59. package/frontiers-rpg-game/assets/models/environment/.optimized/dead-tree-medium/dead-tree-medium.bin +0 -0
  60. package/frontiers-rpg-game/assets/models/environment/.optimized/dead-tree-medium/dead-tree-medium.gltf +1406 -0
  61. package/frontiers-rpg-game/assets/models/environment/.optimized/dead-tree-medium/dead-tree-medium.gltf.md5 +1 -0
  62. package/frontiers-rpg-game/assets/models/environment/.optimized/fallen-fruit/baseColor.png +0 -0
  63. package/frontiers-rpg-game/assets/models/environment/.optimized/fallen-fruit/fallen-fruit-named-nodes.bin +0 -0
  64. package/frontiers-rpg-game/assets/models/environment/.optimized/fallen-fruit/fallen-fruit-named-nodes.gltf +544 -0
  65. package/frontiers-rpg-game/assets/models/environment/.optimized/fallen-fruit/fallen-fruit.bin +0 -0
  66. package/frontiers-rpg-game/assets/models/environment/.optimized/fallen-fruit/fallen-fruit.gltf +142 -0
  67. package/frontiers-rpg-game/assets/models/environment/.optimized/fallen-fruit/fallen-fruit.gltf.md5 +1 -0
  68. package/frontiers-rpg-game/assets/models/environment/.optimized/flower-tuft/baseColor.png +0 -0
  69. package/frontiers-rpg-game/assets/models/environment/.optimized/flower-tuft/flower-tuft-named-nodes.bin +0 -0
  70. package/frontiers-rpg-game/assets/models/environment/.optimized/flower-tuft/flower-tuft-named-nodes.gltf +1703 -0
  71. package/frontiers-rpg-game/assets/models/environment/.optimized/flower-tuft/flower-tuft.bin +0 -0
  72. package/frontiers-rpg-game/assets/models/environment/.optimized/flower-tuft/flower-tuft.gltf +766 -0
  73. package/frontiers-rpg-game/assets/models/environment/.optimized/flower-tuft/flower-tuft.gltf.md5 +1 -0
  74. package/frontiers-rpg-game/assets/models/environment/.optimized/flowers-cluster/baseColor.png +0 -0
  75. package/frontiers-rpg-game/assets/models/environment/.optimized/flowers-cluster/flowers-cluster-named-nodes.bin +0 -0
  76. package/frontiers-rpg-game/assets/models/environment/.optimized/flowers-cluster/flowers-cluster-named-nodes.gltf +2354 -0
  77. package/frontiers-rpg-game/assets/models/environment/.optimized/flowers-cluster/flowers-cluster.bin +0 -0
  78. package/frontiers-rpg-game/assets/models/environment/.optimized/flowers-cluster/flowers-cluster.gltf +685 -0
  79. package/frontiers-rpg-game/assets/models/environment/.optimized/flowers-cluster/flowers-cluster.gltf.md5 +1 -0
  80. package/frontiers-rpg-game/assets/models/environment/.optimized/grass-tall/baseColor.png +0 -0
  81. package/frontiers-rpg-game/assets/models/environment/.optimized/grass-tall/grass-tall-named-nodes.bin +0 -0
  82. package/frontiers-rpg-game/assets/models/environment/.optimized/grass-tall/grass-tall-named-nodes.gltf +365 -0
  83. package/frontiers-rpg-game/assets/models/environment/.optimized/grass-tall/grass-tall.bin +0 -0
  84. package/frontiers-rpg-game/assets/models/environment/.optimized/grass-tall/grass-tall.gltf +301 -0
  85. package/frontiers-rpg-game/assets/models/environment/.optimized/grass-tall/grass-tall.gltf.md5 +1 -0
  86. package/frontiers-rpg-game/assets/models/environment/.optimized/grass-wild-clump/baseColor.png +0 -0
  87. package/frontiers-rpg-game/assets/models/environment/.optimized/grass-wild-clump/grass-wild-clump-named-nodes.bin +0 -0
  88. package/frontiers-rpg-game/assets/models/environment/.optimized/grass-wild-clump/grass-wild-clump-named-nodes.gltf +893 -0
  89. package/frontiers-rpg-game/assets/models/environment/.optimized/grass-wild-clump/grass-wild-clump.bin +0 -0
  90. package/frontiers-rpg-game/assets/models/environment/.optimized/grass-wild-clump/grass-wild-clump.gltf +893 -0
  91. package/frontiers-rpg-game/assets/models/environment/.optimized/grass-wild-clump/grass-wild-clump.gltf.md5 +1 -0
  92. package/frontiers-rpg-game/assets/models/environment/.optimized/mushroom-red-multiple/baseColor.png +0 -0
  93. package/frontiers-rpg-game/assets/models/environment/.optimized/mushroom-red-multiple/mushroom-red-multiple-named-nodes.bin +0 -0
  94. package/frontiers-rpg-game/assets/models/environment/.optimized/mushroom-red-multiple/mushroom-red-multiple-named-nodes.gltf +260 -0
  95. package/frontiers-rpg-game/assets/models/environment/.optimized/mushroom-red-multiple/mushroom-red-multiple.bin +0 -0
  96. package/frontiers-rpg-game/assets/models/environment/.optimized/mushroom-red-multiple/mushroom-red-multiple.gltf +136 -0
  97. package/frontiers-rpg-game/assets/models/environment/.optimized/mushroom-red-multiple/mushroom-red-multiple.gltf.md5 +1 -0
  98. package/frontiers-rpg-game/assets/models/environment/.optimized/oak-stairs/baseColor.png +0 -0
  99. package/frontiers-rpg-game/assets/models/environment/.optimized/oak-stairs/oak-stairs.gltf.md5 +1 -1
  100. package/frontiers-rpg-game/assets/models/environment/.optimized/oak-tree-big/baseColor.png +0 -0
  101. package/frontiers-rpg-game/assets/models/environment/.optimized/oak-tree-big/oak-tree-big-named-nodes.bin +0 -0
  102. package/frontiers-rpg-game/assets/models/environment/.optimized/oak-tree-big/oak-tree-big-named-nodes.gltf +3299 -0
  103. package/frontiers-rpg-game/assets/models/environment/.optimized/oak-tree-big/oak-tree-big.bin +0 -0
  104. package/frontiers-rpg-game/assets/models/environment/.optimized/oak-tree-big/oak-tree-big.gltf +1359 -0
  105. package/frontiers-rpg-game/assets/models/environment/.optimized/oak-tree-big/oak-tree-big.gltf.md5 +1 -0
  106. package/frontiers-rpg-game/assets/models/environment/.optimized/oak-tree-medium/baseColor.png +0 -0
  107. package/frontiers-rpg-game/assets/models/environment/.optimized/oak-tree-medium/oak-tree-medium-named-nodes.bin +0 -0
  108. package/frontiers-rpg-game/assets/models/environment/.optimized/oak-tree-medium/oak-tree-medium-named-nodes.gltf +7187 -0
  109. package/frontiers-rpg-game/assets/models/environment/.optimized/oak-tree-medium/oak-tree-medium.bin +0 -0
  110. package/frontiers-rpg-game/assets/models/environment/.optimized/oak-tree-medium/oak-tree-medium.gltf +1897 -0
  111. package/frontiers-rpg-game/assets/models/environment/.optimized/oak-tree-medium/oak-tree-medium.gltf.md5 +1 -0
  112. package/frontiers-rpg-game/assets/models/environment/.optimized/oak-tree-small/baseColor.png +0 -0
  113. package/frontiers-rpg-game/assets/models/environment/.optimized/oak-tree-small/oak-tree-small-named-nodes.bin +0 -0
  114. package/frontiers-rpg-game/assets/models/environment/.optimized/oak-tree-small/oak-tree-small-named-nodes.gltf +3455 -0
  115. package/frontiers-rpg-game/assets/models/environment/.optimized/oak-tree-small/oak-tree-small.bin +0 -0
  116. package/frontiers-rpg-game/assets/models/environment/.optimized/oak-tree-small/oak-tree-small.gltf +765 -0
  117. package/frontiers-rpg-game/assets/models/environment/.optimized/oak-tree-small/oak-tree-small.gltf.md5 +1 -0
  118. package/frontiers-rpg-game/assets/models/environment/.optimized/redcap-mushroom-group/baseColor.png +0 -0
  119. package/frontiers-rpg-game/assets/models/environment/.optimized/redcap-mushroom-group/redcap-mushroom-group-named-nodes.bin +0 -0
  120. package/frontiers-rpg-game/assets/models/environment/.optimized/redcap-mushroom-group/redcap-mushroom-group-named-nodes.gltf +487 -0
  121. package/frontiers-rpg-game/assets/models/environment/.optimized/redcap-mushroom-group/redcap-mushroom-group.bin +0 -0
  122. package/frontiers-rpg-game/assets/models/environment/.optimized/redcap-mushroom-group/redcap-mushroom-group.gltf +136 -0
  123. package/frontiers-rpg-game/assets/models/environment/.optimized/redcap-mushroom-group/redcap-mushroom-group.gltf.md5 +1 -0
  124. package/frontiers-rpg-game/assets/models/environment/.optimized/scattered-pebbles/baseColor.png +0 -0
  125. package/frontiers-rpg-game/assets/models/environment/.optimized/scattered-pebbles/scattered-pebbles-named-nodes.bin +0 -0
  126. package/frontiers-rpg-game/assets/models/environment/.optimized/scattered-pebbles/scattered-pebbles-named-nodes.gltf +356 -0
  127. package/frontiers-rpg-game/assets/models/environment/.optimized/scattered-pebbles/scattered-pebbles.bin +0 -0
  128. package/frontiers-rpg-game/assets/models/environment/.optimized/scattered-pebbles/scattered-pebbles.gltf +136 -0
  129. package/frontiers-rpg-game/assets/models/environment/.optimized/scattered-pebbles/scattered-pebbles.gltf.md5 +1 -0
  130. package/frontiers-rpg-game/assets/models/environment/.optimized/shell-starfish-group/baseColor.png +0 -0
  131. package/frontiers-rpg-game/assets/models/environment/.optimized/shell-starfish-group/shell-starfish-group-named-nodes.bin +0 -0
  132. package/frontiers-rpg-game/assets/models/environment/.optimized/shell-starfish-group/shell-starfish-group-named-nodes.gltf +772 -0
  133. package/frontiers-rpg-game/assets/models/environment/.optimized/shell-starfish-group/shell-starfish-group.bin +0 -0
  134. package/frontiers-rpg-game/assets/models/environment/.optimized/shell-starfish-group/shell-starfish-group.gltf +142 -0
  135. package/frontiers-rpg-game/assets/models/environment/.optimized/shell-starfish-group/shell-starfish-group.gltf.md5 +1 -0
  136. package/frontiers-rpg-game/assets/models/environment/barrel-wood-1.gltf +1 -0
  137. package/frontiers-rpg-game/assets/models/environment/barrel-wood-2.gltf +1 -0
  138. package/frontiers-rpg-game/assets/models/environment/bush-berry.gltf +1 -0
  139. package/frontiers-rpg-game/assets/models/environment/cat-statue.gltf +1 -0
  140. package/frontiers-rpg-game/assets/models/environment/dead-tree-big.gltf +1 -0
  141. package/frontiers-rpg-game/assets/models/environment/dead-tree-medium.gltf +1 -0
  142. package/frontiers-rpg-game/assets/models/environment/fallen-fruit.gltf +1 -0
  143. package/frontiers-rpg-game/assets/models/environment/flower-tuft.gltf +1 -0
  144. package/frontiers-rpg-game/assets/models/environment/flowers-cluster.gltf +1 -0
  145. package/frontiers-rpg-game/assets/models/environment/grass-tall.gltf +1 -0
  146. package/frontiers-rpg-game/assets/models/environment/grass-wild-clump.gltf +1 -0
  147. package/frontiers-rpg-game/assets/models/environment/mushroom-red-multiple.gltf +1 -0
  148. package/frontiers-rpg-game/assets/models/environment/oak-stairs.gltf +1 -1
  149. package/frontiers-rpg-game/assets/models/environment/oak-tree-big.gltf +1 -0
  150. package/frontiers-rpg-game/assets/models/environment/oak-tree-medium.gltf +1 -0
  151. package/frontiers-rpg-game/assets/models/environment/oak-tree-small.gltf +1 -0
  152. package/frontiers-rpg-game/assets/models/environment/redcap-mushroom-group.gltf +1 -0
  153. package/frontiers-rpg-game/assets/models/environment/scattered-pebbles.gltf +1 -0
  154. package/frontiers-rpg-game/assets/models/environment/shell-starfish-group.gltf +1 -0
  155. package/frontiers-rpg-game/assets/ui/hud.html +24 -3
  156. package/frontiers-rpg-game/assets/ui/index.html +41 -14
  157. package/frontiers-rpg-game/assets/ui/menus/quests.html +4 -3
  158. package/frontiers-rpg-game/assets/ui/scene-ui-templates/entity-nameplate.html +12 -8
  159. package/frontiers-rpg-game/assets/ui/shared/item-tooltips.html +1 -0
  160. package/frontiers-rpg-game/dev/persistence/player-player-1.json +18 -55
  161. package/frontiers-rpg-game/src/GameClock.ts +13 -3
  162. package/frontiers-rpg-game/src/GameManager.ts +8 -0
  163. package/frontiers-rpg-game/src/GamePlayer.ts +4 -0
  164. package/frontiers-rpg-game/src/GamePlayerEntity.ts +46 -9
  165. package/frontiers-rpg-game/src/GameRegion.ts +17 -2
  166. package/frontiers-rpg-game/src/entities/BaseCombatEntity.ts +33 -1
  167. package/frontiers-rpg-game/src/entities/BaseEntity.ts +23 -13
  168. package/frontiers-rpg-game/src/entities/enemies/QueenWeaverEntity.ts +1 -0
  169. package/frontiers-rpg-game/src/entities/enemies/RatkinBruteEntity.ts +2 -2
  170. package/frontiers-rpg-game/src/entities/enemies/RatkinRangerEntity.ts +2 -2
  171. package/frontiers-rpg-game/src/entities/enemies/RatkinSpellcasterEntity.ts +2 -2
  172. package/frontiers-rpg-game/src/entities/enemies/RatkinWarriorEntity.ts +2 -2
  173. package/frontiers-rpg-game/src/items/BaseItem.ts +1 -1
  174. package/frontiers-rpg-game/src/items/BaseWeaponItem.ts +9 -2
  175. package/frontiers-rpg-game/src/items/consumables/MinorHealingPotionItem.ts +1 -1
  176. package/frontiers-rpg-game/src/items/weapons/DullSwordItem.ts +3 -3
  177. package/frontiers-rpg-game/src/items/weapons/IronLongSwordItem.ts +3 -3
  178. package/frontiers-rpg-game/src/items/weapons/TrainingSwordItem.ts +3 -3
  179. package/frontiers-rpg-game/src/regions/hearthwilds/HearthwildsRegion.ts +25 -0
  180. package/package.json +1 -1
@@ -400,6 +400,7 @@ window.ItemTooltips = (function() {
400
400
  .backpack-slot:hover .item-tooltip,
401
401
  .backpack-hotbar-slot:hover .item-tooltip,
402
402
  .backpack-wearable-slot:hover .item-tooltip,
403
+ .hud-hotbar-slot:hover .item-tooltip,
403
404
  .merchant-slot:hover .item-tooltip,
404
405
  .merchant-hotbar-slot:hover .item-tooltip,
405
406
  .crafting-slot:hover .item-tooltip,
@@ -3112,12 +3113,13 @@ window.ItemTooltips = (function() {
3112
3113
 
3113
3114
  .quests-section:first-child {
3114
3115
  flex: 1;
3115
- min-height: 0;
3116
+ min-height: 50%;
3116
3117
  }
3117
3118
 
3118
- /* When active quests section has only placeholder, don't expand */
3119
+ /* When active quests section has only placeholder, still maintain minimum height */
3119
3120
  .quests-section:first-child:has(.quests-empty-section:only-child) {
3120
- flex: none;
3121
+ flex: 1;
3122
+ min-height: 50%;
3121
3123
  }
3122
3124
 
3123
3125
  .quests-section-title {
@@ -6211,6 +6213,16 @@ window.ItemTooltips = (function() {
6211
6213
  else if (healthPercent > 0.33) healthBarFill.classList.add('health-medium');
6212
6214
  else healthBarFill.classList.add('health-low');
6213
6215
  }
6216
+
6217
+ if (state.type) {
6218
+ // Remove any existing type classes
6219
+ nameplate.classList.remove('boss');
6220
+
6221
+ // Apply boss class if entity type is boss
6222
+ if (state.type === 'boss') {
6223
+ nameplate.classList.add('boss');
6224
+ }
6225
+ }
6214
6226
  });
6215
6227
 
6216
6228
  function showDamageNumber(amount, type) {
@@ -6419,14 +6431,8 @@ window.ItemTooltips = (function() {
6419
6431
  .entity-nameplate-health-bar-fill.health-medium { background-color: #FFC107; }
6420
6432
  .entity-nameplate-health-bar-fill.health-low { background-color: #f44336; }
6421
6433
 
6422
- .entity-nameplate.elite .entity-nameplate-name {
6423
- font-size: 12px;
6424
- font-weight: 700;
6425
- background: linear-gradient(45deg, #ffd700, #ffed4e);
6426
- -webkit-background-clip: text;
6427
- -webkit-text-fill-color: transparent;
6428
- background-clip: text;
6429
- filter: drop-shadow(0 0 8px rgba(255,215,0,0.5)) drop-shadow(0 1px 3px rgba(0,0,0,0.9));
6434
+ .entity-nameplate.boss .entity-nameplate-name {
6435
+ color: #ef4444;
6430
6436
  }
6431
6437
  </style>
6432
6438
 
@@ -6856,6 +6862,23 @@ window.ItemTooltips = (function() {
6856
6862
  hytopia.sendData({ type: 'setSelectedHotbarIndex', index });
6857
6863
  }
6858
6864
 
6865
+ // Use shared tooltip system (same as backpack)
6866
+ function createTooltip(slot, itemData) {
6867
+ if (window.ItemTooltips) {
6868
+ ItemTooltips.createTooltip(slot, itemData, {
6869
+ tooltipClass: 'item-tooltip',
6870
+ contentClass: 'item-tooltip-content',
6871
+ showSellPrice: true
6872
+ });
6873
+ }
6874
+ }
6875
+
6876
+ function removeTooltip(slot) {
6877
+ if (window.ItemTooltips) {
6878
+ ItemTooltips.removeTooltip(slot, 'item-tooltip');
6879
+ }
6880
+ }
6881
+
6859
6882
  // Update Functions
6860
6883
  function updateHealthBar(health, maxHealth) {
6861
6884
  const healthBar = document.querySelector('.hud-health-fill');
@@ -6919,6 +6942,9 @@ window.ItemTooltips = (function() {
6919
6942
 
6920
6943
  content.innerHTML = '';
6921
6944
 
6945
+ // Clear existing tooltip
6946
+ removeTooltip(slot);
6947
+
6922
6948
  if (itemData.removed) {
6923
6949
  content.textContent = position + 1;
6924
6950
  } else {
@@ -6934,6 +6960,9 @@ window.ItemTooltips = (function() {
6934
6960
  quantity.textContent = itemData.quantity.toLocaleString();
6935
6961
  content.appendChild(quantity);
6936
6962
  }
6963
+
6964
+ // Create tooltip
6965
+ createTooltip(slot, itemData);
6937
6966
  }
6938
6967
  }
6939
6968
 
@@ -7334,7 +7363,7 @@ window.ItemTooltips = (function() {
7334
7363
  justify-content: center;
7335
7364
  cursor: pointer;
7336
7365
  transition: all var(--hud-transition);
7337
- overflow: hidden;
7366
+ overflow: visible;
7338
7367
  box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.5);
7339
7368
  }
7340
7369
 
@@ -8064,8 +8093,6 @@ window.ItemTooltips = (function() {
8064
8093
  font-size: 8px;
8065
8094
  }
8066
8095
 
8067
-
8068
-
8069
8096
  .hud-help-icon {
8070
8097
  font-size: 18px;
8071
8098
  }
@@ -524,12 +524,13 @@
524
524
 
525
525
  .quests-section:first-child {
526
526
  flex: 1;
527
- min-height: 0;
527
+ min-height: 50%;
528
528
  }
529
529
 
530
- /* When active quests section has only placeholder, don't expand */
530
+ /* When active quests section has only placeholder, still maintain minimum height */
531
531
  .quests-section:first-child:has(.quests-empty-section:only-child) {
532
- flex: none;
532
+ flex: 1;
533
+ min-height: 50%;
533
534
  }
534
535
 
535
536
  .quests-section-title {
@@ -129,6 +129,16 @@
129
129
  else if (healthPercent > 0.33) healthBarFill.classList.add('health-medium');
130
130
  else healthBarFill.classList.add('health-low');
131
131
  }
132
+
133
+ if (state.type) {
134
+ // Remove any existing type classes
135
+ nameplate.classList.remove('boss');
136
+
137
+ // Apply boss class if entity type is boss
138
+ if (state.type === 'boss') {
139
+ nameplate.classList.add('boss');
140
+ }
141
+ }
132
142
  });
133
143
 
134
144
  function showDamageNumber(amount, type) {
@@ -337,13 +347,7 @@
337
347
  .entity-nameplate-health-bar-fill.health-medium { background-color: #FFC107; }
338
348
  .entity-nameplate-health-bar-fill.health-low { background-color: #f44336; }
339
349
 
340
- .entity-nameplate.elite .entity-nameplate-name {
341
- font-size: 12px;
342
- font-weight: 700;
343
- background: linear-gradient(45deg, #ffd700, #ffed4e);
344
- -webkit-background-clip: text;
345
- -webkit-text-fill-color: transparent;
346
- background-clip: text;
347
- filter: drop-shadow(0 0 8px rgba(255,215,0,0.5)) drop-shadow(0 1px 3px rgba(0,0,0,0.9));
350
+ .entity-nameplate.boss .entity-nameplate-name {
351
+ color: #ef4444;
348
352
  }
349
353
  </style>
@@ -151,6 +151,7 @@ window.ItemTooltips = (function() {
151
151
  .backpack-slot:hover .item-tooltip,
152
152
  .backpack-hotbar-slot:hover .item-tooltip,
153
153
  .backpack-wearable-slot:hover .item-tooltip,
154
+ .hud-hotbar-slot:hover .item-tooltip,
154
155
  .merchant-slot:hover .item-tooltip,
155
156
  .merchant-hotbar-slot:hover .item-tooltip,
156
157
  .crafting-slot:hover .item-tooltip,
@@ -1,37 +1,22 @@
1
1
  {
2
- "health": 130,
3
- "currentRegionId": "stalkhaven-port",
2
+ "health": 120,
3
+ "currentRegionId": "chitter-forest",
4
4
  "skillExperience": [
5
5
  [
6
6
  "exploration",
7
- 375
8
- ],
9
- [
10
- "agility",
11
- 79
7
+ 225
12
8
  ],
13
9
  [
14
10
  "combat",
15
- 320
11
+ 162
16
12
  ],
17
13
  [
18
- "foraging",
19
- 8
14
+ "agility",
15
+ 20
20
16
  ]
21
17
  ],
22
18
  "backpack": {
23
- "items": [
24
- {
25
- "position": 0,
26
- "itemId": "common_mushroom",
27
- "quantity": 3
28
- },
29
- {
30
- "position": 1,
31
- "itemId": "ratkin_tooth",
32
- "quantity": 3
33
- }
34
- ]
19
+ "items": []
35
20
  },
36
21
  "hotbar": {
37
22
  "items": [
@@ -46,31 +31,25 @@
46
31
  {
47
32
  "position": 3,
48
33
  "itemId": "gold",
49
- "quantity": 147
34
+ "quantity": 82
50
35
  },
51
36
  {
52
37
  "position": 1,
53
- "itemId": "raw_hide",
54
- "quantity": 2
38
+ "itemId": "ratkin_tail"
55
39
  },
56
40
  {
57
41
  "position": 4,
58
- "itemId": "ratkin_eyes"
42
+ "itemId": "ratkin_tooth"
59
43
  },
60
44
  {
61
45
  "position": 5,
62
- "itemId": "ratkin_tail",
63
- "quantity": 2
46
+ "itemId": "ratkin_eyes",
47
+ "quantity": 3
64
48
  },
65
49
  {
66
50
  "position": 6,
67
51
  "itemId": "ratkin_bones",
68
52
  "quantity": 3
69
- },
70
- {
71
- "position": 7,
72
- "itemId": "common_seeds",
73
- "quantity": 4
74
53
  }
75
54
  ]
76
55
  },
@@ -95,27 +74,11 @@
95
74
  },
96
75
  {
97
76
  "questId": "tested-mettle",
98
- "state": "completed",
77
+ "state": "active",
99
78
  "objectiveProgress": {
100
79
  "kill-5-ratkin": 5,
101
80
  "dodge-3-times": 3,
102
- "talk-to-mark": 1
103
- }
104
- },
105
- {
106
- "questId": "hammers-and-crafting",
107
- "state": "active",
108
- "objectiveProgress": {
109
- "gather-materials": 2,
110
- "craft-item": 0,
111
- "talk-to-arden": 0
112
- }
113
- },
114
- {
115
- "questId": "stalkhavens-outpost",
116
- "state": "active",
117
- "objectiveProgress": {
118
- "talk-to-chanterelion": 0
81
+ "talk-to-mark": 0
119
82
  }
120
83
  }
121
84
  ]
@@ -131,10 +94,10 @@
131
94
  }
132
95
  ]
133
96
  },
134
- "currentRegionSpawnFacingAngle": 180,
97
+ "currentRegionSpawnFacingAngle": 0,
135
98
  "currentRegionSpawnPoint": {
136
- "x": -6,
137
- "y": 8,
138
- "z": -28
99
+ "x": -7,
100
+ "y": 2,
101
+ "z": 76
139
102
  }
140
103
  }
@@ -1,6 +1,6 @@
1
1
  import type GameRegion from './GameRegion';
2
2
 
3
- const CYCLE_CLOCK_INTERVAL_MS = 5000; // Update clock every 1 second
3
+ const CYCLE_CLOCK_INTERVAL_MS = 5000; // Update clock every 5 second
4
4
  const CYCLE_CLOCK_OFFSET_HOURS = 7;
5
5
  const CYCLE_DAY_MAX_SKYBOX_INTENSITY = 1.2;
6
6
  const CYCLE_DURATION_MS = 24 * 60 * 1000; // Day/Night Cycle Every 24 minutes
@@ -49,9 +49,19 @@ export default class GameClock {
49
49
  private _updateRegionClockCycle(region: GameRegion): void {
50
50
  const world = region.world;
51
51
 
52
- // Calculate sun position in circular path
52
+ // Calculate sun position with asymmetric day/night cycle (75% day, 25% night)
53
53
  const timeProgress = this._timeMs / CYCLE_DURATION_MS;
54
- const sunAngle = timeProgress * 2 * Math.PI;
54
+
55
+ // Create asymmetric sun angle: 75% of time for day, 25% for night
56
+ let sunAngle: number;
57
+ if (timeProgress < 0.75) {
58
+ // Day period: map first 75% of cycle to first half of sine wave (0 to π)
59
+ sunAngle = (timeProgress / 0.75) * Math.PI;
60
+ } else {
61
+ // Night period: map last 25% of cycle to second half of sine wave (π to 2π)
62
+ sunAngle = Math.PI + ((timeProgress - 0.75) / 0.25) * Math.PI;
63
+ }
64
+
55
65
  const sunRadius = 300;
56
66
  const sunHeight = 100 + Math.sin(sunAngle) * 150;
57
67
 
@@ -7,6 +7,7 @@ import type GameRegion from './GameRegion';
7
7
 
8
8
  // Regions
9
9
  import ChitterForestRegion from './regions/chitter-forest/ChitterForestRegion';
10
+ import HearthwildsRegion from './regions/hearthwilds/HearthwildsRegion';
10
11
  import RatkinNestRegion from './regions/ratkin-nest/RatkinNestRegion';
11
12
  import StalkhavenRegion from './regions/stalkhaven/StalkhavenRegion';
12
13
  import StalkhavenPortRegion from './regions/stalkhaven-port/StalkhavenPortRegion';
@@ -46,10 +47,17 @@ export default class GameManager {
46
47
  this._regions.set(chitterForestRegion.id, chitterForestRegion);
47
48
  GameClock.instance.addRegionClockCycle(chitterForestRegion);
48
49
 
50
+ // Hearthwilds
51
+ // const hearthwildsRegion = new HearthwildsRegion();
52
+ // this._regions.set(hearthwildsRegion.id, hearthwildsRegion);
53
+ // GameClock.instance.addRegionClockCycle(hearthwildsRegion);
54
+ // this._startRegion = hearthwildsRegion;
55
+
49
56
  // Ratkin Nest
50
57
  const ratkinNestRegion = new RatkinNestRegion();
51
58
  this._regions.set(ratkinNestRegion.id, ratkinNestRegion);
52
59
  GameClock.instance.addRegionClockCycle(ratkinNestRegion);
60
+ // this._startRegion = ratkinNestRegion;
53
61
 
54
62
  // Stalkhaven
55
63
  const stalkhavenRegion = new StalkhavenRegion();
@@ -359,6 +359,10 @@ export default class GamePlayer {
359
359
  this._spawnHeldItem();
360
360
  }
361
361
 
362
+ public onPlayerReconnected(): void {
363
+ this._loadUI();
364
+ }
365
+
362
366
  public removeEntityAlert(entityClass: typeof BaseEntity): void {
363
367
  if (!this._entityAlertClassNames.has(entityClass.name)) return;
364
368
 
@@ -71,16 +71,53 @@ export default class GamePlayerEntity extends DefaultPlayerEntity implements IDa
71
71
  }
72
72
 
73
73
  public get adjustedFacingDirection(): Vector3Like {
74
- const shoulderAngleRad = -this.player.camera.shoulderAngle * Math.PI / 180;
74
+ // This implementation is a bit of a hack to get the right "tuned" facing
75
+ // direction based on the center crosshair of the player relative to the shoulder
76
+ // angle offset. We should probabaly find a better way to handle screen center relative
77
+ // to shoulder angle offset & taking zoom into account in the future..
78
+ const shoulderAngleRad = -this.player.camera.shoulderAngle * 0.017453292519943295;
75
79
  const facingDirection = this.player.camera.facingDirection;
76
- const cos = Math.cos(shoulderAngleRad);
77
- const sin = Math.sin(shoulderAngleRad);
78
-
79
- return {
80
- x: facingDirection.x * cos + facingDirection.z * sin,
81
- y: facingDirection.y,
82
- z: -facingDirection.x * sin + facingDirection.z * cos
83
- }
80
+
81
+ // Pre-calculate trigonometric values
82
+ const shoulderCos = Math.cos(shoulderAngleRad);
83
+ const shoulderSin = Math.sin(shoulderAngleRad);
84
+ const adjustedX = facingDirection.x * shoulderCos + facingDirection.z * shoulderSin;
85
+ const adjustedZ = -facingDirection.x * shoulderSin + facingDirection.z * shoulderCos;
86
+
87
+ // Optimized pitch calculations - single pass
88
+ const pitch = this.player.camera.orientation.pitch;
89
+ const isNegativePitch = pitch < 0;
90
+ const absPitch = isNegativePitch ? -pitch : pitch;
91
+ const maxPitch = isNegativePitch ? 1.2 : 1.8;
92
+ const pitchRatio = absPitch > maxPitch ? 1.0 : absPitch / maxPitch;
93
+ const pitchRatioSquared = pitchRatio * pitchRatio; // Calculate once, use twice
94
+
95
+ // Combined offset calculations
96
+ const rightOffsetFactor = pitchRatioSquared * 0.5236;
97
+ const upwardAdjustment = isNegativePitch ? pitchRatioSquared * 0.08727 : -pitchRatioSquared * 0.08727;
98
+
99
+ // Fast right vector calculation and normalization
100
+ const rightX = -adjustedZ;
101
+ const rightZ = adjustedX;
102
+ const lengthSq = rightX * rightX + rightZ * rightZ;
103
+
104
+ if (lengthSq > 0) {
105
+ const invLength = 1.0 / Math.sqrt(lengthSq);
106
+ const rightOffsetX = rightX * invLength * rightOffsetFactor;
107
+ const rightOffsetZ = rightZ * invLength * rightOffsetFactor;
108
+
109
+ return {
110
+ x: adjustedX + rightOffsetX,
111
+ y: facingDirection.y + upwardAdjustment,
112
+ z: adjustedZ + rightOffsetZ
113
+ };
114
+ }
115
+
116
+ return {
117
+ x: adjustedX,
118
+ y: facingDirection.y + upwardAdjustment,
119
+ z: adjustedZ
120
+ };
84
121
  }
85
122
 
86
123
  public get canDodge(): boolean {
@@ -19,8 +19,8 @@ import GamePlayerEntity from './GamePlayerEntity';
19
19
 
20
20
  const DEFAULT_MAX_AMBIENT_LIGHT_INTENSITY = 1.5;
21
21
  const DEFAULT_MAX_DIRECTIONAL_LIGHT_INTENSITY = 3.25;
22
- const DEFAULT_MIN_AMBIENT_LIGHT_INTENSITY = 0.4;
23
- const DEFAULT_MIN_DIRECTIONAL_LIGHT_INTENSITY = 0.3;
22
+ const DEFAULT_MIN_AMBIENT_LIGHT_INTENSITY = 0.5;
23
+ const DEFAULT_MIN_DIRECTIONAL_LIGHT_INTENSITY = 0.4;
24
24
 
25
25
  export enum GameRegionPlayerEvent {
26
26
  REACHED = 'GameRegion.REACHED',
@@ -86,6 +86,7 @@ export default class GameRegion {
86
86
  this._world.stop(); // Keep it in stopped state, when a player joins the world, we'll start it.
87
87
  this._world.on(PlayerEvent.JOINED_WORLD, ({ player }) => this.onPlayerJoin(player));
88
88
  this._world.on(PlayerEvent.LEFT_WORLD, ({ player }) => this.onPlayerLeave(player));
89
+ this._world.on(PlayerEvent.RECONNECTED_WORLD, ({ player }) => this.onPlayerReconnected(player));
89
90
 
90
91
  // temp
91
92
  // this._world.simulation.enableDebugRendering(true);
@@ -140,6 +141,7 @@ export default class GameRegion {
140
141
  }
141
142
 
142
143
  protected async onPlayerJoin(player: Player) {
144
+ console.log('onPlayerJoin', this.name);
143
145
  const gamePlayer = await GamePlayer.getOrCreate(player);
144
146
 
145
147
  // Set the current region for the player
@@ -189,4 +191,17 @@ export default class GameRegion {
189
191
  this._world.stop();
190
192
  }
191
193
  }
194
+
195
+ // The RECONNECTED_WORLD even is only emitted by the engine when the player disconnects and
196
+ // reconnects to the game with a known connectionId before the close connection timeout finishes
197
+ // which gives them 5 second window to reconnect after disconnecting. This event will fire such
198
+ // as if a player unintentionally refreshes the page, if their browser crashes but restarts quickly
199
+ // with the same connectionId in the URL, etc.
200
+ // The HYTOPIA SDK handles resynchronization of all persisted state back to the player client such as
201
+ // their entity, scene ui states, etc, but anything that uses ephemeral state (Such as UI) we need
202
+ // to handle reloading for them manually here.
203
+ protected async onPlayerReconnected(player: Player) {
204
+ const gamePlayer = await GamePlayer.getOrCreate(player);
205
+ gamePlayer.onPlayerReconnected();
206
+ }
192
207
  }
@@ -14,6 +14,9 @@ import {
14
14
  } from 'hytopia';
15
15
 
16
16
  const MOVEMENT_NOT_STUCK_DISTANCE_SQUARED = 3;
17
+ const COMBAT_REGEN_DEFAULT_DELAY_MS = 7000; // 7 seconds
18
+ const COMBAT_REGEN_DEFAULT_RATE = 0.03; // 3% per second
19
+ const COMBAT_REGEN_INTERVAL_MS = 3000; // 3 seconds
17
20
 
18
21
  import BaseEntity, { BaseEntityOptions } from './BaseEntity';
19
22
  import GamePlayerEntity from '../GamePlayerEntity';
@@ -47,6 +50,8 @@ export type BaseCombatEntityOptions = {
47
50
  aggroTargetTypes?: (typeof BaseEntity | typeof GamePlayerEntity)[];
48
51
  attacks?: BaseCombatEntityAttack[];
49
52
  health: number;
53
+ outOfCombatRegenDelayMs?: number;
54
+ outOfCombatRegenPerSecondRate?: number; // rate per second as a percent, ie 0.03 is 3% per second
50
55
  } & BaseEntityOptions;
51
56
 
52
57
  export default class BaseCombatEntity extends BaseEntity {
@@ -73,6 +78,10 @@ export default class BaseCombatEntity extends BaseEntity {
73
78
  private _attackTotalWeight: number = 0;
74
79
  private _diameterSquared: number = 0;
75
80
  private _nextAttack: BaseCombatEntityAttack | null = null;
81
+ private _outOfCombatRegenAccumulatorMs: number = 0;
82
+ private _outOfCombatRegenDelayAccumulatorMs: number = 0;
83
+ private _outOfCombatRegenDelayMs: number;
84
+ private _outOfCombatRegenPerSecondRate: number;
76
85
  private _stopMoving: boolean = false;
77
86
 
78
87
  constructor(options: BaseCombatEntityOptions) {
@@ -90,6 +99,8 @@ export default class BaseCombatEntity extends BaseEntity {
90
99
  this._attackTotalWeight = this._attacks.reduce((sum, attack) => sum + attack.weight, 0);
91
100
  this._diameterSquared = this.width > this.depth ? this.width ** 2 : this.depth ** 2;
92
101
  this._nextAttack = this._pickRandomAttack();
102
+ this._outOfCombatRegenDelayMs = options.outOfCombatRegenDelayMs ?? COMBAT_REGEN_DEFAULT_DELAY_MS;
103
+ this._outOfCombatRegenPerSecondRate = options.outOfCombatRegenPerSecondRate ?? COMBAT_REGEN_DEFAULT_RATE;
93
104
 
94
105
  // Set accumulator to interval to trigger immediate target check on first tick
95
106
  this._aggroRetargetAccumulatorMs = this._aggroRetargetIntervalMs;
@@ -300,7 +311,28 @@ export default class BaseCombatEntity extends BaseEntity {
300
311
  this._updateTargeting();
301
312
  }
302
313
 
303
- if (!this._aggroActiveTarget) return;
314
+ if (this._aggroActiveTarget) {
315
+ this._outOfCombatRegenAccumulatorMs = 0;
316
+ this._outOfCombatRegenDelayAccumulatorMs = 0;
317
+ } else {
318
+ if (this.health === this.maxHealth || !this._outOfCombatRegenPerSecondRate) return;
319
+
320
+ // Delay regen until we hit the delay threshold if set.
321
+ if (this._outOfCombatRegenDelayMs && this._outOfCombatRegenDelayAccumulatorMs < this._outOfCombatRegenDelayMs) {
322
+ this._outOfCombatRegenDelayAccumulatorMs += tickDeltaMs;
323
+ return;
324
+ }
325
+
326
+ // Regen every interval if set.
327
+ if (this._outOfCombatRegenPerSecondRate && this._outOfCombatRegenAccumulatorMs >= COMBAT_REGEN_INTERVAL_MS) {
328
+ this._outOfCombatRegenAccumulatorMs = 0;
329
+ this.adjustHealth(Math.ceil(this.maxHealth * this._outOfCombatRegenPerSecondRate * (COMBAT_REGEN_INTERVAL_MS / 1000)));
330
+ } else {
331
+ this._outOfCombatRegenAccumulatorMs += tickDeltaMs;
332
+ }
333
+
334
+ return;
335
+ }
304
336
 
305
337
  const targetDistanceSquared = this.calculateDistanceSquaredToTarget(this._aggroActiveTarget);
306
338
 
@@ -56,6 +56,8 @@ export type BaseEntityItemDrop = {
56
56
  quantity?: number;
57
57
  }
58
58
 
59
+ export type BaseEntityNameplateType = 'normal' | 'boss';
60
+
59
61
  export type BaseEntityOptions = {
60
62
  combatExperienceReward?: number;
61
63
  controller?: PathfindingEntityController;
@@ -75,6 +77,7 @@ export type BaseEntityOptions = {
75
77
  moveAnimationSpeed?: number;
76
78
  moveOptions?: MoveOptions;
77
79
  moveSpeed?: number;
80
+ nameplateType?: BaseEntityNameplateType;
78
81
  nameplateViewDistnace?: number;
79
82
  pathfindingOptions?: PathfindingOptions;
80
83
  pushable?: boolean;
@@ -103,6 +106,7 @@ export default class BaseEntity extends Entity implements IInteractable, IDamage
103
106
  private _moveOptions: MoveOptions | undefined;
104
107
  private _moveSpeed: number;
105
108
  private _nameplateSceneUI: SceneUI;
109
+ private _nameplateType: BaseEntityNameplateType | undefined;
106
110
  private _nameplateViewDistance: number | undefined;
107
111
  private _optionMap: Map<number, BaseEntityDialogueOption> = new Map();
108
112
  private _pathfindingOptions: PathfindingOptions | undefined;
@@ -135,6 +139,7 @@ export default class BaseEntity extends Entity implements IInteractable, IDamage
135
139
  this._moveOptions = options.moveOptions;
136
140
  this._moveSpeed = options.moveSpeed ?? 2;
137
141
  this._faceSpeed = options.faceSpeed ?? this._moveSpeed * 2;
142
+ this._nameplateType = options.nameplateType;
138
143
  this._nameplateViewDistance = options.nameplateViewDistnace;
139
144
  this._pathfindingOptions = options.pathfindingOptions;
140
145
  this._pushable = options.pushable ?? false;
@@ -170,6 +175,21 @@ export default class BaseEntity extends Entity implements IInteractable, IDamage
170
175
  public get pathfindingController(): PathfindingEntityController { return this.controller as PathfindingEntityController; }
171
176
  public get pushable(): boolean { return this._pushable; }
172
177
 
178
+ public adjustHealth(amount: number, attacker?: Entity): void {
179
+ // ignore if maHealth is 0 (infinite), or full health and positive amount, or dead and negative amount
180
+ if (this._maxHealth === 0 || (amount > 0 && this._health === this.maxHealth) || (amount < 0 && this._health === 0)) return;
181
+
182
+ this._health = Math.max(0, Math.min(this.maxHealth, this._health + amount));
183
+
184
+ this._nameplateSceneUI.setState({
185
+ health: this._health
186
+ });
187
+
188
+ if (this._health <= 0) {
189
+ this.die(attacker);
190
+ }
191
+ }
192
+
173
193
  public die(killer?: Entity): void {
174
194
  if (this._dying) return;
175
195
 
@@ -303,19 +323,8 @@ export default class BaseEntity extends Entity implements IInteractable, IDamage
303
323
  }
304
324
 
305
325
  public takeDamage(damage: number, attacker?: Entity): void {
306
- // Infinite health, doesn't take damage if max health is 0
307
- if (this._maxHealth === 0) return;
308
-
309
- this._health = Math.max(0, this._health - damage);
310
-
311
- this._nameplateSceneUI.setState({
312
- damage,
313
- health: this._health
314
- });
315
-
316
- if (this._health <= 0) {
317
- this.die(attacker);
318
- }
326
+ console.log(damage);
327
+ this.adjustHealth(-damage, attacker);
319
328
  }
320
329
 
321
330
  public wander(speed: number = this._moveSpeed, options: WanderOptions): void {
@@ -367,6 +376,7 @@ export default class BaseEntity extends Entity implements IInteractable, IDamage
367
376
  interactable: this.isInteractable,
368
377
  interactActionText: this.interactActionText,
369
378
  maxHealth: this.maxHealth,
379
+ type: this._nameplateType,
370
380
  },
371
381
  });
372
382
  }
@@ -67,6 +67,7 @@ export default class QueenWeaverEntity extends BaseCombatEntity {
67
67
  faceSpeed: 4,
68
68
  health: 1000,
69
69
  idleAnimations: [ 'waiting' ],
70
+ nameplateType: 'boss',
70
71
  modelUri: 'models/enemies/weaver.gltf',
71
72
  modelScale: 1.3,
72
73
  moveAnimations: [ 'walking' ],
@@ -51,7 +51,7 @@ export default class RatkinBruteEntity extends BaseCombatEntity {
51
51
  weight: 2,
52
52
  },
53
53
  ],
54
- combatExperienceReward: 30,
54
+ combatExperienceReward: 25,
55
55
  deathAnimations: [ 'death' ],
56
56
  deathDespawnDelayMs: 1000,
57
57
  deathItemDrops: [
@@ -64,7 +64,7 @@ export default class RatkinBruteEntity extends BaseCombatEntity {
64
64
  { itemClass: CommonMushroomItem, minQuantity: 1, maxQuantity: 3, weight: 1 },
65
65
  { itemClass: CommonSeedsItem, minQuantity: 1, maxQuantity: 3, weight: 1 },
66
66
  ],
67
- health: 140,
67
+ health: 70,
68
68
  idleAnimations: [ 'idle' ],
69
69
  modelUri: 'models/enemies/ratkin-brute.gltf',
70
70
  modelScale: 0.6,
@@ -43,7 +43,7 @@ export default class RatkinRangerEntity extends BaseCombatEntity {
43
43
  weight: 3,
44
44
  },
45
45
  ],
46
- combatExperienceReward: 20,
46
+ combatExperienceReward: 18,
47
47
  deathAnimations: [ 'death' ],
48
48
  deathDespawnDelayMs: 1000,
49
49
  deathItemDrops: [
@@ -56,7 +56,7 @@ export default class RatkinRangerEntity extends BaseCombatEntity {
56
56
  { itemClass: CommonMushroomItem, minQuantity: 1, maxQuantity: 3, weight: 1 },
57
57
  { itemClass: CommonSeedsItem, minQuantity: 1, maxQuantity: 3, weight: 1 },
58
58
  ],
59
- health: 100,
59
+ health: 50,
60
60
  idleAnimations: [ 'idle' ],
61
61
  modelUri: 'models/enemies/ratkin-ranger.gltf',
62
62
  modelScale: 0.8,