Files
Wackelpeter/web/src/Staff.ts
T

97 lines
3.1 KiB
TypeScript

import * as THREE from 'three';
import { Weapon } from './Weapon';
import { Player } from './Player';
import { Fireball } from './Fireball';
import { playSound } from './SoundManager';
import { loadGLB } from './MeshLoader';
import { fireballDamage, fireballCooldown, fireballRadius, teleportCooldown } from './Skills';
export class Staff extends Weapon {
constructor() {
super();
this.COOLDOWN1_TIME = 5;
this.COOLDOWN2_TIME = 50;
// Fallback geometry
const shaftGeom = new THREE.CylinderGeometry(0.04, 0.05, 1.0, 8);
const crystalGeom = new THREE.OctahedronGeometry(0.08);
const woodMat = new THREE.MeshToonMaterial({ color: 0x8B4513 });
const crystalMat = new THREE.MeshToonMaterial({ color: 0x4488ff });
const shaft = new THREE.Mesh(shaftGeom, woodMat);
shaft.position.y = 0.3;
shaft.castShadow = true;
const crystal = new THREE.Mesh(crystalGeom, crystalMat);
crystal.position.y = 0.9;
this.mesh.add(shaft);
this.mesh.add(crystal);
this.mesh.position.set(0.35, 0.3, 0.35);
this.mesh.scale.set(0.35, 0.35, 0.35);
this.mesh.rotation.set(-0.2, 0, -0.2);
}
async init() {
try {
const gltf = await loadGLB('staff');
const model = gltf.scene;
const staffTexture = new THREE.TextureLoader().load('./textures/staff1.png');
staffTexture.flipY = false;
staffTexture.colorSpace = THREE.SRGBColorSpace;
model.traverse((child) => {
if (child instanceof THREE.Mesh) {
child.castShadow = true;
child.material = new THREE.MeshToonMaterial({ map: staffTexture });
}
});
while (this.mesh.children.length > 0) {
this.mesh.remove(this.mesh.children[0]);
}
this.mesh.add(model);
} catch {
// Keep fallback
}
}
skill1(groundPoint: THREE.Vector3, player: Player): void {
const level = player.game.skillSystem.getLevel('fireball');
if (level <= 0) return;
if (this.cooldown1 > 0) return;
this.COOLDOWN1_TIME = fireballCooldown(level);
this.cooldown1 = this.COOLDOWN1_TIME;
// Spawn at staff height, fly toward the cursor point
const spawnPos = player.body.position.clone();
spawnPos.y += 0.8;
const dir = new THREE.Vector3()
.subVectors(groundPoint, spawnPos)
.normalize()
.multiplyScalar(25);
dir.setY(0);
const fb = new Fireball(spawnPos, dir);
fb.damage = fireballDamage(level);
fb.explosionRadius = fireballRadius(level);
player.game.scene.add(fb.body);
player.game.fireballs.push(fb);
playSound('fireball', 0.5);
}
skill2(groundPoint: THREE.Vector3, player: Player): void {
const level = player.game.skillSystem.getLevel('teleport');
if (level <= 0) return;
if (this.cooldown2 > 0) return;
this.COOLDOWN2_TIME = teleportCooldown(level);
this.cooldown2 = this.COOLDOWN2_TIME;
const newPos = groundPoint.clone();
newPos.y = 0.5;
newPos.x = Math.max(-47, Math.min(47, newPos.x));
newPos.z = Math.max(-47, Math.min(47, newPos.z));
player.body.position.copy(newPos);
playSound('teleport', 0.5);
}
}