@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.
- package/frontiers-rpg-game/assets/blocks/Brown_dirt_with_splatters_of_light_green_grass/+x.png +0 -0
- package/frontiers-rpg-game/assets/blocks/Brown_dirt_with_splatters_of_light_green_grass/+y.png +0 -0
- package/frontiers-rpg-game/assets/blocks/Brown_dirt_with_splatters_of_light_green_grass/+z.png +0 -0
- package/frontiers-rpg-game/assets/blocks/Brown_dirt_with_splatters_of_light_green_grass/-x.png +0 -0
- package/frontiers-rpg-game/assets/blocks/Brown_dirt_with_splatters_of_light_green_grass/-y.png +0 -0
- package/frontiers-rpg-game/assets/blocks/Brown_dirt_with_splatters_of_light_green_grass/-z.png +0 -0
- package/frontiers-rpg-game/assets/blocks/carved_stone_face/+x.png +0 -0
- package/frontiers-rpg-game/assets/blocks/carved_stone_face/+y.png +0 -0
- package/frontiers-rpg-game/assets/blocks/carved_stone_face/+z.png +0 -0
- package/frontiers-rpg-game/assets/blocks/carved_stone_face/-x.png +0 -0
- package/frontiers-rpg-game/assets/blocks/carved_stone_face/-y.png +0 -0
- package/frontiers-rpg-game/assets/blocks/carved_stone_face/-z.png +0 -0
- package/frontiers-rpg-game/assets/blocks/coral/+x.png +0 -0
- package/frontiers-rpg-game/assets/blocks/coral/+y.png +0 -0
- package/frontiers-rpg-game/assets/blocks/coral/+z.png +0 -0
- package/frontiers-rpg-game/assets/blocks/coral/-x.png +0 -0
- package/frontiers-rpg-game/assets/blocks/coral/-y.png +0 -0
- package/frontiers-rpg-game/assets/blocks/coral/-z.png +0 -0
- package/frontiers-rpg-game/assets/blocks/square_single_stone_brick/+x.png +0 -0
- package/frontiers-rpg-game/assets/blocks/square_single_stone_brick/+y.png +0 -0
- package/frontiers-rpg-game/assets/blocks/square_single_stone_brick/+z.png +0 -0
- package/frontiers-rpg-game/assets/blocks/square_single_stone_brick/-x.png +0 -0
- package/frontiers-rpg-game/assets/blocks/square_single_stone_brick/-y.png +0 -0
- package/frontiers-rpg-game/assets/blocks/square_single_stone_brick/-z.png +0 -0
- package/frontiers-rpg-game/assets/maps/hearthwilds.json +287978 -0
- package/frontiers-rpg-game/assets/models/environment/.optimized/barrel-wood-1/barrel-wood-1-named-nodes.bin +0 -0
- package/frontiers-rpg-game/assets/models/environment/.optimized/barrel-wood-1/barrel-wood-1-named-nodes.gltf +294 -0
- package/frontiers-rpg-game/assets/models/environment/.optimized/barrel-wood-1/barrel-wood-1.bin +0 -0
- package/frontiers-rpg-game/assets/models/environment/.optimized/barrel-wood-1/barrel-wood-1.gltf +136 -0
- package/frontiers-rpg-game/assets/models/environment/.optimized/barrel-wood-1/barrel-wood-1.gltf.md5 +1 -0
- package/frontiers-rpg-game/assets/models/environment/.optimized/barrel-wood-1/baseColor.png +0 -0
- package/frontiers-rpg-game/assets/models/environment/.optimized/barrel-wood-2/barrel-wood-2-named-nodes.bin +0 -0
- package/frontiers-rpg-game/assets/models/environment/.optimized/barrel-wood-2/barrel-wood-2-named-nodes.gltf +410 -0
- package/frontiers-rpg-game/assets/models/environment/.optimized/barrel-wood-2/barrel-wood-2.bin +0 -0
- package/frontiers-rpg-game/assets/models/environment/.optimized/barrel-wood-2/barrel-wood-2.gltf +142 -0
- package/frontiers-rpg-game/assets/models/environment/.optimized/barrel-wood-2/barrel-wood-2.gltf.md5 +1 -0
- package/frontiers-rpg-game/assets/models/environment/.optimized/barrel-wood-2/baseColor.png +0 -0
- package/frontiers-rpg-game/assets/models/environment/.optimized/bush-berry/baseColor.png +0 -0
- package/frontiers-rpg-game/assets/models/environment/.optimized/bush-berry/bush-berry-named-nodes.bin +0 -0
- package/frontiers-rpg-game/assets/models/environment/.optimized/bush-berry/bush-berry-named-nodes.gltf +621 -0
- package/frontiers-rpg-game/assets/models/environment/.optimized/bush-berry/bush-berry.bin +0 -0
- package/frontiers-rpg-game/assets/models/environment/.optimized/bush-berry/bush-berry.gltf +629 -0
- package/frontiers-rpg-game/assets/models/environment/.optimized/bush-berry/bush-berry.gltf.md5 +1 -0
- package/frontiers-rpg-game/assets/models/environment/.optimized/cat-statue/baseColor.png +0 -0
- package/frontiers-rpg-game/assets/models/environment/.optimized/cat-statue/cat-statue-named-nodes.bin +0 -0
- package/frontiers-rpg-game/assets/models/environment/.optimized/cat-statue/cat-statue-named-nodes.gltf +889 -0
- package/frontiers-rpg-game/assets/models/environment/.optimized/cat-statue/cat-statue.bin +0 -0
- package/frontiers-rpg-game/assets/models/environment/.optimized/cat-statue/cat-statue.gltf +136 -0
- package/frontiers-rpg-game/assets/models/environment/.optimized/cat-statue/cat-statue.gltf.md5 +1 -0
- package/frontiers-rpg-game/assets/models/environment/.optimized/dead-tree-big/baseColor.png +0 -0
- package/frontiers-rpg-game/assets/models/environment/.optimized/dead-tree-big/dead-tree-big-named-nodes.bin +0 -0
- package/frontiers-rpg-game/assets/models/environment/.optimized/dead-tree-big/dead-tree-big-named-nodes.gltf +5292 -0
- package/frontiers-rpg-game/assets/models/environment/.optimized/dead-tree-big/dead-tree-big.bin +0 -0
- package/frontiers-rpg-game/assets/models/environment/.optimized/dead-tree-big/dead-tree-big.gltf +2623 -0
- package/frontiers-rpg-game/assets/models/environment/.optimized/dead-tree-big/dead-tree-big.gltf.md5 +1 -0
- package/frontiers-rpg-game/assets/models/environment/.optimized/dead-tree-medium/baseColor.png +0 -0
- package/frontiers-rpg-game/assets/models/environment/.optimized/dead-tree-medium/dead-tree-medium-named-nodes.bin +0 -0
- package/frontiers-rpg-game/assets/models/environment/.optimized/dead-tree-medium/dead-tree-medium-named-nodes.gltf +2763 -0
- package/frontiers-rpg-game/assets/models/environment/.optimized/dead-tree-medium/dead-tree-medium.bin +0 -0
- package/frontiers-rpg-game/assets/models/environment/.optimized/dead-tree-medium/dead-tree-medium.gltf +1406 -0
- package/frontiers-rpg-game/assets/models/environment/.optimized/dead-tree-medium/dead-tree-medium.gltf.md5 +1 -0
- package/frontiers-rpg-game/assets/models/environment/.optimized/fallen-fruit/baseColor.png +0 -0
- package/frontiers-rpg-game/assets/models/environment/.optimized/fallen-fruit/fallen-fruit-named-nodes.bin +0 -0
- package/frontiers-rpg-game/assets/models/environment/.optimized/fallen-fruit/fallen-fruit-named-nodes.gltf +544 -0
- package/frontiers-rpg-game/assets/models/environment/.optimized/fallen-fruit/fallen-fruit.bin +0 -0
- package/frontiers-rpg-game/assets/models/environment/.optimized/fallen-fruit/fallen-fruit.gltf +142 -0
- package/frontiers-rpg-game/assets/models/environment/.optimized/fallen-fruit/fallen-fruit.gltf.md5 +1 -0
- package/frontiers-rpg-game/assets/models/environment/.optimized/flower-tuft/baseColor.png +0 -0
- package/frontiers-rpg-game/assets/models/environment/.optimized/flower-tuft/flower-tuft-named-nodes.bin +0 -0
- package/frontiers-rpg-game/assets/models/environment/.optimized/flower-tuft/flower-tuft-named-nodes.gltf +1703 -0
- package/frontiers-rpg-game/assets/models/environment/.optimized/flower-tuft/flower-tuft.bin +0 -0
- package/frontiers-rpg-game/assets/models/environment/.optimized/flower-tuft/flower-tuft.gltf +766 -0
- package/frontiers-rpg-game/assets/models/environment/.optimized/flower-tuft/flower-tuft.gltf.md5 +1 -0
- package/frontiers-rpg-game/assets/models/environment/.optimized/flowers-cluster/baseColor.png +0 -0
- package/frontiers-rpg-game/assets/models/environment/.optimized/flowers-cluster/flowers-cluster-named-nodes.bin +0 -0
- package/frontiers-rpg-game/assets/models/environment/.optimized/flowers-cluster/flowers-cluster-named-nodes.gltf +2354 -0
- package/frontiers-rpg-game/assets/models/environment/.optimized/flowers-cluster/flowers-cluster.bin +0 -0
- package/frontiers-rpg-game/assets/models/environment/.optimized/flowers-cluster/flowers-cluster.gltf +685 -0
- package/frontiers-rpg-game/assets/models/environment/.optimized/flowers-cluster/flowers-cluster.gltf.md5 +1 -0
- package/frontiers-rpg-game/assets/models/environment/.optimized/grass-tall/baseColor.png +0 -0
- package/frontiers-rpg-game/assets/models/environment/.optimized/grass-tall/grass-tall-named-nodes.bin +0 -0
- package/frontiers-rpg-game/assets/models/environment/.optimized/grass-tall/grass-tall-named-nodes.gltf +365 -0
- package/frontiers-rpg-game/assets/models/environment/.optimized/grass-tall/grass-tall.bin +0 -0
- package/frontiers-rpg-game/assets/models/environment/.optimized/grass-tall/grass-tall.gltf +301 -0
- package/frontiers-rpg-game/assets/models/environment/.optimized/grass-tall/grass-tall.gltf.md5 +1 -0
- package/frontiers-rpg-game/assets/models/environment/.optimized/grass-wild-clump/baseColor.png +0 -0
- package/frontiers-rpg-game/assets/models/environment/.optimized/grass-wild-clump/grass-wild-clump-named-nodes.bin +0 -0
- package/frontiers-rpg-game/assets/models/environment/.optimized/grass-wild-clump/grass-wild-clump-named-nodes.gltf +893 -0
- package/frontiers-rpg-game/assets/models/environment/.optimized/grass-wild-clump/grass-wild-clump.bin +0 -0
- package/frontiers-rpg-game/assets/models/environment/.optimized/grass-wild-clump/grass-wild-clump.gltf +893 -0
- package/frontiers-rpg-game/assets/models/environment/.optimized/grass-wild-clump/grass-wild-clump.gltf.md5 +1 -0
- package/frontiers-rpg-game/assets/models/environment/.optimized/mushroom-red-multiple/baseColor.png +0 -0
- package/frontiers-rpg-game/assets/models/environment/.optimized/mushroom-red-multiple/mushroom-red-multiple-named-nodes.bin +0 -0
- package/frontiers-rpg-game/assets/models/environment/.optimized/mushroom-red-multiple/mushroom-red-multiple-named-nodes.gltf +260 -0
- package/frontiers-rpg-game/assets/models/environment/.optimized/mushroom-red-multiple/mushroom-red-multiple.bin +0 -0
- package/frontiers-rpg-game/assets/models/environment/.optimized/mushroom-red-multiple/mushroom-red-multiple.gltf +136 -0
- package/frontiers-rpg-game/assets/models/environment/.optimized/mushroom-red-multiple/mushroom-red-multiple.gltf.md5 +1 -0
- package/frontiers-rpg-game/assets/models/environment/.optimized/oak-stairs/baseColor.png +0 -0
- package/frontiers-rpg-game/assets/models/environment/.optimized/oak-stairs/oak-stairs.gltf.md5 +1 -1
- package/frontiers-rpg-game/assets/models/environment/.optimized/oak-tree-big/baseColor.png +0 -0
- package/frontiers-rpg-game/assets/models/environment/.optimized/oak-tree-big/oak-tree-big-named-nodes.bin +0 -0
- package/frontiers-rpg-game/assets/models/environment/.optimized/oak-tree-big/oak-tree-big-named-nodes.gltf +3299 -0
- package/frontiers-rpg-game/assets/models/environment/.optimized/oak-tree-big/oak-tree-big.bin +0 -0
- package/frontiers-rpg-game/assets/models/environment/.optimized/oak-tree-big/oak-tree-big.gltf +1359 -0
- package/frontiers-rpg-game/assets/models/environment/.optimized/oak-tree-big/oak-tree-big.gltf.md5 +1 -0
- package/frontiers-rpg-game/assets/models/environment/.optimized/oak-tree-medium/baseColor.png +0 -0
- package/frontiers-rpg-game/assets/models/environment/.optimized/oak-tree-medium/oak-tree-medium-named-nodes.bin +0 -0
- package/frontiers-rpg-game/assets/models/environment/.optimized/oak-tree-medium/oak-tree-medium-named-nodes.gltf +7187 -0
- package/frontiers-rpg-game/assets/models/environment/.optimized/oak-tree-medium/oak-tree-medium.bin +0 -0
- package/frontiers-rpg-game/assets/models/environment/.optimized/oak-tree-medium/oak-tree-medium.gltf +1897 -0
- package/frontiers-rpg-game/assets/models/environment/.optimized/oak-tree-medium/oak-tree-medium.gltf.md5 +1 -0
- package/frontiers-rpg-game/assets/models/environment/.optimized/oak-tree-small/baseColor.png +0 -0
- package/frontiers-rpg-game/assets/models/environment/.optimized/oak-tree-small/oak-tree-small-named-nodes.bin +0 -0
- package/frontiers-rpg-game/assets/models/environment/.optimized/oak-tree-small/oak-tree-small-named-nodes.gltf +3455 -0
- package/frontiers-rpg-game/assets/models/environment/.optimized/oak-tree-small/oak-tree-small.bin +0 -0
- package/frontiers-rpg-game/assets/models/environment/.optimized/oak-tree-small/oak-tree-small.gltf +765 -0
- package/frontiers-rpg-game/assets/models/environment/.optimized/oak-tree-small/oak-tree-small.gltf.md5 +1 -0
- package/frontiers-rpg-game/assets/models/environment/.optimized/redcap-mushroom-group/baseColor.png +0 -0
- package/frontiers-rpg-game/assets/models/environment/.optimized/redcap-mushroom-group/redcap-mushroom-group-named-nodes.bin +0 -0
- package/frontiers-rpg-game/assets/models/environment/.optimized/redcap-mushroom-group/redcap-mushroom-group-named-nodes.gltf +487 -0
- package/frontiers-rpg-game/assets/models/environment/.optimized/redcap-mushroom-group/redcap-mushroom-group.bin +0 -0
- package/frontiers-rpg-game/assets/models/environment/.optimized/redcap-mushroom-group/redcap-mushroom-group.gltf +136 -0
- package/frontiers-rpg-game/assets/models/environment/.optimized/redcap-mushroom-group/redcap-mushroom-group.gltf.md5 +1 -0
- package/frontiers-rpg-game/assets/models/environment/.optimized/scattered-pebbles/baseColor.png +0 -0
- package/frontiers-rpg-game/assets/models/environment/.optimized/scattered-pebbles/scattered-pebbles-named-nodes.bin +0 -0
- package/frontiers-rpg-game/assets/models/environment/.optimized/scattered-pebbles/scattered-pebbles-named-nodes.gltf +356 -0
- package/frontiers-rpg-game/assets/models/environment/.optimized/scattered-pebbles/scattered-pebbles.bin +0 -0
- package/frontiers-rpg-game/assets/models/environment/.optimized/scattered-pebbles/scattered-pebbles.gltf +136 -0
- package/frontiers-rpg-game/assets/models/environment/.optimized/scattered-pebbles/scattered-pebbles.gltf.md5 +1 -0
- package/frontiers-rpg-game/assets/models/environment/.optimized/shell-starfish-group/baseColor.png +0 -0
- package/frontiers-rpg-game/assets/models/environment/.optimized/shell-starfish-group/shell-starfish-group-named-nodes.bin +0 -0
- package/frontiers-rpg-game/assets/models/environment/.optimized/shell-starfish-group/shell-starfish-group-named-nodes.gltf +772 -0
- package/frontiers-rpg-game/assets/models/environment/.optimized/shell-starfish-group/shell-starfish-group.bin +0 -0
- package/frontiers-rpg-game/assets/models/environment/.optimized/shell-starfish-group/shell-starfish-group.gltf +142 -0
- package/frontiers-rpg-game/assets/models/environment/.optimized/shell-starfish-group/shell-starfish-group.gltf.md5 +1 -0
- package/frontiers-rpg-game/assets/models/environment/barrel-wood-1.gltf +1 -0
- package/frontiers-rpg-game/assets/models/environment/barrel-wood-2.gltf +1 -0
- package/frontiers-rpg-game/assets/models/environment/bush-berry.gltf +1 -0
- package/frontiers-rpg-game/assets/models/environment/cat-statue.gltf +1 -0
- package/frontiers-rpg-game/assets/models/environment/dead-tree-big.gltf +1 -0
- package/frontiers-rpg-game/assets/models/environment/dead-tree-medium.gltf +1 -0
- package/frontiers-rpg-game/assets/models/environment/fallen-fruit.gltf +1 -0
- package/frontiers-rpg-game/assets/models/environment/flower-tuft.gltf +1 -0
- package/frontiers-rpg-game/assets/models/environment/flowers-cluster.gltf +1 -0
- package/frontiers-rpg-game/assets/models/environment/grass-tall.gltf +1 -0
- package/frontiers-rpg-game/assets/models/environment/grass-wild-clump.gltf +1 -0
- package/frontiers-rpg-game/assets/models/environment/mushroom-red-multiple.gltf +1 -0
- package/frontiers-rpg-game/assets/models/environment/oak-stairs.gltf +1 -1
- package/frontiers-rpg-game/assets/models/environment/oak-tree-big.gltf +1 -0
- package/frontiers-rpg-game/assets/models/environment/oak-tree-medium.gltf +1 -0
- package/frontiers-rpg-game/assets/models/environment/oak-tree-small.gltf +1 -0
- package/frontiers-rpg-game/assets/models/environment/redcap-mushroom-group.gltf +1 -0
- package/frontiers-rpg-game/assets/models/environment/scattered-pebbles.gltf +1 -0
- package/frontiers-rpg-game/assets/models/environment/shell-starfish-group.gltf +1 -0
- package/frontiers-rpg-game/assets/ui/hud.html +24 -3
- package/frontiers-rpg-game/assets/ui/index.html +41 -14
- package/frontiers-rpg-game/assets/ui/menus/quests.html +4 -3
- package/frontiers-rpg-game/assets/ui/scene-ui-templates/entity-nameplate.html +12 -8
- package/frontiers-rpg-game/assets/ui/shared/item-tooltips.html +1 -0
- package/frontiers-rpg-game/dev/persistence/player-player-1.json +18 -55
- package/frontiers-rpg-game/src/GameClock.ts +13 -3
- package/frontiers-rpg-game/src/GameManager.ts +8 -0
- package/frontiers-rpg-game/src/GamePlayer.ts +4 -0
- package/frontiers-rpg-game/src/GamePlayerEntity.ts +46 -9
- package/frontiers-rpg-game/src/GameRegion.ts +17 -2
- package/frontiers-rpg-game/src/entities/BaseCombatEntity.ts +33 -1
- package/frontiers-rpg-game/src/entities/BaseEntity.ts +23 -13
- package/frontiers-rpg-game/src/entities/enemies/QueenWeaverEntity.ts +1 -0
- package/frontiers-rpg-game/src/entities/enemies/RatkinBruteEntity.ts +2 -2
- package/frontiers-rpg-game/src/entities/enemies/RatkinRangerEntity.ts +2 -2
- package/frontiers-rpg-game/src/entities/enemies/RatkinSpellcasterEntity.ts +2 -2
- package/frontiers-rpg-game/src/entities/enemies/RatkinWarriorEntity.ts +2 -2
- package/frontiers-rpg-game/src/items/BaseItem.ts +1 -1
- package/frontiers-rpg-game/src/items/BaseWeaponItem.ts +9 -2
- package/frontiers-rpg-game/src/items/consumables/MinorHealingPotionItem.ts +1 -1
- package/frontiers-rpg-game/src/items/weapons/DullSwordItem.ts +3 -3
- package/frontiers-rpg-game/src/items/weapons/IronLongSwordItem.ts +3 -3
- package/frontiers-rpg-game/src/items/weapons/TrainingSwordItem.ts +3 -3
- package/frontiers-rpg-game/src/regions/hearthwilds/HearthwildsRegion.ts +25 -0
- 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:
|
|
3116
|
+
min-height: 50%;
|
|
3116
3117
|
}
|
|
3117
3118
|
|
|
3118
|
-
/* When active quests section has only placeholder,
|
|
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:
|
|
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.
|
|
6423
|
-
|
|
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:
|
|
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:
|
|
527
|
+
min-height: 50%;
|
|
528
528
|
}
|
|
529
529
|
|
|
530
|
-
/* When active quests section has only placeholder,
|
|
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:
|
|
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.
|
|
341
|
-
|
|
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":
|
|
3
|
-
"currentRegionId": "
|
|
2
|
+
"health": 120,
|
|
3
|
+
"currentRegionId": "chitter-forest",
|
|
4
4
|
"skillExperience": [
|
|
5
5
|
[
|
|
6
6
|
"exploration",
|
|
7
|
-
|
|
8
|
-
],
|
|
9
|
-
[
|
|
10
|
-
"agility",
|
|
11
|
-
79
|
|
7
|
+
225
|
|
12
8
|
],
|
|
13
9
|
[
|
|
14
10
|
"combat",
|
|
15
|
-
|
|
11
|
+
162
|
|
16
12
|
],
|
|
17
13
|
[
|
|
18
|
-
"
|
|
19
|
-
|
|
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":
|
|
34
|
+
"quantity": 82
|
|
50
35
|
},
|
|
51
36
|
{
|
|
52
37
|
"position": 1,
|
|
53
|
-
"itemId": "
|
|
54
|
-
"quantity": 2
|
|
38
|
+
"itemId": "ratkin_tail"
|
|
55
39
|
},
|
|
56
40
|
{
|
|
57
41
|
"position": 4,
|
|
58
|
-
"itemId": "
|
|
42
|
+
"itemId": "ratkin_tooth"
|
|
59
43
|
},
|
|
60
44
|
{
|
|
61
45
|
"position": 5,
|
|
62
|
-
"itemId": "
|
|
63
|
-
"quantity":
|
|
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": "
|
|
77
|
+
"state": "active",
|
|
99
78
|
"objectiveProgress": {
|
|
100
79
|
"kill-5-ratkin": 5,
|
|
101
80
|
"dodge-3-times": 3,
|
|
102
|
-
"talk-to-mark":
|
|
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":
|
|
97
|
+
"currentRegionSpawnFacingAngle": 0,
|
|
135
98
|
"currentRegionSpawnPoint": {
|
|
136
|
-
"x": -
|
|
137
|
-
"y":
|
|
138
|
-
"z":
|
|
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
|
|
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
|
|
52
|
+
// Calculate sun position with asymmetric day/night cycle (75% day, 25% night)
|
|
53
53
|
const timeProgress = this._timeMs / CYCLE_DURATION_MS;
|
|
54
|
-
|
|
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
|
-
|
|
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
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
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.
|
|
23
|
-
const DEFAULT_MIN_DIRECTIONAL_LIGHT_INTENSITY = 0.
|
|
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 (
|
|
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
|
-
|
|
307
|
-
|
|
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
|
}
|
|
@@ -51,7 +51,7 @@ export default class RatkinBruteEntity extends BaseCombatEntity {
|
|
|
51
51
|
weight: 2,
|
|
52
52
|
},
|
|
53
53
|
],
|
|
54
|
-
combatExperienceReward:
|
|
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:
|
|
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:
|
|
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:
|
|
59
|
+
health: 50,
|
|
60
60
|
idleAnimations: [ 'idle' ],
|
|
61
61
|
modelUri: 'models/enemies/ratkin-ranger.gltf',
|
|
62
62
|
modelScale: 0.8,
|