package com.tiedup.remake.dialogue; import com.tiedup.remake.personality.PersonalityType; import org.jetbrains.annotations.Nullable; import net.minecraft.world.entity.LivingEntity; import net.minecraft.world.entity.player.Player; /** * Context information for dialogue selection. * Holds all relevant state needed to match dialogue conditions. * * Personality System: Data-driven dialogue * Universal NPC Support: Extended for all speaker types */ public class DialogueContext { // Speaker type for dialogue routing private final SpeakerType speakerType; private final PersonalityType personality; private final int mood; // Kidnapper-specific context @Nullable private final String kidnapperTheme; // Merchant-specific context @Nullable private final String merchantMode; // Variable substitution data @Nullable private final String npcName; @Nullable private final String playerName; @Nullable private final String masterName; @Nullable private final String targetName; // Additional state private final boolean isBound; private final boolean isGagged; private final boolean isBlindfold; private final boolean hasCollar; private final float hunger; private DialogueContext(Builder builder) { this.speakerType = builder.speakerType; this.personality = builder.personality; this.mood = builder.mood; this.kidnapperTheme = builder.kidnapperTheme; this.merchantMode = builder.merchantMode; this.npcName = builder.npcName; this.playerName = builder.playerName; this.masterName = builder.masterName; this.targetName = builder.targetName; this.isBound = builder.isBound; this.isGagged = builder.isGagged; this.isBlindfold = builder.isBlindfold; this.hasCollar = builder.hasCollar; this.hunger = builder.hunger; } // --- Getters for condition matching --- /** * Get the speaker type for dialogue routing. */ public SpeakerType getSpeakerType() { return speakerType; } public PersonalityType getPersonality() { return personality; } /** * Get the kidnapper theme (for theme-based personalities). * Only relevant for kidnapper-type speakers. */ @Nullable public String getKidnapperTheme() { return kidnapperTheme; } /** * Get the merchant mode (MERCHANT or HOSTILE). * Only relevant for merchant speakers. */ @Nullable public String getMerchantMode() { return merchantMode; } public int getMood() { return mood; } // --- Getters for variable substitution --- @Nullable public String getNpcName() { return npcName; } @Nullable public String getPlayerName() { return playerName; } @Nullable public String getMasterName() { return masterName; } @Nullable public String getTargetName() { return targetName; } public boolean isBound() { return isBound; } public boolean isGagged() { return isGagged; } public boolean isBlindfold() { return isBlindfold; } public boolean hasCollar() { return hasCollar; } public float getHunger() { return hunger; } /** * Get mood as a string descriptor. */ public String getMoodString() { if (mood >= 70) return "happy"; if (mood >= 40) return "neutral"; if (mood >= 10) return "sad"; return "miserable"; } /** * Get hunger as a string descriptor. */ public String getHungerString() { if (hunger >= 70) return "full"; if (hunger >= 30) return "hungry"; return "starving"; } /** * Substitute variables in dialogue text. * * @param text Text with placeholders like {player}, {npc}, etc. * @return Text with placeholders replaced */ public String substituteVariables(String text) { String result = text; // Entity names if (npcName != null) { result = result.replace("{npc}", npcName); } if (playerName != null) { result = result.replace("{player}", playerName); } if (masterName != null) { result = result.replace("{master}", masterName); } if (targetName != null) { result = result.replace("{target}", targetName); } // State variables result = result.replace("{mood}", getMoodString()); result = result.replace("{hunger}", getHungerString()); result = result.replace( "{personality}", personality.name().toLowerCase() ); return result; } public static Builder builder() { return new Builder(); } /** * Builder for DialogueContext. */ public static class Builder { private SpeakerType speakerType = SpeakerType.DAMSEL; private PersonalityType personality = PersonalityType.CALM; private int mood = 50; private String kidnapperTheme = null; private String merchantMode = null; private String npcName = null; private String playerName = null; private String masterName = null; private String targetName = null; private boolean isBound = false; private boolean isGagged = false; private boolean isBlindfold = false; private boolean hasCollar = false; private float hunger = 100f; public Builder speakerType(SpeakerType speakerType) { this.speakerType = speakerType; return this; } public Builder personality(PersonalityType personality) { this.personality = personality; return this; } public Builder kidnapperTheme(String theme) { this.kidnapperTheme = theme; return this; } public Builder merchantMode(String mode) { this.merchantMode = mode; return this; } public Builder mood(int mood) { this.mood = mood; return this; } public Builder npcName(String name) { this.npcName = name; return this; } public Builder playerName(String name) { this.playerName = name; return this; } public Builder masterName(String name) { this.masterName = name; return this; } public Builder targetName(String name) { this.targetName = name; return this; } public Builder bound(boolean bound) { this.isBound = bound; return this; } public Builder gagged(boolean gagged) { this.isGagged = gagged; return this; } public Builder blindfold(boolean blindfold) { this.isBlindfold = blindfold; return this; } public Builder hasCollar(boolean collar) { this.hasCollar = collar; return this; } public Builder hunger(float hunger) { this.hunger = hunger; return this; } /** * Set player info from a Player entity. */ public Builder fromPlayer(Player player) { this.playerName = player.getName().getString(); return this; } /** * Set target info from a LivingEntity. */ public Builder fromTarget(LivingEntity target) { this.targetName = target.getName().getString(); return this; } public DialogueContext build() { return new DialogueContext(this); } /** * Build from an IDialogueSpeaker. * Automatically sets speakerType, personality, mood, and npcName. * * @param speaker The dialogue speaker * @param player The player interacting (can be null) * @return Builder with speaker data applied */ public Builder fromSpeaker( IDialogueSpeaker speaker, @Nullable Player player ) { this.speakerType = speaker.getSpeakerType(); this.npcName = speaker.getDialogueName(); this.mood = speaker.getSpeakerMood(); if (speaker.getSpeakerPersonality() != null) { this.personality = speaker.getSpeakerPersonality(); } if (player != null) { this.playerName = player.getName().getString(); } return this; } } }