hytopia 0.3.6 → 0.3.8
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/boilerplate/assets/map.json +191 -43
- package/docs/server.playercameramode.md +14 -0
- package/examples/hygrounds/README.md +0 -0
- package/examples/hygrounds/assets/audio/sfx/chest-open-1.mp3 +0 -0
- package/examples/hygrounds/assets/audio/sfx/chest-open-2.mp3 +0 -0
- package/examples/hygrounds/assets/audio/sfx/machine-gun-reload.mp3 +0 -0
- package/examples/hygrounds/assets/audio/sfx/machine-gun-shoot.mp3 +0 -0
- package/examples/hygrounds/assets/audio/sfx/medpack-consume.mp3 +0 -0
- package/examples/hygrounds/assets/audio/sfx/mining-drill-drilling.mp3 +0 -0
- package/examples/hygrounds/assets/audio/sfx/pistol-reload.mp3 +0 -0
- package/examples/hygrounds/assets/audio/sfx/pistol-shoot.mp3 +0 -0
- package/examples/hygrounds/assets/audio/sfx/player-hurt.mp3 +0 -0
- package/examples/hygrounds/assets/audio/sfx/potion-consume.mp3 +0 -0
- package/examples/hygrounds/assets/audio/sfx/rifle-reload.mp3 +0 -0
- package/examples/hygrounds/assets/audio/sfx/rifle-shoot.mp3 +0 -0
- package/examples/hygrounds/assets/audio/sfx/rocket-launcher-explosion.mp3 +0 -0
- package/examples/hygrounds/assets/audio/sfx/rocket-launcher-reload.mp3 +0 -0
- package/examples/hygrounds/assets/audio/sfx/rocket-launcher-shoot.mp3 +0 -0
- package/examples/hygrounds/assets/audio/sfx/shield.png +0 -0
- package/examples/hygrounds/assets/audio/sfx/shotgun-reload.mp3 +0 -0
- package/examples/hygrounds/assets/audio/sfx/shotgun-shoot.mp3 +0 -0
- package/examples/hygrounds/assets/audio/sfx/sniper-reload.mp3 +0 -0
- package/examples/hygrounds/assets/audio/sfx/sniper-shoot.mp3 +0 -0
- package/examples/hygrounds/assets/icons/ak-47.png +0 -0
- package/examples/hygrounds/assets/icons/ammo.png +0 -0
- package/examples/hygrounds/assets/icons/auto-shotgun.png +0 -0
- package/examples/hygrounds/assets/icons/auto-sniper.png +0 -0
- package/examples/hygrounds/assets/icons/block.png +0 -0
- package/examples/hygrounds/assets/icons/bolt-action-sniper.png +0 -0
- package/examples/hygrounds/assets/icons/crown-bronze.png +0 -0
- package/examples/hygrounds/assets/icons/crown-gold.png +0 -0
- package/examples/hygrounds/assets/icons/crown-silver.png +0 -0
- package/examples/hygrounds/assets/icons/gravity-potion.png +0 -0
- package/examples/hygrounds/assets/icons/heart.png +0 -0
- package/examples/hygrounds/assets/icons/light-machine-gun.png +0 -0
- package/examples/hygrounds/assets/icons/medpack.png +0 -0
- package/examples/hygrounds/assets/icons/mining-drill.png +0 -0
- package/examples/hygrounds/assets/icons/pickaxe.png +0 -0
- package/examples/hygrounds/assets/icons/pistol.png +0 -0
- package/examples/hygrounds/assets/icons/revolver.png +0 -0
- package/examples/hygrounds/assets/icons/rocket-launcher.png +0 -0
- package/examples/hygrounds/assets/icons/shield-potion.png +0 -0
- package/examples/hygrounds/assets/icons/shield.png +0 -0
- package/examples/hygrounds/assets/icons/shotgun.png +0 -0
- package/examples/hygrounds/assets/icons/submachine-gun.png +0 -0
- package/examples/hygrounds/assets/map.json +31796 -0
- package/examples/hygrounds/assets/models/environment/.optimized/explosion/explosion-named-nodes.glb +0 -0
- package/examples/hygrounds/assets/models/environment/.optimized/explosion/explosion.glb +0 -0
- package/examples/hygrounds/assets/models/environment/.optimized/explosion/explosion.glb.md5 +1 -0
- package/examples/hygrounds/assets/models/environment/.optimized/explosion-2/explosion-2-named-nodes.glb +0 -0
- package/examples/hygrounds/assets/models/environment/.optimized/explosion-2/explosion-2.glb +0 -0
- package/examples/hygrounds/assets/models/environment/.optimized/explosion-2/explosion-2.glb.md5 +1 -0
- package/examples/hygrounds/assets/models/environment/.optimized/explosion-3/explosion-3-named-nodes.glb +0 -0
- package/examples/hygrounds/assets/models/environment/.optimized/explosion-3/explosion-3.glb +0 -0
- package/examples/hygrounds/assets/models/environment/.optimized/explosion-3/explosion-3.glb.md5 +1 -0
- package/examples/hygrounds/assets/models/environment/.optimized/helicopter/helicopter-named-nodes.glb +0 -0
- package/examples/hygrounds/assets/models/environment/.optimized/helicopter/helicopter.glb +0 -0
- package/examples/hygrounds/assets/models/environment/.optimized/helicopter/helicopter.glb.md5 +1 -0
- package/examples/hygrounds/assets/models/environment/chest.gltf +1 -0
- package/examples/hygrounds/assets/models/environment/explosion.glb +0 -0
- package/examples/hygrounds/assets/models/environment/muzzle-flash.gltf +1 -0
- package/examples/hygrounds/assets/models/items/.optimized/auto-sniper/auto-sniper-named-nodes.glb +0 -0
- package/examples/hygrounds/assets/models/items/.optimized/auto-sniper/auto-sniper.glb +0 -0
- package/examples/hygrounds/assets/models/items/.optimized/auto-sniper/auto-sniper.glb.md5 +1 -0
- package/examples/hygrounds/assets/models/items/.optimized/gravity-potion/gravity-potion-named-nodes.glb +0 -0
- package/examples/hygrounds/assets/models/items/.optimized/gravity-potion/gravity-potion.glb +0 -0
- package/examples/hygrounds/assets/models/items/.optimized/gravity-potion/gravity-potion.glb.md5 +1 -0
- package/examples/hygrounds/assets/models/items/.optimized/medkit/medkit-named-nodes.glb +0 -0
- package/examples/hygrounds/assets/models/items/.optimized/medkit/medkit.glb +0 -0
- package/examples/hygrounds/assets/models/items/.optimized/medkit/medkit.glb.md5 +1 -0
- package/examples/hygrounds/assets/models/items/.optimized/medpack/medpack-named-nodes.glb +0 -0
- package/examples/hygrounds/assets/models/items/.optimized/medpack/medpack.glb +0 -0
- package/examples/hygrounds/assets/models/items/.optimized/medpack/medpack.glb.md5 +1 -0
- package/examples/hygrounds/assets/models/items/.optimized/mining-drill/mining-drill-named-nodes.glb +0 -0
- package/examples/hygrounds/assets/models/items/.optimized/mining-drill/mining-drill.glb +0 -0
- package/examples/hygrounds/assets/models/items/.optimized/mining-drill/mining-drill.glb.md5 +1 -0
- package/examples/hygrounds/assets/models/items/.optimized/revolver/revolver-named-nodes.glb +0 -0
- package/examples/hygrounds/assets/models/items/.optimized/revolver/revolver.glb +0 -0
- package/examples/hygrounds/assets/models/items/.optimized/revolver/revolver.glb.md5 +1 -0
- package/examples/hygrounds/assets/models/items/.optimized/rocket-missile/rocket-missile-named-nodes.glb +0 -0
- package/examples/hygrounds/assets/models/items/.optimized/rocket-missile/rocket-missile.glb +0 -0
- package/examples/hygrounds/assets/models/items/.optimized/rocket-missile/rocket-missile.glb.md5 +1 -0
- package/examples/hygrounds/assets/models/items/.optimized/shield-potion/shield-potion-named-nodes.glb +0 -0
- package/examples/hygrounds/assets/models/items/.optimized/shield-potion/shield-potion.glb +0 -0
- package/examples/hygrounds/assets/models/items/.optimized/shield-potion/shield-potion.glb.md5 +1 -0
- package/examples/hygrounds/assets/models/items/.optimized/shield-potion-2/shield-potion-2-named-nodes.glb +0 -0
- package/examples/hygrounds/assets/models/items/.optimized/shield-potion-2/shield-potion-2.glb +0 -0
- package/examples/hygrounds/assets/models/items/.optimized/shield-potion-2/shield-potion-2.glb.md5 +1 -0
- package/examples/hygrounds/assets/models/items/.optimized/submachine-gun/submachine-gun-named-nodes.glb +0 -0
- package/examples/hygrounds/assets/models/items/.optimized/submachine-gun/submachine-gun.glb +0 -0
- package/examples/hygrounds/assets/models/items/.optimized/submachine-gun/submachine-gun.glb.md5 +1 -0
- package/examples/hygrounds/assets/models/items/ak-47.glb +0 -0
- package/examples/hygrounds/assets/models/items/auto-shotgun.glb +0 -0
- package/examples/hygrounds/assets/models/items/auto-sniper.glb +0 -0
- package/examples/hygrounds/assets/models/items/bolt-action-sniper.glb +0 -0
- package/examples/hygrounds/assets/models/items/gravity-potion.glb +0 -0
- package/examples/hygrounds/assets/models/items/light-machine-gun.glb +0 -0
- package/examples/hygrounds/assets/models/items/medpack.glb +0 -0
- package/examples/hygrounds/assets/models/items/mining-drill.glb +0 -0
- package/examples/hygrounds/assets/models/items/pickaxe.gltf +1 -0
- package/examples/hygrounds/assets/models/items/pistol.glb +0 -0
- package/examples/hygrounds/assets/models/items/revolver.glb +0 -0
- package/examples/hygrounds/assets/models/items/rocket-launcher.glb +0 -0
- package/examples/hygrounds/assets/models/items/rocket-missile.glb +0 -0
- package/examples/hygrounds/assets/models/items/shield-potion.glb +0 -0
- package/examples/hygrounds/assets/models/items/shotgun.glb +0 -0
- package/examples/hygrounds/assets/models/items/submachine-gun.glb +0 -0
- package/examples/hygrounds/assets/models/players/soldier-player.gltf +1 -0
- package/examples/hygrounds/assets/ui/images/scope.png +0 -0
- package/examples/hygrounds/assets/ui/index.html +1122 -0
- package/examples/hygrounds/bun.lock +503 -0
- package/examples/hygrounds/classes/ChestEntity.ts +133 -0
- package/examples/hygrounds/classes/GameManager.ts +422 -0
- package/examples/hygrounds/classes/GamePlayerEntity.ts +595 -0
- package/examples/hygrounds/classes/GunEntity.ts +259 -0
- package/examples/hygrounds/classes/ItemEntity.ts +225 -0
- package/examples/hygrounds/classes/ItemFactory.ts +61 -0
- package/examples/hygrounds/classes/MeleeWeaponEntity.ts +138 -0
- package/examples/hygrounds/classes/TerrainDamageManager.ts +56 -0
- package/examples/hygrounds/classes/items/GravityPotionEntity.ts +48 -0
- package/examples/hygrounds/classes/items/MedPackEntity.ts +43 -0
- package/examples/hygrounds/classes/items/ShieldPotionEntity.ts +43 -0
- package/examples/hygrounds/classes/weapons/AK47Entity.ts +43 -0
- package/examples/hygrounds/classes/weapons/AutoShotgunEntity.ts +80 -0
- package/examples/hygrounds/classes/weapons/AutoSniperEntity.ts +43 -0
- package/examples/hygrounds/classes/weapons/BoltActionSniperEntity.ts +46 -0
- package/examples/hygrounds/classes/weapons/LightMachineGunEntity.ts +43 -0
- package/examples/hygrounds/classes/weapons/MiningDrillEntity.ts +38 -0
- package/examples/hygrounds/classes/weapons/PickaxeEntity.ts +38 -0
- package/examples/hygrounds/classes/weapons/PistolEntity.ts +46 -0
- package/examples/hygrounds/classes/weapons/RevolverEntity.ts +46 -0
- package/examples/hygrounds/classes/weapons/RocketLauncherEntity.ts +195 -0
- package/examples/hygrounds/classes/weapons/ShotgunEntity.ts +84 -0
- package/examples/hygrounds/classes/weapons/SubmachineGunEntity.ts +43 -0
- package/examples/hygrounds/gameConfig.ts +430 -0
- package/examples/hygrounds/index.ts +41 -0
- package/examples/hygrounds/package.json +16 -0
- package/examples/player-persistence/README.md +3 -0
- package/examples/player-persistence/assets/map.json +2623 -0
- package/examples/player-persistence/dev/persistence/player-player-1.json +6 -0
- package/examples/player-persistence/dev/persistence/test.json +3 -0
- package/examples/player-persistence/index.ts +126 -0
- package/examples/player-persistence/package.json +16 -0
- package/package.json +1 -1
- package/server.api.json +21 -0
- package/server.d.ts +2 -1
- package/server.js +113 -113
@@ -0,0 +1,56 @@
|
|
1
|
+
import { Block, Vector3Like, World } from 'hytopia';
|
2
|
+
import {
|
3
|
+
BEDROCK_BLOCK_ID,
|
4
|
+
BLOCK_ID_BREAK_DAMAGE,
|
5
|
+
BLOCK_ID_MATERIALS,
|
6
|
+
} from '../gameConfig';
|
7
|
+
|
8
|
+
interface BlockDamage {
|
9
|
+
blockId: number;
|
10
|
+
totalDamage: number;
|
11
|
+
}
|
12
|
+
|
13
|
+
export default class TerrainDamageManager {
|
14
|
+
public static instance: TerrainDamageManager = new TerrainDamageManager();
|
15
|
+
|
16
|
+
private _blockDamages: Map<string, BlockDamage> = new Map();
|
17
|
+
|
18
|
+
private constructor() {}
|
19
|
+
|
20
|
+
public static getBreakMaterialCount(blockId: number): number {
|
21
|
+
return BLOCK_ID_MATERIALS[blockId] ?? BLOCK_ID_MATERIALS.default;
|
22
|
+
}
|
23
|
+
|
24
|
+
public damageBlock(world: World, block: Block, damage: number): boolean {
|
25
|
+
const coordinateKey = this._coordinateToKey(block.globalCoordinate);
|
26
|
+
let blockDamage = this._blockDamages.get(coordinateKey);
|
27
|
+
|
28
|
+
if (!blockDamage) {
|
29
|
+
const blockId = block.blockType.id;
|
30
|
+
|
31
|
+
if (block.blockType.isLiquid || blockId === BEDROCK_BLOCK_ID) {
|
32
|
+
return false;
|
33
|
+
}
|
34
|
+
|
35
|
+
blockDamage = { blockId, totalDamage: 0 };
|
36
|
+
this._blockDamages.set(coordinateKey, blockDamage);
|
37
|
+
}
|
38
|
+
|
39
|
+
blockDamage.totalDamage += damage;
|
40
|
+
|
41
|
+
const requiredBreakDamage = BLOCK_ID_BREAK_DAMAGE[blockDamage.blockId] ?? BLOCK_ID_BREAK_DAMAGE.default;
|
42
|
+
|
43
|
+
if (blockDamage.totalDamage >= requiredBreakDamage) {
|
44
|
+
world.chunkLattice.setBlock(block.globalCoordinate, 0);
|
45
|
+
this._blockDamages.delete(coordinateKey);
|
46
|
+
|
47
|
+
return true;
|
48
|
+
}
|
49
|
+
|
50
|
+
return false;
|
51
|
+
}
|
52
|
+
|
53
|
+
private _coordinateToKey(coordinate: Vector3Like): string {
|
54
|
+
return `${coordinate.x},${coordinate.y},${coordinate.z}`;
|
55
|
+
}
|
56
|
+
}
|
@@ -0,0 +1,48 @@
|
|
1
|
+
import { Quaternion } from 'hytopia';
|
2
|
+
import ItemEntity from "../ItemEntity";
|
3
|
+
import GamePlayerEntity from '../GamePlayerEntity';
|
4
|
+
import type { ItemEntityOptions } from "../ItemEntity";
|
5
|
+
|
6
|
+
const GRAVITY_SCALE = 0.3;
|
7
|
+
const GRAVITY_DURATION_MS = 15 * 1000; // 15 seconds
|
8
|
+
|
9
|
+
const DEFAULT_GRAVITY_POTION_OPTIONS: ItemEntityOptions = {
|
10
|
+
heldHand: 'right',
|
11
|
+
iconImageUri: 'icons/gravity-potion.png',
|
12
|
+
idleAnimation: 'idle_gun_right',
|
13
|
+
mlAnimation: 'shoot_gun_right',
|
14
|
+
modelUri: 'models/items/gravity-potion.glb',
|
15
|
+
modelScale: 0.4,
|
16
|
+
name: 'Gravity Potion',
|
17
|
+
consumable: true,
|
18
|
+
consumeAudioUri: 'audio/sfx/potion-consume.mp3',
|
19
|
+
consumeTimeMs: 1000,
|
20
|
+
quantity: 1,
|
21
|
+
}
|
22
|
+
|
23
|
+
export default class GravityPotionEntity extends ItemEntity {
|
24
|
+
public constructor(options: Partial<ItemEntityOptions> = {}) {
|
25
|
+
super({ ...DEFAULT_GRAVITY_POTION_OPTIONS, ...options });
|
26
|
+
}
|
27
|
+
|
28
|
+
public override consume(): void {
|
29
|
+
if (!(this.parent instanceof GamePlayerEntity)) {
|
30
|
+
return;
|
31
|
+
}
|
32
|
+
|
33
|
+
const parent = this.parent as GamePlayerEntity;
|
34
|
+
|
35
|
+
// Apply gravity potion effect
|
36
|
+
parent.setGravity(GRAVITY_SCALE);
|
37
|
+
setTimeout(() => parent.setGravity(1), GRAVITY_DURATION_MS);
|
38
|
+
|
39
|
+
super.consume();
|
40
|
+
}
|
41
|
+
|
42
|
+
public override equip(): void {
|
43
|
+
super.equip();
|
44
|
+
|
45
|
+
this.setPosition({ x: 0, y: 0.15, z: -0.2 });
|
46
|
+
this.setRotation(Quaternion.fromEuler(-90, 0, 0));
|
47
|
+
}
|
48
|
+
}
|
@@ -0,0 +1,43 @@
|
|
1
|
+
import { Quaternion } from 'hytopia';
|
2
|
+
import ItemEntity from "../ItemEntity";
|
3
|
+
import GamePlayerEntity from '../GamePlayerEntity';
|
4
|
+
import type { ItemEntityOptions } from "../ItemEntity";
|
5
|
+
|
6
|
+
const ADD_HEALTH_AMOUNT = 50;
|
7
|
+
|
8
|
+
const DEFAULT_MEDPACK_OPTIONS: ItemEntityOptions = {
|
9
|
+
heldHand: 'right',
|
10
|
+
iconImageUri: 'icons/medpack.png',
|
11
|
+
idleAnimation: 'idle_gun_right',
|
12
|
+
mlAnimation: 'shoot_gun_right',
|
13
|
+
modelUri: 'models/items/medpack.glb',
|
14
|
+
modelScale: 0.4,
|
15
|
+
name: 'Med Pack',
|
16
|
+
consumable: true,
|
17
|
+
consumeAudioUri: 'audio/sfx/medpack-consume.mp3',
|
18
|
+
consumeTimeMs: 1000,
|
19
|
+
quantity: 1,
|
20
|
+
}
|
21
|
+
|
22
|
+
export default class MedPackEntity extends ItemEntity {
|
23
|
+
public constructor(options: Partial<ItemEntityOptions> = {}) {
|
24
|
+
super({ ...DEFAULT_MEDPACK_OPTIONS, ...options });
|
25
|
+
}
|
26
|
+
|
27
|
+
public override consume(): void {
|
28
|
+
if (!(this.parent instanceof GamePlayerEntity) || this.parent.health >= this.parent.maxHealth) {
|
29
|
+
return;
|
30
|
+
}
|
31
|
+
|
32
|
+
this.parent.updateHealth(ADD_HEALTH_AMOUNT);
|
33
|
+
|
34
|
+
super.consume();
|
35
|
+
}
|
36
|
+
|
37
|
+
public override equip(): void {
|
38
|
+
super.equip();
|
39
|
+
|
40
|
+
this.setPosition({ x: 0, y: 0.15, z: 0.3 });
|
41
|
+
this.setRotation(Quaternion.fromEuler(-90, 0, 270));
|
42
|
+
}
|
43
|
+
}
|
@@ -0,0 +1,43 @@
|
|
1
|
+
import { Quaternion } from 'hytopia';
|
2
|
+
import ItemEntity from "../ItemEntity";
|
3
|
+
import GamePlayerEntity from '../GamePlayerEntity';
|
4
|
+
import type { ItemEntityOptions } from "../ItemEntity";
|
5
|
+
|
6
|
+
const ADD_SHIELD_AMOUNT = 25;
|
7
|
+
|
8
|
+
const DEFAULT_SHIELD_POTION_OPTIONS: ItemEntityOptions = {
|
9
|
+
heldHand: 'right',
|
10
|
+
iconImageUri: 'icons/shield-potion.png',
|
11
|
+
idleAnimation: 'idle_gun_right',
|
12
|
+
mlAnimation: 'shoot_gun_right',
|
13
|
+
modelUri: 'models/items/shield-potion.glb',
|
14
|
+
modelScale: 0.4,
|
15
|
+
name: 'Shield Potion',
|
16
|
+
consumable: true,
|
17
|
+
consumeAudioUri: 'audio/sfx/potion-consume.mp3',
|
18
|
+
consumeTimeMs: 1000,
|
19
|
+
quantity: 1,
|
20
|
+
}
|
21
|
+
|
22
|
+
export default class ShieldPotionEntity extends ItemEntity {
|
23
|
+
public constructor(options: Partial<ItemEntityOptions> = {}) {
|
24
|
+
super({ ...DEFAULT_SHIELD_POTION_OPTIONS, ...options });
|
25
|
+
}
|
26
|
+
|
27
|
+
public override consume(): void {
|
28
|
+
if (!(this.parent instanceof GamePlayerEntity) || this.parent.shield >= this.parent.maxShield) {
|
29
|
+
return;
|
30
|
+
}
|
31
|
+
|
32
|
+
this.parent.updateShield(ADD_SHIELD_AMOUNT);
|
33
|
+
|
34
|
+
super.consume();
|
35
|
+
}
|
36
|
+
|
37
|
+
public override equip(): void {
|
38
|
+
super.equip();
|
39
|
+
|
40
|
+
this.setPosition({ x: 0, y: 0.15, z: -0.2 });
|
41
|
+
this.setRotation(Quaternion.fromEuler(-90, 0, 0));
|
42
|
+
}
|
43
|
+
}
|
@@ -0,0 +1,43 @@
|
|
1
|
+
import { Quaternion, Vector3Like, QuaternionLike } from 'hytopia';
|
2
|
+
import GunEntity from '../GunEntity';
|
3
|
+
import type { GunEntityOptions } from '../GunEntity';
|
4
|
+
|
5
|
+
const DEFAULT_AK47_OPTIONS: GunEntityOptions = {
|
6
|
+
ammo: 25,
|
7
|
+
damage: 22,
|
8
|
+
fireRate: 5,
|
9
|
+
heldHand: 'both',
|
10
|
+
iconImageUri: 'icons/ak-47.png',
|
11
|
+
idleAnimation: 'idle_gun_both',
|
12
|
+
mlAnimation: 'shoot_gun_both',
|
13
|
+
name: 'AK-47',
|
14
|
+
maxAmmo: 25,
|
15
|
+
totalAmmo: 150,
|
16
|
+
scopeZoom: 2,
|
17
|
+
modelUri: 'models/items/ak-47.glb',
|
18
|
+
modelScale: 1.3,
|
19
|
+
range: 70,
|
20
|
+
reloadAudioUri: 'audio/sfx/rifle-reload.mp3',
|
21
|
+
reloadTimeMs: 2200,
|
22
|
+
shootAudioUri: 'audio/sfx/rifle-shoot.mp3',
|
23
|
+
};
|
24
|
+
|
25
|
+
export default class AK47Entity extends GunEntity {
|
26
|
+
public constructor(options: Partial<GunEntityOptions> = {}) {
|
27
|
+
super({ ...DEFAULT_AK47_OPTIONS, ...options });
|
28
|
+
}
|
29
|
+
|
30
|
+
public override shoot(): void {
|
31
|
+
if (!this.parent || !this.processShoot()) return;
|
32
|
+
|
33
|
+
super.shoot();
|
34
|
+
}
|
35
|
+
|
36
|
+
public override getMuzzleFlashPositionRotation(): { position: Vector3Like, rotation: QuaternionLike } {
|
37
|
+
return {
|
38
|
+
position: { x: 0, y: 0.01, z: -1.25 },
|
39
|
+
rotation: Quaternion.fromEuler(0, 90, 0),
|
40
|
+
};
|
41
|
+
}
|
42
|
+
}
|
43
|
+
|
@@ -0,0 +1,80 @@
|
|
1
|
+
import { Quaternion, Vector3Like, QuaternionLike } from 'hytopia';
|
2
|
+
import GunEntity from '../GunEntity';
|
3
|
+
import type { GunEntityOptions } from '../GunEntity';
|
4
|
+
|
5
|
+
const DEFAULT_AUTO_SHOTGUN_OPTIONS: GunEntityOptions = {
|
6
|
+
ammo: 6,
|
7
|
+
damage: 11,
|
8
|
+
fireRate: 1.5,
|
9
|
+
heldHand: 'both',
|
10
|
+
iconImageUri: 'icons/auto-shotgun.png',
|
11
|
+
idleAnimation: 'idle_gun_both',
|
12
|
+
mlAnimation: 'shoot_gun_both',
|
13
|
+
name: 'Auto Shotgun',
|
14
|
+
maxAmmo: 6,
|
15
|
+
totalAmmo: 30,
|
16
|
+
modelUri: 'models/items/auto-shotgun.glb',
|
17
|
+
modelScale: 1.2,
|
18
|
+
range: 8,
|
19
|
+
reloadAudioUri: 'audio/sfx/shotgun-reload.mp3',
|
20
|
+
reloadTimeMs: 3500,
|
21
|
+
shootAudioUri: 'audio/sfx/shotgun-shoot.mp3',
|
22
|
+
};
|
23
|
+
|
24
|
+
export default class AutoShotgunEntity extends GunEntity {
|
25
|
+
public constructor(options: Partial<GunEntityOptions> = {}) {
|
26
|
+
super({ ...DEFAULT_AUTO_SHOTGUN_OPTIONS, ...options });
|
27
|
+
}
|
28
|
+
|
29
|
+
public override shoot(): void {
|
30
|
+
if (!this.parent || !this.processShoot()) return;
|
31
|
+
|
32
|
+
super.shoot();
|
33
|
+
}
|
34
|
+
|
35
|
+
public override getMuzzleFlashPositionRotation(): { position: Vector3Like, rotation: QuaternionLike } {
|
36
|
+
return {
|
37
|
+
position: { x: 0.015, y: 0, z: -1 },
|
38
|
+
rotation: Quaternion.fromEuler(0, 90, 0),
|
39
|
+
};
|
40
|
+
}
|
41
|
+
|
42
|
+
public override shootRaycast(origin: Vector3Like, direction: Vector3Like, length: number) {
|
43
|
+
// Create spread pattern for auto-shotgun pellets using angles relative to direction
|
44
|
+
const spreadAngles = [
|
45
|
+
{ x: 0, y: 0 }, // Center
|
46
|
+
{ x: 0.05, y: 0.05 }, // Upper right
|
47
|
+
{ x: -0.05, y: 0.05 }, // Upper left
|
48
|
+
{ x: 0.07, y: 0 }, // Right
|
49
|
+
{ x: -0.07, y: 0 }, // Left
|
50
|
+
{ x: 0.05, y: -0.05 }, // Lower right
|
51
|
+
{ x: -0.05, y: -0.05 } // Lower left
|
52
|
+
];
|
53
|
+
|
54
|
+
// Fire each pellet with spread applied to original direction
|
55
|
+
for (const angle of spreadAngles) {
|
56
|
+
// Calculate spread direction relative to original direction
|
57
|
+
const spreadDirection = {
|
58
|
+
x: direction.x + (direction.z * angle.x), // Add horizontal spread
|
59
|
+
y: direction.y + angle.y, // Add vertical spread
|
60
|
+
z: direction.z - (direction.x * angle.x) // Maintain direction magnitude
|
61
|
+
};
|
62
|
+
|
63
|
+
// Normalize the spread direction to maintain consistent range
|
64
|
+
const magnitude = Math.sqrt(
|
65
|
+
spreadDirection.x * spreadDirection.x +
|
66
|
+
spreadDirection.y * spreadDirection.y +
|
67
|
+
spreadDirection.z * spreadDirection.z
|
68
|
+
);
|
69
|
+
|
70
|
+
const normalizedDirection = {
|
71
|
+
x: spreadDirection.x / magnitude,
|
72
|
+
y: spreadDirection.y / magnitude,
|
73
|
+
z: spreadDirection.z / magnitude
|
74
|
+
};
|
75
|
+
|
76
|
+
super.shootRaycast(origin, normalizedDirection, length);
|
77
|
+
}
|
78
|
+
}
|
79
|
+
}
|
80
|
+
|
@@ -0,0 +1,43 @@
|
|
1
|
+
import { Quaternion, Vector3Like, QuaternionLike } from 'hytopia';
|
2
|
+
import GunEntity from '../GunEntity';
|
3
|
+
import type { GunEntityOptions } from '../GunEntity';
|
4
|
+
|
5
|
+
const DEFAULT_AUTO_SNIPER_OPTIONS: GunEntityOptions = {
|
6
|
+
ammo: 10,
|
7
|
+
damage: 50,
|
8
|
+
fireRate: 1.5,
|
9
|
+
heldHand: 'both',
|
10
|
+
iconImageUri: 'icons/auto-sniper.png',
|
11
|
+
idleAnimation: 'idle_gun_both',
|
12
|
+
mlAnimation: 'shoot_gun_both',
|
13
|
+
name: 'Auto Sniper',
|
14
|
+
maxAmmo: 1,
|
15
|
+
totalAmmo: 12,
|
16
|
+
scopeZoom: 5,
|
17
|
+
modelUri: 'models/items/auto-sniper.glb',
|
18
|
+
modelScale: 1.3,
|
19
|
+
range: 100,
|
20
|
+
reloadAudioUri: 'audio/sfx/sniper-reload.mp3',
|
21
|
+
reloadTimeMs: 2200,
|
22
|
+
shootAudioUri: 'audio/sfx/sniper-shoot.mp3',
|
23
|
+
};
|
24
|
+
|
25
|
+
export default class AutoSniperEntity extends GunEntity {
|
26
|
+
public constructor(options: Partial<GunEntityOptions> = {}) {
|
27
|
+
super({ ...DEFAULT_AUTO_SNIPER_OPTIONS, ...options });
|
28
|
+
}
|
29
|
+
|
30
|
+
public override shoot(): void {
|
31
|
+
if (!this.parent || !this.processShoot()) return;
|
32
|
+
|
33
|
+
super.shoot();
|
34
|
+
}
|
35
|
+
|
36
|
+
public override getMuzzleFlashPositionRotation(): { position: Vector3Like, rotation: QuaternionLike } {
|
37
|
+
return {
|
38
|
+
position: { x: 0, y: 0.01, z: -2.7 },
|
39
|
+
rotation: Quaternion.fromEuler(0, 90, 0),
|
40
|
+
};
|
41
|
+
}
|
42
|
+
}
|
43
|
+
|
@@ -0,0 +1,46 @@
|
|
1
|
+
import { Quaternion, Vector3Like, QuaternionLike } from 'hytopia';
|
2
|
+
import GunEntity from '../GunEntity';
|
3
|
+
import type { GunEntityOptions } from '../GunEntity';
|
4
|
+
|
5
|
+
const DEFAULT_BOLT_ACTION_SNIPER_OPTIONS: GunEntityOptions = {
|
6
|
+
ammo: 1,
|
7
|
+
damage: 75,
|
8
|
+
fireRate: 0.5,
|
9
|
+
heldHand: 'both',
|
10
|
+
iconImageUri: 'icons/bolt-action-sniper.png',
|
11
|
+
idleAnimation: 'idle_gun_both',
|
12
|
+
mlAnimation: 'shoot_gun_both',
|
13
|
+
name: 'Bolt Action Sniper',
|
14
|
+
maxAmmo: 1,
|
15
|
+
totalAmmo: 12,
|
16
|
+
scopeZoom: 5,
|
17
|
+
modelUri: 'models/items/bolt-action-sniper.glb',
|
18
|
+
modelScale: 1.3,
|
19
|
+
range: 100,
|
20
|
+
reloadAudioUri: 'audio/sfx/sniper-reload.mp3',
|
21
|
+
reloadTimeMs: 2200,
|
22
|
+
shootAudioUri: 'audio/sfx/sniper-shoot.mp3',
|
23
|
+
};
|
24
|
+
|
25
|
+
export default class BoltActionSniperEntity extends GunEntity {
|
26
|
+
public constructor(options: Partial<GunEntityOptions> = {}) {
|
27
|
+
super({ ...DEFAULT_BOLT_ACTION_SNIPER_OPTIONS, ...options });
|
28
|
+
}
|
29
|
+
|
30
|
+
public override shoot(): void {
|
31
|
+
if (!this.parent || !this.processShoot()) return;
|
32
|
+
|
33
|
+
super.shoot();
|
34
|
+
|
35
|
+
// It's bolt action, auto reload it 300ms after a shot.
|
36
|
+
setTimeout(() => { this.reload() }, 300);
|
37
|
+
}
|
38
|
+
|
39
|
+
public override getMuzzleFlashPositionRotation(): { position: Vector3Like, rotation: QuaternionLike } {
|
40
|
+
return { // TODO: FIX MUZZLE FLASH POSITION
|
41
|
+
position: { x: 0, y: 0.01, z: -1.25 },
|
42
|
+
rotation: Quaternion.fromEuler(0, 90, 0),
|
43
|
+
};
|
44
|
+
}
|
45
|
+
}
|
46
|
+
|
@@ -0,0 +1,43 @@
|
|
1
|
+
import { Quaternion, Vector3Like, QuaternionLike } from 'hytopia';
|
2
|
+
import GunEntity from '../GunEntity';
|
3
|
+
import type { GunEntityOptions } from '../GunEntity';
|
4
|
+
|
5
|
+
const DEFAULT_LIGHT_MACHINE_GUN_OPTIONS: GunEntityOptions = {
|
6
|
+
ammo: 50,
|
7
|
+
damage: 9,
|
8
|
+
fireRate: 10,
|
9
|
+
heldHand: 'both',
|
10
|
+
iconImageUri: 'icons/light-machine-gun.png',
|
11
|
+
idleAnimation: 'idle_gun_both',
|
12
|
+
mlAnimation: 'shoot_gun_both',
|
13
|
+
name: 'Light Machine Gun',
|
14
|
+
maxAmmo: 50,
|
15
|
+
totalAmmo: 300,
|
16
|
+
scopeZoom: 1.35,
|
17
|
+
modelUri: 'models/items/light-machine-gun.glb',
|
18
|
+
modelScale: 1.3,
|
19
|
+
range: 50,
|
20
|
+
reloadAudioUri: 'audio/sfx/machine-gun-reload.mp3',
|
21
|
+
reloadTimeMs: 4200,
|
22
|
+
shootAudioUri: 'audio/sfx/machine-gun-shoot.mp3',
|
23
|
+
};
|
24
|
+
|
25
|
+
export default class LightMachineGunEntity extends GunEntity {
|
26
|
+
public constructor(options: Partial<GunEntityOptions> = {}) {
|
27
|
+
super({ ...DEFAULT_LIGHT_MACHINE_GUN_OPTIONS, ...options });
|
28
|
+
}
|
29
|
+
|
30
|
+
public override shoot(): void {
|
31
|
+
if (!this.parent || !this.processShoot()) return;
|
32
|
+
|
33
|
+
super.shoot();
|
34
|
+
}
|
35
|
+
|
36
|
+
public override getMuzzleFlashPositionRotation(): { position: Vector3Like, rotation: QuaternionLike } {
|
37
|
+
return {
|
38
|
+
position: { x: 0, y: 0.05, z: -1.7 },
|
39
|
+
rotation: Quaternion.fromEuler(0, 90, 0),
|
40
|
+
};
|
41
|
+
}
|
42
|
+
}
|
43
|
+
|
@@ -0,0 +1,38 @@
|
|
1
|
+
import { Quaternion } from 'hytopia';
|
2
|
+
import MeleeWeaponEntity from '../MeleeWeaponEntity';
|
3
|
+
import type { MeleeWeaponEntityOptions } from '../MeleeWeaponEntity';
|
4
|
+
|
5
|
+
const DEFAULT_MINING_DRILL_OPTIONS: MeleeWeaponEntityOptions = {
|
6
|
+
damage: 40,
|
7
|
+
attackRate: 5,
|
8
|
+
heldHand: 'right',
|
9
|
+
iconImageUri: 'icons/mining-drill.png',
|
10
|
+
idleAnimation: 'idle_gun_right',
|
11
|
+
mlAnimation: 'shoot_gun_right',
|
12
|
+
name: 'Mining Drill',
|
13
|
+
modelUri: 'models/items/mining-drill.glb',
|
14
|
+
modelScale: 0.05,
|
15
|
+
range: 1.5,
|
16
|
+
minesMaterials: true,
|
17
|
+
attackAudioUri: 'audio/sfx/mining-drill-drilling.mp3',
|
18
|
+
hitAudioUri: 'audio/sfx/dig/dig-stone.mp3',
|
19
|
+
};
|
20
|
+
|
21
|
+
export default class MiningDrillEntity extends MeleeWeaponEntity {
|
22
|
+
public constructor(options: Partial<MeleeWeaponEntityOptions> = {}) {
|
23
|
+
super({ ...DEFAULT_MINING_DRILL_OPTIONS, ...options, tag: 'mining-drill' });
|
24
|
+
}
|
25
|
+
|
26
|
+
public override attack(): void {
|
27
|
+
if (!this.parent || !this.processAttack()) return;
|
28
|
+
|
29
|
+
super.attack();
|
30
|
+
}
|
31
|
+
|
32
|
+
public override equip(): void {
|
33
|
+
super.equip();
|
34
|
+
|
35
|
+
this.setPosition({ x: -0.3, y: 0.5, z: -0.1 });
|
36
|
+
this.setRotation(Quaternion.fromEuler(180, 0, -90));
|
37
|
+
}
|
38
|
+
}
|
@@ -0,0 +1,38 @@
|
|
1
|
+
import { Quaternion } from 'hytopia';
|
2
|
+
import MeleeWeaponEntity from '../MeleeWeaponEntity';
|
3
|
+
import type { MeleeWeaponEntityOptions } from '../MeleeWeaponEntity';
|
4
|
+
|
5
|
+
const DEFAULT_PICKAXE_OPTIONS: MeleeWeaponEntityOptions = {
|
6
|
+
damage: 10, // 10 hits to kill unshielded
|
7
|
+
attackRate: 4.5, // Slower attack rate to prevent spam
|
8
|
+
heldHand: 'right',
|
9
|
+
iconImageUri: 'icons/pickaxe.png',
|
10
|
+
idleAnimation: 'idle_gun_right',
|
11
|
+
mlAnimation: 'simple_interact',
|
12
|
+
name: 'Pickaxe',
|
13
|
+
modelUri: 'models/items/pickaxe.gltf',
|
14
|
+
modelScale: 1.25,
|
15
|
+
range: 2,
|
16
|
+
minesMaterials: true,
|
17
|
+
attackAudioUri: 'audio/sfx/player/player-swing-woosh.mp3',
|
18
|
+
hitAudioUri: 'audio/sfx/dig/dig-stone.mp3',
|
19
|
+
};
|
20
|
+
|
21
|
+
export default class PickaxeEntity extends MeleeWeaponEntity {
|
22
|
+
public constructor(options: Partial<MeleeWeaponEntityOptions> = {}) {
|
23
|
+
super({ ...DEFAULT_PICKAXE_OPTIONS, ...options, tag: 'pickaxe' });
|
24
|
+
}
|
25
|
+
|
26
|
+
public override attack(): void {
|
27
|
+
if (!this.parent || !this.processAttack()) return;
|
28
|
+
|
29
|
+
super.attack();
|
30
|
+
}
|
31
|
+
|
32
|
+
public override equip(): void {
|
33
|
+
super.equip();
|
34
|
+
|
35
|
+
this.setPosition({ x: 0, y: 0.2, z: 0 });
|
36
|
+
this.setRotation(Quaternion.fromEuler(-90, 0, 90));
|
37
|
+
}
|
38
|
+
}
|
@@ -0,0 +1,46 @@
|
|
1
|
+
import { Quaternion, Vector3Like, QuaternionLike } from 'hytopia';
|
2
|
+
import GunEntity from '../GunEntity';
|
3
|
+
import type { GunEntityOptions } from '../GunEntity';
|
4
|
+
import type GamePlayerEntity from '../GamePlayerEntity';
|
5
|
+
|
6
|
+
const DEFAULT_PISTOL_OPTIONS: GunEntityOptions = {
|
7
|
+
ammo: 15,
|
8
|
+
damage: 18,
|
9
|
+
fireRate: 6,
|
10
|
+
heldHand: 'right',
|
11
|
+
iconImageUri: 'icons/pistol.png',
|
12
|
+
idleAnimation: 'idle_gun_right',
|
13
|
+
mlAnimation: 'shoot_gun_right',
|
14
|
+
name: 'Pistol',
|
15
|
+
maxAmmo: 15,
|
16
|
+
totalAmmo: 75,
|
17
|
+
modelUri: 'models/items/pistol.glb',
|
18
|
+
modelScale: 1.3,
|
19
|
+
range: 30,
|
20
|
+
reloadAudioUri: 'audio/sfx/pistol-reload.mp3',
|
21
|
+
reloadTimeMs: 1500,
|
22
|
+
shootAudioUri: 'audio/sfx/pistol-shoot.mp3',
|
23
|
+
};
|
24
|
+
|
25
|
+
export default class PistolEntity extends GunEntity {
|
26
|
+
public constructor(options: Partial<GunEntityOptions> = {}) {
|
27
|
+
super({ ...DEFAULT_PISTOL_OPTIONS, ...options });
|
28
|
+
}
|
29
|
+
|
30
|
+
public override shoot(): void {
|
31
|
+
if (!this.parent || !this.processShoot()) return;
|
32
|
+
|
33
|
+
super.shoot();
|
34
|
+
|
35
|
+
// Cancel input since pistol requires click-to-shoot
|
36
|
+
(this.parent as GamePlayerEntity).player.input.ml = false;
|
37
|
+
}
|
38
|
+
|
39
|
+
public override getMuzzleFlashPositionRotation(): { position: Vector3Like, rotation: QuaternionLike } {
|
40
|
+
return {
|
41
|
+
position: { x: 0.03, y: 0.1, z: -0.5 },
|
42
|
+
rotation: Quaternion.fromEuler(0, 90, 0),
|
43
|
+
};
|
44
|
+
}
|
45
|
+
}
|
46
|
+
|
@@ -0,0 +1,46 @@
|
|
1
|
+
import { Quaternion, Vector3Like, QuaternionLike } from 'hytopia';
|
2
|
+
import GunEntity from '../GunEntity';
|
3
|
+
import type { GunEntityOptions } from '../GunEntity';
|
4
|
+
import type GamePlayerEntity from '../GamePlayerEntity';
|
5
|
+
|
6
|
+
const DEFAULT_REVOLVER_OPTIONS: GunEntityOptions = {
|
7
|
+
ammo: 6,
|
8
|
+
damage: 45,
|
9
|
+
fireRate: 2,
|
10
|
+
heldHand: 'right',
|
11
|
+
iconImageUri: 'icons/revolver.png',
|
12
|
+
idleAnimation: 'idle_gun_right',
|
13
|
+
mlAnimation: 'shoot_gun_right',
|
14
|
+
name: 'Revolver',
|
15
|
+
maxAmmo: 6,
|
16
|
+
totalAmmo: 24,
|
17
|
+
modelUri: 'models/items/revolver.glb',
|
18
|
+
modelScale: 1.3,
|
19
|
+
range: 30,
|
20
|
+
reloadAudioUri: 'audio/sfx/pistol-reload.mp3',
|
21
|
+
reloadTimeMs: 2000,
|
22
|
+
shootAudioUri: 'audio/sfx/rifle-shoot.mp3',
|
23
|
+
};
|
24
|
+
|
25
|
+
export default class RevolverEntity extends GunEntity {
|
26
|
+
public constructor(options: Partial<GunEntityOptions> = {}) {
|
27
|
+
super({ ...DEFAULT_REVOLVER_OPTIONS, ...options });
|
28
|
+
}
|
29
|
+
|
30
|
+
public override shoot(): void {
|
31
|
+
if (!this.parent || !this.processShoot()) return;
|
32
|
+
|
33
|
+
super.shoot();
|
34
|
+
|
35
|
+
// Cancel input since pistol requires click-to-shoot
|
36
|
+
(this.parent as GamePlayerEntity).player.input.ml = false;
|
37
|
+
}
|
38
|
+
|
39
|
+
public override getMuzzleFlashPositionRotation(): { position: Vector3Like, rotation: QuaternionLike } {
|
40
|
+
return {
|
41
|
+
position: { x: 0.03, y: 0.18, z: -0.7 },
|
42
|
+
rotation: Quaternion.fromEuler(0, 90, 0),
|
43
|
+
};
|
44
|
+
}
|
45
|
+
}
|
46
|
+
|