Kampfsystem: Hier Position des Zweihänders und neues feature zum editieren des offsets

This commit is contained in:
2026-10-15 14:04:34 +02:00
parent 6bb195da90
commit d19538bb63
12 changed files with 874 additions and 102 deletions

View File

@@ -12,6 +12,8 @@ import com.jme3.scene.control.AbstractControl;
import de.blight.common.model.Item;
import de.blight.common.model.ItemGrip;
import de.blight.common.model.ItemSubCategory;
import de.blight.common.model.WeaponAttachmentIO;
import de.blight.common.model.WeaponCategoryAttachment;
import de.blight.game.animation.RetargetingSystem;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -146,14 +148,13 @@ public class NpcWeaponAttachmentControl extends AbstractControl {
boolean usesTwoHand = isTwoHand && leftForeArmNode != null
&& wGrip != null
&& (wGrip.getGrip2PosX() != 0f || wGrip.getGrip2PosY() != 0f || wGrip.getGrip2PosZ() != 0f);
WeaponCategoryAttachment cfg = WeaponAttachmentIO.get(
weaponItem != null ? weaponItem.getSubCategory() : null);
if (usesTwoHand) {
Vector3f handballen = (palmOffsetLocal != null)
? boneInChar.subtract(boneRotInChar.mult(palmOffsetLocal.mult(0.5f)))
: boneInChar;
applyTwoHandTransform(weaponSpatial, handballen, boneRotInChar,
wGrip, charWorldRotInv, charWorldPos);
applyTwoHandTransform(weaponSpatial, attachInChar, boneRotInChar,
wGrip, charWorldRotInv, charWorldPos, cfg);
} else {
applyHandTransform(weaponSpatial, attachInChar, boneRotInChar, wGrip);
applyHandTransform(weaponSpatial, attachInChar, boneRotInChar, wGrip, cfg);
}
} else {
applyBackTransform(weaponSpatial, boneInChar, boneRotInChar,
@@ -196,7 +197,8 @@ public class NpcWeaponAttachmentControl extends AbstractControl {
// ── Hand-Transform (1:1 von WeaponAttachmentControl) ─────────────────────────
private void applyHandTransform(Spatial s, Vector3f bonePosInChar,
Quaternion boneRotInChar, ItemGrip grip) {
Quaternion boneRotInChar, ItemGrip grip,
WeaponCategoryAttachment cfg) {
Quaternion gripRot = (grip != null)
? new Quaternion().fromAngles(DEG_TO_RAD * grip.getRotX(),
DEG_TO_RAD * grip.getRotY(),
@@ -214,8 +216,8 @@ public class NpcWeaponAttachmentControl extends AbstractControl {
: new Quaternion();
Quaternion weaponRot = animDelta.mult(bladeFlip).mult(gripRot.inverse());
Vector3f handOff = bladeAtMinusZ
? new Vector3f(HAND_GRIP_OFFSET.x, HAND_GRIP_OFFSET.y, -HAND_GRIP_OFFSET.z)
: HAND_GRIP_OFFSET;
? new Vector3f(cfg.getHandOffX(), cfg.getHandOffY(), -cfg.getHandOffZ())
: new Vector3f(cfg.getHandOffX(), cfg.getHandOffY(), cfg.getHandOffZ());
Vector3f weaponPos = bonePosInChar.subtract(weaponRot.mult(gripPos));
weaponPos = weaponPos.add(weaponRot.mult(handOff));
s.setLocalRotation(weaponRot);
@@ -223,7 +225,8 @@ public class NpcWeaponAttachmentControl extends AbstractControl {
}
private void applyTwoHandTransform(Spatial s, Vector3f bonePosInChar, Quaternion boneRotInChar,
ItemGrip grip, Quaternion charWorldRotInv, Vector3f charWorldPos) {
ItemGrip grip, Quaternion charWorldRotInv, Vector3f charWorldPos,
WeaponCategoryAttachment cfg) {
Quaternion gripRot = new Quaternion().fromAngles(
DEG_TO_RAD * grip.getRotX(), DEG_TO_RAD * grip.getRotY(), DEG_TO_RAD * grip.getRotZ());
Quaternion animDelta = (handBindRotInChar != null)
@@ -236,28 +239,21 @@ public class NpcWeaponAttachmentControl extends AbstractControl {
Vector3f g1 = new Vector3f(grip.getPosX(), grip.getPosY(), grip.getPosZ());
Vector3f g2 = new Vector3f(grip.getGrip2PosX(), grip.getGrip2PosY(), grip.getGrip2PosZ());
// Griffspanne virtuell auf 22cm; g1 (rechte Hand) 10cm weiter Richtung Klinge
Vector3f gripAxis = g1.subtract(g2).normalizeLocal();
Vector3f gripCenter = g1.add(g2).multLocal(0.5f);
g1 = gripCenter.add(gripAxis.mult(0.21f));
g2 = gripCenter.subtract(gripAxis.mult(0.11f));
Vector3f handOff = bladeAtMinusZ
? new Vector3f(cfg.getHandOffX(), cfg.getHandOffY(), -cfg.getHandOffZ())
: new Vector3f(cfg.getHandOffX(), cfg.getHandOffY(), cfg.getHandOffZ());
Vector3f hand2Off = bladeAtMinusZ
? new Vector3f(cfg.getHand2OffX(), cfg.getHand2OffY(), -cfg.getHand2OffZ())
: new Vector3f(cfg.getHand2OffX(), cfg.getHand2OffY(), cfg.getHand2OffZ());
Vector3f g1eff = g1.subtract(handOff);
Vector3f g2eff = g2.add(hand2Off);
Vector3f leftHandInChar = charWorldRotInv.mult(leftForeArmNode.getWorldTranslation().subtract(charWorldPos));
Quaternion leftBoneRotInChar = charWorldRotInv.mult(leftForeArmNode.getWorldRotation());
Vector3f leftHandballen = (palmOffsetLocal != null)
? leftHandInChar.subtract(leftBoneRotInChar.mult(palmOffsetLocal.mult(0.5f)))
: leftHandInChar;
leftHandballen.addLocal(0.10f, 0f, 0f);
Vector3f currentGripDir = weaponRot.mult(g2eff.subtract(g1eff).normalizeLocal());
Vector3f targetDir = leftHandInChar.subtract(bonePosInChar).normalizeLocal();
weaponRot = swingFromTo(currentGripDir, targetDir).mult(weaponRot);
// Swing: Griffachse auf linken Handballen ausrichten (inkl. X-Korrektur)
Vector3f currentGripDir = weaponRot.mult(g2.subtract(g1).normalizeLocal());
Vector3f targetDir = leftHandballen.subtract(bonePosInChar).normalizeLocal();
float dot = currentGripDir.dot(targetDir);
if (dot > 0f) {
weaponRot = swingFromTo(currentGripDir, targetDir).mult(weaponRot);
}
// g1 exakt an der rechten Hand anpinnen — linke-Hand-Korrekturen beeinflussen rechte nicht
Vector3f weaponPos = bonePosInChar.subtract(weaponRot.mult(g1));
Vector3f weaponPos = bonePosInChar.subtract(weaponRot.mult(g1eff));
s.setLocalRotation(weaponRot);
s.setLocalTranslation(weaponPos);
}

View File

@@ -13,6 +13,8 @@ import de.blight.common.model.Item;
import de.blight.common.model.ItemGrip;
import de.blight.common.model.ItemSubCategory;
import de.blight.common.model.MainCharacter;
import de.blight.common.model.WeaponAttachmentIO;
import de.blight.common.model.WeaponCategoryAttachment;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -188,6 +190,7 @@ public class WeaponAttachmentControl extends AbstractControl {
if (drawn) {
boolean isTwoHand = item != null && item.getSubCategory() == ItemSubCategory.TWO_HANDED_SWORD;
WeaponCategoryAttachment cfg = WeaponAttachmentIO.get(item != null ? item.getSubCategory() : null);
Vector3f attachInChar = (palmOffsetLocal != null)
? boneInChar.add(boneRotInChar.mult(palmOffsetLocal.mult(0.5f)))
: boneInChar;
@@ -195,20 +198,17 @@ public class WeaponAttachmentControl extends AbstractControl {
&& grip != null
&& (grip.getGrip2PosX() != 0f || grip.getGrip2PosY() != 0f || grip.getGrip2PosZ() != 0f);
if (usesTwoHand) {
// Handballen: entgegengesetzte Richtung von palmOffset (der Richtung Finger zeigt)
Vector3f handballen = (palmOffsetLocal != null)
? boneInChar.subtract(boneRotInChar.mult(palmOffsetLocal.mult(0.5f)))
: boneInChar;
applyTwoHandTransform(handballen, boneRotInChar, grip, charWorldRotInv, charWorldPos);
applyTwoHandTransform(attachInChar, boneRotInChar, grip, charWorldRotInv, charWorldPos, cfg);
} else {
applyHandTransform(attachInChar, boneRotInChar, grip);
applyHandTransform(attachInChar, boneRotInChar, grip, cfg);
}
} else {
applyBackTransform(boneInChar, boneRotInChar, grip);
}
}
private void applyHandTransform(Vector3f bonePosInChar, Quaternion boneRotInChar, ItemGrip grip) {
private void applyHandTransform(Vector3f bonePosInChar, Quaternion boneRotInChar, ItemGrip grip,
WeaponCategoryAttachment cfg) {
Quaternion gripRot = (grip != null)
? new Quaternion().fromAngles(DEG_TO_RAD * grip.getRotX(), DEG_TO_RAD * grip.getRotY(), DEG_TO_RAD * grip.getRotZ())
: new Quaternion();
@@ -259,8 +259,8 @@ public class WeaponAttachmentControl extends AbstractControl {
}
Vector3f handOff2 = bladeAtMinusZ2
? new Vector3f(HAND_GRIP_OFFSET.x, HAND_GRIP_OFFSET.y, -HAND_GRIP_OFFSET.z)
: HAND_GRIP_OFFSET;
? new Vector3f(cfg.getHandOffX(), cfg.getHandOffY(), -cfg.getHandOffZ())
: new Vector3f(cfg.getHandOffX(), cfg.getHandOffY(), cfg.getHandOffZ());
Vector3f weaponPos = bonePosInChar.subtract(weaponRot.mult(gripPos));
weaponPos = weaponPos.add(weaponRot.mult(handOff2));
if (grip != null && (grip.getHandOffsetX() != 0f || grip.getHandOffsetY() != 0f || grip.getHandOffsetZ() != 0f)) {
@@ -272,7 +272,8 @@ public class WeaponAttachmentControl extends AbstractControl {
private void applyTwoHandTransform(Vector3f bonePosInChar, Quaternion boneRotInChar,
ItemGrip grip,
Quaternion charWorldRotInv, Vector3f charWorldPos) {
Quaternion charWorldRotInv, Vector3f charWorldPos,
WeaponCategoryAttachment cfg) {
// Basis-Rotation aus rechter Hand (gibt Roll/Handflächenausrichtung)
Quaternion gripRot = new Quaternion().fromAngles(
DEG_TO_RAD * grip.getRotX(), DEG_TO_RAD * grip.getRotY(), DEG_TO_RAD * grip.getRotZ());
@@ -286,29 +287,25 @@ public class WeaponAttachmentControl extends AbstractControl {
Vector3f g1 = new Vector3f(grip.getPosX(), grip.getPosY(), grip.getPosZ());
Vector3f g2 = new Vector3f(grip.getGrip2PosX(), grip.getGrip2PosY(), grip.getGrip2PosZ());
// Griffspanne virtuell auf 22cm; g1 (rechte Hand) 10cm weiter Richtung Klinge
Vector3f gripAxis = g1.subtract(g2).normalizeLocal();
Vector3f gripCenter = g1.add(g2).multLocal(0.5f);
g1 = gripCenter.add(gripAxis.mult(0.21f));
g2 = gripCenter.subtract(gripAxis.mult(0.11f));
Vector3f leftHandInChar = charWorldRotInv.mult(leftForeArmNode.getWorldTranslation().subtract(charWorldPos));
// Linke Hand: Handballen-Korrektur (Palm-Offset entgegen Fingerrichtung) – nur für midTarget, nicht für targetDir
Quaternion leftBoneRotInChar = charWorldRotInv.mult(leftForeArmNode.getWorldRotation());
Vector3f leftHandballen = (palmOffsetLocal != null)
? leftHandInChar.subtract(leftBoneRotInChar.mult(palmOffsetLocal.mult(0.5f)))
: leftHandInChar;
leftHandballen.addLocal(0.10f, 0f, 0f);
// g1 hat handOff eingebaut (Kategorie-Config), g2 nicht → g1eff bereinigt den Unterschied
Vector3f handOff = bladeAtMinusZ
? new Vector3f(cfg.getHandOffX(), cfg.getHandOffY(), -cfg.getHandOffZ())
: new Vector3f(cfg.getHandOffX(), cfg.getHandOffY(), cfg.getHandOffZ());
// Korrektur g2 durch hand2Offset der Kategorie
Vector3f hand2Off = bladeAtMinusZ
? new Vector3f(cfg.getHand2OffX(), cfg.getHand2OffY(), -cfg.getHand2OffZ())
: new Vector3f(cfg.getHand2OffX(), cfg.getHand2OffY(), cfg.getHand2OffZ());
Vector3f g1eff = g1.subtract(handOff);
Vector3f g2eff = g2.add(hand2Off);
// Swing: Griffachse auf linken Handballen ausrichten (inkl. X-Korrektur)
Vector3f currentGripDir = weaponRot.mult(g2.subtract(g1).normalizeLocal());
Vector3f targetDir = leftHandballen.subtract(bonePosInChar).normalizeLocal();
float dot = currentGripDir.dot(targetDir);
if (dot > 0f) {
weaponRot = swingFromTo(currentGripDir, targetDir).mult(weaponRot);
}
// Swing: g1eff→g2eff-Richtung auf rechteHand→linkeHand ausrichten
Vector3f leftHandInChar = charWorldRotInv.mult(leftForeArmNode.getWorldTranslation().subtract(charWorldPos));
Vector3f currentGripDir = weaponRot.mult(g2eff.subtract(g1eff).normalizeLocal());
Vector3f targetDir = leftHandInChar.subtract(bonePosInChar).normalizeLocal();
weaponRot = swingFromTo(currentGripDir, targetDir).mult(weaponRot);
// g1 exakt an der rechten Hand anpinnen — linke-Hand-Korrekturen beeinflussen rechte nicht
Vector3f weaponPos = bonePosInChar.subtract(weaponRot.mult(g1));
// g1eff an bonePosInChar pinnen
Vector3f weaponPos = bonePosInChar.subtract(weaponRot.mult(g1eff));
weaponSpatial.setLocalRotation(weaponRot);
weaponSpatial.setLocalTranslation(weaponPos);
}