import * as THREE from 'three'; import type { Game } from './Game'; import { Brute } from './Brute'; export class Golem extends Brute { constructor() { super(); this.health = 800; this.maxHealth = 800; this.isBoss = true; this.displayName = 'Golem'; this.speed = 3; this.xp = 80; this.contactDps = 50; this.contactRadius = 3.4; this.guaranteedDrop = true; // Brute-Standardmodell verwerfen und als Fels-Golem neu aufbauen this.model.clear(); const rockMat = new THREE.MeshToonMaterial({ color: 0x6a6a78 }); const darkMat = new THREE.MeshToonMaterial({ color: 0x3c3c46 }); const mossMat = new THREE.MeshToonMaterial({ color: 0x4a8a4a }); const eyeMat = new THREE.MeshBasicMaterial({ color: 0xff6622 }); // Facettierte Fels-Optik: flache Normalen auf der unindizierten Geometrie const rockGeom = (r: number) => { const g = new THREE.DodecahedronGeometry(r); g.computeVertexNormals(); return g; }; // Becken + Rumpf (facettierte Felsbrocken) const pelvis = new THREE.Mesh(rockGeom(0.42), darkMat); pelvis.scale.set(1.2, 0.8, 0.9); pelvis.position.y = 0.75; this.registerFadeMesh(pelvis); this.model.add(pelvis); const torso = new THREE.Mesh(rockGeom(0.72), rockMat); torso.scale.set(1.25, 1.05, 0.95); torso.position.y = 1.4; torso.castShadow = true; this.registerFadeMesh(torso); this.model.add(torso); // Glühender Kern in der Brust (+Z) const core = new THREE.Mesh(new THREE.BoxGeometry(0.28, 0.36, 0.08), eyeMat); core.position.set(0, 1.45, 0.66); this.model.add(core); // Kopf mit Stirnplatte, Augen und Kiefer (+Z) const head = new THREE.Mesh(rockGeom(0.38), rockMat); head.position.y = 2.15; head.castShadow = true; this.registerFadeMesh(head); this.model.add(head); const brow = new THREE.Mesh(new THREE.BoxGeometry(0.5, 0.1, 0.12), darkMat); brow.position.set(0, 2.3, 0.3); this.registerFadeMesh(brow); this.model.add(brow); for (const side of [-1, 1]) { const eye = new THREE.Mesh(new THREE.BoxGeometry(0.13, 0.09, 0.05), eyeMat); eye.position.set(side * 0.15, 2.15, 0.33); this.model.add(eye); } const jaw = new THREE.Mesh(new THREE.BoxGeometry(0.3, 0.12, 0.2), darkMat); jaw.position.set(0, 1.93, 0.25); this.registerFadeMesh(jaw); this.model.add(jaw); // Felsstacheln auf dem Rücken for (const side of [-1, 1]) { const spike = new THREE.Mesh(new THREE.ConeGeometry(0.14, 0.45, 5), darkMat); spike.position.set(side * 0.3, 1.75, -0.6); spike.rotation.x = 0.6; this.registerFadeMesh(spike); this.model.add(spike); } // Moosflecken const mossSpots: [number, number, number, number][] = [ [-0.9, 2.15, 0.1, 0.12], [0.5, 1.95, 0.3, 0.1], [0.3, 2.4, -0.1, 0.09], ]; for (const [x, y, z, r] of mossSpots) { const moss = new THREE.Mesh(rockGeom(r), mossMat); moss.position.set(x, y, z); this.registerFadeMesh(moss); this.model.add(moss); } // Schultern + gegliederte Arme (Schulter-Pivot für Laufanimation) for (const side of [-1, 1]) { const shoulder = new THREE.Mesh(rockGeom(0.48), rockMat); shoulder.position.set(side * 0.95, 1.75, 0); shoulder.castShadow = true; this.registerFadeMesh(shoulder); this.model.add(shoulder); const arm = new THREE.Group(); arm.position.set(side * 0.95, 1.7, 0); this.model.add(arm); const upperArm = new THREE.Mesh(new THREE.CylinderGeometry(0.16, 0.2, 0.55, 6), rockMat); upperArm.position.y = -0.3; this.registerFadeMesh(upperArm); arm.add(upperArm); const elbow = new THREE.Mesh(rockGeom(0.18), darkMat); elbow.position.y = -0.6; this.registerFadeMesh(elbow); arm.add(elbow); const foreArm = new THREE.Mesh(new THREE.CylinderGeometry(0.14, 0.18, 0.5, 6), darkMat); foreArm.position.y = -0.85; this.registerFadeMesh(foreArm); arm.add(foreArm); const fist = new THREE.Mesh(rockGeom(0.24), rockMat); fist.scale.set(1, 0.8, 1.1); fist.position.y = -1.15; this.registerFadeMesh(fist); arm.add(fist); if (side < 0) { this.armL = arm; } else { this.armR = arm; } } // Beine (Hüft-Pivot für Laufanimation) for (const side of [-1, 1]) { const leg = new THREE.Group(); leg.position.set(side * 0.4, 0.75, 0); this.model.add(leg); const thigh = new THREE.Mesh(new THREE.CylinderGeometry(0.18, 0.24, 0.4, 6), rockMat); thigh.position.y = -0.18; this.registerFadeMesh(thigh); leg.add(thigh); const knee = new THREE.Mesh(rockGeom(0.16), darkMat); knee.position.y = -0.38; this.registerFadeMesh(knee); leg.add(knee); const shin = new THREE.Mesh(new THREE.CylinderGeometry(0.14, 0.18, 0.35, 6), darkMat); shin.position.y = -0.52; this.registerFadeMesh(shin); leg.add(shin); const foot = new THREE.Mesh(new THREE.BoxGeometry(0.32, 0.16, 0.5), rockMat); foot.position.set(0, -0.67, 0.08); this.registerFadeMesh(foot); leg.add(foot); if (side < 0) { this.legL = leg; } else { this.legR = leg; } } this.model.scale.setScalar(2.1); // Krone (Boss-Markierung) const crownMat = new THREE.MeshToonMaterial({ color: 0xffcc33 }); const crown = new THREE.Mesh( new THREE.ConeGeometry(0.3, 0.4, 8, 1, true), crownMat ); crown.position.y = 2.55; crown.castShadow = true; this.registerFadeMesh(crown); this.model.add(crown); } protected onDeath(_game: Game) { this.beginFadeDeath(); } }