Kampfsystem für Zweihänder erweitert
This commit is contained in:
@@ -53,10 +53,13 @@ public enum AnimationAction {
|
||||
AXE_IDLE, AXE_WALK, AXE_RUN,
|
||||
|
||||
// ── Zweihänder ────────────────────────────────────────────────────────────
|
||||
TWO_HAND_DRAW, TWO_HAND_SHEATHE, TWO_HAND_BLOCK,
|
||||
TWO_HAND_DRAW, TWO_HAND_SHEATHE, TWO_HAND_BLOCK,
|
||||
TWO_HAND_ATTACK_1, TWO_HAND_ATTACK_2, TWO_HAND_ATTACK_3, TWO_HAND_HEAVY_ATTACK,
|
||||
TWO_HAND_IDLE_TO_BLOCK, TWO_HAND_PARADE, TWO_HAND_BLOCK_IMPACT, TWO_HAND_IDLE_IMPACT,
|
||||
TWO_HAND_IDLE, TWO_HAND_WALK, TWO_HAND_RUN,
|
||||
TWO_HAND_IDLE, TWO_HAND_WALK, TWO_HAND_RUN, TWO_HAND_JUMP, TWO_HAND_RUNNING_JUMP,
|
||||
TWO_HAND_IDLE_BORED, TWO_HAND_IDLE_BORED_2, TWO_HAND_IDLE_BORED_3,
|
||||
TWO_HAND_DEATH, TWO_HAND_DEATH_2,
|
||||
TWO_HAND_BLOCK_MOVE, TWO_HAND_BLOCK_MOVE_BACKWARD, TWO_HAND_BLOCK_STRAFE_LEFT, TWO_HAND_BLOCK_STRAFE_RIGHT,
|
||||
|
||||
// ── Bogen ─────────────────────────────────────────────────────────────────
|
||||
BOW_DRAW, BOW_SHEATHE, BOW_HIT_TAKEN,
|
||||
@@ -157,8 +160,19 @@ public enum AnimationAction {
|
||||
case TWO_HAND_BLOCK_IMPACT -> TextRegistry.resolve(null, key, "Block-Treffer (Zweihänder)");
|
||||
case TWO_HAND_IDLE_IMPACT -> TextRegistry.resolve(null, key, "Treffer (Zweihänder)");
|
||||
case TWO_HAND_IDLE -> TextRegistry.resolve(null, key, "Stehen (Zweihänder)");
|
||||
case TWO_HAND_WALK -> TextRegistry.resolve(null, key, "Gehen (Zweihänder)");
|
||||
case TWO_HAND_RUN -> TextRegistry.resolve(null, key, "Laufen (Zweihänder)");
|
||||
case TWO_HAND_WALK -> TextRegistry.resolve(null, key, "Gehen (Zweihänder)");
|
||||
case TWO_HAND_RUN -> TextRegistry.resolve(null, key, "Laufen (Zweihänder)");
|
||||
case TWO_HAND_JUMP -> TextRegistry.resolve(null, key, "Sprung (Zweihänder)");
|
||||
case TWO_HAND_RUNNING_JUMP -> TextRegistry.resolve(null, key, "Sprung Laufend (Zweihänder)");
|
||||
case TWO_HAND_IDLE_BORED -> TextRegistry.resolve(null, key, "Idle Gelangweilt (Zweihänder)");
|
||||
case TWO_HAND_IDLE_BORED_2 -> TextRegistry.resolve(null, key, "Idle Gelangweilt 2 (Zweihänder)");
|
||||
case TWO_HAND_IDLE_BORED_3 -> TextRegistry.resolve(null, key, "Idle Gelangweilt 3 (Zweihänder)");
|
||||
case TWO_HAND_DEATH -> TextRegistry.resolve(null, key, "Tod (Zweihänder)");
|
||||
case TWO_HAND_DEATH_2 -> TextRegistry.resolve(null, key, "Tod 2 (Zweihänder)");
|
||||
case TWO_HAND_BLOCK_MOVE -> TextRegistry.resolve(null, key, "Block Vorwärts (Zweihänder)");
|
||||
case TWO_HAND_BLOCK_MOVE_BACKWARD -> TextRegistry.resolve(null, key, "Block Rückwärts (Zweihänder)");
|
||||
case TWO_HAND_BLOCK_STRAFE_LEFT -> TextRegistry.resolve(null, key, "Block Strafe Links (Zweihänder)");
|
||||
case TWO_HAND_BLOCK_STRAFE_RIGHT -> TextRegistry.resolve(null, key, "Block Strafe Rechts (Zweihänder)");
|
||||
|
||||
case BOW_DRAW -> TextRegistry.resolve(null, key, "Ziehen (Bogen)");
|
||||
case BOW_SHEATHE -> TextRegistry.resolve(null, key, "Wegstecken (Bogen)");
|
||||
|
||||
@@ -31,9 +31,8 @@ public final class SwordShieldCombat extends CombatStyleBase {
|
||||
public static AnimationAction resolveIdleImpactAction(ItemSubCategory weaponType) {
|
||||
if (weaponType == null) { return AnimationAction.SWORD_IDLE_IMPACT; }
|
||||
return switch (weaponType) {
|
||||
case AXE -> AnimationAction.AXE_IDLE_IMPACT;
|
||||
case TWO_HANDED_SWORD -> AnimationAction.TWO_HAND_IDLE_IMPACT;
|
||||
default -> AnimationAction.SWORD_IDLE_IMPACT;
|
||||
case AXE -> AnimationAction.AXE_IDLE_IMPACT;
|
||||
default -> AnimationAction.SWORD_IDLE_IMPACT;
|
||||
};
|
||||
}
|
||||
|
||||
@@ -44,9 +43,8 @@ public final class SwordShieldCombat extends CombatStyleBase {
|
||||
public static AnimationAction resolveBlockImpactAction(ItemSubCategory weaponType) {
|
||||
if (weaponType == null) { return AnimationAction.SWORD_BLOCK_IMPACT; }
|
||||
return switch (weaponType) {
|
||||
case AXE -> AnimationAction.AXE_BLOCK_IMPACT;
|
||||
case TWO_HANDED_SWORD -> AnimationAction.TWO_HAND_BLOCK_IMPACT;
|
||||
default -> AnimationAction.SWORD_BLOCK_IMPACT;
|
||||
case AXE -> AnimationAction.AXE_BLOCK_IMPACT;
|
||||
default -> AnimationAction.SWORD_BLOCK_IMPACT;
|
||||
};
|
||||
}
|
||||
|
||||
@@ -57,9 +55,8 @@ public final class SwordShieldCombat extends CombatStyleBase {
|
||||
public static AnimationAction resolveParadeAction(ItemSubCategory weaponType) {
|
||||
if (weaponType == null) { return AnimationAction.SWORD_PARADE; }
|
||||
return switch (weaponType) {
|
||||
case AXE -> AnimationAction.AXE_PARADE;
|
||||
case TWO_HANDED_SWORD -> AnimationAction.TWO_HAND_PARADE;
|
||||
default -> AnimationAction.SWORD_PARADE;
|
||||
case AXE -> AnimationAction.AXE_PARADE;
|
||||
default -> AnimationAction.SWORD_PARADE;
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,68 @@
|
||||
package de.blight.game.combat.twohanded;
|
||||
|
||||
import de.blight.game.animation.AnimationAction;
|
||||
import de.blight.game.combat.CombatStyleBase;
|
||||
|
||||
/**
|
||||
* Gemeinsame Kampflogik für den Zweihänder-Stil.
|
||||
*
|
||||
* Wird von beiden Seiten genutzt:
|
||||
* – {@code PlayerInputControl} (Held)
|
||||
* – {@code WorldNpcsState} (Gegner-KI)
|
||||
*
|
||||
* Alle Animations-Auflösungen (welche Animation für welches Ereignis?) und
|
||||
* alle Reaktions-Anwendungen (Impact, Stagger, Konterparade) sind hier
|
||||
* zentralisiert. Bug-Fixes gelten damit automatisch für Held und NPC.
|
||||
*
|
||||
* Neuer Kampfstil: erbt von {@link CombatStyleBase} und folgt demselben
|
||||
* Muster in einem eigenen Unter-Package.
|
||||
*/
|
||||
public final class TwoHandedCombat extends CombatStyleBase {
|
||||
|
||||
private TwoHandedCombat() {}
|
||||
|
||||
// ── Animations-Auflösung ──────────────────────────────────────────────────
|
||||
|
||||
/**
|
||||
* Impact-Animation in Idle/Kampf-Haltung (Entität wurde getroffen).
|
||||
* Identisch für Spieler und NPC.
|
||||
*/
|
||||
public static AnimationAction resolveIdleImpactAction() {
|
||||
return AnimationAction.TWO_HAND_IDLE_IMPACT;
|
||||
}
|
||||
|
||||
/**
|
||||
* Block-Impact-Animation (Entität hat einen Treffer abgeblockt).
|
||||
* Identisch für Spieler und NPC.
|
||||
*/
|
||||
public static AnimationAction resolveBlockImpactAction() {
|
||||
return AnimationAction.TWO_HAND_BLOCK_IMPACT;
|
||||
}
|
||||
|
||||
/**
|
||||
* Konterangriff-Animation nach erfolgreicher Parade.
|
||||
* Identisch für Spieler und NPC.
|
||||
*/
|
||||
public static AnimationAction resolveParadeAction() {
|
||||
return AnimationAction.TWO_HAND_PARADE;
|
||||
}
|
||||
|
||||
// ── Reaktionen anwenden ───────────────────────────────────────────────────
|
||||
|
||||
/**
|
||||
* Normaler Treffer-Impact (Entität wurde getroffen, kein Block).
|
||||
* Für Held: {@code PlayerInputControl} implementiert {@link AnimReceiver}.
|
||||
* Für NPC: {@code WorldNpcsState.npcAnimReceiver(s)} liefert den Adapter.
|
||||
*/
|
||||
public static void applyNormalImpact(AnimReceiver receiver) {
|
||||
receiver.receiveBlockingAnim(resolveIdleImpactAction(), IMPACT_SPEED_NORMAL, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Konterparade-Impact (Angreifer wird durch Parade gestoppt – Slow Motion).
|
||||
* Wird aufgerufen auf dem ANGREIFER, nicht auf dem Parierenden.
|
||||
*/
|
||||
public static void applyParriedImpact(AnimReceiver receiver) {
|
||||
receiver.receiveBlockingAnim(resolveIdleImpactAction(), IMPACT_SPEED_PARRIED, null);
|
||||
}
|
||||
}
|
||||
@@ -34,6 +34,7 @@ import de.blight.game.combat.CombatStyleBase;
|
||||
import de.blight.game.combat.MeleeAttackCallback;
|
||||
import de.blight.game.combat.WeaponCombatState;
|
||||
import de.blight.game.combat.swordshield.SwordShieldCombat;
|
||||
import de.blight.game.combat.twohanded.TwoHandedCombat;
|
||||
import de.blight.game.navigation.CharacterNavigator;
|
||||
import de.blight.game.state.TerrainChunkState;
|
||||
|
||||
@@ -1254,10 +1255,11 @@ public class PlayerInputControl implements CombatStyleBase.AnimReceiver {
|
||||
} else if (blockPhase == BlockPhase.HOLDING && !combatAnimActive) {
|
||||
// Beim Blocken: Bewegungsanimation nach Taste, Strafe hat Vorrang
|
||||
AnimationAction blockMoveAnim;
|
||||
if (right) blockMoveAnim = AnimationAction.SWORD_BLOCK_STRAFE_RIGHT;
|
||||
else if (left) blockMoveAnim = AnimationAction.SWORD_BLOCK_STRAFE_LEFT;
|
||||
else if (forward) blockMoveAnim = AnimationAction.SWORD_BLOCK_MOVE;
|
||||
else if (backward) blockMoveAnim = AnimationAction.SWORD_BLOCK_MOVE_BACKWARD;
|
||||
boolean twoHand = drawnWeaponType == ItemSubCategory.TWO_HANDED_SWORD;
|
||||
if (right) blockMoveAnim = twoHand ? AnimationAction.TWO_HAND_BLOCK_STRAFE_RIGHT : AnimationAction.SWORD_BLOCK_STRAFE_RIGHT;
|
||||
else if (left) blockMoveAnim = twoHand ? AnimationAction.TWO_HAND_BLOCK_STRAFE_LEFT : AnimationAction.SWORD_BLOCK_STRAFE_LEFT;
|
||||
else if (forward) blockMoveAnim = twoHand ? AnimationAction.TWO_HAND_BLOCK_MOVE : AnimationAction.SWORD_BLOCK_MOVE;
|
||||
else if (backward) blockMoveAnim = twoHand ? AnimationAction.TWO_HAND_BLOCK_MOVE_BACKWARD : AnimationAction.SWORD_BLOCK_MOVE_BACKWARD;
|
||||
else blockMoveAnim = getMeleeBlockAction(drawnWeaponType);
|
||||
|
||||
if (blockMoveAnim != currentAnim) {
|
||||
@@ -1861,10 +1863,12 @@ public class PlayerInputControl implements CombatStyleBase.AnimReceiver {
|
||||
}
|
||||
|
||||
public static AnimationAction getMeleeBlockImpactAction(ItemSubCategory s) {
|
||||
if (s == ItemSubCategory.TWO_HANDED_SWORD) { return TwoHandedCombat.resolveBlockImpactAction(); }
|
||||
return SwordShieldCombat.resolveBlockImpactAction(s);
|
||||
}
|
||||
|
||||
public static AnimationAction getMeleeIdleImpactAction(ItemSubCategory s) {
|
||||
if (s == ItemSubCategory.TWO_HANDED_SWORD) { return TwoHandedCombat.resolveIdleImpactAction(); }
|
||||
return SwordShieldCombat.resolveIdleImpactAction(s);
|
||||
}
|
||||
|
||||
@@ -2143,7 +2147,9 @@ public class PlayerInputControl implements CombatStyleBase.AnimReceiver {
|
||||
SWORD_WALK, AXE_WALK, TWO_HAND_WALK,
|
||||
BOW_WALK, CROSSBOW_WALK, CRYSTAL_WALK,
|
||||
SWORD_BLOCK_MOVE, SWORD_BLOCK_MOVE_BACKWARD,
|
||||
SWORD_BLOCK_STRAFE_LEFT, SWORD_BLOCK_STRAFE_RIGHT -> "walking";
|
||||
SWORD_BLOCK_STRAFE_LEFT, SWORD_BLOCK_STRAFE_RIGHT,
|
||||
TWO_HAND_BLOCK_MOVE, TWO_HAND_BLOCK_MOVE_BACKWARD,
|
||||
TWO_HAND_BLOCK_STRAFE_LEFT, TWO_HAND_BLOCK_STRAFE_RIGHT -> "walking";
|
||||
case RUN,
|
||||
SWORD_RUN, AXE_RUN, TWO_HAND_RUN,
|
||||
BOW_RUN, CROSSBOW_RUN, CRYSTAL_RUN -> "running";
|
||||
|
||||
@@ -55,6 +55,7 @@ import de.blight.game.combat.DamageCalculator;
|
||||
import de.blight.game.combat.MeleeAttackCallback;
|
||||
import de.blight.game.combat.WeaponCombatState;
|
||||
import de.blight.game.combat.swordshield.SwordShieldCombat;
|
||||
import de.blight.game.combat.twohanded.TwoHandedCombat;
|
||||
import de.blight.game.npc.AggroEvent;
|
||||
import de.blight.game.npc.NpcAggroBehavior;
|
||||
import de.blight.lang.TextResolver;
|
||||
@@ -2036,7 +2037,12 @@ public class WorldNpcsState extends BaseAppState implements MeleeAttackCallback
|
||||
s.combat.phase = WeaponCombatState.Phase.COUNTER_WINDOW;
|
||||
s.combat.timer = dur * 2f;
|
||||
s.paradeFromParry = true;
|
||||
SwordShieldCombat.applyParriedImpact(playerInput, playerInput.getDrawnWeaponType());
|
||||
ItemSubCategory pwt = playerInput.getDrawnWeaponType();
|
||||
if (pwt == ItemSubCategory.TWO_HANDED_SWORD) {
|
||||
TwoHandedCombat.applyParriedImpact(playerInput);
|
||||
} else {
|
||||
SwordShieldCombat.applyParriedImpact(playerInput, pwt);
|
||||
}
|
||||
return;
|
||||
}
|
||||
s.konterParadeAttackId = -1; // Entscheidung war kein Konter → zurücksetzen
|
||||
@@ -2501,11 +2507,19 @@ public class WorldNpcsState extends BaseAppState implements MeleeAttackCallback
|
||||
}
|
||||
|
||||
private void staggerNpc(SpawnedNpc s) {
|
||||
SwordShieldCombat.applyNormalImpact(npcAnimReceiver(s), s.combatWeaponType);
|
||||
if (s.combatWeaponType == ItemSubCategory.TWO_HANDED_SWORD) {
|
||||
TwoHandedCombat.applyNormalImpact(npcAnimReceiver(s));
|
||||
} else {
|
||||
SwordShieldCombat.applyNormalImpact(npcAnimReceiver(s), s.combatWeaponType);
|
||||
}
|
||||
}
|
||||
|
||||
private void staggerNpcSlow(SpawnedNpc s) {
|
||||
SwordShieldCombat.applyParriedImpact(npcAnimReceiver(s), s.combatWeaponType);
|
||||
if (s.combatWeaponType == ItemSubCategory.TWO_HANDED_SWORD) {
|
||||
TwoHandedCombat.applyParriedImpact(npcAnimReceiver(s));
|
||||
} else {
|
||||
SwordShieldCombat.applyParriedImpact(npcAnimReceiver(s), s.combatWeaponType);
|
||||
}
|
||||
}
|
||||
|
||||
private void setNpcCurrentActionSpeed(SpawnedNpc s, float speed) {
|
||||
@@ -2575,15 +2589,18 @@ public class WorldNpcsState extends BaseAppState implements MeleeAttackCallback
|
||||
s.paradeFromParry, playerInput.isBlocking());
|
||||
|
||||
if (isHeavy) {
|
||||
ItemSubCategory pwtH = playerInput.getDrawnWeaponType();
|
||||
if (playerInput.isBlocking()) {
|
||||
// Schwerer Angriff bricht Block — kein HP-Verlust, aber Stagger
|
||||
if (weaponSoundSystem != null) { weaponSoundSystem.play("impact"); }
|
||||
playerInput.triggerBlockImpact();
|
||||
SwordShieldCombat.applyNormalImpact(playerInput, playerInput.getDrawnWeaponType());
|
||||
if (pwtH == ItemSubCategory.TWO_HANDED_SWORD) { TwoHandedCombat.applyNormalImpact(playerInput); }
|
||||
else { SwordShieldCombat.applyNormalImpact(playerInput, pwtH); }
|
||||
} else {
|
||||
if (weaponSoundSystem != null) { weaponSoundSystem.play("impact"); }
|
||||
applyPlayerDamage(s, Math.max(1, base * 3));
|
||||
SwordShieldCombat.applyNormalImpact(playerInput, playerInput.getDrawnWeaponType());
|
||||
if (pwtH == ItemSubCategory.TWO_HANDED_SWORD) { TwoHandedCombat.applyNormalImpact(playerInput); }
|
||||
else { SwordShieldCombat.applyNormalImpact(playerInput, pwtH); }
|
||||
}
|
||||
return;
|
||||
}
|
||||
@@ -2600,7 +2617,9 @@ public class WorldNpcsState extends BaseAppState implements MeleeAttackCallback
|
||||
// Konterparade: Spieler wurde bereits per applyParriedImpact gestaggert → keine zweite Animation.
|
||||
// Block+Konter: Spieler war NICHT gestaggert → normale Impact-Animation abspielen.
|
||||
if (!s.paradeFromParry) {
|
||||
SwordShieldCombat.applyNormalImpact(playerInput, playerInput.getDrawnWeaponType());
|
||||
ItemSubCategory pwtN = playerInput.getDrawnWeaponType();
|
||||
if (pwtN == ItemSubCategory.TWO_HANDED_SWORD) { TwoHandedCombat.applyNormalImpact(playerInput); }
|
||||
else { SwordShieldCombat.applyNormalImpact(playerInput, pwtN); }
|
||||
}
|
||||
s.paradeFromParry = false;
|
||||
}
|
||||
@@ -2686,14 +2705,17 @@ public class WorldNpcsState extends BaseAppState implements MeleeAttackCallback
|
||||
}
|
||||
|
||||
private AnimationAction resolveNpcBlockImpactAction(SpawnedNpc s) {
|
||||
if (s.combatWeaponType == ItemSubCategory.TWO_HANDED_SWORD) { return TwoHandedCombat.resolveBlockImpactAction(); }
|
||||
return SwordShieldCombat.resolveBlockImpactAction(s.combatWeaponType);
|
||||
}
|
||||
|
||||
private AnimationAction resolveNpcParadeAction(SpawnedNpc s) {
|
||||
if (s.combatWeaponType == ItemSubCategory.TWO_HANDED_SWORD) { return TwoHandedCombat.resolveParadeAction(); }
|
||||
return SwordShieldCombat.resolveParadeAction(s.combatWeaponType);
|
||||
}
|
||||
|
||||
private AnimationAction resolveNpcStaggerAction(SpawnedNpc s) {
|
||||
if (s.combatWeaponType == ItemSubCategory.TWO_HANDED_SWORD) { return TwoHandedCombat.resolveIdleImpactAction(); }
|
||||
return SwordShieldCombat.resolveIdleImpactAction(s.combatWeaponType);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user