Soundsystem weiter ausgebaut
This commit is contained in:
@@ -129,6 +129,9 @@ public final class MapData {
|
||||
/** Spawnpunkt Z-Koordinate in Welteinheiten (default: 0 = Kartenmitte). */
|
||||
public float spawnZ = 0f;
|
||||
|
||||
/** Blickrichtung am permanenten Spawnpunkt in Grad (0 = +Z, 90 = +X, Uhrzeigersinn von oben). */
|
||||
public float spawnYaw = 0f;
|
||||
|
||||
/** Terrain-Slot (0-7) für flache Voxel-Flächen (TexFlat), -1 = nicht gesetzt. */
|
||||
public int voxelFlatSlot = -1;
|
||||
/** Terrain-Slot (0-7) für steile Wände (TexSteep), -1 = nicht gesetzt. */
|
||||
|
||||
@@ -63,7 +63,7 @@ public final class MapIO {
|
||||
}
|
||||
|
||||
private static final int MAGIC = 0x424C4947; // "BLIG"
|
||||
private static final int VERSION = 14;
|
||||
private static final int VERSION = 15;
|
||||
|
||||
// Größen älterer Saves (v≤9) – für Migrations-Upsampling
|
||||
private static final int OLD_TERRAIN_VERTS = 4097;
|
||||
@@ -124,6 +124,8 @@ public final class MapIO {
|
||||
// v4: spawnpunkt
|
||||
out.writeFloat(data.spawnX);
|
||||
out.writeFloat(data.spawnZ);
|
||||
// v15: spawn-blickrichtung
|
||||
out.writeFloat(data.spawnYaw);
|
||||
// v5: splatA + texturpfade + gebirge-splatmap
|
||||
out.write(data.splatA);
|
||||
writeStrings(out, data.terrainTextures);
|
||||
@@ -232,6 +234,9 @@ public final class MapIO {
|
||||
data.spawnX = in.readFloat();
|
||||
data.spawnZ = in.readFloat();
|
||||
}
|
||||
if (version >= 15) {
|
||||
data.spawnYaw = in.readFloat();
|
||||
}
|
||||
if (version >= 5) {
|
||||
if (version >= 10) {
|
||||
in.readFully(data.splatA);
|
||||
|
||||
@@ -32,7 +32,8 @@ public record ModelMeta(
|
||||
float interactableOffsetX,
|
||||
float interactableOffsetY,
|
||||
float interactableOffsetZ,
|
||||
float interactableRotY
|
||||
float interactableRotY,
|
||||
String footstepSurface
|
||||
) {
|
||||
/** Lichtquelle relativ zum Modell-Ursprung. */
|
||||
public record AttachedLight(
|
||||
@@ -52,6 +53,6 @@ public record ModelMeta(
|
||||
"", "", 30f, 80f, 120f,
|
||||
List.of(), List.of(),
|
||||
de.blight.common.model.InteractableType.NONE,
|
||||
0f, 0.5f, 0f, 0f);
|
||||
0f, 0.5f, 0f, 0f, "");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -39,6 +39,7 @@ public final class ModelMetaIO {
|
||||
p.setProperty("interactableOffsetY", String.valueOf(m.interactableOffsetY()));
|
||||
p.setProperty("interactableOffsetZ", String.valueOf(m.interactableOffsetZ()));
|
||||
p.setProperty("interactableRotY", String.valueOf(m.interactableRotY()));
|
||||
p.setProperty("footstepSurface", m.footstepSurface() != null ? m.footstepSurface() : "");
|
||||
|
||||
// Anhänge: Lichter
|
||||
List<ModelMeta.AttachedLight> lights = m.attachedLights();
|
||||
@@ -138,7 +139,8 @@ public final class ModelMetaIO {
|
||||
parseFloat(p, "interactableOffsetX", 0f),
|
||||
parseFloat(p, "interactableOffsetY", 0.5f),
|
||||
parseFloat(p, "interactableOffsetZ", 0f),
|
||||
parseFloat(p, "interactableRotY", 0f)
|
||||
parseFloat(p, "interactableRotY", 0f),
|
||||
p.getProperty("footstepSurface", "")
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -40,4 +40,10 @@ public class Bed implements Interactable {
|
||||
public String getDisplayText() {
|
||||
return TextRegistry.resolve(name, id != null ? id : "Bett");
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getLabelKey() {
|
||||
if (name != null && name.id() != null && !name.id().isBlank()) return name.id();
|
||||
return "interactable.bed.name";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -41,4 +41,10 @@ public class Bench implements Interactable {
|
||||
public String getDisplayText() {
|
||||
return TextRegistry.resolve(name, id != null ? id : "Bank");
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getLabelKey() {
|
||||
if (name != null && name.id() != null && !name.id().isBlank()) return name.id();
|
||||
return "interactable.bench.name";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,5 +2,8 @@ package de.blight.common.model;
|
||||
|
||||
public interface Interactable {
|
||||
|
||||
public String getDisplayText();
|
||||
String getDisplayText();
|
||||
|
||||
/** Gibt den Lokalisierungsschlüssel für das HUD-Label zurück (z.B. "item.driftwood.name"). */
|
||||
default String getLabelKey() { return ""; }
|
||||
}
|
||||
|
||||
@@ -30,4 +30,10 @@ public class Item implements Interactable {
|
||||
public String getDisplayText() {
|
||||
return TextRegistry.resolve(name, itemId != null ? itemId : "?");
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getLabelKey() {
|
||||
if (name != null && name.id() != null && !name.id().isBlank()) return name.id();
|
||||
return itemId != null ? "item." + itemId + ".name" : "";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
package de.blight.common.model;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.EnumMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
@@ -11,7 +13,7 @@ import lombok.Setter;
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
public class NPC extends GameCharacter {
|
||||
public class NPC extends GameCharacter implements Interactable {
|
||||
|
||||
private static final Logger LOG = LoggerFactory.getLogger(NPC.class);
|
||||
|
||||
@@ -23,6 +25,15 @@ public class NPC extends GameCharacter {
|
||||
|
||||
private List<DialogOption> currentOptions;
|
||||
|
||||
/** Nur im Editor relevant: Optionen die nicht mit currentOptions verbunden sind, aber erhalten werden sollen. */
|
||||
private List<DialogOption> editorOnlyOptions;
|
||||
|
||||
/**
|
||||
* Standard-Nachrichten je Status, die angezeigt werden wenn keine Dialog-Optionen
|
||||
* verfügbar sind. Schlüssel = Status-Wert des NPCs zum Gesprächszeitpunkt.
|
||||
*/
|
||||
private Map<Status, TextReference> defaultMessages = new EnumMap<>(Status.class);
|
||||
|
||||
/** Tagesabläufe dieses NPCs. Die erste Routine gilt standardmäßig als aktiv. */
|
||||
private List<NpcRoutine> routines = new ArrayList<>();
|
||||
|
||||
@@ -58,6 +69,35 @@ public class NPC extends GameCharacter {
|
||||
this.activeRoutineName = routineName;
|
||||
}
|
||||
|
||||
// ── Interactable ─────────────────────────────────────────────────────────
|
||||
|
||||
@Override
|
||||
public String getDisplayText() {
|
||||
return TextRegistry.resolve(getName(), getCharacterId() != null ? getCharacterId() : "NPC");
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getLabelKey() {
|
||||
TextReference nameRef = getName();
|
||||
if (nameRef != null && nameRef.id() != null && !nameRef.id().isBlank()) return nameRef.id();
|
||||
return getCharacterId() != null ? "npc." + getCharacterId() + ".name" : "";
|
||||
}
|
||||
|
||||
/**
|
||||
* Gibt die Default-Nachricht für den aktuellen Status zurück.
|
||||
* Fällt auf den nächst-freundlicheren Status zurück wenn kein Eintrag gefunden wird.
|
||||
*/
|
||||
public TextReference getDefaultMessage() {
|
||||
if (defaultMessages == null || defaultMessages.isEmpty()) return null;
|
||||
Status s = status != null ? status : Status.NEUTRAL;
|
||||
Status[] fallback = {s, Status.NEUTRAL, Status.FRIENDLY, Status.ENRAGED, Status.ENEMY};
|
||||
for (Status candidate : fallback) {
|
||||
TextReference ref = defaultMessages.get(candidate);
|
||||
if (ref != null) return ref;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
// ── Dialog-Methoden ──────────────────────────────────────────────────────
|
||||
|
||||
public List<DialogOption> getAvailableOptions(MainCharacter character) {
|
||||
|
||||
Reference in New Issue
Block a user