Rework necromancer, archer, shaman and golem models with procedural animations
This commit is contained in:
+139
-2
@@ -15,15 +15,152 @@ export class Golem extends Brute {
|
||||
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);
|
||||
|
||||
// Crown
|
||||
// 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.25;
|
||||
crown.position.y = 2.55;
|
||||
crown.castShadow = true;
|
||||
this.registerFadeMesh(crown);
|
||||
this.model.add(crown);
|
||||
|
||||
Reference in New Issue
Block a user