Search in sources :

Example 1 with TongueModifier

use of com.lilithsthrone.game.character.body.valueEnums.TongueModifier in project liliths-throne-public by Innoxia.

the class MainController method manageMainListeners.

private void manageMainListeners() {
    document = (Document) webEngine.executeScript("document");
    EventListenerDataMap.put(document, new ArrayList<>());
    String id = "";
    if (flashMessageColour != null && flashMessageText != null) {
        Main.game.flashMessage(flashMessageColour, flashMessageText);
        flashMessageColour = null;
        flashMessageText = null;
    }
    if (((EventTarget) document.getElementById("copy-content-button")) != null) {
        addEventListener(document, "copy-content-button", "click", copyDialogueButtonListener, false);
        addEventListener(document, "copy-content-button", "mousemove", moveTooltipListener, false);
        addEventListener(document, "copy-content-button", "mouseleave", hideTooltipListener, false);
        addEventListener(document, "copy-content-button", "mouseenter", copyInfoListener, false);
    }
    if (((EventTarget) document.getElementById("export-character-button")) != null) {
        addEventListener(document, "export-character-button", "click", e -> {
            if (Main.game.getCurrentDialogueNode().equals(CharactersPresentDialogue.MENU)) {
                Game.exportCharacter(CharactersPresentDialogue.characterViewed);
            } else {
                Game.exportCharacter(Main.game.getPlayer());
            }
            Main.game.flashMessage(Colour.GENERIC_EXCELLENT, "Character Exported!");
        }, false);
        addEventListener(document, "export-character-button", "mousemove", moveTooltipListener, false);
        addEventListener(document, "export-character-button", "mouseleave", hideTooltipListener, false);
        addEventListener(document, "export-character-button", "mouseenter", new TooltipInformationEventListener().setInformation("Export Character", "Export the currently displayed character to the 'data/characters' folder. Exported characters can be imported at the auction block in Slaver Alley."), false);
    }
    if (Main.game.getCurrentDialogueNode().equals(DebugDialogue.SPAWN_MENU)) {
        id = "";
        for (AbstractClothingType clothingType : DebugDialogue.clothingTotal) {
            id = clothingType.getId() + "_SPAWN";
            if (((EventTarget) document.getElementById(id)) != null) {
                ((EventTarget) document.getElementById(id)).addEventListener("click", e -> {
                    Main.game.getActiveWorld().getCell(Main.game.getPlayer().getLocation()).getInventory().addClothing(AbstractClothingType.generateClothing(clothingType));
                    this.updateUIRightPanel();
                }, false);
                addEventListener(document, id, "mousemove", moveTooltipListener, false);
                addEventListener(document, id, "mouseleave", hideTooltipListener, false);
                InventoryTooltipEventListener el = new InventoryTooltipEventListener().setGenericClothing(clothingType, clothingType.getAvailablePrimaryColours().get(0));
                addEventListener(document, id, "mouseenter", el, false);
            }
        }
        for (AbstractWeaponType weaponType : DebugDialogue.weaponsTotal) {
            id = weaponType.getId() + "_SPAWN";
            if (((EventTarget) document.getElementById(id)) != null) {
                ((EventTarget) document.getElementById(id)).addEventListener("click", e -> {
                    Main.game.getActiveWorld().getCell(Main.game.getPlayer().getLocation()).getInventory().addWeapon(AbstractWeaponType.generateWeapon(weaponType));
                    this.updateUIRightPanel();
                }, false);
                addEventListener(document, id, "mousemove", moveTooltipListener, false);
                addEventListener(document, id, "mouseleave", hideTooltipListener, false);
                InventoryTooltipEventListener el = new InventoryTooltipEventListener().setGenericWeapon(weaponType, weaponType.getAvailableDamageTypes().get(0));
                addEventListener(document, id, "mouseenter", el, false);
            }
        }
        for (AbstractItemType itemType : DebugDialogue.itemsTotal) {
            id = itemType.getId() + "_SPAWN";
            if (((EventTarget) document.getElementById(id)) != null) {
                ((EventTarget) document.getElementById(id)).addEventListener("click", e -> {
                    Main.game.getActiveWorld().getCell(Main.game.getPlayer().getLocation()).getInventory().addItem(AbstractItemType.generateItem(itemType));
                    this.updateUIRightPanel();
                }, false);
                addEventListener(document, id, "mousemove", moveTooltipListener, false);
                addEventListener(document, id, "mouseleave", hideTooltipListener, false);
                InventoryTooltipEventListener el = new InventoryTooltipEventListener().setGenericItem(itemType);
                addEventListener(document, id, "mouseenter", el, false);
            }
        }
        for (InventorySlot slot : InventorySlot.values()) {
            id = slot + "_SPAWN_SELECT";
            if (((EventTarget) document.getElementById(id)) != null) {
                ((EventTarget) document.getElementById(id)).addEventListener("click", e -> {
                    DebugDialogue.activeSlot = slot;
                    Main.game.setContent(new Response("", "", Main.game.getCurrentDialogueNode()));
                }, false);
            }
        }
        id = "ITEM_SPAWN_SELECT";
        if (((EventTarget) document.getElementById(id)) != null) {
            ((EventTarget) document.getElementById(id)).addEventListener("click", e -> {
                DebugDialogue.activeSlot = null;
                Main.game.setContent(new Response("", "", Main.game.getCurrentDialogueNode()));
            }, false);
        }
    }
    if (Main.game.getCurrentDialogueNode() == CharacterCreation.BACKGROUND_SELECTION_MENU) {
        for (History history : History.values()) {
            id = "HISTORY_" + history;
            if (((EventTarget) document.getElementById(id)) != null) {
                addEventListener(document, id, "mousemove", moveTooltipListener, false);
                addEventListener(document, id, "mouseleave", hideTooltipListener, false);
                addEventListener(document, id, "mouseenter", new TooltipInformationEventListener().setPerk(history.getAssociatedPerk(), Main.game.getPlayer()), false);
                ((EventTarget) document.getElementById(id)).addEventListener("click", event -> {
                    Main.game.getPlayer().setHistory(history);
                    Main.game.setContent(new Response("", "", Main.game.getCurrentDialogueNode()));
                }, false);
            }
        }
    }
    if (Main.game.isStarted()) {
        id = "";
        // Equipped inventory:
        // For weapons:
        InventorySlot[] inventorySlots = { InventorySlot.WEAPON_MAIN, InventorySlot.WEAPON_OFFHAND };
        for (InventorySlot invSlot : inventorySlots) {
            id = "PLAYER_" + invSlot.toString() + "Slot";
            if (((EventTarget) document.getElementById(id)) != null) {
                InventorySelectedItemEventListener el = new InventorySelectedItemEventListener().setWeaponEquipped(Main.game.getPlayer(), invSlot);
                addEventListener(document, id, "click", el, false);
                addEventListener(document, id, "mousemove", moveTooltipListener, false);
                addEventListener(document, id, "mouseleave", hideTooltipListener, false);
                InventoryTooltipEventListener el2 = new InventoryTooltipEventListener().setInventorySlot(invSlot, Main.game.getPlayer());
                addEventListener(document, id, "mouseenter", el2, false);
            }
            id = "NPC_" + invSlot.toString() + "Slot";
            if (((EventTarget) document.getElementById(id)) != null) {
                InventorySelectedItemEventListener el = new InventorySelectedItemEventListener().setWeaponEquipped(InventoryDialogue.getInventoryNPC(), invSlot);
                addEventListener(document, id, "click", el, false);
                addEventListener(document, id, "mousemove", moveTooltipListener, false);
                addEventListener(document, id, "mouseleave", hideTooltipListener, false);
                InventoryTooltipEventListener el2 = new InventoryTooltipEventListener().setInventorySlot(invSlot, InventoryDialogue.getInventoryNPC());
                addEventListener(document, id, "mouseenter", el2, false);
            }
            id = "NPC_VIEW_" + invSlot.toString() + "Slot";
            if (((EventTarget) document.getElementById(id)) != null) {
                addEventListener(document, id, "mousemove", moveTooltipListener, false);
                addEventListener(document, id, "mouseleave", hideTooltipListener, false);
                InventoryTooltipEventListener el2 = new InventoryTooltipEventListener().setInventorySlot(invSlot, CharactersPresentDialogue.characterViewed);
                addEventListener(document, id, "mouseenter", el2, false);
            }
        }
        // For all equipped clothing slots:
        for (InventorySlot invSlot : InventorySlot.values()) {
            id = "PLAYER_" + invSlot.toString() + "Slot";
            if (invSlot != InventorySlot.WEAPON_MAIN && invSlot != InventorySlot.WEAPON_OFFHAND) {
                if (((EventTarget) document.getElementById(id)) != null) {
                    InventorySelectedItemEventListener el = new InventorySelectedItemEventListener().setClothingEquipped(Main.game.getPlayer(), invSlot);
                    addEventListener(document, id, "click", el, false);
                    addEventListener(document, id, "mousemove", moveTooltipListener, false);
                    addEventListener(document, id, "mouseleave", hideTooltipListener, false);
                    InventoryTooltipEventListener el2 = new InventoryTooltipEventListener().setInventorySlot(invSlot, Main.game.getPlayer());
                    addEventListener(document, id, "mouseenter", el2, false);
                }
            }
            id = "NPC_" + invSlot.toString() + "Slot";
            if (invSlot != InventorySlot.WEAPON_MAIN && invSlot != InventorySlot.WEAPON_OFFHAND) {
                if (((EventTarget) document.getElementById(id)) != null) {
                    InventorySelectedItemEventListener el = new InventorySelectedItemEventListener().setClothingEquipped(InventoryDialogue.getInventoryNPC(), invSlot);
                    addEventListener(document, id, "click", el, false);
                    addEventListener(document, id, "mousemove", moveTooltipListener, false);
                    addEventListener(document, id, "mouseleave", hideTooltipListener, false);
                    InventoryTooltipEventListener el2 = new InventoryTooltipEventListener().setInventorySlot(invSlot, InventoryDialogue.getInventoryNPC());
                    addEventListener(document, id, "mouseenter", el2, false);
                }
            }
            id = "NPC_VIEW_" + invSlot.toString() + "Slot";
            if (invSlot != InventorySlot.WEAPON_MAIN && invSlot != InventorySlot.WEAPON_OFFHAND) {
                if (((EventTarget) document.getElementById(id)) != null) {
                    addEventListener(document, id, "mousemove", moveTooltipListener, false);
                    addEventListener(document, id, "mouseleave", hideTooltipListener, false);
                    InventoryTooltipEventListener el2 = new InventoryTooltipEventListener().setInventorySlot(invSlot, CharactersPresentDialogue.characterViewed);
                    addEventListener(document, id, "mouseenter", el2, false);
                }
            }
        }
        // Gifts:
        if (Main.game.getCurrentDialogueNode().equals(GiftDialogue.GIFT_DIALOGUE)) {
            for (Entry<AbstractWeapon, Integer> entry : Main.game.getPlayer().getMapOfDuplicateWeapons().entrySet()) {
                id = "GIFT_" + entry.getKey().hashCode();
                if (((EventTarget) document.getElementById(id)) != null) {
                    ((EventTarget) document.getElementById(id)).addEventListener("click", e -> {
                        Main.game.setContent(new Response("Give Gift", ":3", GiftDialogue.getDialogueToProceedTo()) {

                            @Override
                            public void effects() {
                                Main.game.getTextStartStringBuilder().append(GiftDialogue.getReceiver().getGiftReaction(entry.getKey(), true));
                                Main.game.getPlayer().removeWeapon(entry.getKey());
                            }
                        });
                    }, false);
                    addEventListener(document, id, "mousemove", moveTooltipListener, false);
                    addEventListener(document, id, "mouseleave", hideTooltipListener, false);
                    InventoryTooltipEventListener el2 = new InventoryTooltipEventListener().setWeapon(entry.getKey(), Main.game.getPlayer());
                    addEventListener(document, id, "mouseenter", el2, false);
                }
            }
            for (Entry<AbstractItem, Integer> entry : Main.game.getPlayer().getMapOfDuplicateItems().entrySet()) {
                id = "GIFT_" + entry.getKey().hashCode();
                if (((EventTarget) document.getElementById(id)) != null) {
                    ((EventTarget) document.getElementById(id)).addEventListener("click", e -> {
                        Main.game.setContent(new Response("Give Gift", ":3", GiftDialogue.getDialogueToProceedTo()) {

                            @Override
                            public void effects() {
                                Main.game.getTextStartStringBuilder().append(GiftDialogue.getReceiver().getGiftReaction(entry.getKey(), true));
                                Main.game.getPlayer().removeItem(entry.getKey());
                            }
                        });
                    }, false);
                    addEventListener(document, id, "mousemove", moveTooltipListener, false);
                    addEventListener(document, id, "mouseleave", hideTooltipListener, false);
                    InventoryTooltipEventListener el2 = new InventoryTooltipEventListener().setItem(entry.getKey(), Main.game.getPlayer(), null);
                    addEventListener(document, id, "mouseenter", el2, false);
                }
            }
            for (Entry<AbstractClothing, Integer> entry : Main.game.getPlayer().getMapOfDuplicateClothing().entrySet()) {
                id = "GIFT_" + entry.getKey().hashCode();
                if (((EventTarget) document.getElementById(id)) != null) {
                    ((EventTarget) document.getElementById(id)).addEventListener("click", e -> {
                        Main.game.setContent(new Response("Give Gift", ":3", GiftDialogue.getDialogueToProceedTo()) {

                            @Override
                            public void effects() {
                                Main.game.getTextStartStringBuilder().append(GiftDialogue.getReceiver().getGiftReaction(entry.getKey(), true));
                                Main.game.getPlayer().removeClothing(entry.getKey());
                            }
                        });
                    }, false);
                    addEventListener(document, id, "mousemove", moveTooltipListener, false);
                    addEventListener(document, id, "mouseleave", hideTooltipListener, false);
                    InventoryTooltipEventListener el2 = new InventoryTooltipEventListener().setClothing(entry.getKey(), Main.game.getPlayer(), null);
                    addEventListener(document, id, "mouseenter", el2, false);
                }
            }
        }
        // Player:
        for (Entry<AbstractWeapon, Integer> entry : Main.game.getPlayer().getMapOfDuplicateWeapons().entrySet()) {
            id = "PLAYER_WEAPON_" + entry.getKey().hashCode();
            if (((EventTarget) document.getElementById(id)) != null) {
                InventorySelectedItemEventListener el = new InventorySelectedItemEventListener().setWeaponInventory(entry.getKey(), Main.game.getPlayer());
                addEventListener(document, id, "click", el, false);
                addEventListener(document, id, "mousemove", moveTooltipListener, false);
                addEventListener(document, id, "mouseleave", hideTooltipListener, false);
                InventoryTooltipEventListener el2 = new InventoryTooltipEventListener().setWeapon(entry.getKey(), Main.game.getPlayer());
                addEventListener(document, id, "mouseenter", el2, false);
            }
        }
        for (Entry<AbstractItem, Integer> entry : Main.game.getPlayer().getMapOfDuplicateItems().entrySet()) {
            id = "PLAYER_ITEM_" + entry.getKey().hashCode();
            if (((EventTarget) document.getElementById(id)) != null) {
                InventorySelectedItemEventListener el = new InventorySelectedItemEventListener().setItemInventory(entry.getKey(), Main.game.getPlayer());
                addEventListener(document, id, "click", el, false);
                addEventListener(document, id, "mousemove", moveTooltipListener, false);
                addEventListener(document, id, "mouseleave", hideTooltipListener, false);
                InventoryTooltipEventListener el2 = new InventoryTooltipEventListener().setItem(entry.getKey(), Main.game.getPlayer(), null);
                addEventListener(document, id, "mouseenter", el2, false);
            }
        }
        for (Entry<AbstractClothing, Integer> entry : Main.game.getPlayer().getMapOfDuplicateClothing().entrySet()) {
            id = "PLAYER_CLOTHING_" + entry.getKey().hashCode();
            if (((EventTarget) document.getElementById(id)) != null) {
                InventorySelectedItemEventListener el = new InventorySelectedItemEventListener().setClothingInventory(entry.getKey(), Main.game.getPlayer());
                addEventListener(document, id, "click", el, false);
                addEventListener(document, id, "mousemove", moveTooltipListener, false);
                addEventListener(document, id, "mouseleave", hideTooltipListener, false);
                InventoryTooltipEventListener el2 = new InventoryTooltipEventListener().setClothing(entry.getKey(), Main.game.getPlayer(), null);
                addEventListener(document, id, "mouseenter", el2, false);
            }
        }
        // Partner:
        if (InventoryDialogue.getInventoryNPC() != null) {
            String idModifier = "NPC_" + InventoryDialogue.getInventoryNPC().getId() + "_";
            for (Entry<AbstractWeapon, Integer> entry : InventoryDialogue.getInventoryNPC().getMapOfDuplicateWeapons().entrySet()) {
                id = idModifier + "WEAPON_" + entry.getKey().hashCode();
                if (((EventTarget) document.getElementById(id)) != null) {
                    InventorySelectedItemEventListener el = new InventorySelectedItemEventListener().setWeaponInventory(entry.getKey(), InventoryDialogue.getInventoryNPC());
                    addEventListener(document, id, "click", el, false);
                    addEventListener(document, id, "mousemove", moveTooltipListener, false);
                    addEventListener(document, id, "mouseleave", hideTooltipListener, false);
                    InventoryTooltipEventListener el2 = new InventoryTooltipEventListener().setWeapon(entry.getKey(), InventoryDialogue.getInventoryNPC());
                    addEventListener(document, id, "mouseenter", el2, false);
                }
            }
            for (Entry<AbstractClothing, Integer> entry : InventoryDialogue.getInventoryNPC().getMapOfDuplicateClothing().entrySet()) {
                id = idModifier + "CLOTHING_" + entry.getKey().hashCode();
                if (((EventTarget) document.getElementById(id)) != null) {
                    InventorySelectedItemEventListener el = new InventorySelectedItemEventListener().setClothingInventory(entry.getKey(), InventoryDialogue.getInventoryNPC());
                    addEventListener(document, id, "click", el, false);
                    addEventListener(document, id, "mousemove", moveTooltipListener, false);
                    addEventListener(document, id, "mouseleave", hideTooltipListener, false);
                    InventoryTooltipEventListener el2 = new InventoryTooltipEventListener().setClothing(entry.getKey(), InventoryDialogue.getInventoryNPC(), null);
                    addEventListener(document, id, "mouseenter", el2, false);
                }
            }
            for (Entry<AbstractItem, Integer> entry : InventoryDialogue.getInventoryNPC().getMapOfDuplicateItems().entrySet()) {
                id = idModifier + "ITEM_" + entry.getKey().hashCode();
                if (((EventTarget) document.getElementById(id)) != null) {
                    InventorySelectedItemEventListener el = new InventorySelectedItemEventListener().setItemInventory(entry.getKey(), InventoryDialogue.getInventoryNPC());
                    addEventListener(document, id, "click", el, false);
                    addEventListener(document, id, "mousemove", moveTooltipListener, false);
                    addEventListener(document, id, "mouseleave", hideTooltipListener, false);
                    InventoryTooltipEventListener el2 = new InventoryTooltipEventListener().setItem(entry.getKey(), InventoryDialogue.getInventoryNPC(), null);
                    addEventListener(document, id, "mouseenter", el2, false);
                }
            }
        // Floor:
        } else {
            // Weapons on floor:
            for (Entry<AbstractWeapon, Integer> entry : Main.game.getPlayerCell().getInventory().getMapOfDuplicateWeapons().entrySet()) {
                id = "WEAPON_FLOOR_" + entry.getKey().hashCode();
                if (((EventTarget) document.getElementById(id)) != null) {
                    InventorySelectedItemEventListener el = new InventorySelectedItemEventListener().setWeaponInventory(entry.getKey(), null);
                    addEventListener(document, id, "click", el, false);
                    addEventListener(document, id, "mousemove", moveTooltipListener, false);
                    addEventListener(document, id, "mouseleave", hideTooltipListener, false);
                    InventoryTooltipEventListener el2 = new InventoryTooltipEventListener().setWeapon(entry.getKey(), null);
                    addEventListener(document, id, "mouseenter", el2, false);
                }
            }
            // Clothing on floor:
            for (Entry<AbstractClothing, Integer> entry : Main.game.getPlayerCell().getInventory().getMapOfDuplicateClothing().entrySet()) {
                id = "CLOTHING_FLOOR_" + entry.getKey().hashCode();
                if (((EventTarget) document.getElementById(id)) != null) {
                    InventorySelectedItemEventListener el = new InventorySelectedItemEventListener().setClothingInventory(entry.getKey(), null);
                    addEventListener(document, id, "click", el, false);
                    addEventListener(document, id, "mousemove", moveTooltipListener, false);
                    addEventListener(document, id, "mouseleave", hideTooltipListener, false);
                    InventoryTooltipEventListener el2 = new InventoryTooltipEventListener().setClothing(entry.getKey(), null, null);
                    addEventListener(document, id, "mouseenter", el2, false);
                }
            }
            // Items on floor:
            for (Entry<AbstractItem, Integer> entry : Main.game.getPlayerCell().getInventory().getMapOfDuplicateItems().entrySet()) {
                id = "ITEM_FLOOR_" + entry.getKey().hashCode();
                if (((EventTarget) document.getElementById(id)) != null) {
                    InventorySelectedItemEventListener el = new InventorySelectedItemEventListener().setItemInventory(entry.getKey(), null);
                    addEventListener(document, id, "click", el, false);
                    addEventListener(document, id, "mousemove", moveTooltipListener, false);
                    addEventListener(document, id, "mouseleave", hideTooltipListener, false);
                    InventoryTooltipEventListener el2 = new InventoryTooltipEventListener().setItem(entry.getKey(), null, null);
                    addEventListener(document, id, "mouseenter", el2, false);
                }
            }
        }
        if (InventoryDialogue.getNPCInventoryInteraction() == InventoryInteraction.TRADING) {
            if (InventoryDialogue.getInventoryNPC() != null) {
                // Buyback panel:
                for (int i = Main.game.getPlayer().getBuybackStack().size() - 1; i >= 0; i--) {
                    if (((EventTarget) document.getElementById("WEAPON_" + i)) != null) {
                        InventorySelectedItemEventListener el = new InventorySelectedItemEventListener().setWeaponInventory((AbstractWeapon) Main.game.getPlayer().getBuybackStack().get(i).getAbstractItemSold(), InventoryDialogue.getInventoryNPC(), i);
                        ((EventTarget) document.getElementById("WEAPON_" + i)).addEventListener("click", el, false);
                        addEventListener(document, "WEAPON_" + i, "mousemove", moveTooltipListener, false);
                        addEventListener(document, "WEAPON_" + i, "mouseleave", hideTooltipListener, false);
                        InventoryTooltipEventListener el2 = new InventoryTooltipEventListener().setWeapon((AbstractWeapon) Main.game.getPlayer().getBuybackStack().get(i).getAbstractItemSold(), InventoryDialogue.getInventoryNPC());
                        ((EventTarget) document.getElementById("WEAPON_" + i)).addEventListener("mouseenter", el2, false);
                    }
                    if (((EventTarget) document.getElementById("CLOTHING_" + i)) != null) {
                        InventorySelectedItemEventListener el = new InventorySelectedItemEventListener().setClothingInventory((AbstractClothing) Main.game.getPlayer().getBuybackStack().get(i).getAbstractItemSold(), InventoryDialogue.getInventoryNPC(), i);
                        addEventListener(document, "CLOTHING_" + i, "click", el, false);
                        addEventListener(document, "CLOTHING_" + i, "mousemove", moveTooltipListener, false);
                        addEventListener(document, "CLOTHING_" + i, "mouseleave", hideTooltipListener, false);
                        InventoryTooltipEventListener el2 = new InventoryTooltipEventListener().setClothing((AbstractClothing) Main.game.getPlayer().getBuybackStack().get(i).getAbstractItemSold(), InventoryDialogue.getInventoryNPC(), null);
                        addEventListener(document, "CLOTHING_" + i, "mouseenter", el2, false);
                    }
                    if (((EventTarget) document.getElementById("ITEM_" + i)) != null) {
                        InventorySelectedItemEventListener el = new InventorySelectedItemEventListener().setItemInventory((AbstractItem) Main.game.getPlayer().getBuybackStack().get(i).getAbstractItemSold(), InventoryDialogue.getInventoryNPC(), i);
                        addEventListener(document, "ITEM_" + i, "click", el, false);
                        addEventListener(document, "ITEM_" + i, "mousemove", moveTooltipListener, false);
                        addEventListener(document, "ITEM_" + i, "mouseleave", hideTooltipListener, false);
                        InventoryTooltipEventListener el2 = new InventoryTooltipEventListener().setItem((AbstractItem) Main.game.getPlayer().getBuybackStack().get(i).getAbstractItemSold(), InventoryDialogue.getInventoryNPC(), null);
                        addEventListener(document, "ITEM_" + i, "mouseenter", el2, false);
                    }
                }
            }
        }
        for (TFEssence essence : TFEssence.values()) {
            if (((EventTarget) document.getElementById("ESSENCE_" + essence.hashCode())) != null) {
                addEventListener(document, "ESSENCE_" + essence.hashCode(), "mousemove", moveTooltipListener, false);
                addEventListener(document, "ESSENCE_" + essence.hashCode(), "mouseleave", hideTooltipListener, false);
                InventoryTooltipEventListener el2 = new InventoryTooltipEventListener().setEssence(essence);
                addEventListener(document, "ESSENCE_" + essence.hashCode(), "mouseenter", el2, false);
            }
            if (((EventTarget) document.getElementById("ESSENCE_COST_" + essence.hashCode())) != null) {
                addEventListener(document, "ESSENCE_COST_" + essence.hashCode(), "mousemove", moveTooltipListener, false);
                addEventListener(document, "ESSENCE_COST_" + essence.hashCode(), "mouseleave", hideTooltipListener, false);
                InventoryTooltipEventListener el2 = new InventoryTooltipEventListener().setEssence(essence);
                addEventListener(document, "ESSENCE_COST_" + essence.hashCode(), "mouseenter", el2, false);
            }
        }
        // Tooltips:
        if (((EventTarget) document.getElementById("MOD_PRIMARY_ENCHANTING")) != null) {
            EnchantmentEventListener el = new EnchantmentEventListener().setPrimaryModifier(TFModifier.NONE);
            addEventListener(document, "MOD_PRIMARY_ENCHANTING", "click", el, false);
            addEventListener(document, "MOD_PRIMARY_ENCHANTING", "mousemove", moveTooltipListener, false);
            addEventListener(document, "MOD_PRIMARY_ENCHANTING", "mouseleave", hideTooltipListener, false);
            InventoryTooltipEventListener el2 = new InventoryTooltipEventListener().setTFModifier(EnchantmentDialogue.primaryMod);
            addEventListener(document, "MOD_PRIMARY_ENCHANTING", "mouseenter", el2, false);
        }
        if (((EventTarget) document.getElementById("MOD_SECONDARY_ENCHANTING")) != null) {
            EnchantmentEventListener el = new EnchantmentEventListener().setSecondaryModifier(TFModifier.NONE);
            addEventListener(document, "MOD_SECONDARY_ENCHANTING", "click", el, false);
            addEventListener(document, "MOD_SECONDARY_ENCHANTING", "mousemove", moveTooltipListener, false);
            addEventListener(document, "MOD_SECONDARY_ENCHANTING", "mouseleave", hideTooltipListener, false);
            InventoryTooltipEventListener el2 = new InventoryTooltipEventListener().setTFModifier(EnchantmentDialogue.secondaryMod);
            addEventListener(document, "MOD_SECONDARY_ENCHANTING", "mouseenter", el2, false);
        }
        for (TFPotency potency : TFPotency.values()) {
            id = "POTENCY_" + potency;
            if (((EventTarget) document.getElementById(id)) != null) {
                EnchantmentEventListener el = new EnchantmentEventListener().setPotency(potency);
                addEventListener(document, id, "click", el, false);
                addEventListener(document, id, "mousemove", moveTooltipListener, false);
                addEventListener(document, id, "mouseleave", hideTooltipListener, false);
                InventoryTooltipEventListener el2 = new InventoryTooltipEventListener().setTFPotency(potency);
                addEventListener(document, id, "mouseenter", el2, false);
            }
        }
        for (int effectCount = 0; effectCount < EnchantmentDialogue.effects.size(); effectCount++) {
            id = "DELETE_EFFECT_" + effectCount;
            if (((EventTarget) document.getElementById(id)) != null) {
                EnchantmentEventListener el = new EnchantmentEventListener().removeEffect(effectCount);
                addEventListener(document, id, "click", el, false);
                addEventListener(document, id, "mousemove", moveTooltipListener, false);
                addEventListener(document, id, "mouseleave", hideTooltipListener, false);
                TooltipInformationEventListener el2 = new TooltipInformationEventListener().setInformation("Delete Effect", "");
                addEventListener(document, id, "mouseenter", el2, false);
            }
        }
        id = "LIMIT_MINIMUM";
        if (((EventTarget) document.getElementById(id)) != null) {
            if (EnchantmentDialogue.limit > 0) {
                EnchantmentEventListener el = new EnchantmentEventListener().setLimit(0);
                addEventListener(document, id, "click", el, false);
            }
            addEventListener(document, id, "mousemove", moveTooltipListener, false);
            addEventListener(document, id, "mouseleave", hideTooltipListener, false);
            TooltipInformationEventListener el2 = new TooltipInformationEventListener().setInformation((EnchantmentDialogue.limit == 0 ? "Minimum Limit Reached" : "Limit Minimum"), "");
            addEventListener(document, id, "mouseenter", el2, false);
        }
        id = "LIMIT_DECREASE_LARGE";
        if (((EventTarget) document.getElementById(id)) != null) {
            if (EnchantmentDialogue.limit > 0) {
                EnchantmentEventListener el = new EnchantmentEventListener().setLimit(Math.max(0, EnchantmentDialogue.limit - (EnchantmentDialogue.ingredient.getEnchantmentEffect().getLimits(EnchantmentDialogue.primaryMod, EnchantmentDialogue.secondaryMod) / 10)));
                addEventListener(document, id, "click", el, false);
            }
            addEventListener(document, id, "mousemove", moveTooltipListener, false);
            addEventListener(document, id, "mouseleave", hideTooltipListener, false);
            TooltipInformationEventListener el2 = new TooltipInformationEventListener().setInformation((EnchantmentDialogue.limit == 0 ? "Minimum Limit Reached" : "Large Limit Decrease"), "");
            addEventListener(document, id, "mouseenter", el2, false);
        }
        id = "LIMIT_DECREASE";
        if (((EventTarget) document.getElementById(id)) != null) {
            if (EnchantmentDialogue.limit > 0) {
                EnchantmentEventListener el = new EnchantmentEventListener().setLimit(EnchantmentDialogue.limit - 1);
                addEventListener(document, id, "click", el, false);
            }
            addEventListener(document, id, "mousemove", moveTooltipListener, false);
            addEventListener(document, id, "mouseleave", hideTooltipListener, false);
            TooltipInformationEventListener el2 = new TooltipInformationEventListener().setInformation((EnchantmentDialogue.limit == 0 ? "Minimum Limit Reached" : "Limit Decrease"), "");
            addEventListener(document, id, "mouseenter", el2, false);
        }
        id = "LIMIT_INCREASE";
        if (((EventTarget) document.getElementById(id)) != null) {
            if (EnchantmentDialogue.limit < EnchantmentDialogue.ingredient.getEnchantmentEffect().getLimits(EnchantmentDialogue.primaryMod, EnchantmentDialogue.secondaryMod)) {
                EnchantmentEventListener el = new EnchantmentEventListener().setLimit(EnchantmentDialogue.limit + 1);
                addEventListener(document, id, "click", el, false);
            }
            addEventListener(document, id, "mousemove", moveTooltipListener, false);
            addEventListener(document, id, "mouseleave", hideTooltipListener, false);
            TooltipInformationEventListener el2 = new TooltipInformationEventListener().setInformation((EnchantmentDialogue.limit < EnchantmentDialogue.ingredient.getEnchantmentEffect().getLimits(EnchantmentDialogue.primaryMod, EnchantmentDialogue.secondaryMod) ? "Limit Increase" : "Maximum Limit Reached"), "");
            addEventListener(document, id, "mouseenter", el2, false);
        }
        id = "LIMIT_INCREASE_LARGE";
        if (((EventTarget) document.getElementById(id)) != null) {
            int limit = EnchantmentDialogue.ingredient.getEnchantmentEffect().getLimits(EnchantmentDialogue.primaryMod, EnchantmentDialogue.secondaryMod);
            if (EnchantmentDialogue.limit < limit) {
                EnchantmentEventListener el = new EnchantmentEventListener().setLimit(Math.min(limit, EnchantmentDialogue.limit + (limit / 10)));
                addEventListener(document, id, "click", el, false);
            }
            addEventListener(document, id, "mousemove", moveTooltipListener, false);
            addEventListener(document, id, "mouseleave", hideTooltipListener, false);
            TooltipInformationEventListener el2 = new TooltipInformationEventListener().setInformation((EnchantmentDialogue.limit < EnchantmentDialogue.ingredient.getEnchantmentEffect().getLimits(EnchantmentDialogue.primaryMod, EnchantmentDialogue.secondaryMod) ? "Large Limit Increase" : "Maximum Limit Reached"), "");
            addEventListener(document, id, "mouseenter", el2, false);
        }
        id = "LIMIT_MAXIMUM";
        if (((EventTarget) document.getElementById(id)) != null) {
            if (EnchantmentDialogue.limit < EnchantmentDialogue.ingredient.getEnchantmentEffect().getLimits(EnchantmentDialogue.primaryMod, EnchantmentDialogue.secondaryMod)) {
                EnchantmentEventListener el = new EnchantmentEventListener().setLimit(EnchantmentDialogue.ingredient.getEnchantmentEffect().getLimits(EnchantmentDialogue.primaryMod, EnchantmentDialogue.secondaryMod));
                addEventListener(document, id, "click", el, false);
            }
            addEventListener(document, id, "mousemove", moveTooltipListener, false);
            addEventListener(document, id, "mouseleave", hideTooltipListener, false);
            TooltipInformationEventListener el2 = new TooltipInformationEventListener().setInformation((EnchantmentDialogue.limit < EnchantmentDialogue.ingredient.getEnchantmentEffect().getLimits(EnchantmentDialogue.primaryMod, EnchantmentDialogue.secondaryMod) ? "Set Limit To Maximum" : "Maximum Limit Reached"), "");
            addEventListener(document, id, "mouseenter", el2, false);
        }
        // Ingredient icon:
        if (((EventTarget) document.getElementById("INGREDIENT_ENCHANTING")) != null) {
            ((EventTarget) document.getElementById("INGREDIENT_ENCHANTING")).addEventListener("click", e -> {
                Main.game.setResponseTab(1);
                if (EnchantmentDialogue.ingredient instanceof AbstractItem) {
                    Main.game.setContent(new Response("Back", "Stop enchanting.", InventoryDialogue.ITEM_INVENTORY) {

                        @Override
                        public void effects() {
                            EnchantmentDialogue.resetEnchantmentVariables();
                        }
                    });
                } else if (EnchantmentDialogue.ingredient instanceof AbstractClothing) {
                    Main.game.setContent(new Response("Back", "Stop enchanting.", InventoryDialogue.CLOTHING_INVENTORY) {

                        @Override
                        public void effects() {
                            EnchantmentDialogue.resetEnchantmentVariables();
                        }
                    });
                } else {
                    Main.game.setContent(new Response("Back", "Stop enchanting.", InventoryDialogue.WEAPON_INVENTORY) {

                        @Override
                        public void effects() {
                            EnchantmentDialogue.resetEnchantmentVariables();
                        }
                    });
                }
            }, false);
            addEventListener(document, "INGREDIENT_ENCHANTING", "mousemove", moveTooltipListener, false);
            addEventListener(document, "INGREDIENT_ENCHANTING", "mouseleave", hideTooltipListener, false);
            InventoryTooltipEventListener el2;
            if (EnchantmentDialogue.ingredient instanceof AbstractItem) {
                el2 = new InventoryTooltipEventListener().setItem((AbstractItem) EnchantmentDialogue.ingredient, Main.game.getPlayer(), null);
            } else if (EnchantmentDialogue.ingredient instanceof AbstractClothing) {
                el2 = new InventoryTooltipEventListener().setClothing((AbstractClothing) EnchantmentDialogue.ingredient, Main.game.getPlayer(), null);
            } else {
                el2 = new InventoryTooltipEventListener().setWeapon((AbstractWeapon) EnchantmentDialogue.ingredient, Main.game.getPlayer());
            }
            addEventListener(document, "INGREDIENT_ENCHANTING", "mouseenter", el2, false);
        }
        // Output icon:
        if (((EventTarget) document.getElementById("OUTPUT_ENCHANTING")) != null) {
            ((EventTarget) document.getElementById("OUTPUT_ENCHANTING")).addEventListener("click", e -> {
                if (EnchantmentDialogue.effects.isEmpty()) {
                } else if (EnchantmentDialogue.canAffordCost(EnchantmentDialogue.ingredient, EnchantmentDialogue.effects)) {
                    Main.game.setContent(new ResponseEffectsOnly("Craft", "Craft '" + EnchantingUtils.getPotionName(EnchantmentDialogue.ingredient, EnchantmentDialogue.effects) + "'.") {

                        @Override
                        public void effects() {
                            EnchantmentDialogue.craftItem(EnchantmentDialogue.ingredient, EnchantmentDialogue.effects);
                            if ((EnchantmentDialogue.previousIngredient instanceof AbstractItem ? Main.game.getPlayer().hasItem((AbstractItem) EnchantmentDialogue.previousIngredient) : true) && (EnchantmentDialogue.previousIngredient instanceof AbstractClothing ? Main.game.getPlayer().hasClothing((AbstractClothing) EnchantmentDialogue.previousIngredient) : true) && (EnchantmentDialogue.previousIngredient instanceof AbstractWeapon ? Main.game.getPlayer().hasWeapon((AbstractWeapon) EnchantmentDialogue.previousIngredient) : true)) {
                                EnchantmentDialogue.ingredient = EnchantmentDialogue.previousIngredient;
                                Main.game.setContent(new Response("", "", EnchantmentDialogue.ENCHANTMENT_MENU));
                            } else {
                                Main.game.setContent(new Response("", "", InventoryDialogue.INVENTORY_MENU));
                            }
                        // EnchantmentDialogue.craftItem(EnchantmentDialogue.ingredient, EnchantmentDialogue.effects);
                        // 
                        // if(EnchantmentDialogue.ingredient instanceof AbstractItem) {
                        // if(Main.game.getPlayer().hasItem((AbstractItem) EnchantmentDialogue.previousIngredient)) {
                        // EnchantmentDialogue.ingredient = EnchantmentDialogue.previousIngredient;
                        // Main.game.setContent(new Response("", "", EnchantmentDialogue.ENCHANTMENT_MENU));
                        // } else {
                        // Main.game.setContent(new Response("", "", InventoryDialogue.INVENTORY_MENU));
                        // }
                        // 
                        // } else if(EnchantmentDialogue.ingredient instanceof AbstractClothing) {
                        // if(Main.game.getPlayer().hasClothing((AbstractClothing) EnchantmentDialogue.previousIngredient)) {
                        // EnchantmentDialogue.ingredient = EnchantmentDialogue.previousIngredient;
                        // Main.game.setContent(new Response("", "", EnchantmentDialogue.ENCHANTMENT_MENU));
                        // } else {
                        // Main.game.setContent(new Response("", "", InventoryDialogue.INVENTORY_MENU));
                        // }
                        // 
                        // } else if(EnchantmentDialogue.ingredient instanceof AbstractWeapon) {
                        // if(Main.game.getPlayer().hasWeapon((AbstractWeapon) EnchantmentDialogue.previousIngredient)) {
                        // EnchantmentDialogue.ingredient = EnchantmentDialogue.previousIngredient;
                        // Main.game.setContent(new Response("", "", EnchantmentDialogue.ENCHANTMENT_MENU));
                        // } else {
                        // Main.game.setContent(new Response("", "", InventoryDialogue.INVENTORY_MENU));
                        // }
                        // }
                        }
                    });
                }
            }, false);
            addEventListener(document, "OUTPUT_ENCHANTING", "mousemove", moveTooltipListener, false);
            addEventListener(document, "OUTPUT_ENCHANTING", "mouseleave", hideTooltipListener, false);
            TooltipInformationEventListener el2 = new TooltipInformationEventListener().setInformation("Craft", "Click to craft this item!");
            addEventListener(document, "OUTPUT_ENCHANTING", "mouseenter", el2, false);
        }
        // Adding an effect:
        id = "ENCHANT_ADD_BUTTON";
        if (((EventTarget) document.getElementById(id)) != null) {
            ((EventTarget) document.getElementById(id)).addEventListener("click", e -> {
                if (EnchantmentDialogue.ingredient.getEnchantmentEffect().getEffectsDescription(EnchantmentDialogue.primaryMod, EnchantmentDialogue.secondaryMod, EnchantmentDialogue.potency, EnchantmentDialogue.limit, Main.game.getPlayer(), Main.game.getPlayer()) == null) {
                } else {
                    Main.game.setContent(new Response("Add", "Add the effect.", EnchantmentDialogue.ENCHANTMENT_MENU) {

                        @Override
                        public void effects() {
                            EnchantmentDialogue.effects.add(new ItemEffect(EnchantmentDialogue.ingredient.getEnchantmentEffect(), EnchantmentDialogue.primaryMod, EnchantmentDialogue.secondaryMod, EnchantmentDialogue.potency, EnchantmentDialogue.limit));
                        }
                    });
                }
            }, false);
            addEventListener(document, id, "mousemove", moveTooltipListener, false);
            addEventListener(document, id, "mouseleave", hideTooltipListener, false);
            TooltipInformationEventListener el2 = new TooltipInformationEventListener().setInformation("Add Effect", "");
            addEventListener(document, id, "mouseenter", el2, false);
        }
        id = "ENCHANT_ADD_BUTTON_DISABLED";
        if (((EventTarget) document.getElementById(id)) != null) {
            addEventListener(document, id, "mousemove", moveTooltipListener, false);
            addEventListener(document, id, "mouseleave", hideTooltipListener, false);
            TooltipInformationEventListener el2 = new TooltipInformationEventListener().setInformation("Add Effect", EnchantmentDialogue.effects.size() >= EnchantmentDialogue.ingredient.getEnchantmentLimit() ? "You have already added the maximum number of effects for this item!" : "");
            addEventListener(document, id, "mouseenter", el2, false);
        }
        // Choosing a primary modifier:
        if (EnchantmentDialogue.ingredient != null) {
            for (TFModifier tfMod : EnchantmentDialogue.ingredient.getEnchantmentEffect().getPrimaryModifiers()) {
                if (((EventTarget) document.getElementById("MOD_PRIMARY_" + tfMod.hashCode())) != null) {
                    EnchantmentEventListener el = new EnchantmentEventListener().setPrimaryModifier(tfMod);
                    addEventListener(document, "MOD_PRIMARY_" + tfMod.hashCode(), "click", el, false);
                    addEventListener(document, "MOD_PRIMARY_" + tfMod.hashCode(), "mousemove", moveTooltipListener, false);
                    addEventListener(document, "MOD_PRIMARY_" + tfMod.hashCode(), "mouseleave", hideTooltipListener, false);
                    InventoryTooltipEventListener el2 = new InventoryTooltipEventListener().setTFModifier(tfMod);
                    addEventListener(document, "MOD_PRIMARY_" + tfMod.hashCode(), "mouseenter", el2, false);
                }
            }
        }
        // Choosing a secondary modifier:
        if (EnchantmentDialogue.ingredient != null) {
            for (TFModifier tfMod : EnchantmentDialogue.ingredient.getEnchantmentEffect().getSecondaryModifiers(EnchantmentDialogue.primaryMod)) {
                if (((EventTarget) document.getElementById("MOD_SECONDARY_" + tfMod.hashCode())) != null) {
                    EnchantmentEventListener el = new EnchantmentEventListener().setSecondaryModifier(tfMod);
                    addEventListener(document, "MOD_SECONDARY_" + tfMod.hashCode(), "click", el, false);
                    addEventListener(document, "MOD_SECONDARY_" + tfMod.hashCode(), "mousemove", moveTooltipListener, false);
                    addEventListener(document, "MOD_SECONDARY_" + tfMod.hashCode(), "mouseleave", hideTooltipListener, false);
                    InventoryTooltipEventListener el2 = new InventoryTooltipEventListener().setTFModifier(tfMod);
                    addEventListener(document, "MOD_SECONDARY_" + tfMod.hashCode(), "mouseenter", el2, false);
                }
            }
        }
        if (Main.game.getCurrentDialogueNode() == SlaveryManagementDialogue.ROOM_MANAGEMENT) {
            for (Cell c : SlaveryManagementDialogue.importantCells) {
                id = c.getId();
                if (((EventTarget) document.getElementById(id)) != null) {
                    ((EventTarget) document.getElementById(id)).addEventListener("click", e -> {
                        Main.game.setContent(new Response("", "", Main.game.getCurrentDialogueNode()) {

                            @Override
                            public void effects() {
                                SlaveryManagementDialogue.cellToInspect = c;
                            }

                            @Override
                            public DialogueNodeOld getNextDialogue() {
                                return SlaveryManagementDialogue.ROOM_UPGRADES;
                            }
                        });
                    }, false);
                    addEventListener(document, id, "mousemove", moveTooltipListener, false);
                    addEventListener(document, id, "mouseleave", hideTooltipListener, false);
                    TooltipInformationEventListener el = new TooltipInformationEventListener().setInformation("Manage Room", "Open this room's management screen.");
                    addEventListener(document, id, "mouseenter", el, false);
                }
                id = c.getId() + "_DISABLED";
                if (((EventTarget) document.getElementById(id)) != null) {
                    addEventListener(document, id, "mousemove", moveTooltipListener, false);
                    addEventListener(document, id, "mouseleave", hideTooltipListener, false);
                    TooltipInformationEventListener el = new TooltipInformationEventListener().setInformation("Manage Room", "You are not able to manage this room!");
                    addEventListener(document, id, "mouseenter", el, false);
                }
                id = c.getId() + "_PRESENT";
                if (((EventTarget) document.getElementById(id)) != null) {
                    ((EventTarget) document.getElementById(id)).addEventListener("click", e -> {
                        Main.game.setContent(new Response("", "", Main.game.getCurrentDialogueNode()) {

                            @Override
                            public void effects() {
                                SlaveryManagementDialogue.cellToInspect = c;
                            }

                            @Override
                            public DialogueNodeOld getNextDialogue() {
                                return SlaveryManagementDialogue.ROOM_UPGRADES;
                            }
                        });
                    }, false);
                    addEventListener(document, id, "mousemove", moveTooltipListener, false);
                    addEventListener(document, id, "mouseleave", hideTooltipListener, false);
                    TooltipInformationEventListener el = new TooltipInformationEventListener().setInformation("Manage Room", "Open this room's management screen.");
                    addEventListener(document, id, "mouseenter", el, false);
                }
                id = c.getId() + "_PRESENT_DISABLED";
                if (((EventTarget) document.getElementById(id)) != null) {
                    addEventListener(document, id, "mousemove", moveTooltipListener, false);
                    addEventListener(document, id, "mouseleave", hideTooltipListener, false);
                    TooltipInformationEventListener el = new TooltipInformationEventListener().setInformation("Manage Room", "You are not able to manage this room!");
                    addEventListener(document, id, "mouseenter", el, false);
                }
            }
        }
        if (Main.game.getCurrentDialogueNode() == SlaveryManagementDialogue.ROOM_UPGRADES) {
            for (PlaceUpgrade placeUpgrade : PlaceUpgrade.values()) {
                id = placeUpgrade + "_BUY";
                if (((EventTarget) document.getElementById(id)) != null) {
                    ((EventTarget) document.getElementById(id)).addEventListener("click", e -> {
                        if (placeUpgrade != PlaceUpgrade.LILAYA_ARTHUR_ROOM) {
                            Main.game.setContent(new Response("", "", Main.game.getCurrentDialogueNode()) {

                                @Override
                                public void effects() {
                                    SlaveryManagementDialogue.cellToInspect.getPlace().addPlaceUpgrade(placeUpgrade);
                                    Main.game.getPlayer().incrementMoney(-placeUpgrade.getInstallCost());
                                }
                            });
                        } else {
                            Main.game.setContent(new Response("", "", LilayaHomeGeneric.ROOM_ARTHUR_INSTALLATION) {

                                @Override
                                public void effects() {
                                    Main.game.getArthur().setLocation(Main.game.getPlayer().getWorldLocation(), Main.game.getPlayer().getLocation(), true);
                                    SlaveryManagementDialogue.cellToInspect.getPlace().addPlaceUpgrade(placeUpgrade);
                                    Main.game.getDialogueFlags().setFlag(DialogueFlagValue.arthursRoomInstalled, true);
                                }
                            });
                        }
                    }, false);
                    addEventListener(document, id, "mousemove", moveTooltipListener, false);
                    addEventListener(document, id, "mouseleave", hideTooltipListener, false);
                    TooltipInformationEventListener el = new TooltipInformationEventListener().setInformation("Purchase Modification", "This will cost: " + UtilText.formatAsMoney(placeUpgrade.getInstallCost()) + "</br>" + SlaveryManagementDialogue.getPurchaseAvailabilityTooltipText(SlaveryManagementDialogue.cellToInspect.getPlace(), placeUpgrade));
                    addEventListener(document, id, "mouseenter", el, false);
                }
                id = placeUpgrade + "_BUY_DISABLED";
                if (((EventTarget) document.getElementById(id)) != null) {
                    addEventListener(document, id, "mousemove", moveTooltipListener, false);
                    addEventListener(document, id, "mouseleave", hideTooltipListener, false);
                    TooltipInformationEventListener el = new TooltipInformationEventListener().setInformation("Purchase Modification", "This will cost: " + UtilText.formatAsMoney(placeUpgrade.getInstallCost()) + "</br>" + SlaveryManagementDialogue.getPurchaseAvailabilityTooltipText(SlaveryManagementDialogue.cellToInspect.getPlace(), placeUpgrade));
                    addEventListener(document, id, "mouseenter", el, false);
                }
                id = placeUpgrade + "_SELL";
                if (((EventTarget) document.getElementById(id)) != null) {
                    ((EventTarget) document.getElementById(id)).addEventListener("click", e -> {
                        Main.game.setContent(new Response("", "", Main.game.getCurrentDialogueNode()) {

                            @Override
                            public void effects() {
                                SlaveryManagementDialogue.cellToInspect.getPlace().removePlaceUpgrade(placeUpgrade);
                                Main.game.getPlayer().incrementMoney(-placeUpgrade.getRemovalCost());
                            }
                        });
                    }, false);
                    addEventListener(document, id, "mousemove", moveTooltipListener, false);
                    addEventListener(document, id, "mouseleave", hideTooltipListener, false);
                    TooltipInformationEventListener el = new TooltipInformationEventListener().setInformation("Remove Modification", "This will cost: " + UtilText.formatAsMoney(placeUpgrade.getRemovalCost()) + "</br>" + SlaveryManagementDialogue.getPurchaseAvailabilityTooltipText(SlaveryManagementDialogue.cellToInspect.getPlace(), placeUpgrade));
                    addEventListener(document, id, "mouseenter", el, false);
                }
                id = placeUpgrade + "_SELL_DISABLED";
                if (((EventTarget) document.getElementById(id)) != null) {
                    addEventListener(document, id, "mousemove", moveTooltipListener, false);
                    addEventListener(document, id, "mouseleave", hideTooltipListener, false);
                    TooltipInformationEventListener el = new TooltipInformationEventListener().setInformation("Remove Modification", (placeUpgrade.isCoreRoomUpgrade() ? "You cannot directly remove core upgrades. Instead, you'll have to purchase a different core modification in order to remove the current one." : "This will cost: " + UtilText.formatAsMoney(placeUpgrade.getRemovalCost()) + "</br>" + SlaveryManagementDialogue.getPurchaseAvailabilityTooltipText(SlaveryManagementDialogue.cellToInspect.getPlace(), placeUpgrade)));
                    addEventListener(document, id, "mouseenter", el, false);
                }
            }
            id = "rename_room_button";
            if (((EventTarget) document.getElementById(id)) != null) {
                ((EventTarget) document.getElementById(id)).addEventListener("click", e -> {
                    boolean unsuitableName = false;
                    if (Main.mainController.getWebEngine().executeScript("document.getElementById('nameInput')") != null) {
                        Main.mainController.getWebEngine().executeScript("document.getElementById('hiddenFieldName').innerHTML=document.getElementById('nameInput').value;");
                        if (Main.mainController.getWebEngine().getDocument() != null) {
                            unsuitableName = Main.mainController.getWebEngine().getDocument().getElementById("hiddenFieldName").getTextContent().length() < 1 || Main.mainController.getWebEngine().getDocument().getElementById("hiddenFieldName").getTextContent().length() > 32;
                        }
                        if (!unsuitableName) {
                            Main.game.setContent(new Response("Rename Room", "Rename this room to whatever you've entered in the text box.", Main.game.getCurrentDialogueNode()) {

                                @Override
                                public void effects() {
                                    SlaveryManagementDialogue.cellToInspect.getPlace().setName(Main.mainController.getWebEngine().getDocument().getElementById("hiddenFieldName").getTextContent());
                                }
                            });
                        }
                    }
                }, false);
            }
        }
        if (Main.game.getCurrentDialogueNode() == SlaveryManagementDialogue.SLAVERY_OVERVIEW) {
            id = "PREVIOUS_DAY";
            if (((EventTarget) document.getElementById(id)) != null) {
                ((EventTarget) document.getElementById(id)).addEventListener("click", e -> {
                    SlaveryManagementDialogue.incrementDayNumber(-1);
                    Main.game.setContent(new Response("Rename", "", Main.game.getCurrentDialogueNode()));
                }, false);
            }
            id = "NEXT_DAY";
            if (((EventTarget) document.getElementById(id)) != null) {
                ((EventTarget) document.getElementById(id)).addEventListener("click", e -> {
                    SlaveryManagementDialogue.incrementDayNumber(1);
                    Main.game.setContent(new Response("Rename", "", Main.game.getCurrentDialogueNode()));
                }, false);
            }
        }
        if (Main.game.getDialogueFlags().getSlaveryManagerSlaveSelected() != null) {
            id = Main.game.getDialogueFlags().getSlaveryManagerSlaveSelected().getId() + "_RENAME";
            if (((EventTarget) document.getElementById(id)) != null) {
                ((EventTarget) document.getElementById(id)).addEventListener("click", e -> {
                    boolean unsuitableName = false;
                    if (Main.mainController.getWebEngine().executeScript("document.getElementById('slaveNameInput')") != null) {
                        Main.mainController.getWebEngine().executeScript("document.getElementById('hiddenFieldName').innerHTML=document.getElementById('slaveNameInput').value;");
                        if (Main.mainController.getWebEngine().getDocument() != null) {
                            if (Main.mainController.getWebEngine().getDocument().getElementById("hiddenFieldName").getTextContent().length() < 1 || Main.mainController.getWebEngine().getDocument().getElementById("hiddenFieldName").getTextContent().length() > 32)
                                unsuitableName = true;
                            else {
                                unsuitableName = false;
                            }
                        }
                        if (!unsuitableName) {
                            Main.game.setContent(new Response("Rename", "", Main.game.getCurrentDialogueNode()) {

                                @Override
                                public void effects() {
                                    Main.game.getDialogueFlags().getSlaveryManagerSlaveSelected().setName(new NameTriplet(Main.mainController.getWebEngine().getDocument().getElementById("hiddenFieldName").getTextContent()));
                                }
                            });
                        }
                    }
                }, false);
            }
            id = Main.game.getDialogueFlags().getSlaveryManagerSlaveSelected().getId() + "_CALLS_PLAYER";
            if (((EventTarget) document.getElementById(id)) != null) {
                ((EventTarget) document.getElementById(id)).addEventListener("click", e -> {
                    boolean unsuitableName = false;
                    if (Main.mainController.getWebEngine().executeScript("document.getElementById('slaveToPlayerNameInput')") != null) {
                        Main.mainController.getWebEngine().executeScript("document.getElementById('hiddenFieldName').innerHTML=document.getElementById('slaveToPlayerNameInput').value;");
                        if (Main.mainController.getWebEngine().getDocument() != null) {
                            unsuitableName = Main.mainController.getWebEngine().getDocument().getElementById("hiddenFieldName").getTextContent().length() < 1 || Main.mainController.getWebEngine().getDocument().getElementById("hiddenFieldName").getTextContent().length() > 32;
                        }
                        if (!unsuitableName) {
                            Main.game.setContent(new Response("Rename", "", Main.game.getCurrentDialogueNode()) {

                                @Override
                                public void effects() {
                                    Main.game.getDialogueFlags().getSlaveryManagerSlaveSelected().setPlayerPetName(Main.mainController.getWebEngine().getDocument().getElementById("hiddenFieldName").getTextContent());
                                }
                            });
                        }
                    }
                }, false);
            }
            id = "GLOBAL_CALLS_PLAYER";
            if (((EventTarget) document.getElementById(id)) != null) {
                ((EventTarget) document.getElementById(id)).addEventListener("click", e -> {
                    boolean unsuitableName = false;
                    if (Main.mainController.getWebEngine().executeScript("document.getElementById('slaveToPlayerNameInput')") != null) {
                        Main.mainController.getWebEngine().executeScript("document.getElementById('hiddenFieldName').innerHTML=document.getElementById('slaveToPlayerNameInput').value;");
                        if (Main.mainController.getWebEngine().getDocument() != null) {
                            unsuitableName = Main.mainController.getWebEngine().getDocument().getElementById("hiddenFieldName").getTextContent().length() < 1 || Main.mainController.getWebEngine().getDocument().getElementById("hiddenFieldName").getTextContent().length() > 32;
                        }
                        if (!unsuitableName) {
                            Main.game.setContent(new Response("Rename", "", Main.game.getCurrentDialogueNode()) {

                                @Override
                                public void effects() {
                                    for (String id : Main.game.getPlayer().getSlavesOwned()) {
                                        Main.game.getNPCById(id).setPlayerPetName(Main.mainController.getWebEngine().getDocument().getElementById("hiddenFieldName").getTextContent());
                                    }
                                }
                            });
                        }
                    }
                }, false);
            }
            // Job hours:
            for (int i = 0; i < 24; i++) {
                allocateWorkTime(i);
            }
            for (SlaveJobHours preset : SlaveJobHours.values()) {
                id = preset + "_TIME";
                if (((EventTarget) document.getElementById(id)) != null) {
                    ((EventTarget) document.getElementById(id)).addEventListener("click", e -> {
                        Main.game.getDialogueFlags().getSlaveryManagerSlaveSelected().resetWorkHours();
                        for (int hour = preset.getStartHour(); hour < preset.getStartHour() + preset.getLength(); hour++) {
                            if (hour >= 24) {
                                Main.game.getDialogueFlags().getSlaveryManagerSlaveSelected().setWorkHour(hour - 24, true);
                            } else {
                                Main.game.getDialogueFlags().getSlaveryManagerSlaveSelected().setWorkHour(hour, true);
                            }
                        }
                        Main.game.setContent(new Response("", "", SlaveryManagementDialogue.getSlaveryManagementSlaveJobsDialogue(Main.game.getDialogueFlags().getSlaveryManagerSlaveSelected())));
                    }, false);
                    addEventListener(document, id, "mousemove", moveTooltipListener, false);
                    addEventListener(document, id, "mouseleave", hideTooltipListener, false);
                    TooltipInformationEventListener el = new TooltipInformationEventListener().setInformation("Set Preset Work Hours", preset.getDescription());
                    addEventListener(document, id, "mouseenter", el, false);
                }
                id = preset + "_TIME_DISABLED";
                if (((EventTarget) document.getElementById(id)) != null) {
                    addEventListener(document, id, "mousemove", moveTooltipListener, false);
                    addEventListener(document, id, "mouseleave", hideTooltipListener, false);
                    TooltipInformationEventListener el = new TooltipInformationEventListener().setInformation("Set Preset Work Hours", "You can't assign hours to a slave who is idle. Assign them a job first.");
                    addEventListener(document, id, "mouseenter", el, false);
                }
            }
            // Jobs:
            for (SlaveJob job : SlaveJob.values()) {
                id = job + "_ASSIGN";
                if (((EventTarget) document.getElementById(id)) != null) {
                    ((EventTarget) document.getElementById(id)).addEventListener("click", e -> {
                        Main.game.getDialogueFlags().getSlaveryManagerSlaveSelected().setSlaveJob(job);
                        Main.game.setContent(new Response("", "", SlaveryManagementDialogue.getSlaveryManagementSlaveJobsDialogue(Main.game.getDialogueFlags().getSlaveryManagerSlaveSelected())));
                    }, false);
                    addEventListener(document, id, "mousemove", moveTooltipListener, false);
                    addEventListener(document, id, "mouseleave", hideTooltipListener, false);
                    TooltipInformationEventListener el = new TooltipInformationEventListener().setInformation("Assign Job", job.getDescription());
                    addEventListener(document, id, "mouseenter", el, false);
                }
                id = job + "_ASSIGN_DISABLED";
                if (((EventTarget) document.getElementById(id)) != null) {
                    addEventListener(document, id, "mousemove", moveTooltipListener, false);
                    addEventListener(document, id, "mouseleave", hideTooltipListener, false);
                    TooltipInformationEventListener el = new TooltipInformationEventListener().setInformation("Assign Job", UtilText.parse(Main.game.getDialogueFlags().getSlaveryManagerSlaveSelected(), job.getAvailabilityText(Main.game.getDialogueFlags().getSlaveryManagerSlaveSelected())));
                    addEventListener(document, id, "mouseenter", el, false);
                }
                for (SlaveJobSetting setting : job.getMutualSettings()) {
                    id = setting + "_ADD";
                    if (((EventTarget) document.getElementById(id)) != null) {
                        ((EventTarget) document.getElementById(id)).addEventListener("click", e -> {
                            Main.game.getDialogueFlags().getSlaveryManagerSlaveSelected().addSlaveJobSettings(setting);
                            Main.game.setContent(new Response("", "", SlaveryManagementDialogue.getSlaveryManagementSlaveJobsDialogue(Main.game.getDialogueFlags().getSlaveryManagerSlaveSelected())));
                        }, false);
                        addEventListener(document, id, "mousemove", moveTooltipListener, false);
                        addEventListener(document, id, "mouseleave", hideTooltipListener, false);
                        TooltipInformationEventListener el = new TooltipInformationEventListener().setInformation("Apply Setting", setting.getDescription());
                        addEventListener(document, id, "mouseenter", el, false);
                    }
                    id = setting + "_REMOVE";
                    if (((EventTarget) document.getElementById(id)) != null) {
                        ((EventTarget) document.getElementById(id)).addEventListener("click", e -> {
                            Main.game.getDialogueFlags().getSlaveryManagerSlaveSelected().removeSlaveJobSettings(setting);
                            Main.game.setContent(new Response("", "", SlaveryManagementDialogue.getSlaveryManagementSlaveJobsDialogue(Main.game.getDialogueFlags().getSlaveryManagerSlaveSelected())));
                        }, false);
                        addEventListener(document, id, "mousemove", moveTooltipListener, false);
                        addEventListener(document, id, "mouseleave", hideTooltipListener, false);
                        TooltipInformationEventListener el = new TooltipInformationEventListener().setInformation("Remove Setting", setting.getDescription());
                        addEventListener(document, id, "mouseenter", el, false);
                    }
                    id = setting + "_DISABLED";
                    if (((EventTarget) document.getElementById(id)) != null) {
                        addEventListener(document, id, "mousemove", moveTooltipListener, false);
                        addEventListener(document, id, "mouseleave", hideTooltipListener, false);
                        TooltipInformationEventListener el = new TooltipInformationEventListener().setInformation("Apply Setting", UtilText.parse(Main.game.getDialogueFlags().getSlaveryManagerSlaveSelected(), "You'll need to assign this job to [npc.name] before you can apply any settings."));
                        addEventListener(document, id, "mouseenter", el, false);
                    }
                }
                for (Entry<String, List<SlaveJobSetting>> entry : job.getMutuallyExclusiveSettings().entrySet()) {
                    for (SlaveJobSetting setting : entry.getValue()) {
                        id = setting + "_TOGGLE_ADD";
                        if (((EventTarget) document.getElementById(id)) != null) {
                            ((EventTarget) document.getElementById(id)).addEventListener("click", e -> {
                                for (SlaveJobSetting settingRem : entry.getValue()) {
                                    Main.game.getDialogueFlags().getSlaveryManagerSlaveSelected().removeSlaveJobSettings(settingRem);
                                }
                                Main.game.getDialogueFlags().getSlaveryManagerSlaveSelected().addSlaveJobSettings(setting);
                                Main.game.setContent(new Response("", "", SlaveryManagementDialogue.getSlaveryManagementSlaveJobsDialogue(Main.game.getDialogueFlags().getSlaveryManagerSlaveSelected())));
                            }, false);
                            addEventListener(document, id, "mousemove", moveTooltipListener, false);
                            addEventListener(document, id, "mouseleave", hideTooltipListener, false);
                            TooltipInformationEventListener el = new TooltipInformationEventListener().setInformation("Apply Setting", setting.getDescription());
                            addEventListener(document, id, "mouseenter", el, false);
                        }
                        id = setting + "_DISABLED";
                        if (((EventTarget) document.getElementById(id)) != null) {
                            addEventListener(document, id, "mousemove", moveTooltipListener, false);
                            addEventListener(document, id, "mouseleave", hideTooltipListener, false);
                            TooltipInformationEventListener el = new TooltipInformationEventListener().setInformation("Setting Applied", setting.getDescription());
                            addEventListener(document, id, "mouseenter", el, false);
                        }
                    }
                }
            }
            // Permissions:
            for (SlavePermission permission : SlavePermission.values()) {
                for (SlavePermissionSetting setting : permission.getSettings()) {
                    id = setting + "_ADD";
                    if (((EventTarget) document.getElementById(id)) != null) {
                        ((EventTarget) document.getElementById(id)).addEventListener("click", e -> {
                            Main.game.getDialogueFlags().getSlaveryManagerSlaveSelected().addSlavePermissionSetting(permission, setting);
                            Main.game.setContent(new Response("", "", SlaveryManagementDialogue.getSlaveryManagementSlavePermissionsDialogue(Main.game.getDialogueFlags().getSlaveryManagerSlaveSelected())));
                        }, false);
                        addEventListener(document, id, "mousemove", moveTooltipListener, false);
                        addEventListener(document, id, "mouseleave", hideTooltipListener, false);
                        TooltipInformationEventListener el = new TooltipInformationEventListener().setInformation("Apply Setting", setting.getDescription());
                        addEventListener(document, id, "mouseenter", el, false);
                    }
                    id = setting + "_REMOVE";
                    if (((EventTarget) document.getElementById(id)) != null) {
                        ((EventTarget) document.getElementById(id)).addEventListener("click", e -> {
                            Main.game.getDialogueFlags().getSlaveryManagerSlaveSelected().removeSlavePermissionSetting(permission, setting);
                            Main.game.setContent(new Response("", "", SlaveryManagementDialogue.getSlaveryManagementSlavePermissionsDialogue(Main.game.getDialogueFlags().getSlaveryManagerSlaveSelected())));
                        }, false);
                        addEventListener(document, id, "mousemove", moveTooltipListener, false);
                        addEventListener(document, id, "mouseleave", hideTooltipListener, false);
                        TooltipInformationEventListener el = new TooltipInformationEventListener().setInformation("Remove Setting", setting.getDescription());
                        addEventListener(document, id, "mouseenter", el, false);
                    }
                    id = setting + "_REMOVE_ME";
                    if (((EventTarget) document.getElementById(id)) != null) {
                        addEventListener(document, id, "mousemove", moveTooltipListener, false);
                        addEventListener(document, id, "mouseleave", hideTooltipListener, false);
                        TooltipInformationEventListener el = new TooltipInformationEventListener().setInformation("Remove Setting", "You cannot remove mutually exclusive settings! Choose a different option instead.");
                        addEventListener(document, id, "mouseenter", el, false);
                    }
                }
            }
        }
        for (String slaveId : Main.game.getPlayer().getSlavesOwned()) {
            id = slaveId;
            NPC slave = (NPC) Main.game.getNPCById(slaveId);
            if (((EventTarget) document.getElementById(id)) != null) {
                ((EventTarget) document.getElementById(id)).addEventListener("click", e -> {
                    Main.game.setContent(new Response("", "", SlaveryManagementDialogue.getSlaveryManagementInspectSlaveDialogue(slave)));
                }, false);
                addEventListener(document, id, "mousemove", moveTooltipListener, false);
                addEventListener(document, id, "mouseleave", hideTooltipListener, false);
                TooltipInformationEventListener el = new TooltipInformationEventListener().setInformation("Inspect Slave", UtilText.parse(slave, "Inspect [npc.name]."));
                addEventListener(document, id, "mouseenter", el, false);
            }
            // TODO
            id = slaveId + "_JOB";
            if (((EventTarget) document.getElementById(id)) != null) {
                ((EventTarget) document.getElementById(id)).addEventListener("click", e -> {
                    Main.game.setContent(new Response("", "", SlaveryManagementDialogue.getSlaveryManagementSlaveJobsDialogue(slave)));
                }, false);
                addEventListener(document, id, "mousemove", moveTooltipListener, false);
                addEventListener(document, id, "mouseleave", hideTooltipListener, false);
                TooltipInformationEventListener el = new TooltipInformationEventListener().setInformation("Manage Slave's Job", UtilText.parse(slave, "Set [npc.name]'s job and work hours."));
                addEventListener(document, id, "mouseenter", el, false);
            }
            // TODO
            id = slaveId + "_PERMISSIONS";
            if (((EventTarget) document.getElementById(id)) != null) {
                ((EventTarget) document.getElementById(id)).addEventListener("click", e -> {
                    Main.game.setContent(new Response("", "", SlaveryManagementDialogue.getSlaveryManagementSlavePermissionsDialogue(slave)));
                }, false);
                addEventListener(document, id, "mousemove", moveTooltipListener, false);
                addEventListener(document, id, "mouseleave", hideTooltipListener, false);
                TooltipInformationEventListener el = new TooltipInformationEventListener().setInformation("Manage Slave's Permissions", UtilText.parse(slave, "Manage [npc.name]'s permissions."));
                addEventListener(document, id, "mouseenter", el, false);
            }
            id = slaveId + "_INVENTORY";
            if (((EventTarget) document.getElementById(id)) != null) {
                ((EventTarget) document.getElementById(id)).addEventListener("click", e -> {
                    Main.mainController.openInventory(slave, InventoryInteraction.FULL_MANAGEMENT);
                }, false);
                addEventListener(document, id, "mousemove", moveTooltipListener, false);
                addEventListener(document, id, "mouseleave", hideTooltipListener, false);
                TooltipInformationEventListener el = new TooltipInformationEventListener().setInformation("Manage Slave's Inventory", UtilText.parse(slave, "Manage [npc.name]'s inventory."));
                addEventListener(document, id, "mouseenter", el, false);
            }
            id = slaveId + "_TRANSFER";
            if (((EventTarget) document.getElementById(id)) != null) {
                ((EventTarget) document.getElementById(id)).addEventListener("click", e -> {
                    Main.game.setContent(new Response("", "", Main.game.getCurrentDialogueNode()) {

                        @Override
                        public void effects() {
                            slave.setHomeLocation(Main.game.getPlayer().getWorldLocation(), Main.game.getPlayer().getLocation());
                            slave.returnToHome();
                        }
                    });
                }, false);
                addEventListener(document, id, "mousemove", moveTooltipListener, false);
                addEventListener(document, id, "mouseleave", hideTooltipListener, false);
                TooltipInformationEventListener el = new TooltipInformationEventListener().setInformation("Move Slave Here", UtilText.parse(slave, "Move [npc.name] to your current location."));
                addEventListener(document, id, "mouseenter", el, false);
            }
            id = slaveId + "_TRANSFER_DISABLED";
            if (((EventTarget) document.getElementById(id)) != null) {
                addEventListener(document, id, "mousemove", moveTooltipListener, false);
                addEventListener(document, id, "mouseleave", hideTooltipListener, false);
                TooltipInformationEventListener el = new TooltipInformationEventListener().setInformation("Move Slave Here", UtilText.parse(slave, "You cannot move [npc.name] to this location, as there's no room for [npc.herHim] here."));
                addEventListener(document, id, "mouseenter", el, false);
            }
            id = slaveId + "_SELL";
            if (((EventTarget) document.getElementById(id)) != null) {
                ((EventTarget) document.getElementById(id)).addEventListener("click", e -> {
                    Main.game.setContent(new Response("", "", Main.game.getCurrentDialogueNode()) {

                        @Override
                        public void effects() {
                            Main.game.getPlayer().incrementMoney((int) (slave.getValueAsSlave() * Main.game.getDialogueFlags().getSlaveTrader().getBuyModifier()));
                            Main.game.getDialogueFlags().getSlaveTrader().addSlave(slave);
                            slave.setLocation(Main.game.getDialogueFlags().getSlaveTrader().getWorldLocation(), Main.game.getDialogueFlags().getSlaveTrader().getLocation(), true);
                        }
                    });
                }, false);
                addEventListener(document, id, "mousemove", moveTooltipListener, false);
                addEventListener(document, id, "mouseleave", hideTooltipListener, false);
                TooltipInformationEventListener el = new TooltipInformationEventListener().setInformation("Sell Slave", UtilText.parse(slave, "[npc.Name] has a value of " + UtilText.formatAsMoney(slave.getValueAsSlave(), "b", Colour.GENERIC_GOOD) + "</br>" + "However, " + Main.game.getDialogueFlags().getSlaveTrader().getName() + " will buy [npc.herHim] for " + UtilText.formatAsMoney((int) (slave.getValueAsSlave() * Main.game.getDialogueFlags().getSlaveTrader().getBuyModifier()), "b", Colour.GENERIC_ARCANE) + "."));
                addEventListener(document, id, "mouseenter", el, false);
            }
            id = slaveId + "_SELL_DISABLED";
            if (((EventTarget) document.getElementById(id)) != null) {
                addEventListener(document, id, "mousemove", moveTooltipListener, false);
                addEventListener(document, id, "mouseleave", hideTooltipListener, false);
                TooltipInformationEventListener el = new TooltipInformationEventListener().setInformation("Sell Slave", UtilText.parse(slave, "You cannot sell [npc.name], as there's nobody here to sell [npc.herHim] to."));
                addEventListener(document, id, "mouseenter", el, false);
            }
            id = slaveId + "_COSMETICS";
            if (((EventTarget) document.getElementById(id)) != null) {
                ((EventTarget) document.getElementById(id)).addEventListener("click", e -> {
                    Main.game.setContent(new Response("", "", SlaveryManagementDialogue.SLAVE_MANAGEMENT_COSMETICS_HAIR) {

                        @Override
                        public void effects() {
                            Main.game.getDialogueFlags().setSlaveryManagerSlaveSelected(slave);
                            BodyChanging.setTarget(slave);
                        }
                    });
                }, false);
                addEventListener(document, id, "mousemove", moveTooltipListener, false);
                addEventListener(document, id, "mouseleave", hideTooltipListener, false);
                TooltipInformationEventListener el = new TooltipInformationEventListener().setInformation("Send Slave to Kate", UtilText.parse(slave, "Send [npc.name] to Kate's beauty salon, 'Succubi's Secrets', to get [npc.her] appearance changed."));
                addEventListener(document, id, "mouseenter", el, false);
            }
            id = slaveId + "_COSMETICS_DISABLED";
            if (((EventTarget) document.getElementById(id)) != null) {
                addEventListener(document, id, "mousemove", moveTooltipListener, false);
                addEventListener(document, id, "mouseleave", hideTooltipListener, false);
                TooltipInformationEventListener el = new TooltipInformationEventListener().setInformation("Send Slave to Kate", UtilText.parse(slave, "You haven't met Kate yet!"));
                addEventListener(document, id, "mouseenter", el, false);
            }
        }
        if (Main.game.getDialogueFlags().getSlaveTrader() != null) {
            for (String slaveId : Main.game.getDialogueFlags().getSlaveTrader().getSlavesOwned()) {
                id = slaveId + "_TRADER";
                NPC slave = (NPC) Main.game.getNPCById(slaveId);
                if (((EventTarget) document.getElementById(id)) != null) {
                    ((EventTarget) document.getElementById(id)).addEventListener("click", e -> {
                        Main.game.setContent(new Response("", "", SlaveryManagementDialogue.getSlaveryManagementInspectSlaveDialogue(slave)));
                    }, false);
                    addEventListener(document, id, "mousemove", moveTooltipListener, false);
                    addEventListener(document, id, "mouseleave", hideTooltipListener, false);
                    TooltipInformationEventListener el = new TooltipInformationEventListener().setInformation("Inspect Slave", UtilText.parse(slave, "Take a detailed look at [npc.name]."));
                    addEventListener(document, id, "mouseenter", el, false);
                }
                id = slaveId + "_TRADER_JOB";
                if (((EventTarget) document.getElementById(id)) != null) {
                    addEventListener(document, id, "mousemove", moveTooltipListener, false);
                    addEventListener(document, id, "mouseleave", hideTooltipListener, false);
                    TooltipInformationEventListener el = new TooltipInformationEventListener().setInformation("Manage Slave's Job", UtilText.parse(slave, "You cannot manage [npc.name]'s job, as you don't own [npc.herHim]!"));
                    addEventListener(document, id, "mouseenter", el, false);
                }
                id = slaveId + "_TRADER_PERMISSIONS";
                if (((EventTarget) document.getElementById(id)) != null) {
                    addEventListener(document, id, "mousemove", moveTooltipListener, false);
                    addEventListener(document, id, "mouseleave", hideTooltipListener, false);
                    TooltipInformationEventListener el = new TooltipInformationEventListener().setInformation("Manage Slave's Permissions", UtilText.parse(slave, "You cannot manage [npc.name]'s permissions, as you don't own [npc.herHim]!"));
                    addEventListener(document, id, "mouseenter", el, false);
                }
                id = slaveId + "_TRADER_INVENTORY";
                if (((EventTarget) document.getElementById(id)) != null) {
                    addEventListener(document, id, "mousemove", moveTooltipListener, false);
                    addEventListener(document, id, "mouseleave", hideTooltipListener, false);
                    TooltipInformationEventListener el = new TooltipInformationEventListener().setInformation("Manage Slave's Inventory", UtilText.parse(slave, "You cannot manage [npc.name]'s inventory, as you don't own [npc.herHim]!"));
                    addEventListener(document, id, "mouseenter", el, false);
                }
                id = slaveId + "_TRADER_TRANSFER";
                if (((EventTarget) document.getElementById(id)) != null) {
                    addEventListener(document, id, "mousemove", moveTooltipListener, false);
                    addEventListener(document, id, "mouseleave", hideTooltipListener, false);
                    TooltipInformationEventListener el = new TooltipInformationEventListener().setInformation("Move Slave To Here", UtilText.parse(slave, "You cannot move [npc.name] to this location, as you don't own [npc.herHim], as well as due to the fact that [npc.she]'s already here!"));
                    addEventListener(document, id, "mouseenter", el, false);
                }
                id = slaveId + "_BUY";
                if (((EventTarget) document.getElementById(id)) != null) {
                    ((EventTarget) document.getElementById(id)).addEventListener("click", e -> {
                        Main.game.setContent(new Response("", "", Main.game.getCurrentDialogueNode()) {

                            @Override
                            public void effects() {
                                Main.game.getPlayer().incrementMoney(-(int) (slave.getValueAsSlave() * Main.game.getDialogueFlags().getSlaveTrader().getSellModifier()));
                                Main.game.getPlayer().addSlave(slave);
                                slave.setLocation(WorldType.SLAVER_ALLEY, PlaceType.SLAVER_ALLEY_SLAVERY_ADMINISTRATION, true);
                            }
                        });
                    }, false);
                    addEventListener(document, id, "mousemove", moveTooltipListener, false);
                    addEventListener(document, id, "mouseleave", hideTooltipListener, false);
                    TooltipInformationEventListener el = new TooltipInformationEventListener().setInformation("Buy Slave", UtilText.parse(slave, "[npc.Name] has a value of " + UtilText.formatAsMoney(slave.getValueAsSlave(), "b", Colour.GENERIC_GOOD) + "</br>" + "However, " + Main.game.getDialogueFlags().getSlaveTrader().getName() + " will sell [npc.herHim] for " + UtilText.formatAsMoney((int) (slave.getValueAsSlave() * Main.game.getDialogueFlags().getSlaveTrader().getSellModifier()), "b", Colour.GENERIC_ARCANE) + "."));
                    addEventListener(document, id, "mouseenter", el, false);
                }
                id = slaveId + "_BUY_DISABLED";
                if (((EventTarget) document.getElementById(id)) != null) {
                    addEventListener(document, id, "mousemove", moveTooltipListener, false);
                    addEventListener(document, id, "mouseleave", hideTooltipListener, false);
                    TooltipInformationEventListener el = new TooltipInformationEventListener().setInformation("Buy Slave", UtilText.parse(slave, "You cannot buy [npc.name], as you don't have enough money!"));
                    addEventListener(document, id, "mouseenter", el, false);
                }
                id = slaveId + "_TRADER_COSMETICS";
                if (((EventTarget) document.getElementById(id)) != null) {
                    addEventListener(document, id, "mousemove", moveTooltipListener, false);
                    addEventListener(document, id, "mouseleave", hideTooltipListener, false);
                    TooltipInformationEventListener el = new TooltipInformationEventListener().setInformation("Send Slave to Kate", UtilText.parse(slave, "You can't send a slave you don't own to Kate!"));
                    addEventListener(document, id, "mouseenter", el, false);
                }
            }
        }
        if (Main.game.getActiveNPC() != null) {
            id = Main.game.getActiveNPC().getId() + "_PET_NAME";
            if (((EventTarget) document.getElementById(id)) != null) {
                ((EventTarget) document.getElementById(id)).addEventListener("click", e -> {
                    boolean unsuitableName = false;
                    if (Main.mainController.getWebEngine().executeScript("document.getElementById('offspringPetNameInput')") != null) {
                        Main.mainController.getWebEngine().executeScript("document.getElementById('hiddenFieldName').innerHTML=document.getElementById('offspringPetNameInput').value;");
                        if (Main.mainController.getWebEngine().getDocument() != null) {
                            if (Main.mainController.getWebEngine().getDocument().getElementById("hiddenFieldName").getTextContent().length() < 2 || Main.mainController.getWebEngine().getDocument().getElementById("hiddenFieldName").getTextContent().length() > 32)
                                unsuitableName = true;
                            else {
                                unsuitableName = false;
                            }
                        }
                        if (!unsuitableName) {
                            Main.game.setContent(new Response("Rename", "", Main.game.getCurrentDialogueNode()) {

                                @Override
                                public void effects() {
                                    Main.game.getActiveNPC().setPlayerPetName(Main.mainController.getWebEngine().getDocument().getElementById("hiddenFieldName").getTextContent());
                                }
                            });
                        }
                    }
                }, false);
            }
        }
        if (!Main.game.isInNewWorld()) {
            for (Month month : Month.values()) {
                id = "STARTING_MONTH_" + month;
                if (((EventTarget) document.getElementById(id)) != null) {
                    ((EventTarget) document.getElementById(id)).addEventListener("click", e -> {
                        Main.game.setStartingDateMonth(month);
                        Main.game.setContent(new Response("", "", Main.game.getCurrentDialogueNode()));
                    }, false);
                }
            }
            // Sex experiences:
            for (int i : CharacterModificationUtils.soSilly) {
                // Given:
                id = "HANDJOBS_GIVEN_" + i;
                if (((EventTarget) document.getElementById(id)) != null) {
                    ((EventTarget) document.getElementById(id)).addEventListener("click", e -> {
                        CharacterModificationUtils.setSexExperience(new SexType(SexParticipantType.PITCHER, PenetrationType.FINGER, OrificeType.URETHRA), i);
                        Main.game.setContent(new Response("", "", Main.game.getCurrentDialogueNode()));
                    }, false);
                }
                id = "FINGERINGS_GIVEN_" + i;
                if (((EventTarget) document.getElementById(id)) != null) {
                    ((EventTarget) document.getElementById(id)).addEventListener("click", e -> {
                        CharacterModificationUtils.setSexExperience(new SexType(SexParticipantType.PITCHER, PenetrationType.FINGER, OrificeType.VAGINA), i);
                        Main.game.setContent(new Response("", "", Main.game.getCurrentDialogueNode()));
                    }, false);
                }
                id = "BLOWJOBS_GIVEN_" + i;
                if (((EventTarget) document.getElementById(id)) != null) {
                    ((EventTarget) document.getElementById(id)).addEventListener("click", e -> {
                        CharacterModificationUtils.setSexExperience(new SexType(SexParticipantType.CATCHER, PenetrationType.PENIS, OrificeType.MOUTH), i);
                        Main.game.setContent(new Response("", "", Main.game.getCurrentDialogueNode()));
                    }, false);
                }
                id = "CUNNILINGUS_GIVEN_" + i;
                if (((EventTarget) document.getElementById(id)) != null) {
                    ((EventTarget) document.getElementById(id)).addEventListener("click", e -> {
                        CharacterModificationUtils.setSexExperience(new SexType(SexParticipantType.PITCHER, PenetrationType.TONGUE, OrificeType.VAGINA), i);
                        Main.game.setContent(new Response("", "", Main.game.getCurrentDialogueNode()));
                    }, false);
                }
                id = "VAGINAL_GIVEN_" + i;
                if (((EventTarget) document.getElementById(id)) != null) {
                    ((EventTarget) document.getElementById(id)).addEventListener("click", e -> {
                        CharacterModificationUtils.setSexExperience(new SexType(SexParticipantType.PITCHER, PenetrationType.PENIS, OrificeType.VAGINA), i);
                        Main.game.setContent(new Response("", "", Main.game.getCurrentDialogueNode()));
                    }, false);
                }
                id = "ANAL_GIVEN_" + i;
                if (((EventTarget) document.getElementById(id)) != null) {
                    ((EventTarget) document.getElementById(id)).addEventListener("click", e -> {
                        CharacterModificationUtils.setSexExperience(new SexType(SexParticipantType.PITCHER, PenetrationType.PENIS, OrificeType.ANUS), i);
                        Main.game.setContent(new Response("", "", Main.game.getCurrentDialogueNode()));
                    }, false);
                }
                // Received:
                id = "HANDJOBS_TAKEN_" + i;
                if (((EventTarget) document.getElementById(id)) != null) {
                    ((EventTarget) document.getElementById(id)).addEventListener("click", e -> {
                        CharacterModificationUtils.setSexExperience(new SexType(SexParticipantType.CATCHER, PenetrationType.FINGER, OrificeType.URETHRA), i);
                        Main.game.setContent(new Response("", "", Main.game.getCurrentDialogueNode()));
                    }, false);
                }
                id = "FINGERINGS_TAKEN_" + i;
                if (((EventTarget) document.getElementById(id)) != null) {
                    ((EventTarget) document.getElementById(id)).addEventListener("click", e -> {
                        CharacterModificationUtils.setSexExperience(new SexType(SexParticipantType.CATCHER, PenetrationType.FINGER, OrificeType.VAGINA), i);
                        Main.game.setContent(new Response("", "", Main.game.getCurrentDialogueNode()));
                    }, false);
                }
                id = "BLOWJOBS_TAKEN_" + i;
                if (((EventTarget) document.getElementById(id)) != null) {
                    ((EventTarget) document.getElementById(id)).addEventListener("click", e -> {
                        CharacterModificationUtils.setSexExperience(new SexType(SexParticipantType.PITCHER, PenetrationType.PENIS, OrificeType.MOUTH), i);
                        Main.game.setContent(new Response("", "", Main.game.getCurrentDialogueNode()));
                    }, false);
                }
                id = "CUNNILINGUS_TAKEN_" + i;
                if (((EventTarget) document.getElementById(id)) != null) {
                    ((EventTarget) document.getElementById(id)).addEventListener("click", e -> {
                        CharacterModificationUtils.setSexExperience(new SexType(SexParticipantType.CATCHER, PenetrationType.TONGUE, OrificeType.VAGINA), i);
                        Main.game.setContent(new Response("", "", Main.game.getCurrentDialogueNode()));
                    }, false);
                }
                id = "VAGINAL_TAKEN_" + i;
                if (((EventTarget) document.getElementById(id)) != null) {
                    ((EventTarget) document.getElementById(id)).addEventListener("click", e -> {
                        CharacterModificationUtils.setSexExperience(new SexType(SexParticipantType.CATCHER, PenetrationType.PENIS, OrificeType.VAGINA), i);
                        Main.game.setContent(new Response("", "", Main.game.getCurrentDialogueNode()));
                    }, false);
                }
                id = "ANAL_TAKEN_" + i;
                if (((EventTarget) document.getElementById(id)) != null) {
                    ((EventTarget) document.getElementById(id)).addEventListener("click", e -> {
                        CharacterModificationUtils.setSexExperience(new SexType(SexParticipantType.CATCHER, PenetrationType.PENIS, OrificeType.ANUS), i);
                        Main.game.setContent(new Response("", "", Main.game.getCurrentDialogueNode()));
                    }, false);
                }
            }
        }
        if (!Main.game.isInNewWorld() || Main.game.getCurrentDialogueNode().equals(BodyChanging.BODY_CHANGING_CORE) || Main.game.getCurrentDialogueNode().equals(BodyChanging.BODY_CHANGING_FACE) || Main.game.getCurrentDialogueNode().equals(BodyChanging.BODY_CHANGING_ASS) || Main.game.getCurrentDialogueNode().equals(BodyChanging.BODY_CHANGING_BREASTS) || Main.game.getCurrentDialogueNode().equals(BodyChanging.BODY_CHANGING_VAGINA) || Main.game.getCurrentDialogueNode().equals(BodyChanging.BODY_CHANGING_PENIS)) {
            // Gender:
            id = "CHOOSE_GENDER_MALE";
            if (((EventTarget) document.getElementById(id)) != null) {
                ((EventTarget) document.getElementById(id)).addEventListener("click", e -> {
                    CharacterCreation.setGenderMale();
                    Main.game.setContent(new Response("", "", Main.game.getCurrentDialogueNode()));
                }, false);
            }
            id = "CHOOSE_GENDER_FEMALE";
            if (((EventTarget) document.getElementById(id)) != null) {
                ((EventTarget) document.getElementById(id)).addEventListener("click", e -> {
                    CharacterCreation.setGenderFemale();
                    Main.game.setContent(new Response("", "", Main.game.getCurrentDialogueNode()));
                }, false);
            }
            // Femininity
            id = "CHOOSE_FEM_MASCULINE_STRONG";
            if (((EventTarget) document.getElementById(id)) != null) {
                ((EventTarget) document.getElementById(id)).addEventListener("click", e -> {
                    BodyChanging.getTarget().setFemininity(Femininity.MASCULINE_STRONG.getMedianFemininity());
                    if (!Main.game.isInNewWorld()) {
                        CharacterCreation.getDressed();
                    }
                    Main.game.setContent(new Response("", "", Main.game.getCurrentDialogueNode()));
                }, false);
            }
            id = "CHOOSE_FEM_MASCULINE";
            if (((EventTarget) document.getElementById(id)) != null) {
                ((EventTarget) document.getElementById(id)).addEventListener("click", e -> {
                    BodyChanging.getTarget().setFemininity(Femininity.MASCULINE.getMedianFemininity());
                    if (!Main.game.isInNewWorld()) {
                        CharacterCreation.getDressed();
                    }
                    Main.game.setContent(new Response("", "", Main.game.getCurrentDialogueNode()));
                }, false);
            }
            id = "CHOOSE_FEM_ANDROGYNOUS";
            if (((EventTarget) document.getElementById(id)) != null) {
                ((EventTarget) document.getElementById(id)).addEventListener("click", e -> {
                    BodyChanging.getTarget().setFemininity(Femininity.ANDROGYNOUS.getMedianFemininity());
                    if (!Main.game.isInNewWorld()) {
                        CharacterCreation.getDressed();
                    }
                    Main.game.setContent(new Response("", "", Main.game.getCurrentDialogueNode()));
                }, false);
            }
            id = "CHOOSE_FEM_FEMININE";
            if (((EventTarget) document.getElementById(id)) != null) {
                ((EventTarget) document.getElementById(id)).addEventListener("click", e -> {
                    BodyChanging.getTarget().setFemininity(Femininity.FEMININE.getMedianFemininity());
                    if (!Main.game.isInNewWorld()) {
                        CharacterCreation.getDressed();
                    }
                    Main.game.setContent(new Response("", "", Main.game.getCurrentDialogueNode()));
                }, false);
            }
            id = "CHOOSE_FEM_FEMININE_STRONG";
            if (((EventTarget) document.getElementById(id)) != null) {
                ((EventTarget) document.getElementById(id)).addEventListener("click", e -> {
                    BodyChanging.getTarget().setFemininity(Femininity.FEMININE_STRONG.getMedianFemininity());
                    if (!Main.game.isInNewWorld()) {
                        CharacterCreation.getDressed();
                    }
                    Main.game.setContent(new Response("", "", Main.game.getCurrentDialogueNode()));
                }, false);
            }
            // Personality:
            for (Personality personality : Personality.values()) {
                id = "PERSONALITY_" + personality;
                if (((EventTarget) document.getElementById(id)) != null) {
                    ((EventTarget) document.getElementById(id)).addEventListener("click", e -> {
                        BodyChanging.getTarget().setPersonality(personality);
                        Main.game.setContent(new Response("", "", Main.game.getCurrentDialogueNode()));
                    }, false);
                }
            }
            // Orientation:
            for (SexualOrientation orientation : SexualOrientation.values()) {
                id = "SEXUAL_ORIENTATION_" + orientation;
                if (((EventTarget) document.getElementById(id)) != null) {
                    ((EventTarget) document.getElementById(id)).addEventListener("click", e -> {
                        BodyChanging.getTarget().setSexualOrientation(orientation);
                        Main.game.setContent(new Response("", "", Main.game.getCurrentDialogueNode()));
                    }, false);
                }
            }
            // Height:
            id = "HEIGHT_INCREASE";
            if (((EventTarget) document.getElementById(id)) != null) {
                ((EventTarget) document.getElementById(id)).addEventListener("click", e -> {
                    BodyChanging.getTarget().incrementHeight(1);
                    Main.game.setContent(new Response("", "", Main.game.getCurrentDialogueNode()));
                }, false);
            }
            id = "HEIGHT_INCREASE_LARGE";
            if (((EventTarget) document.getElementById(id)) != null) {
                ((EventTarget) document.getElementById(id)).addEventListener("click", e -> {
                    BodyChanging.getTarget().incrementHeight(5);
                    Main.game.setContent(new Response("", "", Main.game.getCurrentDialogueNode()));
                }, false);
            }
            id = "HEIGHT_DECREASE";
            if (((EventTarget) document.getElementById(id)) != null) {
                ((EventTarget) document.getElementById(id)).addEventListener("click", e -> {
                    BodyChanging.getTarget().incrementHeight(-1);
                    Main.game.setContent(new Response("", "", Main.game.getCurrentDialogueNode()));
                }, false);
            }
            id = "HEIGHT_DECREASE_LARGE";
            if (((EventTarget) document.getElementById(id)) != null) {
                ((EventTarget) document.getElementById(id)).addEventListener("click", e -> {
                    BodyChanging.getTarget().incrementHeight(-5);
                    Main.game.setContent(new Response("", "", Main.game.getCurrentDialogueNode()));
                }, false);
            }
            // Body size:
            for (BodySize bs : BodySize.values()) {
                id = "BODY_SIZE_" + bs;
                if (((EventTarget) document.getElementById(id)) != null) {
                    ((EventTarget) document.getElementById(id)).addEventListener("click", e -> {
                        BodyChanging.getTarget().setBodySize(bs.getMedianValue());
                        Main.game.setContent(new Response("", "", Main.game.getCurrentDialogueNode()));
                    }, false);
                }
            }
            // Muscles:
            for (Muscle muscle : Muscle.values()) {
                id = "MUSCLE_" + muscle;
                if (((EventTarget) document.getElementById(id)) != null) {
                    ((EventTarget) document.getElementById(id)).addEventListener("click", e -> {
                        BodyChanging.getTarget().setMuscle(muscle.getMedianValue());
                        Main.game.setContent(new Response("", "", Main.game.getCurrentDialogueNode()));
                    }, false);
                }
            }
            // Lip Size:
            for (LipSize ls : LipSize.values()) {
                id = "LIP_SIZE_" + ls;
                if (((EventTarget) document.getElementById(id)) != null) {
                    ((EventTarget) document.getElementById(id)).addEventListener("click", e -> {
                        BodyChanging.getTarget().setLipSize(ls.getValue());
                        Main.game.setContent(new Response("", "", Main.game.getCurrentDialogueNode()));
                    }, false);
                }
            }
            // Lip puffiness:
            id = "LIP_PUFFY_ON";
            if (((EventTarget) document.getElementById(id)) != null) {
                ((EventTarget) document.getElementById(id)).addEventListener("click", e -> {
                    BodyChanging.getTarget().addFaceOrificeModifier(OrificeModifier.PUFFY);
                    Main.game.setContent(new Response("", "", Main.game.getCurrentDialogueNode()));
                }, false);
            }
            id = "LIP_PUFFY_OFF";
            if (((EventTarget) document.getElementById(id)) != null) {
                ((EventTarget) document.getElementById(id)).addEventListener("click", e -> {
                    BodyChanging.getTarget().removeFaceOrificeModifier(OrificeModifier.PUFFY);
                    Main.game.setContent(new Response("", "", Main.game.getCurrentDialogueNode()));
                }, false);
            }
            // Breast size:
            for (CupSize cs : CupSize.values()) {
                id = "BREAST_SIZE_" + cs;
                if (((EventTarget) document.getElementById(id)) != null) {
                    ((EventTarget) document.getElementById(id)).addEventListener("click", e -> {
                        BodyChanging.getTarget().setBreastSize(cs.getMeasurement());
                        Main.game.setContent(new Response("", "", Main.game.getCurrentDialogueNode()));
                    }, false);
                }
            }
            // Breast Shape:
            for (BreastShape bs : BreastShape.values()) {
                id = "BREAST_SHAPE_" + bs;
                if (((EventTarget) document.getElementById(id)) != null) {
                    ((EventTarget) document.getElementById(id)).addEventListener("click", e -> {
                        BodyChanging.getTarget().setBreastShape(bs);
                        Main.game.setContent(new Response("", "", Main.game.getCurrentDialogueNode()));
                    }, false);
                }
            }
            // Nipple size:
            for (NippleSize ns : NippleSize.values()) {
                id = "NIPPLE_SIZE_" + ns;
                if (((EventTarget) document.getElementById(id)) != null) {
                    ((EventTarget) document.getElementById(id)).addEventListener("click", e -> {
                        BodyChanging.getTarget().setNippleSize(ns.getValue());
                        Main.game.setContent(new Response("", "", Main.game.getCurrentDialogueNode()));
                    }, false);
                }
            }
            // Areolae size:
            for (AreolaeSize as : AreolaeSize.values()) {
                id = "AREOLAE_SIZE_" + as;
                if (((EventTarget) document.getElementById(id)) != null) {
                    ((EventTarget) document.getElementById(id)).addEventListener("click", e -> {
                        BodyChanging.getTarget().setAreolaeSize(as.getValue());
                        Main.game.setContent(new Response("", "", Main.game.getCurrentDialogueNode()));
                    }, false);
                }
            }
            // Nipple puffiness:
            id = "NIPPLE_PUFFY_ON";
            if (((EventTarget) document.getElementById(id)) != null) {
                ((EventTarget) document.getElementById(id)).addEventListener("click", e -> {
                    BodyChanging.getTarget().addNippleOrificeModifier(OrificeModifier.PUFFY);
                    Main.game.setContent(new Response("", "", Main.game.getCurrentDialogueNode()));
                }, false);
            }
            id = "NIPPLE_PUFFY_OFF";
            if (((EventTarget) document.getElementById(id)) != null) {
                ((EventTarget) document.getElementById(id)).addEventListener("click", e -> {
                    BodyChanging.getTarget().removeNippleOrificeModifier(OrificeModifier.PUFFY);
                    Main.game.setContent(new Response("", "", Main.game.getCurrentDialogueNode()));
                }, false);
            }
            // Lactation:
            for (int i : CharacterModificationUtils.getLactationQuantitiesAvailable()) {
                id = "LACTATION_" + i;
                if (((EventTarget) document.getElementById(id)) != null) {
                    ((EventTarget) document.getElementById(id)).addEventListener("click", e -> {
                        BodyChanging.getTarget().setBreastMilkStorage(i);
                        Main.game.setContent(new Response("", "", Main.game.getCurrentDialogueNode()));
                    }, false);
                }
            }
            // Ass size:
            for (AssSize as : CharacterModificationUtils.getAssSizesAvailable()) {
                id = "ASS_SIZE_" + as;
                if (((EventTarget) document.getElementById(id)) != null) {
                    ((EventTarget) document.getElementById(id)).addEventListener("click", e -> {
                        BodyChanging.getTarget().setAssSize(as.getValue());
                        Main.game.setContent(new Response("", "", Main.game.getCurrentDialogueNode()));
                    }, false);
                }
            }
            // Hip size:
            for (HipSize hs : CharacterModificationUtils.getHipSizesAvailable()) {
                id = "HIP_SIZE_" + hs;
                if (((EventTarget) document.getElementById(id)) != null) {
                    ((EventTarget) document.getElementById(id)).addEventListener("click", e -> {
                        BodyChanging.getTarget().setHipSize(hs.getValue());
                        Main.game.setContent(new Response("", "", Main.game.getCurrentDialogueNode()));
                    }, false);
                }
            }
            // Bleached anus:
            id = "ANUS_BLEACHED_ON";
            if (((EventTarget) document.getElementById(id)) != null) {
                ((EventTarget) document.getElementById(id)).addEventListener("click", e -> {
                    BodyChanging.getTarget().setAssBleached(true);
                    Main.game.setContent(new Response("", "", Main.game.getCurrentDialogueNode()));
                }, false);
            }
            id = "ANUS_BLEACHED_OFF";
            if (((EventTarget) document.getElementById(id)) != null) {
                ((EventTarget) document.getElementById(id)).addEventListener("click", e -> {
                    BodyChanging.getTarget().setAssBleached(false);
                    Main.game.setContent(new Response("", "", Main.game.getCurrentDialogueNode()));
                }, false);
            }
            // Penis size:
            for (int ps : CharacterModificationUtils.getPenisSizesAvailable()) {
                id = "PENIS_SIZE_" + ps;
                if (((EventTarget) document.getElementById(id)) != null) {
                    ((EventTarget) document.getElementById(id)).addEventListener("click", e -> {
                        BodyChanging.getTarget().setPenisSize(ps);
                        Main.game.setContent(new Response("", "", Main.game.getCurrentDialogueNode()));
                    }, false);
                }
            }
            // Penis girth:
            for (PenisGirth girth : PenisGirth.values()) {
                id = "PENIS_GIRTH_" + girth;
                if (((EventTarget) document.getElementById(id)) != null) {
                    ((EventTarget) document.getElementById(id)).addEventListener("click", e -> {
                        BodyChanging.getTarget().setPenisGirth(girth.getValue());
                        Main.game.setContent(new Response("", "", Main.game.getCurrentDialogueNode()));
                    }, false);
                }
            }
            // Testicle size:
            for (TesticleSize ts : CharacterModificationUtils.getTesticleSizesAvailable()) {
                id = "TESTICLE_SIZE_" + ts;
                if (((EventTarget) document.getElementById(id)) != null) {
                    ((EventTarget) document.getElementById(id)).addEventListener("click", e -> {
                        BodyChanging.getTarget().setTesticleSize(ts.getValue());
                        Main.game.setContent(new Response("", "", Main.game.getCurrentDialogueNode()));
                    }, false);
                }
            }
            // Cum production:
            for (CumProduction cp : CharacterModificationUtils.getCumProductionAvailable()) {
                id = "CUM_PRODUCTION_" + cp;
                if (((EventTarget) document.getElementById(id)) != null) {
                    ((EventTarget) document.getElementById(id)).addEventListener("click", e -> {
                        BodyChanging.getTarget().setCumProduction(cp.getMedianValue());
                        Main.game.setContent(new Response("", "", Main.game.getCurrentDialogueNode()));
                    }, false);
                }
            }
            // Vagina capacity:
            for (Capacity capacity : Capacity.values()) {
                id = "VAGINA_CAPACITY_" + capacity;
                if (((EventTarget) document.getElementById(id)) != null) {
                    ((EventTarget) document.getElementById(id)).addEventListener("click", e -> {
                        BodyChanging.getTarget().setVaginaCapacity(capacity.getMedianValue(), true);
                        Main.game.setContent(new Response("", "", Main.game.getCurrentDialogueNode()));
                    }, false);
                }
            }
            // Vagina wetness:
            for (Wetness wetness : Wetness.values()) {
                id = "VAGINA_WETNESS_" + wetness;
                if (((EventTarget) document.getElementById(id)) != null) {
                    ((EventTarget) document.getElementById(id)).addEventListener("click", e -> {
                        BodyChanging.getTarget().setVaginaWetness(wetness.getValue());
                        Main.game.setContent(new Response("", "", Main.game.getCurrentDialogueNode()));
                    }, false);
                }
            }
            // Vagina elastcity:
            for (OrificeElasticity elasticity : OrificeElasticity.values()) {
                id = "VAGINA_ELASTICITY_" + elasticity;
                if (((EventTarget) document.getElementById(id)) != null) {
                    ((EventTarget) document.getElementById(id)).addEventListener("click", e -> {
                        BodyChanging.getTarget().setVaginaElasticity(elasticity.getValue());
                        Main.game.setContent(new Response("", "", Main.game.getCurrentDialogueNode()));
                    }, false);
                }
            }
            // Vagina plasticity:
            for (OrificePlasticity plasticity : OrificePlasticity.values()) {
                id = "VAGINA_PLASTICITY_" + plasticity;
                if (((EventTarget) document.getElementById(id)) != null) {
                    ((EventTarget) document.getElementById(id)).addEventListener("click", e -> {
                        BodyChanging.getTarget().setVaginaPlasticity(plasticity.getValue());
                        Main.game.setContent(new Response("", "", Main.game.getCurrentDialogueNode()));
                    }, false);
                }
            }
            // Clit size:
            for (ClitorisSize cs : ClitorisSize.values()) {
                id = "CLITORIS_SIZE_" + cs;
                if (((EventTarget) document.getElementById(id)) != null) {
                    ((EventTarget) document.getElementById(id)).addEventListener("click", e -> {
                        BodyChanging.getTarget().setVaginaClitorisSize(cs.getMedianValue());
                        Main.game.setContent(new Response("", "", Main.game.getCurrentDialogueNode()));
                    }, false);
                }
            }
            // Labia size:
            for (LabiaSize ls : LabiaSize.values()) {
                id = "LABIA_SIZE_" + ls;
                if (((EventTarget) document.getElementById(id)) != null) {
                    ((EventTarget) document.getElementById(id)).addEventListener("click", e -> {
                        BodyChanging.getTarget().setVaginaLabiaSize(ls.getValue());
                        Main.game.setContent(new Response("", "", Main.game.getCurrentDialogueNode()));
                    }, false);
                }
            }
            for (ArmType armType : ArmType.values()) {
                id = "CHANGE_ARM_" + armType;
                if (((EventTarget) document.getElementById(id)) != null) {
                    ((EventTarget) document.getElementById(id)).addEventListener("click", e -> {
                        BodyChanging.getTarget().setArmType(armType);
                        Main.game.setContent(new Response("", "", Main.game.getCurrentDialogueNode()));
                    }, false);
                }
            }
            for (EyeType eyeType : EyeType.values()) {
                id = "CHANGE_EYE_" + eyeType;
                if (((EventTarget) document.getElementById(id)) != null) {
                    ((EventTarget) document.getElementById(id)).addEventListener("click", e -> {
                        BodyChanging.getTarget().setEyeType(eyeType);
                        Main.game.setContent(new Response("", "", Main.game.getCurrentDialogueNode()));
                    }, false);
                }
            }
            for (EarType earType : EarType.values()) {
                id = "CHANGE_EAR_" + earType;
                if (((EventTarget) document.getElementById(id)) != null) {
                    ((EventTarget) document.getElementById(id)).addEventListener("click", e -> {
                        BodyChanging.getTarget().setEarType(earType);
                        Main.game.setContent(new Response("", "", Main.game.getCurrentDialogueNode()));
                    }, false);
                }
            }
            for (HornType hornType : HornType.values()) {
                id = "CHANGE_HORN_" + hornType;
                if (((EventTarget) document.getElementById(id)) != null) {
                    ((EventTarget) document.getElementById(id)).addEventListener("click", e -> {
                        BodyChanging.getTarget().setHornType(hornType);
                        Main.game.setContent(new Response("", "", Main.game.getCurrentDialogueNode()));
                    }, false);
                }
            }
            for (AntennaType antennaType : AntennaType.values()) {
                id = "CHANGE_ANTENNA_" + antennaType;
                if (((EventTarget) document.getElementById(id)) != null) {
                    ((EventTarget) document.getElementById(id)).addEventListener("click", e -> {
                        BodyChanging.getTarget().setAntennaType(antennaType);
                        Main.game.setContent(new Response("", "", Main.game.getCurrentDialogueNode()));
                    }, false);
                }
            }
            for (HairType hairType : HairType.values()) {
                id = "CHANGE_HAIR_" + hairType;
                if (((EventTarget) document.getElementById(id)) != null) {
                    ((EventTarget) document.getElementById(id)).addEventListener("click", e -> {
                        BodyChanging.getTarget().setHairType(hairType);
                        Main.game.setContent(new Response("", "", Main.game.getCurrentDialogueNode()));
                    }, false);
                }
            }
            for (LegType legType : LegType.values()) {
                id = "CHANGE_LEG_" + legType;
                if (((EventTarget) document.getElementById(id)) != null) {
                    ((EventTarget) document.getElementById(id)).addEventListener("click", e -> {
                        BodyChanging.getTarget().setLegType(legType);
                        Main.game.setContent(new Response("", "", Main.game.getCurrentDialogueNode()));
                    }, false);
                }
            }
            for (FaceType faceType : FaceType.values()) {
                id = "CHANGE_FACE_" + faceType;
                if (((EventTarget) document.getElementById(id)) != null) {
                    ((EventTarget) document.getElementById(id)).addEventListener("click", e -> {
                        BodyChanging.getTarget().setFaceType(faceType);
                        Main.game.setContent(new Response("", "", Main.game.getCurrentDialogueNode()));
                    }, false);
                }
            }
            for (SkinType skinType : SkinType.values()) {
                id = "CHANGE_SKIN_" + skinType;
                if (((EventTarget) document.getElementById(id)) != null) {
                    ((EventTarget) document.getElementById(id)).addEventListener("click", e -> {
                        BodyChanging.getTarget().setSkinType(skinType);
                        Main.game.setContent(new Response("", "", Main.game.getCurrentDialogueNode()));
                    }, false);
                }
            }
            for (TailType tailType : TailType.values()) {
                id = "CHANGE_TAIL_" + tailType;
                if (((EventTarget) document.getElementById(id)) != null) {
                    ((EventTarget) document.getElementById(id)).addEventListener("click", e -> {
                        BodyChanging.getTarget().setTailType(tailType);
                        Main.game.setContent(new Response("", "", Main.game.getCurrentDialogueNode()));
                    }, false);
                }
            }
            for (WingType wingType : WingType.values()) {
                id = "CHANGE_WING_" + wingType;
                if (((EventTarget) document.getElementById(id)) != null) {
                    ((EventTarget) document.getElementById(id)).addEventListener("click", e -> {
                        BodyChanging.getTarget().setWingType(wingType);
                        Main.game.setContent(new Response("", "", Main.game.getCurrentDialogueNode()));
                    }, false);
                }
            }
            for (AssType assType : AssType.values()) {
                id = "CHANGE_ASS_" + assType;
                if (((EventTarget) document.getElementById(id)) != null) {
                    ((EventTarget) document.getElementById(id)).addEventListener("click", e -> {
                        BodyChanging.getTarget().setAssType(assType);
                        Main.game.setContent(new Response("", "", Main.game.getCurrentDialogueNode()));
                    }, false);
                }
            }
            for (BreastType breastType : BreastType.values()) {
                id = "CHANGE_BREAST_" + breastType;
                if (((EventTarget) document.getElementById(id)) != null) {
                    ((EventTarget) document.getElementById(id)).addEventListener("click", e -> {
                        BodyChanging.getTarget().setBreastType(breastType);
                        Main.game.setContent(new Response("", "", Main.game.getCurrentDialogueNode()));
                    }, false);
                }
            }
            for (EyeShape eyeShape : EyeShape.values()) {
                id = "CHANGE_IRIS_SHAPE_" + eyeShape;
                if (((EventTarget) document.getElementById(id)) != null) {
                    ((EventTarget) document.getElementById(id)).addEventListener("click", e -> {
                        BodyChanging.getTarget().setIrisShape(eyeShape);
                        Main.game.setContent(new Response("", "", Main.game.getCurrentDialogueNode()));
                    }, false);
                }
                id = "CHANGE_PUPIL_SHAPE_" + eyeShape;
                if (((EventTarget) document.getElementById(id)) != null) {
                    ((EventTarget) document.getElementById(id)).addEventListener("click", e -> {
                        BodyChanging.getTarget().setPupilShape(eyeShape);
                        Main.game.setContent(new Response("", "", Main.game.getCurrentDialogueNode()));
                    }, false);
                }
            }
            for (LipSize lipSize : LipSize.values()) {
                id = "CHANGE_LIP_SIZE_" + lipSize;
                if (((EventTarget) document.getElementById(id)) != null) {
                    ((EventTarget) document.getElementById(id)).addEventListener("click", e -> {
                        BodyChanging.getTarget().setLipSize(lipSize.getValue());
                        Main.game.setContent(new Response("", "", Main.game.getCurrentDialogueNode()));
                    }, false);
                }
            }
            for (OrificeModifier orificeMod : OrificeModifier.values()) {
                id = "CHANGE_MOUTH_MOD_" + orificeMod;
                if (((EventTarget) document.getElementById(id)) != null) {
                    ((EventTarget) document.getElementById(id)).addEventListener("click", e -> {
                        if (BodyChanging.getTarget().hasFaceOrificeModifier(orificeMod)) {
                            BodyChanging.getTarget().removeFaceOrificeModifier(orificeMod);
                        } else {
                            BodyChanging.getTarget().addFaceOrificeModifier(orificeMod);
                        }
                        Main.game.setContent(new Response("", "", Main.game.getCurrentDialogueNode()));
                    }, false);
                }
            }
            for (TongueModifier tongueMod : TongueModifier.values()) {
                id = "CHANGE_TONGUE_MOD_" + tongueMod;
                if (((EventTarget) document.getElementById(id)) != null) {
                    ((EventTarget) document.getElementById(id)).addEventListener("click", e -> {
                        if (BodyChanging.getTarget().hasTongueModifier(tongueMod)) {
                            BodyChanging.getTarget().removeTongueModifier(tongueMod);
                        } else {
                            BodyChanging.getTarget().addTongueModifier(tongueMod);
                        }
                        Main.game.setContent(new Response("", "", Main.game.getCurrentDialogueNode()));
                    }, false);
                }
            }
            for (OrificeModifier orificeMod : OrificeModifier.values()) {
                id = "CHANGE_ANUS_MOD_" + orificeMod;
                if (((EventTarget) document.getElementById(id)) != null) {
                    ((EventTarget) document.getElementById(id)).addEventListener("click", e -> {
                        if (BodyChanging.getTarget().hasAssOrificeModifier(orificeMod)) {
                            BodyChanging.getTarget().removeAssOrificeModifier(orificeMod);
                        } else {
                            BodyChanging.getTarget().addAssOrificeModifier(orificeMod);
                        }
                        Main.game.setContent(new Response("", "", Main.game.getCurrentDialogueNode()));
                    }, false);
                }
            }
            // Ass size:
            for (AssSize as : AssSize.values()) {
                id = "CHANGE_ASS_SIZE_" + as;
                if (((EventTarget) document.getElementById(id)) != null) {
                    ((EventTarget) document.getElementById(id)).addEventListener("click", e -> {
                        BodyChanging.getTarget().setAssSize(as.getValue());
                        Main.game.setContent(new Response("", "", Main.game.getCurrentDialogueNode()));
                    }, false);
                }
            }
            for (HipSize hs : HipSize.values()) {
                id = "CHANGE_HIP_SIZE_" + hs;
                if (((EventTarget) document.getElementById(id)) != null) {
                    ((EventTarget) document.getElementById(id)).addEventListener("click", e -> {
                        BodyChanging.getTarget().setHipSize(hs.getValue());
                        Main.game.setContent(new Response("", "", Main.game.getCurrentDialogueNode()));
                    }, false);
                }
            }
            for (Capacity capacity : Capacity.values()) {
                id = "ANUS_CAPACITY_" + capacity;
                if (((EventTarget) document.getElementById(id)) != null) {
                    ((EventTarget) document.getElementById(id)).addEventListener("click", e -> {
                        BodyChanging.getTarget().setAssCapacity(capacity.getMedianValue(), true);
                        Main.game.setContent(new Response("", "", Main.game.getCurrentDialogueNode()));
                    }, false);
                }
            }
            for (Wetness wetness : Wetness.values()) {
                id = "ANUS_WETNESS_" + wetness;
                if (((EventTarget) document.getElementById(id)) != null) {
                    ((EventTarget) document.getElementById(id)).addEventListener("click", e -> {
                        BodyChanging.getTarget().setAssWetness(wetness.getValue());
                        Main.game.setContent(new Response("", "", Main.game.getCurrentDialogueNode()));
                    }, false);
                }
            }
            for (OrificeElasticity elasticity : OrificeElasticity.values()) {
                id = "ANUS_ELASTICITY_" + elasticity;
                if (((EventTarget) document.getElementById(id)) != null) {
                    ((EventTarget) document.getElementById(id)).addEventListener("click", e -> {
                        BodyChanging.getTarget().setAssElasticity(elasticity.getValue());
                        Main.game.setContent(new Response("", "", Main.game.getCurrentDialogueNode()));
                    }, false);
                }
            }
            for (OrificePlasticity plasticity : OrificePlasticity.values()) {
                id = "ANUS_PLASTICITY_" + plasticity;
                if (((EventTarget) document.getElementById(id)) != null) {
                    ((EventTarget) document.getElementById(id)).addEventListener("click", e -> {
                        BodyChanging.getTarget().setAssPlasticity(plasticity.getValue());
                        Main.game.setContent(new Response("", "", Main.game.getCurrentDialogueNode()));
                    }, false);
                }
            }
            for (int i = 1; i <= Breast.MAXIMUM_BREAST_ROWS; i++) {
                setBreastCountListener(i);
            }
            for (int i = 1; i <= Breast.MAXIMUM_NIPPLES_PER_BREAST; i++) {
                setNippleCountListener(i);
            }
            // Nipple capacity:
            for (Capacity capacity : Capacity.values()) {
                id = "NIPPLE_CAPACITY_" + capacity;
                if (((EventTarget) document.getElementById(id)) != null) {
                    ((EventTarget) document.getElementById(id)).addEventListener("click", e -> {
                        BodyChanging.getTarget().setNippleCapacity(capacity.getMedianValue(), true);
                        Main.game.setContent(new Response("", "", Main.game.getCurrentDialogueNode()));
                    }, false);
                }
            }
            // Nipple elastcity:
            for (OrificeElasticity elasticity : OrificeElasticity.values()) {
                id = "NIPPLE_ELASTICITY_" + elasticity;
                if (((EventTarget) document.getElementById(id)) != null) {
                    ((EventTarget) document.getElementById(id)).addEventListener("click", e -> {
                        BodyChanging.getTarget().setNippleElasticity(elasticity.getValue());
                        Main.game.setContent(new Response("", "", Main.game.getCurrentDialogueNode()));
                    }, false);
                }
            }
            // Nipple plasticity:
            for (OrificePlasticity plasticity : OrificePlasticity.values()) {
                id = "NIPPLE_PLASTICITY_" + plasticity;
                if (((EventTarget) document.getElementById(id)) != null) {
                    ((EventTarget) document.getElementById(id)).addEventListener("click", e -> {
                        BodyChanging.getTarget().setNipplePlasticity(plasticity.getValue());
                        Main.game.setContent(new Response("", "", Main.game.getCurrentDialogueNode()));
                    }, false);
                }
            }
            for (int i : CharacterModificationUtils.demonLactationValues) {
                id = "LACTATION_" + i;
                if (((EventTarget) document.getElementById(id)) != null) {
                    ((EventTarget) document.getElementById(id)).addEventListener("click", e -> {
                        BodyChanging.getTarget().setBreastMilkStorage(i);
                        Main.game.setContent(new Response("", "", Main.game.getCurrentDialogueNode()));
                    }, false);
                }
            }
            for (OrificeModifier orificeMod : OrificeModifier.values()) {
                id = "CHANGE_NIPPLE_MOD_" + orificeMod;
                if (((EventTarget) document.getElementById(id)) != null) {
                    ((EventTarget) document.getElementById(id)).addEventListener("click", e -> {
                        if (BodyChanging.getTarget().hasNippleOrificeModifier(orificeMod)) {
                            BodyChanging.getTarget().removeNippleOrificeModifier(orificeMod);
                        } else {
                            BodyChanging.getTarget().addNippleOrificeModifier(orificeMod);
                        }
                        Main.game.setContent(new Response("", "", Main.game.getCurrentDialogueNode()));
                    }, false);
                }
            }
            for (VaginaType vaginaType : VaginaType.values()) {
                id = "CHANGE_VAGINA_" + vaginaType;
                if (((EventTarget) document.getElementById(id)) != null) {
                    ((EventTarget) document.getElementById(id)).addEventListener("click", e -> {
                        BodyChanging.getTarget().setVaginaType(vaginaType);
                        Main.game.setContent(new Response("", "", Main.game.getCurrentDialogueNode()));
                    }, false);
                }
            }
            for (OrificeModifier orificeMod : OrificeModifier.values()) {
                id = "CHANGE_VAGINA_MOD_" + orificeMod;
                if (((EventTarget) document.getElementById(id)) != null) {
                    ((EventTarget) document.getElementById(id)).addEventListener("click", e -> {
                        if (BodyChanging.getTarget().hasVaginaOrificeModifier(orificeMod)) {
                            BodyChanging.getTarget().removeVaginaOrificeModifier(orificeMod);
                        } else {
                            BodyChanging.getTarget().addVaginaOrificeModifier(orificeMod);
                        }
                        Main.game.setContent(new Response("", "", Main.game.getCurrentDialogueNode()));
                    }, false);
                }
            }
            for (PenisType penisType : PenisType.values()) {
                id = "CHANGE_PENIS_" + penisType;
                if (((EventTarget) document.getElementById(id)) != null) {
                    ((EventTarget) document.getElementById(id)).addEventListener("click", e -> {
                        BodyChanging.getTarget().setPenisType(penisType);
                        Main.game.setContent(new Response("", "", Main.game.getCurrentDialogueNode()));
                    }, false);
                }
            }
            for (PenisSize ps : PenisSize.values()) {
                id = "PENIS_SIZE_" + ps.getMinimumValue();
                if (((EventTarget) document.getElementById(id)) != null) {
                    ((EventTarget) document.getElementById(id)).addEventListener("click", e -> {
                        BodyChanging.getTarget().setPenisSize(ps.getMinimumValue());
                        Main.game.setContent(new Response("", "", Main.game.getCurrentDialogueNode()));
                    }, false);
                }
                id = "PENIS_SIZE_" + ps.getMedianValue();
                if (((EventTarget) document.getElementById(id)) != null) {
                    ((EventTarget) document.getElementById(id)).addEventListener("click", e -> {
                        BodyChanging.getTarget().setPenisSize(ps.getMedianValue());
                        Main.game.setContent(new Response("", "", Main.game.getCurrentDialogueNode()));
                    }, false);
                }
            }
            for (TesticleSize size : TesticleSize.values()) {
                id = "TESTICLE_SIZE_" + size;
                if (((EventTarget) document.getElementById(id)) != null) {
                    ((EventTarget) document.getElementById(id)).addEventListener("click", e -> {
                        BodyChanging.getTarget().setTesticleSize(size.getValue());
                        Main.game.setContent(new Response("", "", Main.game.getCurrentDialogueNode()));
                    }, false);
                }
            }
            for (int i = Testicle.MIN_TESTICLE_COUNT; i <= Testicle.MAX_TESTICLE_COUNT; i += 2) {
                setTesticleCountListener(i);
            }
            for (Capacity capacity : Capacity.values()) {
                id = "URETHRA_CAPACITY_" + capacity;
                if (((EventTarget) document.getElementById(id)) != null) {
                    ((EventTarget) document.getElementById(id)).addEventListener("click", e -> {
                        BodyChanging.getTarget().setPenisCapacity(capacity.getMedianValue(), true);
                        Main.game.setContent(new Response("", "", Main.game.getCurrentDialogueNode()));
                    }, false);
                }
            }
            for (CumProduction cumProduction : CumProduction.values()) {
                id = "CUM_PRODUCTION_" + cumProduction.getMinimumValue();
                if (((EventTarget) document.getElementById(id)) != null) {
                    ((EventTarget) document.getElementById(id)).addEventListener("click", e -> {
                        BodyChanging.getTarget().setCumProduction(cumProduction.getMinimumValue());
                        Main.game.setContent(new Response("", "", Main.game.getCurrentDialogueNode()));
                    }, false);
                }
                id = "CUM_PRODUCTION_" + cumProduction.getMedianValue();
                if (((EventTarget) document.getElementById(id)) != null) {
                    ((EventTarget) document.getElementById(id)).addEventListener("click", e -> {
                        BodyChanging.getTarget().setCumProduction(cumProduction.getMedianValue());
                        Main.game.setContent(new Response("", "", Main.game.getCurrentDialogueNode()));
                    }, false);
                }
            }
            for (OrificeElasticity elasticity : OrificeElasticity.values()) {
                id = "URETHRA_ELASTICITY_" + elasticity;
                if (((EventTarget) document.getElementById(id)) != null) {
                    ((EventTarget) document.getElementById(id)).addEventListener("click", e -> {
                        BodyChanging.getTarget().setUrethraElasticity(elasticity.getValue());
                        Main.game.setContent(new Response("", "", Main.game.getCurrentDialogueNode()));
                    }, false);
                }
            }
            for (OrificePlasticity plasticity : OrificePlasticity.values()) {
                id = "URETHRA_PLASTICITY_" + plasticity;
                if (((EventTarget) document.getElementById(id)) != null) {
                    ((EventTarget) document.getElementById(id)).addEventListener("click", e -> {
                        BodyChanging.getTarget().setUrethraPlasticity(plasticity.getValue());
                        Main.game.setContent(new Response("", "", Main.game.getCurrentDialogueNode()));
                    }, false);
                }
            }
            for (PenisModifier orificeMod : PenisModifier.values()) {
                id = "CHANGE_PENIS_MOD_" + orificeMod;
                if (((EventTarget) document.getElementById(id)) != null) {
                    ((EventTarget) document.getElementById(id)).addEventListener("click", e -> {
                        if (BodyChanging.getTarget().hasPenisModifier(orificeMod)) {
                            BodyChanging.getTarget().removePenisModifier(orificeMod);
                        } else {
                            BodyChanging.getTarget().addPenisModifier(orificeMod);
                        }
                        Main.game.setContent(new Response("", "", Main.game.getCurrentDialogueNode()));
                    }, false);
                }
            }
            for (OrificeModifier orificeMod : OrificeModifier.values()) {
                id = "CHANGE_URETHRA_MOD_" + orificeMod;
                if (((EventTarget) document.getElementById(id)) != null) {
                    ((EventTarget) document.getElementById(id)).addEventListener("click", e -> {
                        if (BodyChanging.getTarget().hasUrethraOrificeModifier(orificeMod)) {
                            BodyChanging.getTarget().removeUrethraOrificeModifier(orificeMod);
                        } else {
                            BodyChanging.getTarget().addUrethraOrificeModifier(orificeMod);
                        }
                        Main.game.setContent(new Response("", "", Main.game.getCurrentDialogueNode()));
                    }, false);
                }
            }
        }
        // -------------------- Cosmetics -------------------- //
        boolean noCost = !Main.game.isInNewWorld() || Main.game.getCurrentDialogueNode().getMapDisplay() == MapDisplay.PHONE;
        for (BodyCoveringType bct : BodyCoveringType.values()) {
            id = "APPLY_COVERING_" + bct;
            if (((EventTarget) document.getElementById(id)) != null) {
                ((EventTarget) document.getElementById(id)).addEventListener("click", e -> {
                    if (Main.game.getPlayer().getMoney() >= SuccubisSecrets.getBodyCoveringTypeCost(bct) || noCost) {
                        Main.game.setContent(new Response("", "", Main.game.getCurrentDialogueNode()) {

                            @Override
                            public void effects() {
                                if (CharacterModificationUtils.getCoveringsToBeApplied().containsKey(bct)) {
                                    if (!noCost) {
                                        Main.game.getPlayer().incrementMoney(-SuccubisSecrets.getBodyCoveringTypeCost(bct));
                                    }
                                    BodyChanging.getTarget().setSkinCovering(new Covering(CharacterModificationUtils.getCoveringsToBeApplied().get(bct)), false);
                                    if (noCost) {
                                        if (bct == BodyCoveringType.HUMAN) {
                                            BodyChanging.getTarget().getBody().updateCoverings(false, false, false, true);
                                        }
                                    }
                                }
                            }
                        });
                    }
                }, false);
            }
            id = bct + "_PRIMARY_GLOW_OFF";
            if (((EventTarget) document.getElementById(id)) != null) {
                ((EventTarget) document.getElementById(id)).addEventListener("click", e -> {
                    Main.game.setContent(new Response("", "", Main.game.getCurrentDialogueNode()) {

                        @Override
                        public void effects() {
                            CharacterModificationUtils.getCoveringsToBeApplied().putIfAbsent(bct, new Covering(BodyChanging.getTarget().getCovering(bct)));
                            CharacterModificationUtils.getCoveringsToBeApplied().get(bct).setPrimaryGlowing(false);
                        }
                    });
                }, false);
            }
            id = bct + "_PRIMARY_GLOW_ON";
            if (((EventTarget) document.getElementById(id)) != null) {
                ((EventTarget) document.getElementById(id)).addEventListener("click", e -> {
                    Main.game.setContent(new Response("", "", Main.game.getCurrentDialogueNode()) {

                        @Override
                        public void effects() {
                            CharacterModificationUtils.getCoveringsToBeApplied().putIfAbsent(bct, new Covering(BodyChanging.getTarget().getCovering(bct)));
                            CharacterModificationUtils.getCoveringsToBeApplied().get(bct).setPrimaryGlowing(true);
                        }
                    });
                }, false);
            }
            id = bct + "_SECONDARY_GLOW_OFF";
            if (((EventTarget) document.getElementById(id)) != null) {
                ((EventTarget) document.getElementById(id)).addEventListener("click", e -> {
                    Main.game.setContent(new Response("", "", Main.game.getCurrentDialogueNode()) {

                        @Override
                        public void effects() {
                            CharacterModificationUtils.getCoveringsToBeApplied().putIfAbsent(bct, new Covering(BodyChanging.getTarget().getCovering(bct)));
                            CharacterModificationUtils.getCoveringsToBeApplied().get(bct).setSecondaryGlowing(false);
                        }
                    });
                }, false);
            }
            id = bct + "_SECONDARY_GLOW_ON";
            if (((EventTarget) document.getElementById(id)) != null) {
                ((EventTarget) document.getElementById(id)).addEventListener("click", e -> {
                    Main.game.setContent(new Response("", "", Main.game.getCurrentDialogueNode()) {

                        @Override
                        public void effects() {
                            CharacterModificationUtils.getCoveringsToBeApplied().putIfAbsent(bct, new Covering(BodyChanging.getTarget().getCovering(bct)));
                            CharacterModificationUtils.getCoveringsToBeApplied().get(bct).setSecondaryGlowing(true);
                        }
                    });
                }, false);
            }
            for (CoveringPattern pattern : CoveringPattern.values()) {
                id = bct + "_PATTERN_" + pattern;
                if (((EventTarget) document.getElementById(id)) != null) {
                    ((EventTarget) document.getElementById(id)).addEventListener("click", e -> {
                        Main.game.setContent(new Response("", "", Main.game.getCurrentDialogueNode()) {

                            @Override
                            public void effects() {
                                CharacterModificationUtils.getCoveringsToBeApplied().putIfAbsent(bct, new Covering(BodyChanging.getTarget().getCovering(bct)));
                                CharacterModificationUtils.getCoveringsToBeApplied().get(bct).setPattern(pattern);
                            }
                        });
                    }, false);
                }
            }
            for (CoveringModifier modifier : CoveringModifier.values()) {
                id = bct + "_MODIFIER_" + modifier;
                if (((EventTarget) document.getElementById(id)) != null) {
                    ((EventTarget) document.getElementById(id)).addEventListener("click", e -> {
                        Main.game.setContent(new Response("", "", Main.game.getCurrentDialogueNode()) {

                            @Override
                            public void effects() {
                                CharacterModificationUtils.getCoveringsToBeApplied().putIfAbsent(bct, new Covering(BodyChanging.getTarget().getCovering(bct)));
                                CharacterModificationUtils.getCoveringsToBeApplied().get(bct).setModifier(modifier);
                            }
                        });
                    }, false);
                }
            }
            for (Colour colour : bct.getAllPrimaryColours()) {
                id = bct + "_PRIMARY_" + colour;
                if (((EventTarget) document.getElementById(id)) != null) {
                    ((EventTarget) document.getElementById(id)).addEventListener("click", e -> {
                        Main.game.setContent(new Response("", "", Main.game.getCurrentDialogueNode()) {

                            @Override
                            public void effects() {
                                CharacterModificationUtils.getCoveringsToBeApplied().putIfAbsent(bct, new Covering(BodyChanging.getTarget().getCovering(bct)));
                                CharacterModificationUtils.getCoveringsToBeApplied().get(bct).setPrimaryColour(colour);
                                CharacterModificationUtils.getCoveringsToBeApplied().get(bct).setPrimaryGlowing((colour != Colour.COVERING_NONE && BodyChanging.getTarget().getCovering(bct).isPrimaryGlowing()));
                            }
                        });
                    }, false);
                }
            }
            for (Colour colour : bct.getAllSecondaryColours()) {
                id = bct + "_SECONDARY_" + colour;
                if (((EventTarget) document.getElementById(id)) != null) {
                    ((EventTarget) document.getElementById(id)).addEventListener("click", e -> {
                        Main.game.setContent(new Response("", "", Main.game.getCurrentDialogueNode()) {

                            @Override
                            public void effects() {
                                CharacterModificationUtils.getCoveringsToBeApplied().putIfAbsent(bct, new Covering(BodyChanging.getTarget().getCovering(bct)));
                                CharacterModificationUtils.getCoveringsToBeApplied().get(bct).setSecondaryColour(colour);
                                CharacterModificationUtils.getCoveringsToBeApplied().get(bct).setSecondaryGlowing(colour != Colour.COVERING_NONE && BodyChanging.getTarget().getCovering(bct).isSecondaryGlowing());
                            }
                        });
                    }, false);
                }
            }
        }
        for (HairLength hairLength : HairLength.values()) {
            id = "HAIR_LENGTH_" + hairLength;
            if (((EventTarget) document.getElementById(id)) != null) {
                ((EventTarget) document.getElementById(id)).addEventListener("click", e -> {
                    if (Main.game.getPlayer().getMoney() >= SuccubisSecrets.BASE_HAIR_LENGTH_COST || noCost) {
                        Main.game.setContent(new Response("", "", Main.game.getCurrentDialogueNode()) {

                            @Override
                            public void effects() {
                                if (!noCost) {
                                    Main.game.getPlayer().incrementMoney(-SuccubisSecrets.BASE_HAIR_LENGTH_COST);
                                }
                                BodyChanging.getTarget().setHairLength(hairLength.getMedianValue());
                            }
                        });
                    }
                }, false);
            }
        }
        for (HairStyle hairStyle : HairStyle.values()) {
            id = "HAIR_STYLE_" + hairStyle;
            if (((EventTarget) document.getElementById(id)) != null) {
                ((EventTarget) document.getElementById(id)).addEventListener("click", e -> {
                    if (Main.game.getPlayer().getMoney() >= SuccubisSecrets.BASE_HAIR_STYLE_COST || noCost) {
                        Main.game.setContent(new Response("", "", Main.game.getCurrentDialogueNode()) {

                            @Override
                            public void effects() {
                                if (!noCost) {
                                    Main.game.getPlayer().incrementMoney(-SuccubisSecrets.BASE_HAIR_STYLE_COST);
                                }
                                BodyChanging.getTarget().setHairStyle(hairStyle);
                            }
                        });
                    }
                }, false);
            }
        }
        for (PiercingType piercingType : PiercingType.values()) {
            id = piercingType + "_PIERCE_REMOVE";
            if (((EventTarget) document.getElementById(id)) != null) {
                ((EventTarget) document.getElementById(id)).addEventListener("click", e -> {
                    if (Main.game.getPlayer().getMoney() >= SuccubisSecrets.getPiercingCost(piercingType) || noCost) {
                        Main.game.setContent(new Response("", "", Main.game.getCurrentDialogueNode()) {

                            @Override
                            public void effects() {
                                if (!noCost) {
                                    Main.game.getPlayer().incrementMoney(-SuccubisSecrets.getPiercingCost(piercingType));
                                }
                                switch(piercingType) {
                                    case EAR:
                                        BodyChanging.getTarget().setPiercedEar(false);
                                        break;
                                    case LIP:
                                        BodyChanging.getTarget().setPiercedLip(false);
                                        break;
                                    case NAVEL:
                                        BodyChanging.getTarget().setPiercedNavel(false);
                                        break;
                                    case NIPPLE:
                                        BodyChanging.getTarget().setPiercedNipples(false);
                                        break;
                                    case NOSE:
                                        BodyChanging.getTarget().setPiercedNose(false);
                                        break;
                                    case PENIS:
                                        BodyChanging.getTarget().setPiercedPenis(false);
                                        break;
                                    case TONGUE:
                                        BodyChanging.getTarget().setPiercedTongue(false);
                                        break;
                                    case VAGINA:
                                        BodyChanging.getTarget().setPiercedVagina(false);
                                        break;
                                }
                            }
                        });
                    }
                }, false);
            }
            id = piercingType + "_PIERCE";
            if (((EventTarget) document.getElementById(id)) != null) {
                ((EventTarget) document.getElementById(id)).addEventListener("click", e -> {
                    if (Main.game.getPlayer().getMoney() >= SuccubisSecrets.getPiercingCost(piercingType) || noCost) {
                        Main.game.setContent(new Response("", "", Main.game.getCurrentDialogueNode()) {

                            @Override
                            public void effects() {
                                if (!noCost) {
                                    Main.game.getPlayer().incrementMoney(-SuccubisSecrets.getPiercingCost(piercingType));
                                }
                                switch(piercingType) {
                                    case EAR:
                                        BodyChanging.getTarget().setPiercedEar(true);
                                        break;
                                    case LIP:
                                        BodyChanging.getTarget().setPiercedLip(true);
                                        break;
                                    case NAVEL:
                                        BodyChanging.getTarget().setPiercedNavel(true);
                                        break;
                                    case NIPPLE:
                                        BodyChanging.getTarget().setPiercedNipples(true);
                                        break;
                                    case NOSE:
                                        BodyChanging.getTarget().setPiercedNose(true);
                                        break;
                                    case PENIS:
                                        BodyChanging.getTarget().setPiercedPenis(true);
                                        break;
                                    case TONGUE:
                                        BodyChanging.getTarget().setPiercedTongue(true);
                                        break;
                                    case VAGINA:
                                        BodyChanging.getTarget().setPiercedVagina(true);
                                        break;
                                }
                            }
                        });
                    }
                }, false);
            }
        }
        if (((EventTarget) document.getElementById("BLEACHING_OFF")) != null) {
            ((EventTarget) document.getElementById("BLEACHING_OFF")).addEventListener("click", e -> {
                if (Main.game.getPlayer().getMoney() >= SuccubisSecrets.BASE_ANAL_BLEACHING_COST || noCost) {
                    Main.game.setContent(new Response("", "", Main.game.getCurrentDialogueNode()) {

                        @Override
                        public void effects() {
                            if (!noCost) {
                                Main.game.getPlayer().incrementMoney(-SuccubisSecrets.BASE_ANAL_BLEACHING_COST);
                            }
                            BodyChanging.getTarget().setAssBleached(false);
                        }
                    });
                }
            }, false);
        }
        if (((EventTarget) document.getElementById("BLEACHING_ON")) != null) {
            ((EventTarget) document.getElementById("BLEACHING_ON")).addEventListener("click", e -> {
                if (Main.game.getPlayer().getMoney() >= SuccubisSecrets.BASE_ANAL_BLEACHING_COST || noCost) {
                    Main.game.setContent(new Response("", "", Main.game.getCurrentDialogueNode()) {

                        @Override
                        public void effects() {
                            if (!noCost) {
                                Main.game.getPlayer().incrementMoney(-SuccubisSecrets.BASE_ANAL_BLEACHING_COST);
                            }
                            BodyChanging.getTarget().setAssBleached(true);
                        }
                    });
                }
            }, false);
        }
        for (BodyHair bodyHair : BodyHair.values()) {
            id = "ASS_HAIR_" + bodyHair;
            if (((EventTarget) document.getElementById(id)) != null) {
                ((EventTarget) document.getElementById(id)).addEventListener("click", e -> {
                    if (Main.game.getPlayer().getMoney() >= SuccubisSecrets.BASE_BODY_HAIR_COST || noCost) {
                        Main.game.setContent(new Response("", "", Main.game.getCurrentDialogueNode()) {

                            @Override
                            public void effects() {
                                if (!noCost) {
                                    Main.game.getPlayer().incrementMoney(-SuccubisSecrets.BASE_BODY_HAIR_COST);
                                }
                                BodyChanging.getTarget().setAssHair(bodyHair);
                            }
                        });
                    }
                }, false);
            }
            id = "UNDERARM_HAIR_" + bodyHair;
            if (((EventTarget) document.getElementById(id)) != null) {
                ((EventTarget) document.getElementById(id)).addEventListener("click", e -> {
                    if (Main.game.getPlayer().getMoney() >= SuccubisSecrets.BASE_BODY_HAIR_COST || noCost) {
                        Main.game.setContent(new Response("", "", Main.game.getCurrentDialogueNode()) {

                            @Override
                            public void effects() {
                                if (!noCost) {
                                    Main.game.getPlayer().incrementMoney(-SuccubisSecrets.BASE_BODY_HAIR_COST);
                                }
                                BodyChanging.getTarget().setUnderarmHair(bodyHair);
                            }
                        });
                    }
                }, false);
            }
            id = "PUBIC_HAIR_" + bodyHair;
            if (((EventTarget) document.getElementById(id)) != null) {
                ((EventTarget) document.getElementById(id)).addEventListener("click", e -> {
                    if (Main.game.getPlayer().getMoney() >= SuccubisSecrets.BASE_BODY_HAIR_COST || noCost) {
                        Main.game.setContent(new Response("", "", Main.game.getCurrentDialogueNode()) {

                            @Override
                            public void effects() {
                                if (!noCost) {
                                    Main.game.getPlayer().incrementMoney(-SuccubisSecrets.BASE_BODY_HAIR_COST);
                                }
                                BodyChanging.getTarget().setPubicHair(bodyHair);
                            }
                        });
                    }
                }, false);
            }
            id = "FACIAL_HAIR_" + bodyHair;
            if (((EventTarget) document.getElementById(id)) != null) {
                ((EventTarget) document.getElementById(id)).addEventListener("click", e -> {
                    if (Main.game.getPlayer().getMoney() >= SuccubisSecrets.BASE_BODY_HAIR_COST || noCost) {
                        Main.game.setContent(new Response("", "", Main.game.getCurrentDialogueNode()) {

                            @Override
                            public void effects() {
                                if (!noCost) {
                                    Main.game.getPlayer().incrementMoney(-SuccubisSecrets.BASE_BODY_HAIR_COST);
                                }
                                BodyChanging.getTarget().setFacialHair(bodyHair);
                            }
                        });
                    }
                }, false);
            }
        }
        // Phone item viewer:
        for (AbstractClothingType clothing : ClothingType.getAllClothing()) {
            for (Colour c : clothing.getAllAvailablePrimaryColours()) {
                id = "PRIMARY_" + clothing.hashCode() + "_" + c.toString();
                if ((EventTarget) document.getElementById(id) != null) {
                    ((EventTarget) document.getElementById(id)).addEventListener("click", e -> {
                        InventoryDialogue.dyePreviewPrimary = c;
                        Main.game.setContent(new Response("", "", Main.game.getCurrentDialogueNode()));
                    }, false);
                    addEventListener(document, id, "mousemove", moveTooltipListener, false);
                    addEventListener(document, id, "mouseleave", hideTooltipListener, false);
                    InventoryTooltipEventListener el2 = new InventoryTooltipEventListener().setDyeClothingPrimary(InventoryDialogue.getClothing(), c);
                    addEventListener(document, id, "mouseenter", el2, false);
                }
            }
            if (!clothing.getAllAvailableSecondaryColours().isEmpty()) {
                for (Colour c : clothing.getAllAvailableSecondaryColours()) {
                    id = "SECONDARY_" + clothing.hashCode() + "_" + c.toString();
                    if ((EventTarget) document.getElementById(id) != null) {
                        ((EventTarget) document.getElementById(id)).addEventListener("click", e -> {
                            InventoryDialogue.dyePreviewSecondary = c;
                            Main.game.setContent(new Response("", "", Main.game.getCurrentDialogueNode()));
                        }, false);
                        addEventListener(document, id, "mousemove", moveTooltipListener, false);
                        addEventListener(document, id, "mouseleave", hideTooltipListener, false);
                        InventoryTooltipEventListener el2 = new InventoryTooltipEventListener().setDyeClothingSecondary(InventoryDialogue.getClothing(), c);
                        addEventListener(document, id, "mouseenter", el2, false);
                    }
                }
            }
            if (!clothing.getAllAvailableTertiaryColours().isEmpty()) {
                for (Colour c : clothing.getAllAvailableTertiaryColours()) {
                    id = "TERTIARY_" + clothing.hashCode() + "_" + c.toString();
                    if ((EventTarget) document.getElementById(id) != null) {
                        ((EventTarget) document.getElementById(id)).addEventListener("click", e -> {
                            InventoryDialogue.dyePreviewTertiary = c;
                            Main.game.setContent(new Response("", "", Main.game.getCurrentDialogueNode()));
                        }, false);
                        addEventListener(document, id, "mousemove", moveTooltipListener, false);
                        addEventListener(document, id, "mouseleave", hideTooltipListener, false);
                        InventoryTooltipEventListener el2 = new InventoryTooltipEventListener().setDyeClothingTertiary(InventoryDialogue.getClothing(), c);
                        addEventListener(document, id, "mouseenter", el2, false);
                    }
                }
            }
        }
        for (AbstractClothingType clothing : ClothingType.getAllClothing()) {
            for (Colour colour : clothing.getAllAvailablePrimaryColours()) {
                if ((EventTarget) document.getElementById(clothing.hashCode() + "_" + colour.toString()) != null) {
                    addEventListener(document, clothing.hashCode() + "_" + colour.toString(), "mousemove", moveTooltipListener, false);
                    addEventListener(document, clothing.hashCode() + "_" + colour.toString(), "mouseleave", hideTooltipListener, false);
                    InventoryTooltipEventListener el2 = new InventoryTooltipEventListener().setGenericClothing(clothing, colour);
                    addEventListener(document, clothing.hashCode() + "_" + colour.toString(), "mouseenter", el2, false);
                }
            }
        }
        for (AbstractWeaponType weapon : WeaponType.allweapons) {
            for (DamageType dt : weapon.getAvailableDamageTypes()) {
                if ((EventTarget) document.getElementById(weapon.hashCode() + "_" + dt.toString()) != null) {
                    addEventListener(document, weapon.hashCode() + "_" + dt.toString(), "mousemove", moveTooltipListener, false);
                    addEventListener(document, weapon.hashCode() + "_" + dt.toString(), "mouseleave", hideTooltipListener, false);
                    InventoryTooltipEventListener el2 = new InventoryTooltipEventListener().setGenericWeapon(weapon, dt);
                    addEventListener(document, weapon.hashCode() + "_" + dt.toString(), "mouseenter", el2, false);
                }
            }
        }
        for (Perk perk : Perk.values()) {
            // TODO
            if (perk.getPerkCategory() == PerkCategory.JOB) {
                id = "HISTORY_" + perk;
                if (((EventTarget) document.getElementById(id)) != null) {
                    addEventListener(document, id, "mousemove", moveTooltipListener, false);
                    addEventListener(document, id, "mouseleave", hideTooltipListener, false);
                    addEventListener(document, id, "mouseenter", new TooltipInformationEventListener().setLevelUpPerk(0, perk, Main.game.getPlayer()), false);
                }
            } else {
                id = "TRAIT_" + perk;
                if (((EventTarget) document.getElementById(id)) != null) {
                    addEventListener(document, id, "mousemove", moveTooltipListener, false);
                    addEventListener(document, id, "mouseleave", hideTooltipListener, false);
                    addEventListener(document, id, "mouseenter", new TooltipInformationEventListener().setLevelUpPerk(PerkManager.MANAGER.getPerkRow(perk), perk, Main.game.getPlayer()), false);
                    ((EventTarget) document.getElementById(id)).addEventListener("click", event -> {
                        Main.game.getPlayer().removeTrait(perk);
                        Main.game.setContent(new Response("", "", Main.game.getCurrentDialogueNode()));
                    }, false);
                }
            }
        }
        // Level up dialogue:
        if (Main.game.getCurrentDialogueNode() == PhoneDialogue.CHARACTER_LEVEL_UP) {
            for (int i = 0; i < PerkManager.ROWS; i++) {
                for (Entry<PerkCategory, List<PerkEntry>> entry : PerkManager.MANAGER.getPerkTree().get(i).entrySet()) {
                    for (PerkEntry e : entry.getValue()) {
                        id = i + "_" + e.getPerk();
                        if (((EventTarget) document.getElementById(id)) != null) {
                            addEventListener(document, id, "mousemove", moveTooltipListener, false);
                            addEventListener(document, id, "mouseleave", hideTooltipListener, false);
                            addEventListener(document, id, "mouseenter", new TooltipInformationEventListener().setLevelUpPerk(i, e.getPerk(), Main.game.getPlayer()), false);
                            ((EventTarget) document.getElementById(id)).addEventListener("click", event -> {
                                if (e.getPerk().isMajor() && PerkManager.MANAGER.isPerkOwned(e)) {
                                    if (!Main.game.getPlayer().hasTraitActivated(e.getPerk())) {
                                        Main.game.getPlayer().addTrait(e.getPerk());
                                    } else {
                                        Main.game.getPlayer().removeTrait(e.getPerk());
                                    }
                                    Main.game.setContent(new Response("", "", Main.game.getCurrentDialogueNode()));
                                } else if (Main.game.getPlayer().getPerkPoints() >= 1 && PerkManager.MANAGER.isPerkAvailable(e)) {
                                    if (Main.game.getPlayer().addPerk(e.getRow(), e.getPerk())) {
                                        Main.game.getPlayer().incrementPerkPoints(-1);
                                        if (e.getPerk().isMajor() && Main.game.getPlayer().getTraits().size() < GameCharacter.MAX_TRAITS) {
                                            Main.game.getPlayer().addTrait(e.getPerk());
                                        }
                                        Main.game.setContent(new Response("", "", Main.game.getCurrentDialogueNode()));
                                    }
                                }
                            }, false);
                        }
                    }
                }
            }
        }
        if (Main.game.getCurrentDialogueNode() == PhoneDialogue.CHARACTER_FETISHES) {
            for (Fetish f : Fetish.values()) {
                id = "fetishUnlock" + f;
                if (((EventTarget) document.getElementById(id)) != null) {
                    ((EventTarget) document.getElementById(id)).addEventListener("click", e -> {
                        if (Main.game.getPlayer().getEssenceCount(TFEssence.ARCANE) >= f.getCost()) {
                            if (Main.game.getPlayer().addFetish(f)) {
                                Main.game.getPlayer().incrementEssenceCount(TFEssence.ARCANE, -f.getCost());
                                Main.game.setContent(new Response("", "", Main.game.getCurrentDialogueNode()));
                            }
                        }
                    }, false);
                    addEventListener(document, id, "mousemove", moveTooltipListener, false);
                    addEventListener(document, id, "mouseleave", hideTooltipListener, false);
                    addEventListener(document, id, "mouseenter", new TooltipInformationEventListener().setFetish(f, Main.game.getPlayer()), false);
                }
                id = f + "_EXPERIENCE";
                if (((EventTarget) document.getElementById(id)) != null) {
                    addEventListener(document, id, "mousemove", moveTooltipListener, false);
                    addEventListener(document, id, "mouseleave", hideTooltipListener, false);
                    addEventListener(document, id, "mouseenter", new TooltipInformationEventListener().setFetishExperience(f, Main.game.getPlayer()), false);
                }
                for (FetishDesire desire : FetishDesire.values()) {
                    id = f + "_" + desire;
                    if (((EventTarget) document.getElementById(id)) != null) {
                        ((EventTarget) document.getElementById(id)).addEventListener("click", e -> {
                            if (Main.game.getPlayer().getEssenceCount(TFEssence.ARCANE) >= FetishDesire.getCostToChange()) {
                                if (Main.game.getPlayer().setFetishDesire(f, desire)) {
                                    Main.game.getPlayer().incrementEssenceCount(TFEssence.ARCANE, -FetishDesire.getCostToChange());
                                    Main.game.setContent(new Response("", "", Main.game.getCurrentDialogueNode()));
                                }
                            }
                        }, false);
                        addEventListener(document, id, "mousemove", moveTooltipListener, false);
                        addEventListener(document, id, "mouseleave", hideTooltipListener, false);
                        addEventListener(document, id, "mouseenter", new TooltipInformationEventListener().setFetishDesire(f, desire, Main.game.getPlayer()), false);
                    }
                }
            }
        }
    }
    // Hotkey bindings:
    if (Main.game.getCurrentDialogueNode() == OptionsDialogue.KEYBINDS) {
        for (KeyboardAction ka : KeyboardAction.values()) {
            if (((EventTarget) document.getElementById("primary_" + ka)) != null)
                ((EventTarget) document.getElementById("primary_" + ka)).addEventListener("click", e -> {
                    actionToBind = ka;
                    primaryBinding = true;
                    Main.game.setContent(new Response("", "", Main.game.getCurrentDialogueNode()));
                }, false);
            if (((EventTarget) document.getElementById("primaryClear_" + ka)) != null)
                ((EventTarget) document.getElementById("primaryClear_" + ka)).addEventListener("click", e -> {
                    Main.getProperties().hotkeyMapPrimary.put(ka, null);
                    Main.saveProperties();
                    Main.game.setContent(new Response("", "", Main.game.getCurrentDialogueNode()));
                }, false);
            if (((EventTarget) document.getElementById("secondary_" + ka)) != null)
                ((EventTarget) document.getElementById("secondary_" + ka)).addEventListener("click", e -> {
                    actionToBind = ka;
                    primaryBinding = false;
                    Main.game.setContent(new Response("", "", Main.game.getCurrentDialogueNode()));
                }, false);
            if (((EventTarget) document.getElementById("secondaryClear_" + ka)) != null)
                ((EventTarget) document.getElementById("secondaryClear_" + ka)).addEventListener("click", e -> {
                    Main.getProperties().hotkeyMapSecondary.put(ka, null);
                    Main.saveProperties();
                    Main.game.setContent(new Response("", "", Main.game.getCurrentDialogueNode()));
                }, false);
        }
    }
    // Gender preferences:
    if (Main.game.getCurrentDialogueNode() == OptionsDialogue.GENDER_PREFERENCE) {
        for (Gender g : Gender.values()) {
            for (GenderPreference preference : GenderPreference.values()) {
                if (((EventTarget) document.getElementById(preference + "_" + g)) != null) {
                    ((EventTarget) document.getElementById(preference + "_" + g)).addEventListener("click", e -> {
                        Main.getProperties().genderPreferencesMap.put(g, preference.getValue());
                        Main.saveProperties();
                        Main.game.setContent(new Response("", "", Main.game.getCurrentDialogueNode()));
                    }, false);
                }
            }
        }
    }
    // Furry preferences:
    if (Main.game.getCurrentDialogueNode() == OptionsDialogue.FURRY_PREFERENCE) {
        // Human encounter rates:
        if (((EventTarget) document.getElementById("furry_preference_human_encounter_zero")) != null) {
            ((EventTarget) document.getElementById("furry_preference_human_encounter_zero")).addEventListener("click", e -> {
                Main.getProperties().humanEncountersLevel = 0;
                Main.saveProperties();
                Main.game.setContent(new Response("", "", Main.game.getCurrentDialogueNode()));
            }, false);
            addEventListener(document, "furry_preference_human_encounter_zero", "mousemove", moveTooltipListener, false);
            addEventListener(document, "furry_preference_human_encounter_zero", "mouseleave", hideTooltipListener, false);
            TooltipInformationEventListener el = new TooltipInformationEventListener().setInformation("Disabled", "Randomly generated NPCs will never be fully human, unless all of the other furry preference options are set to disabled.");
            addEventListener(document, "furry_preference_human_encounter_zero", "mouseenter", el, false);
        }
        if (((EventTarget) document.getElementById("furry_preference_human_encounter_one")) != null) {
            ((EventTarget) document.getElementById("furry_preference_human_encounter_one")).addEventListener("click", e -> {
                Main.getProperties().humanEncountersLevel = 1;
                Main.saveProperties();
                Main.game.setContent(new Response("", "", Main.game.getCurrentDialogueNode()));
            }, false);
            addEventListener(document, "furry_preference_human_encounter_one", "mousemove", moveTooltipListener, false);
            addEventListener(document, "furry_preference_human_encounter_one", "mouseleave", hideTooltipListener, false);
            TooltipInformationEventListener el = new TooltipInformationEventListener().setInformation("5%", "There will be a 5% chance for any randomly generated NPC to be fully human. (It will be 100% if all of the other furry preference options are set to disabled)");
            addEventListener(document, "furry_preference_human_encounter_one", "mouseenter", el, false);
        }
        if (((EventTarget) document.getElementById("furry_preference_human_encounter_two")) != null) {
            ((EventTarget) document.getElementById("furry_preference_human_encounter_two")).addEventListener("click", e -> {
                Main.getProperties().humanEncountersLevel = 2;
                Main.saveProperties();
                Main.game.setContent(new Response("", "", Main.game.getCurrentDialogueNode()));
            }, false);
            addEventListener(document, "furry_preference_human_encounter_two", "mousemove", moveTooltipListener, false);
            addEventListener(document, "furry_preference_human_encounter_two", "mouseleave", hideTooltipListener, false);
            TooltipInformationEventListener el = new TooltipInformationEventListener().setInformation("25%", "There will be a 25% chance for any randomly generated NPC to be fully human. (It will be 100% if all of the other furry preference options are set to disabled)");
            addEventListener(document, "furry_preference_human_encounter_two", "mouseenter", el, false);
        }
        if (((EventTarget) document.getElementById("furry_preference_human_encounter_three")) != null) {
            ((EventTarget) document.getElementById("furry_preference_human_encounter_three")).addEventListener("click", e -> {
                Main.getProperties().humanEncountersLevel = 3;
                Main.saveProperties();
                Main.game.setContent(new Response("", "", Main.game.getCurrentDialogueNode()));
            }, false);
            addEventListener(document, "furry_preference_human_encounter_three", "mousemove", moveTooltipListener, false);
            addEventListener(document, "furry_preference_human_encounter_three", "mouseleave", hideTooltipListener, false);
            TooltipInformationEventListener el = new TooltipInformationEventListener().setInformation("50%", "There will be a 50% chance for any randomly generated NPC to be fully human. (It will be 100% if all of the other furry preference options are set to disabled)");
            addEventListener(document, "furry_preference_human_encounter_three", "mouseenter", el, false);
        }
        if (((EventTarget) document.getElementById("furry_preference_human_encounter_four")) != null) {
            ((EventTarget) document.getElementById("furry_preference_human_encounter_four")).addEventListener("click", e -> {
                Main.getProperties().humanEncountersLevel = 4;
                Main.saveProperties();
                Main.game.setContent(new Response("", "", Main.game.getCurrentDialogueNode()));
            }, false);
            addEventListener(document, "furry_preference_human_encounter_four", "mousemove", moveTooltipListener, false);
            addEventListener(document, "furry_preference_human_encounter_four", "mouseleave", hideTooltipListener, false);
            TooltipInformationEventListener el = new TooltipInformationEventListener().setInformation("75%", "There will be a 75% chance for any randomly generated NPC to be fully human. (It will be 100% if all of the other furry preference options are set to disabled)");
            addEventListener(document, "furry_preference_human_encounter_four", "mouseenter", el, false);
        }
        // Forced TF racial limits:
        id = "forced_tf_limit_human";
        if (((EventTarget) document.getElementById(id)) != null) {
            ((EventTarget) document.getElementById(id)).addEventListener("click", e -> {
                Main.getProperties().forcedTFPreference = FurryPreference.HUMAN;
                Main.saveProperties();
                Main.game.setContent(new Response("", "", Main.game.getCurrentDialogueNode()));
            }, false);
            addEventListener(document, id, "mousemove", moveTooltipListener, false);
            addEventListener(document, id, "mouseleave", hideTooltipListener, false);
            TooltipInformationEventListener el = new TooltipInformationEventListener().setInformation("Human Only", "Forced transformations from NPCs will only ever affect your body's non-racial stats, and if a new part is required (such as a vagina or penis) it will always grow to be a human one.");
            addEventListener(document, id, "mouseenter", el, false);
        }
        id = "forced_tf_limit_minimum";
        if (((EventTarget) document.getElementById(id)) != null) {
            ((EventTarget) document.getElementById(id)).addEventListener("click", e -> {
                Main.getProperties().forcedTFPreference = FurryPreference.MINIMUM;
                Main.saveProperties();
                Main.game.setContent(new Response("", "", Main.game.getCurrentDialogueNode()));
            }, false);
            addEventListener(document, id, "mousemove", moveTooltipListener, false);
            addEventListener(document, id, "mouseleave", hideTooltipListener, false);
            TooltipInformationEventListener el = new TooltipInformationEventListener().setInformation("Minimum Furry", "Forced transformations from NPCs will have the chance to give you non-human hair, ears, eyes, tails, horns, antenna, and wings. All other parts will always remain human.");
            addEventListener(document, id, "mouseenter", el, false);
        }
        id = "forced_tf_limit_reduced";
        if (((EventTarget) document.getElementById(id)) != null) {
            ((EventTarget) document.getElementById(id)).addEventListener("click", e -> {
                Main.getProperties().forcedTFPreference = FurryPreference.REDUCED;
                Main.saveProperties();
                Main.game.setContent(new Response("", "", Main.game.getCurrentDialogueNode()));
            }, false);
            addEventListener(document, id, "mousemove", moveTooltipListener, false);
            addEventListener(document, id, "mouseleave", hideTooltipListener, false);
            TooltipInformationEventListener el = new TooltipInformationEventListener().setInformation("Lesser Furry", "Forced transformations from NPCs will have the chance to give you non-human hair, ears, eyes, tails, horns, antenna, wings, breasts, ass, genitalia, arms, and legs. Your skin and face will always remain human.");
            addEventListener(document, id, "mouseenter", el, false);
        }
        id = "forced_tf_limit_normal";
        if (((EventTarget) document.getElementById(id)) != null) {
            ((EventTarget) document.getElementById(id)).addEventListener("click", e -> {
                Main.getProperties().forcedTFPreference = FurryPreference.NORMAL;
                Main.saveProperties();
                Main.game.setContent(new Response("", "", Main.game.getCurrentDialogueNode()));
            }, false);
            addEventListener(document, id, "mousemove", moveTooltipListener, false);
            addEventListener(document, id, "mouseleave", hideTooltipListener, false);
            TooltipInformationEventListener el = new TooltipInformationEventListener().setInformation("Greater Furry", "Forced transformations from NPCs will have the chance to give you non-human hair, ears, eyes, tails, horns, antenna, wings, breasts, ass, genitalia, arms, legs, skin, and face. (So everything can be affected.)");
            addEventListener(document, id, "mouseenter", el, false);
        }
        id = "forced_tf_limit_maximum";
        if (((EventTarget) document.getElementById(id)) != null) {
            ((EventTarget) document.getElementById(id)).addEventListener("click", e -> {
                Main.getProperties().forcedTFPreference = FurryPreference.MAXIMUM;
                Main.saveProperties();
                Main.game.setContent(new Response("", "", Main.game.getCurrentDialogueNode()));
            }, false);
            addEventListener(document, id, "mousemove", moveTooltipListener, false);
            addEventListener(document, id, "mouseleave", hideTooltipListener, false);
            TooltipInformationEventListener el = new TooltipInformationEventListener().setInformation("Always Greater Furry", "Forced transformations from NPCs will always give you non-human hair, ears, eyes, tails, horns, antenna, wings, breasts, genitalia, ass, arms, legs, skin, and face. (So everything will be affected.)");
            addEventListener(document, id, "mouseenter", el, false);
        }
        // Multi-breast options:
        if (((EventTarget) document.getElementById("furry_preference_multi_breast_zero")) != null) {
            ((EventTarget) document.getElementById("furry_preference_multi_breast_zero")).addEventListener("click", e -> {
                Main.getProperties().multiBreasts = 0;
                Main.saveProperties();
                Main.game.setContent(new Response("", "", Main.game.getCurrentDialogueNode()));
            }, false);
            addEventListener(document, "furry_preference_multi_breast_zero", "mousemove", moveTooltipListener, false);
            addEventListener(document, "furry_preference_multi_breast_zero", "mouseleave", hideTooltipListener, false);
            TooltipInformationEventListener el = new TooltipInformationEventListener().setInformation("Off", "Randomly-generated NPCs will never spawn in with multiple rows of breasts.");
            addEventListener(document, "furry_preference_multi_breast_zero", "mouseenter", el, false);
        }
        if (((EventTarget) document.getElementById("furry_preference_multi_breast_one")) != null) {
            ((EventTarget) document.getElementById("furry_preference_multi_breast_one")).addEventListener("click", e -> {
                Main.getProperties().multiBreasts = 1;
                Main.saveProperties();
                Main.game.setContent(new Response("", "", Main.game.getCurrentDialogueNode()));
            }, false);
            addEventListener(document, "furry_preference_multi_breast_one", "mousemove", moveTooltipListener, false);
            addEventListener(document, "furry_preference_multi_breast_one", "mouseleave", hideTooltipListener, false);
            TooltipInformationEventListener el = new TooltipInformationEventListener().setInformation("Furry-only", "Randomly-generated NPCs will only spawn in with multiple rows of breasts if they have furry skin.");
            addEventListener(document, "furry_preference_multi_breast_one", "mouseenter", el, false);
        }
        if (((EventTarget) document.getElementById("furry_preference_multi_breast_two")) != null) {
            ((EventTarget) document.getElementById("furry_preference_multi_breast_two")).addEventListener("click", e -> {
                Main.getProperties().multiBreasts = 2;
                Main.saveProperties();
                Main.game.setContent(new Response("", "", Main.game.getCurrentDialogueNode()));
            }, false);
            addEventListener(document, "furry_preference_multi_breast_two", "mousemove", moveTooltipListener, false);
            addEventListener(document, "furry_preference_multi_breast_two", "mouseleave", hideTooltipListener, false);
            TooltipInformationEventListener el = new TooltipInformationEventListener().setInformation("On", "Randomly-generated NPCs will spawn in with multiple rows of breasts if their breast type is furry (starts at 'Minor morph' level).");
            addEventListener(document, "furry_preference_multi_breast_two", "mouseenter", el, false);
        }
        // Race preferences:
        if (((EventTarget) document.getElementById("furry_preference_female_human_all")) != null) {
            ((EventTarget) document.getElementById("furry_preference_female_human_all")).addEventListener("click", e -> {
                for (Subspecies r : Subspecies.values()) {
                    Main.getProperties().subspeciesFeminineFurryPreferencesMap.put(r, FurryPreference.HUMAN);
                    Main.getProperties().subspeciesMasculineFurryPreferencesMap.put(r, FurryPreference.HUMAN);
                }
                Main.saveProperties();
                Main.game.setContent(new Response("", "", Main.game.getCurrentDialogueNode()));
            }, false);
        }
        if (((EventTarget) document.getElementById("furry_preference_female_minimum_all")) != null) {
            ((EventTarget) document.getElementById("furry_preference_female_minimum_all")).addEventListener("click", e -> {
                for (Subspecies r : Subspecies.values()) {
                    Main.getProperties().subspeciesFeminineFurryPreferencesMap.put(r, FurryPreference.MINIMUM);
                    Main.getProperties().subspeciesMasculineFurryPreferencesMap.put(r, FurryPreference.MINIMUM);
                }
                Main.saveProperties();
                Main.game.setContent(new Response("", "", Main.game.getCurrentDialogueNode()));
            }, false);
        }
        if (((EventTarget) document.getElementById("furry_preference_female_reduced_all")) != null) {
            ((EventTarget) document.getElementById("furry_preference_female_reduced_all")).addEventListener("click", e -> {
                for (Subspecies r : Subspecies.values()) {
                    Main.getProperties().subspeciesFeminineFurryPreferencesMap.put(r, FurryPreference.REDUCED);
                    Main.getProperties().subspeciesMasculineFurryPreferencesMap.put(r, FurryPreference.REDUCED);
                }
                Main.saveProperties();
                Main.game.setContent(new Response("", "", Main.game.getCurrentDialogueNode()));
            }, false);
        }
        if (((EventTarget) document.getElementById("furry_preference_female_normal_all")) != null) {
            ((EventTarget) document.getElementById("furry_preference_female_normal_all")).addEventListener("click", e -> {
                for (Subspecies r : Subspecies.values()) {
                    Main.getProperties().subspeciesFeminineFurryPreferencesMap.put(r, FurryPreference.NORMAL);
                    Main.getProperties().subspeciesMasculineFurryPreferencesMap.put(r, FurryPreference.NORMAL);
                }
                Main.saveProperties();
                Main.game.setContent(new Response("", "", Main.game.getCurrentDialogueNode()));
            }, false);
        }
        if (((EventTarget) document.getElementById("furry_preference_female_maximum_all")) != null) {
            ((EventTarget) document.getElementById("furry_preference_female_maximum_all")).addEventListener("click", e -> {
                for (Subspecies r : Subspecies.values()) {
                    Main.getProperties().subspeciesFeminineFurryPreferencesMap.put(r, FurryPreference.MAXIMUM);
                    Main.getProperties().subspeciesMasculineFurryPreferencesMap.put(r, FurryPreference.MAXIMUM);
                }
                Main.saveProperties();
                Main.game.setContent(new Response("", "", Main.game.getCurrentDialogueNode()));
            }, false);
        }
        for (Subspecies s : Subspecies.values()) {
            for (FurryPreference preference : FurryPreference.values()) {
                id = "FEMININE_" + preference + "_" + s;
                if (((EventTarget) document.getElementById(id)) != null) {
                    ((EventTarget) document.getElementById(id)).addEventListener("click", e -> {
                        Main.getProperties().subspeciesFeminineFurryPreferencesMap.put(s, preference);
                        Main.saveProperties();
                        Main.game.setContent(new Response("", "", Main.game.getCurrentDialogueNode()));
                    }, false);
                    addEventListener(document, id, "mousemove", moveTooltipListener, false);
                    addEventListener(document, id, "mouseleave", hideTooltipListener, false);
                    TooltipInformationEventListener el = new TooltipInformationEventListener().setInformation(preference.getName(), preference.getDescriptionFeminine(s));
                    addEventListener(document, id, "mouseenter", el, false);
                }
                id = "MASCULINE_" + preference + "_" + s;
                if (((EventTarget) document.getElementById(id)) != null) {
                    ((EventTarget) document.getElementById(id)).addEventListener("click", e -> {
                        Main.getProperties().subspeciesMasculineFurryPreferencesMap.put(s, preference);
                        Main.saveProperties();
                        Main.game.setContent(new Response("", "", Main.game.getCurrentDialogueNode()));
                    }, false);
                    addEventListener(document, id, "mousemove", moveTooltipListener, false);
                    addEventListener(document, id, "mouseleave", hideTooltipListener, false);
                    TooltipInformationEventListener el = new TooltipInformationEventListener().setInformation(preference.getName(), preference.getDescriptionMasculine(s));
                    addEventListener(document, id, "mouseenter", el, false);
                }
            }
        }
    // for (Subspecies s : Subspecies.values()) {
    // for(SubspeciesPreference preference : SubspeciesPreference.values()) {
    // id = "FEMININE_" + preference+"_"+s;
    // if (((EventTarget) document.getElementById(id)) != null) {
    // ((EventTarget) document.getElementById(id)).addEventListener("click", e -> {
    // Main.getProperties().subspeciesFemininePreferencesMap.put(s, preference);
    // Main.saveProperties();
    // Main.game.setContent(new Response("", "", Main.game.getCurrentDialogueNode()));
    // }, false);
    // 
    // addEventListener(document, id, "mousemove", moveTooltipListener, false);
    // addEventListener(document, id, "mouseleave", hideTooltipListener, false);
    // TooltipInformationEventListener el = new TooltipInformationEventListener().setInformation(preference.getName(), "");
    // addEventListener(document, id, "mouseenter", el, false);
    // }
    // id = "MASCULINE_" + preference+"_"+s;
    // if (((EventTarget) document.getElementById(id)) != null) {
    // ((EventTarget) document.getElementById(id)).addEventListener("click", e -> {
    // Main.getProperties().subspeciesFemininePreferencesMap.put(s, preference);
    // Main.saveProperties();
    // Main.game.setContent(new Response("", "", Main.game.getCurrentDialogueNode()));
    // }, false);
    // 
    // addEventListener(document, id, "mousemove", moveTooltipListener, false);
    // addEventListener(document, id, "mouseleave", hideTooltipListener, false);
    // TooltipInformationEventListener el = new TooltipInformationEventListener().setInformation(preference.getName(), "");
    // addEventListener(document, id, "mouseenter", el, false);
    // }
    // }
    // }
    }
    if (Main.game.getCurrentDialogueNode() == OptionsDialogue.CONTENT_PREFERENCE || Main.game.getCurrentDialogueNode() == CharacterCreation.CONTENT_PREFERENCES) {
        id = "NON_CON_ON";
        if (((EventTarget) document.getElementById(id)) != null) {
            ((EventTarget) document.getElementById(id)).addEventListener("click", e -> {
                Main.getProperties().nonConContent = true;
                Main.saveProperties();
                Main.game.setContent(new Response("", "", Main.game.getCurrentDialogueNode()));
            }, false);
        }
        id = "NON_CON_OFF";
        if (((EventTarget) document.getElementById(id)) != null) {
            ((EventTarget) document.getElementById(id)).addEventListener("click", e -> {
                Main.getProperties().nonConContent = false;
                Main.saveProperties();
                Main.game.setContent(new Response("", "", Main.game.getCurrentDialogueNode()));
            }, false);
        }
        id = "INCEST_ON";
        if (((EventTarget) document.getElementById(id)) != null) {
            ((EventTarget) document.getElementById(id)).addEventListener("click", e -> {
                Main.getProperties().incestContent = true;
                Main.saveProperties();
                Main.game.setContent(new Response("", "", Main.game.getCurrentDialogueNode()));
            }, false);
        }
        id = "INCEST_OFF";
        if (((EventTarget) document.getElementById(id)) != null) {
            ((EventTarget) document.getElementById(id)).addEventListener("click", e -> {
                Main.getProperties().incestContent = false;
                Main.saveProperties();
                Main.game.setContent(new Response("", "", Main.game.getCurrentDialogueNode()));
            }, false);
        }
        id = "HAIR_FACIAL_ON";
        if (((EventTarget) document.getElementById(id)) != null) {
            ((EventTarget) document.getElementById(id)).addEventListener("click", e -> {
                Main.getProperties().facialHairContent = !Main.getProperties().facialHairContent;
                Main.saveProperties();
                Main.game.setContent(new Response("", "", Main.game.getCurrentDialogueNode()));
            }, false);
        }
        id = "HAIR_FACIAL_OFF";
        if (((EventTarget) document.getElementById(id)) != null) {
            ((EventTarget) document.getElementById(id)).addEventListener("click", e -> {
                Main.getProperties().facialHairContent = !Main.getProperties().facialHairContent;
                Main.saveProperties();
                Main.game.setContent(new Response("", "", Main.game.getCurrentDialogueNode()));
            }, false);
        }
        id = "HAIR_PUBIC_ON";
        if (((EventTarget) document.getElementById(id)) != null) {
            ((EventTarget) document.getElementById(id)).addEventListener("click", e -> {
                Main.getProperties().pubicHairContent = !Main.getProperties().pubicHairContent;
                Main.saveProperties();
                Main.game.setContent(new Response("", "", Main.game.getCurrentDialogueNode()));
            }, false);
        }
        id = "HAIR_PUBIC_OFF";
        if (((EventTarget) document.getElementById(id)) != null) {
            ((EventTarget) document.getElementById(id)).addEventListener("click", e -> {
                Main.getProperties().pubicHairContent = !Main.getProperties().pubicHairContent;
                Main.saveProperties();
                Main.game.setContent(new Response("", "", Main.game.getCurrentDialogueNode()));
            }, false);
        }
        id = "HAIR_BODY_ON";
        if (((EventTarget) document.getElementById(id)) != null) {
            ((EventTarget) document.getElementById(id)).addEventListener("click", e -> {
                Main.getProperties().bodyHairContent = !Main.getProperties().bodyHairContent;
                Main.saveProperties();
                Main.game.setContent(new Response("", "", Main.game.getCurrentDialogueNode()));
            }, false);
        }
        id = "HAIR_BODY_OFF";
        if (((EventTarget) document.getElementById(id)) != null) {
            ((EventTarget) document.getElementById(id)).addEventListener("click", e -> {
                Main.getProperties().bodyHairContent = !Main.getProperties().bodyHairContent;
                Main.saveProperties();
                Main.game.setContent(new Response("", "", Main.game.getCurrentDialogueNode()));
            }, false);
        }
        id = "FEMININE_BEARD_ON";
        if (((EventTarget) document.getElementById(id)) != null) {
            ((EventTarget) document.getElementById(id)).addEventListener("click", e -> {
                Main.getProperties().feminineBeardsContent = !Main.getProperties().feminineBeardsContent;
                Main.saveProperties();
                Main.game.setContent(new Response("", "", Main.game.getCurrentDialogueNode()));
            }, false);
        }
        id = "FEMININE_BEARD_OFF";
        if (((EventTarget) document.getElementById(id)) != null) {
            ((EventTarget) document.getElementById(id)).addEventListener("click", e -> {
                Main.getProperties().feminineBeardsContent = !Main.getProperties().feminineBeardsContent;
                Main.saveProperties();
                Main.game.setContent(new Response("", "", Main.game.getCurrentDialogueNode()));
            }, false);
        }
        id = "FURRY_TAIL_PENETRATION_ON";
        if (((EventTarget) document.getElementById(id)) != null) {
            ((EventTarget) document.getElementById(id)).addEventListener("click", e -> {
                Main.getProperties().furryTailPenetrationContent = !Main.getProperties().furryTailPenetrationContent;
                Main.saveProperties();
                Main.game.setContent(new Response("", "", Main.game.getCurrentDialogueNode()));
            }, false);
        }
        id = "FURRY_TAIL_PENETRATION_OFF";
        if (((EventTarget) document.getElementById(id)) != null) {
            ((EventTarget) document.getElementById(id)).addEventListener("click", e -> {
                Main.getProperties().furryTailPenetrationContent = !Main.getProperties().furryTailPenetrationContent;
                Main.saveProperties();
                Main.game.setContent(new Response("", "", Main.game.getCurrentDialogueNode()));
            }, false);
        }
        id = "INFLATION_CONTENT_ON";
        if (((EventTarget) document.getElementById(id)) != null) {
            ((EventTarget) document.getElementById(id)).addEventListener("click", e -> {
                Main.getProperties().inflationContent = !Main.getProperties().inflationContent;
                Main.saveProperties();
                Main.game.setContent(new Response("", "", Main.game.getCurrentDialogueNode()));
            }, false);
        }
        id = "INFLATION_CONTENT_OFF";
        if (((EventTarget) document.getElementById(id)) != null) {
            ((EventTarget) document.getElementById(id)).addEventListener("click", e -> {
                Main.getProperties().inflationContent = !Main.getProperties().inflationContent;
                Main.saveProperties();
                Main.game.setContent(new Response("", "", Main.game.getCurrentDialogueNode()));
            }, false);
        }
        id = "FORCED_TF_ON";
        if (((EventTarget) document.getElementById(id)) != null) {
            ((EventTarget) document.getElementById(id)).addEventListener("click", e -> {
                Main.getProperties().forcedTFPercentage = Math.min(100, Main.getProperties().forcedTFPercentage + 10);
                Main.saveProperties();
                Main.game.setContent(new Response("", "", Main.game.getCurrentDialogueNode()));
            }, false);
        }
        id = "FORCED_TF_OFF";
        if (((EventTarget) document.getElementById(id)) != null) {
            ((EventTarget) document.getElementById(id)).addEventListener("click", e -> {
                Main.getProperties().forcedTFPercentage = Math.max(0, Main.getProperties().forcedTFPercentage - 10);
                Main.saveProperties();
                Main.game.setContent(new Response("", "", Main.game.getCurrentDialogueNode()));
            }, false);
        }
        id = "PREGNANCY_BREAST_GROWTH_ON";
        if (((EventTarget) document.getElementById(id)) != null) {
            ((EventTarget) document.getElementById(id)).addEventListener("click", e -> {
                Main.getProperties().pregnancyBreastGrowth = Math.min(10, Main.getProperties().pregnancyBreastGrowth + 1);
                Main.saveProperties();
                Main.game.setContent(new Response("", "", Main.game.getCurrentDialogueNode()));
            }, false);
        }
        id = "PREGNANCY_BREAST_GROWTH_OFF";
        if (((EventTarget) document.getElementById(id)) != null) {
            ((EventTarget) document.getElementById(id)).addEventListener("click", e -> {
                Main.getProperties().pregnancyBreastGrowth = Math.max(0, Main.getProperties().pregnancyBreastGrowth - 1);
                Main.saveProperties();
                Main.game.setContent(new Response("", "", Main.game.getCurrentDialogueNode()));
            }, false);
        }
        id = "PREGNANCY_BREAST_GROWTH_LIMIT_ON";
        if (((EventTarget) document.getElementById(id)) != null) {
            ((EventTarget) document.getElementById(id)).addEventListener("click", e -> {
                Main.getProperties().pregnancyBreastGrowthLimit = Math.min(100, Main.getProperties().pregnancyBreastGrowthLimit + 1);
                Main.saveProperties();
                Main.game.setContent(new Response("", "", Main.game.getCurrentDialogueNode()));
            }, false);
        }
        id = "PREGNANCY_BREAST_GROWTH_LIMIT_OFF";
        if (((EventTarget) document.getElementById(id)) != null) {
            ((EventTarget) document.getElementById(id)).addEventListener("click", e -> {
                Main.getProperties().pregnancyBreastGrowthLimit = Math.max(0, Main.getProperties().pregnancyBreastGrowthLimit - 1);
                Main.saveProperties();
                Main.game.setContent(new Response("", "", Main.game.getCurrentDialogueNode()));
            }, false);
        }
        id = "PREGNANCY_LACTATION_ON";
        if (((EventTarget) document.getElementById(id)) != null) {
            ((EventTarget) document.getElementById(id)).addEventListener("click", e -> {
                Main.getProperties().pregnancyLactationIncrease = Math.min(1000, Main.getProperties().pregnancyLactationIncrease + 50);
                Main.saveProperties();
                Main.game.setContent(new Response("", "", Main.game.getCurrentDialogueNode()));
            }, false);
        }
        id = "PREGNANCY_LACTATION_OFF";
        if (((EventTarget) document.getElementById(id)) != null) {
            ((EventTarget) document.getElementById(id)).addEventListener("click", e -> {
                Main.getProperties().pregnancyLactationIncrease = Math.max(0, Main.getProperties().pregnancyLactationIncrease - 50);
                Main.saveProperties();
                Main.game.setContent(new Response("", "", Main.game.getCurrentDialogueNode()));
            }, false);
        }
        id = "PREGNANCY_LACTATION_LIMIT_ON";
        if (((EventTarget) document.getElementById(id)) != null) {
            ((EventTarget) document.getElementById(id)).addEventListener("click", e -> {
                Main.getProperties().pregnancyLactationLimit = Math.min(Lactation.SEVEN_MONSTROUS_AMOUNT_POURING.getMaximumValue(), Main.getProperties().pregnancyLactationLimit + 250);
                Main.saveProperties();
                Main.game.setContent(new Response("", "", Main.game.getCurrentDialogueNode()));
            }, false);
        }
        id = "PREGNANCY_LACTATION_LIMIT_OFF";
        if (((EventTarget) document.getElementById(id)) != null) {
            ((EventTarget) document.getElementById(id)).addEventListener("click", e -> {
                Main.getProperties().pregnancyLactationLimit = Math.max(0, Main.getProperties().pregnancyLactationLimit - 250);
                Main.saveProperties();
                Main.game.setContent(new Response("", "", Main.game.getCurrentDialogueNode()));
            }, false);
        }
        id = "FORCED_FETISH_ON";
        if (((EventTarget) document.getElementById(id)) != null) {
            ((EventTarget) document.getElementById(id)).addEventListener("click", e -> {
                Main.getProperties().forcedFetishPercentage = Math.min(100, Main.getProperties().forcedFetishPercentage + 10);
                Main.saveProperties();
                Main.game.setContent(new Response("", "", Main.game.getCurrentDialogueNode()));
            }, false);
        }
        id = "FORCED_FETISH_OFF";
        if (((EventTarget) document.getElementById(id)) != null) {
            ((EventTarget) document.getElementById(id)).addEventListener("click", e -> {
                Main.getProperties().forcedFetishPercentage = Math.max(0, Main.getProperties().forcedFetishPercentage - 10);
                Main.saveProperties();
                Main.game.setContent(new Response("", "", Main.game.getCurrentDialogueNode()));
            }, false);
        }
        // Forced TF Tendency setting events
        id = "FORCED_TF_TENDENCY_" + ForcedTFTendency.NEUTRAL;
        if (((EventTarget) document.getElementById(id)) != null) {
            ((EventTarget) document.getElementById(id)).addEventListener("click", e -> {
                Main.getProperties().forcedTFTendency = ForcedTFTendency.NEUTRAL;
                Main.saveProperties();
                Main.game.setContent(new Response("", "", Main.game.getCurrentDialogueNode()));
            }, false);
            addEventListener(document, id, "mousemove", moveTooltipListener, false);
            addEventListener(document, id, "mouseleave", hideTooltipListener, false);
            TooltipInformationEventListener el = new TooltipInformationEventListener().setInformation(ForcedTFTendency.NEUTRAL.getName(), ForcedTFTendency.NEUTRAL.getDescription());
            addEventListener(document, id, "mouseenter", el, false);
        }
        id = "FORCED_TF_TENDENCY_" + ForcedTFTendency.FEMININE;
        if (((EventTarget) document.getElementById(id)) != null) {
            ((EventTarget) document.getElementById(id)).addEventListener("click", e -> {
                Main.getProperties().forcedTFTendency = ForcedTFTendency.FEMININE;
                Main.saveProperties();
                Main.game.setContent(new Response("", "", Main.game.getCurrentDialogueNode()));
            }, false);
            addEventListener(document, id, "mousemove", moveTooltipListener, false);
            addEventListener(document, id, "mouseleave", hideTooltipListener, false);
            TooltipInformationEventListener el = new TooltipInformationEventListener().setInformation(ForcedTFTendency.FEMININE.getName(), ForcedTFTendency.FEMININE.getDescription());
            addEventListener(document, id, "mouseenter", el, false);
        }
        id = "FORCED_TF_TENDENCY_" + ForcedTFTendency.FEMININE_HEAVY;
        if (((EventTarget) document.getElementById(id)) != null) {
            ((EventTarget) document.getElementById(id)).addEventListener("click", e -> {
                Main.getProperties().forcedTFTendency = ForcedTFTendency.FEMININE_HEAVY;
                Main.saveProperties();
                Main.game.setContent(new Response("", "", Main.game.getCurrentDialogueNode()));
            }, false);
            addEventListener(document, id, "mousemove", moveTooltipListener, false);
            addEventListener(document, id, "mouseleave", hideTooltipListener, false);
            TooltipInformationEventListener el = new TooltipInformationEventListener().setInformation(ForcedTFTendency.FEMININE_HEAVY.getName(), ForcedTFTendency.FEMININE_HEAVY.getDescription());
            addEventListener(document, id, "mouseenter", el, false);
        }
        id = "FORCED_TF_TENDENCY_" + ForcedTFTendency.MASCULINE;
        if (((EventTarget) document.getElementById(id)) != null) {
            ((EventTarget) document.getElementById(id)).addEventListener("click", e -> {
                Main.getProperties().forcedTFTendency = ForcedTFTendency.MASCULINE;
                Main.saveProperties();
                Main.game.setContent(new Response("", "", Main.game.getCurrentDialogueNode()));
            }, false);
            addEventListener(document, id, "mousemove", moveTooltipListener, false);
            addEventListener(document, id, "mouseleave", hideTooltipListener, false);
            TooltipInformationEventListener el = new TooltipInformationEventListener().setInformation(ForcedTFTendency.MASCULINE.getName(), ForcedTFTendency.MASCULINE.getDescription());
            addEventListener(document, id, "mouseenter", el, false);
        }
        id = "FORCED_TF_TENDENCY_" + ForcedTFTendency.MASCULINE_HEAVY;
        if (((EventTarget) document.getElementById(id)) != null) {
            ((EventTarget) document.getElementById(id)).addEventListener("click", e -> {
                Main.getProperties().forcedTFTendency = ForcedTFTendency.MASCULINE_HEAVY;
                Main.saveProperties();
                Main.game.setContent(new Response("", "", Main.game.getCurrentDialogueNode()));
            }, false);
            addEventListener(document, id, "mousemove", moveTooltipListener, false);
            addEventListener(document, id, "mouseleave", hideTooltipListener, false);
            TooltipInformationEventListener el = new TooltipInformationEventListener().setInformation(ForcedTFTendency.MASCULINE_HEAVY.getName(), ForcedTFTendency.MASCULINE_HEAVY.getDescription());
            addEventListener(document, id, "mouseenter", el, false);
        }
        // Forced Fetish Tendency setting events
        id = "FORCED_FETISH_TENDENCY_" + ForcedFetishTendency.NEUTRAL;
        if (((EventTarget) document.getElementById(id)) != null) {
            ((EventTarget) document.getElementById(id)).addEventListener("click", e -> {
                Main.getProperties().forcedFetishTendency = ForcedFetishTendency.NEUTRAL;
                Main.saveProperties();
                Main.game.setContent(new Response("", "", Main.game.getCurrentDialogueNode()));
            }, false);
            addEventListener(document, id, "mousemove", moveTooltipListener, false);
            addEventListener(document, id, "mouseleave", hideTooltipListener, false);
            TooltipInformationEventListener el = new TooltipInformationEventListener().setInformation(ForcedFetishTendency.NEUTRAL.getName(), ForcedFetishTendency.NEUTRAL.getDescription());
            addEventListener(document, id, "mouseenter", el, false);
        }
        id = "FORCED_FETISH_TENDENCY_" + ForcedFetishTendency.BOTTOM;
        if (((EventTarget) document.getElementById(id)) != null) {
            ((EventTarget) document.getElementById(id)).addEventListener("click", e -> {
                Main.getProperties().forcedFetishTendency = ForcedFetishTendency.BOTTOM;
                Main.saveProperties();
                Main.game.setContent(new Response("", "", Main.game.getCurrentDialogueNode()));
            }, false);
            addEventListener(document, id, "mousemove", moveTooltipListener, false);
            addEventListener(document, id, "mouseleave", hideTooltipListener, false);
            TooltipInformationEventListener el = new TooltipInformationEventListener().setInformation(ForcedFetishTendency.BOTTOM.getName(), ForcedFetishTendency.BOTTOM.getDescription());
            addEventListener(document, id, "mouseenter", el, false);
        }
        id = "FORCED_FETISH_TENDENCY_" + ForcedFetishTendency.BOTTOM_HEAVY;
        if (((EventTarget) document.getElementById(id)) != null) {
            ((EventTarget) document.getElementById(id)).addEventListener("click", e -> {
                Main.getProperties().forcedFetishTendency = ForcedFetishTendency.BOTTOM_HEAVY;
                Main.saveProperties();
                Main.game.setContent(new Response("", "", Main.game.getCurrentDialogueNode()));
            }, false);
            addEventListener(document, id, "mousemove", moveTooltipListener, false);
            addEventListener(document, id, "mouseleave", hideTooltipListener, false);
            TooltipInformationEventListener el = new TooltipInformationEventListener().setInformation(ForcedFetishTendency.BOTTOM_HEAVY.getName(), ForcedFetishTendency.BOTTOM_HEAVY.getDescription());
            addEventListener(document, id, "mouseenter", el, false);
        }
        id = "FORCED_FETISH_TENDENCY_" + ForcedFetishTendency.TOP;
        if (((EventTarget) document.getElementById(id)) != null) {
            ((EventTarget) document.getElementById(id)).addEventListener("click", e -> {
                Main.getProperties().forcedFetishTendency = ForcedFetishTendency.TOP;
                Main.saveProperties();
                Main.game.setContent(new Response("", "", Main.game.getCurrentDialogueNode()));
            }, false);
            addEventListener(document, id, "mousemove", moveTooltipListener, false);
            addEventListener(document, id, "mouseleave", hideTooltipListener, false);
            TooltipInformationEventListener el = new TooltipInformationEventListener().setInformation(ForcedFetishTendency.TOP.getName(), ForcedFetishTendency.TOP.getDescription());
            addEventListener(document, id, "mouseenter", el, false);
        }
        id = "FORCED_FETISH_TENDENCY_" + ForcedFetishTendency.TOP_HEAVY;
        if (((EventTarget) document.getElementById(id)) != null) {
            ((EventTarget) document.getElementById(id)).addEventListener("click", e -> {
                Main.getProperties().forcedFetishTendency = ForcedFetishTendency.TOP_HEAVY;
                Main.saveProperties();
                Main.game.setContent(new Response("", "", Main.game.getCurrentDialogueNode()));
            }, false);
            addEventListener(document, id, "mousemove", moveTooltipListener, false);
            addEventListener(document, id, "mouseleave", hideTooltipListener, false);
            TooltipInformationEventListener el = new TooltipInformationEventListener().setInformation(ForcedFetishTendency.TOP_HEAVY.getName(), ForcedFetishTendency.TOP_HEAVY.getDescription());
            addEventListener(document, id, "mouseenter", el, false);
        }
    }
    // Save/load:
    if (Main.game.getCurrentDialogueNode() == OptionsDialogue.SAVE_LOAD) {
        for (File f : Main.getSavedGames()) {
            id = "overwrite_saved_" + f.getName().substring(0, f.getName().lastIndexOf('.'));
            if (((EventTarget) document.getElementById(id)) != null) {
                ((EventTarget) document.getElementById(id)).addEventListener("click", e -> {
                    if (!Main.getProperties().overwriteWarning || OptionsDialogue.overwriteConfirmationName.equals(f.getName())) {
                        OptionsDialogue.overwriteConfirmationName = "";
                        Main.saveGame(f.getName().substring(0, f.getName().lastIndexOf('.')), true);
                    } else {
                        OptionsDialogue.overwriteConfirmationName = f.getName();
                        OptionsDialogue.loadConfirmationName = "";
                        OptionsDialogue.deleteConfirmationName = "";
                        Main.game.setContent(new Response("Save/Load", "Open the save/load game window.", OptionsDialogue.SAVE_LOAD));
                    }
                }, false);
                addEventListener(document, id, "mousemove", moveTooltipListener, false);
                addEventListener(document, id, "mouseleave", hideTooltipListener, false);
                TooltipInformationEventListener el2 = new TooltipInformationEventListener().setInformation("Overwrite", "");
                addEventListener(document, id, "mouseenter", el2, false);
            }
            id = "load_saved_" + f.getName().substring(0, f.getName().lastIndexOf('.'));
            if (((EventTarget) document.getElementById(id)) != null) {
                ((EventTarget) document.getElementById(id)).addEventListener("click", e -> {
                    if (!Main.getProperties().overwriteWarning || OptionsDialogue.loadConfirmationName.equals(f.getName())) {
                        OptionsDialogue.loadConfirmationName = "";
                        Main.loadGame(f.getName().substring(0, f.getName().lastIndexOf('.')));
                    } else {
                        OptionsDialogue.overwriteConfirmationName = "";
                        OptionsDialogue.loadConfirmationName = f.getName();
                        OptionsDialogue.deleteConfirmationName = "";
                        Main.game.setContent(new Response("Save/Load", "Open the save/load game window.", OptionsDialogue.SAVE_LOAD));
                    }
                }, false);
                addEventListener(document, id, "mousemove", moveTooltipListener, false);
                addEventListener(document, id, "mouseleave", hideTooltipListener, false);
                TooltipInformationEventListener el2 = new TooltipInformationEventListener().setInformation("Load", "");
                addEventListener(document, id, "mouseenter", el2, false);
            }
            id = "delete_saved_" + f.getName().substring(0, f.getName().lastIndexOf('.'));
            if (((EventTarget) document.getElementById(id)) != null) {
                ((EventTarget) document.getElementById(id)).addEventListener("click", e -> {
                    if (!Main.getProperties().overwriteWarning || OptionsDialogue.deleteConfirmationName.equals(f.getName())) {
                        OptionsDialogue.deleteConfirmationName = "";
                        Main.deleteGame(f.getName().substring(0, f.getName().lastIndexOf('.')));
                    } else {
                        OptionsDialogue.overwriteConfirmationName = "";
                        OptionsDialogue.loadConfirmationName = "";
                        OptionsDialogue.deleteConfirmationName = f.getName();
                        Main.game.setContent(new Response("Save/Load", "Open the save/load game window.", OptionsDialogue.SAVE_LOAD));
                    }
                }, false);
                addEventListener(document, id, "mousemove", moveTooltipListener, false);
                addEventListener(document, id, "mouseleave", hideTooltipListener, false);
                TooltipInformationEventListener el2 = new TooltipInformationEventListener().setInformation("Delete", "");
                addEventListener(document, id, "mouseenter", el2, false);
            }
        }
        id = "new_saved";
        if (((EventTarget) document.getElementById(id)) != null) {
            ((EventTarget) document.getElementById(id)).addEventListener("click", e -> {
                Main.mainController.getWebEngine().executeScript("document.getElementById('hiddenPField').innerHTML=document.getElementById('new_save_name').value;");
                Main.saveGame(Main.mainController.getWebEngine().getDocument().getElementById("hiddenPField").getTextContent(), false);
            }, false);
            addEventListener(document, id, "mousemove", moveTooltipListener, false);
            addEventListener(document, id, "mouseleave", hideTooltipListener, false);
            TooltipInformationEventListener el2 = new TooltipInformationEventListener().setInformation("Save", "");
            addEventListener(document, id, "mouseenter", el2, false);
        }
        id = "new_saved_disabled";
        if (((EventTarget) document.getElementById(id)) != null) {
            addEventListener(document, id, "mousemove", moveTooltipListener, false);
            addEventListener(document, id, "mouseleave", hideTooltipListener, false);
            TooltipInformationEventListener el2 = new TooltipInformationEventListener().setInformation("Save (Disabled)", (!Main.game.isStarted() ? "You need to have started a game before you can save!" : "You cannot save the game unless you are in a tile's default scene!"));
            addEventListener(document, id, "mouseenter", el2, false);
        }
    }
    // Import:
    if (Main.game.getCurrentDialogueNode() == OptionsDialogue.IMPORT_EXPORT) {
        for (File f : Main.getCharactersForImport()) {
            id = "delete_saved_character_" + f.getName().substring(0, f.getName().lastIndexOf('.'));
            if (((EventTarget) document.getElementById(id)) != null) {
                ((EventTarget) document.getElementById(id)).addEventListener("click", e -> {
                    if (!Main.getProperties().overwriteWarning || OptionsDialogue.deleteConfirmationName.equals(f.getName())) {
                        OptionsDialogue.deleteConfirmationName = "";
                        Main.deleteExportedCharacter(f.getName().substring(0, f.getName().lastIndexOf('.')));
                    } else {
                        OptionsDialogue.overwriteConfirmationName = "";
                        OptionsDialogue.loadConfirmationName = "";
                        OptionsDialogue.deleteConfirmationName = f.getName();
                        Main.game.setContent(new Response("Save/Load", "Open the save/load game window.", OptionsDialogue.SAVE_LOAD));
                    }
                }, false);
                addEventListener(document, id, "mousemove", moveTooltipListener, false);
                addEventListener(document, id, "mouseleave", hideTooltipListener, false);
                TooltipInformationEventListener el2 = new TooltipInformationEventListener().setInformation("Delete", "");
                addEventListener(document, id, "mouseenter", el2, false);
            }
        }
        if (((EventTarget) document.getElementById("new_saved")) != null) {
            ((EventTarget) document.getElementById("new_saved")).addEventListener("click", e -> {
                Main.mainController.getWebEngine().executeScript("document.getElementById('hiddenPField').innerHTML=document.getElementById('new_save_name').value;");
                Main.saveGame(Main.mainController.getWebEngine().getDocument().getElementById("hiddenPField").getTextContent(), false);
            }, false);
        }
    }
    if (Main.game.getCurrentDialogueNode() == CharacterCreation.IMPORT_CHOOSE) {
        for (File f : Main.getCharactersForImport()) {
            if (((EventTarget) document.getElementById("character_import_" + f.getName().substring(0, f.getName().lastIndexOf('.')))) != null) {
                ((EventTarget) document.getElementById("character_import_" + f.getName().substring(0, f.getName().lastIndexOf('.')))).addEventListener("click", e -> {
                    Main.importCharacter(f);
                }, false);
            }
        }
    }
    // Slave import:
    if (Main.game.getCurrentDialogueNode() == SlaverAlleyDialogue.AUCTION_IMPORT) {
        for (File f : Main.getSlavesForImport()) {
            if (((EventTarget) document.getElementById("import_slave_" + f.getName().substring(0, f.getName().lastIndexOf('.')))) != null) {
                ((EventTarget) document.getElementById("import_slave_" + f.getName().substring(0, f.getName().lastIndexOf('.')))).addEventListener("click", e -> {
                    try {
                        Game.importCharacterAsSlave(f.getName().substring(0, f.getName().lastIndexOf('.')));
                        this.updateUI();
                        Main.game.flashMessage(Colour.GENERIC_GOOD, "Imported Character!");
                    } catch (Exception ex) {
                        Main.game.flashMessage(Colour.GENERIC_BAD, "Import Failed!");
                    }
                }, false);
            }
        }
    }
    if (Main.game.getCurrentDialogueNode() == SlaverAlleyDialogue.AUCTION_BLOCK_LIST) {
        for (NPC npc : Main.game.getCharactersPresent()) {
            id = npc.getId() + "_BID";
            if (((EventTarget) document.getElementById(id)) != null) {
                if (Main.game.getPlayer().isHasSlaverLicense()) {
                    ((EventTarget) document.getElementById(id)).addEventListener("click", e -> {
                        SlaverAlleyDialogue.setupBidding(npc);
                        Main.game.setContent(new Response("", "", SlaverAlleyDialogue.AUCTION_BIDDING));
                    }, false);
                    addEventListener(document, id, "mousemove", moveTooltipListener, false);
                    addEventListener(document, id, "mouseleave", hideTooltipListener, false);
                    TooltipInformationEventListener el = new TooltipInformationEventListener().setInformation(UtilText.parse(npc, "Bid on [npc.name]"), UtilText.parse(npc, "Start bidding on [npc.name]. There's a chance that the bidding might exceed [npc.her] value, so make sure you have enough money first!"));
                    addEventListener(document, id, "mouseenter", el, false);
                } else {
                    addEventListener(document, id, "mousemove", moveTooltipListener, false);
                    addEventListener(document, id, "mouseleave", hideTooltipListener, false);
                    TooltipInformationEventListener el = new TooltipInformationEventListener().setInformation(UtilText.parse(npc, "Bid on [npc.name]"), UtilText.parse(npc, "You don't have a slaver license, so you're unable to big on any slaves!"));
                    addEventListener(document, id, "mouseenter", el, false);
                }
            }
        }
    }
    setResponseEventListeners();
}
Also used : TooltipInformationEventListener(com.lilithsthrone.controller.eventListeners.TooltipInformationEventListener) AssSize(com.lilithsthrone.game.character.body.valueEnums.AssSize) TestNPC(com.lilithsthrone.game.character.npc.dominion.TestNPC) HipSize(com.lilithsthrone.game.character.body.valueEnums.HipSize) CharactersPresentDialogue(com.lilithsthrone.game.dialogue.utils.CharactersPresentDialogue) ButtonInventoryEventHandler(com.lilithsthrone.controller.eventListeners.buttons.ButtonInventoryEventHandler) PenisType(com.lilithsthrone.game.character.body.types.PenisType) OrificePlasticity(com.lilithsthrone.game.character.body.valueEnums.OrificePlasticity) ButtonCopyDialogueEventListener(com.lilithsthrone.controller.eventListeners.buttons.ButtonCopyDialogueEventListener) TFModifier(com.lilithsthrone.game.inventory.enchanting.TFModifier) ButtonMoveSouthEventListener(com.lilithsthrone.controller.eventListeners.buttons.ButtonMoveSouthEventListener) BreastShape(com.lilithsthrone.game.character.body.valueEnums.BreastShape) NPC(com.lilithsthrone.game.character.npc.NPC) GenderNames(com.lilithsthrone.game.character.gender.GenderNames) PenisSize(com.lilithsthrone.game.character.body.valueEnums.PenisSize) Document(org.w3c.dom.Document) Map(java.util.Map) NippleSize(com.lilithsthrone.game.character.body.valueEnums.NippleSize) PenisModifier(com.lilithsthrone.game.character.body.valueEnums.PenisModifier) SlaveryManagementDialogue(com.lilithsthrone.game.dialogue.SlaveryManagementDialogue) InventoryDialogue(com.lilithsthrone.game.dialogue.utils.InventoryDialogue) TooltipMoveEventListener(com.lilithsthrone.controller.eventListeners.TooltipMoveEventListener) SpecialAttack(com.lilithsthrone.game.combat.SpecialAttack) Colour(com.lilithsthrone.utils.Colour) PhoneDialogue(com.lilithsthrone.game.dialogue.utils.PhoneDialogue) SlaveJobHours(com.lilithsthrone.game.slavery.SlaveJobHours) EnchantingUtils(com.lilithsthrone.game.inventory.enchanting.EnchantingUtils) KeyEvent(javafx.scene.input.KeyEvent) TongueModifier(com.lilithsthrone.game.character.body.valueEnums.TongueModifier) CityHall(com.lilithsthrone.game.dialogue.places.dominion.CityHall) ClothingType(com.lilithsthrone.game.inventory.clothing.ClothingType) SlaverAlleyDialogue(com.lilithsthrone.game.dialogue.places.dominion.slaverAlley.SlaverAlleyDialogue) DamageType(com.lilithsthrone.game.combat.DamageType) SexParticipantType(com.lilithsthrone.game.sex.SexParticipantType) FaceType(com.lilithsthrone.game.character.body.types.FaceType) TFPotency(com.lilithsthrone.game.inventory.enchanting.TFPotency) Combat(com.lilithsthrone.game.combat.Combat) SuccubisSecrets(com.lilithsthrone.game.dialogue.places.dominion.shoppingArcade.SuccubisSecrets) Game(com.lilithsthrone.game.Game) Femininity(com.lilithsthrone.game.character.body.valueEnums.Femininity) AntennaType(com.lilithsthrone.game.character.body.types.AntennaType) SlavePermission(com.lilithsthrone.game.slavery.SlavePermission) PlaceType(com.lilithsthrone.world.places.PlaceType) WeaponType(com.lilithsthrone.game.inventory.weapon.WeaponType) Cell(com.lilithsthrone.world.Cell) SexType(com.lilithsthrone.game.sex.SexType) ButtonMoveEastEventListener(com.lilithsthrone.controller.eventListeners.buttons.ButtonMoveEastEventListener) ResponseEffectsOnly(com.lilithsthrone.game.dialogue.responses.ResponseEffectsOnly) AbstractItem(com.lilithsthrone.game.inventory.item.AbstractItem) AbstractCoreItem(com.lilithsthrone.game.inventory.AbstractCoreItem) SetContentEventListener(com.lilithsthrone.controller.eventListeners.SetContentEventListener) BodyChanging(com.lilithsthrone.game.dialogue.utils.BodyChanging) BodyCoveringType(com.lilithsthrone.game.character.body.types.BodyCoveringType) PlaceUpgrade(com.lilithsthrone.world.places.PlaceUpgrade) ArrayList(java.util.ArrayList) CupSize(com.lilithsthrone.game.character.body.valueEnums.CupSize) NameTriplet(com.lilithsthrone.game.character.NameTriplet) FurryPreference(com.lilithsthrone.game.character.race.FurryPreference) ResourceBundle(java.util.ResourceBundle) ButtonMoveNorthEventListener(com.lilithsthrone.controller.eventListeners.buttons.ButtonMoveNorthEventListener) OrificeType(com.lilithsthrone.game.sex.OrificeType) HairLength(com.lilithsthrone.game.character.body.valueEnums.HairLength) LabiaSize(com.lilithsthrone.game.character.body.valueEnums.LabiaSize) BodyHair(com.lilithsthrone.game.character.body.valueEnums.BodyHair) InventorySlot(com.lilithsthrone.game.inventory.InventorySlot) Personality(com.lilithsthrone.game.character.Personality) KeyboardAction(com.lilithsthrone.game.settings.KeyboardAction) Sex(com.lilithsthrone.game.sex.Sex) OptionsDialogue(com.lilithsthrone.game.dialogue.utils.OptionsDialogue) GridPane(javafx.scene.layout.GridPane) KeyCodeWithModifiers(com.lilithsthrone.game.settings.KeyCodeWithModifiers) SlaveJobSetting(com.lilithsthrone.game.slavery.SlaveJobSetting) TesticleSize(com.lilithsthrone.game.character.body.valueEnums.TesticleSize) BodySize(com.lilithsthrone.game.character.body.valueEnums.BodySize) ButtonMoveWestEventListener(com.lilithsthrone.controller.eventListeners.buttons.ButtonMoveWestEventListener) TooltipResponseDescriptionEventListener(com.lilithsthrone.controller.eventListeners.TooltipResponseDescriptionEventListener) Gender(com.lilithsthrone.game.character.gender.Gender) Breast(com.lilithsthrone.game.character.body.Breast) AbstractClothing(com.lilithsthrone.game.inventory.clothing.AbstractClothing) Rarity(com.lilithsthrone.game.inventory.Rarity) EnchantmentEventListener(com.lilithsthrone.controller.eventListeners.EnchantmentEventListener) Perk(com.lilithsthrone.game.character.effects.Perk) ClitorisSize(com.lilithsthrone.game.character.body.valueEnums.ClitorisSize) PenisGirth(com.lilithsthrone.game.character.body.valueEnums.PenisGirth) DebugDialogue(com.lilithsthrone.game.dialogue.DebugDialogue) File(java.io.File) LilayaHomeGeneric(com.lilithsthrone.game.dialogue.places.dominion.lilayashome.LilayaHomeGeneric) ButtonMainMenuEventListener(com.lilithsthrone.controller.eventListeners.buttons.ButtonMainMenuEventListener) ItemEffect(com.lilithsthrone.game.inventory.item.ItemEffect) EventListener(org.w3c.dom.events.EventListener) PenetrationType(com.lilithsthrone.game.sex.PenetrationType) TooltipInformationEventListener(com.lilithsthrone.controller.eventListeners.TooltipInformationEventListener) Subspecies(com.lilithsthrone.game.character.race.Subspecies) Main(com.lilithsthrone.main.Main) ObservableValue(javafx.beans.value.ObservableValue) PerkManager(com.lilithsthrone.game.character.effects.PerkManager) AssType(com.lilithsthrone.game.character.body.types.AssType) GameCharacter(com.lilithsthrone.game.character.GameCharacter) SkinType(com.lilithsthrone.game.character.body.types.SkinType) EventHandler(javafx.event.EventHandler) Initializable(javafx.fxml.Initializable) Muscle(com.lilithsthrone.game.character.body.valueEnums.Muscle) URL(java.net.URL) InventoryTooltipEventListener(com.lilithsthrone.controller.eventListeners.InventoryTooltipEventListener) SexualOrientation(com.lilithsthrone.game.character.SexualOrientation) Spell(com.lilithsthrone.game.combat.Spell) RenderingEngine(com.lilithsthrone.rendering.RenderingEngine) VBox(javafx.scene.layout.VBox) CoveringModifier(com.lilithsthrone.game.character.body.valueEnums.CoveringModifier) TooltipResponseMoveEventListener(com.lilithsthrone.controller.eventListeners.TooltipResponseMoveEventListener) LegType(com.lilithsthrone.game.character.body.types.LegType) VaginaType(com.lilithsthrone.game.character.body.types.VaginaType) EventTarget(org.w3c.dom.events.EventTarget) CumProduction(com.lilithsthrone.game.character.body.valueEnums.CumProduction) AbstractItemType(com.lilithsthrone.game.inventory.item.AbstractItemType) TooltipHideEventListener(com.lilithsthrone.controller.eventListeners.TooltipHideEventListener) LipSize(com.lilithsthrone.game.character.body.valueEnums.LipSize) TailType(com.lilithsthrone.game.character.body.types.TailType) ListValue(com.lilithsthrone.utils.Util.ListValue) BreastType(com.lilithsthrone.game.character.body.types.BreastType) UtilText(com.lilithsthrone.game.dialogue.utils.UtilText) SlavePermissionSetting(com.lilithsthrone.game.slavery.SlavePermissionSetting) OrificeModifier(com.lilithsthrone.game.character.body.valueEnums.OrificeModifier) DialogueFlagValue(com.lilithsthrone.game.dialogue.DialogueFlagValue) CopyInfoEventListener(com.lilithsthrone.controller.eventListeners.information.CopyInfoEventListener) InventorySelectedItemEventListener(com.lilithsthrone.controller.eventListeners.InventorySelectedItemEventListener) CharacterModificationUtils(com.lilithsthrone.game.dialogue.utils.CharacterModificationUtils) EarType(com.lilithsthrone.game.character.body.types.EarType) GiftDialogue(com.lilithsthrone.game.dialogue.utils.GiftDialogue) Response(com.lilithsthrone.game.dialogue.responses.Response) CharacterCreation(com.lilithsthrone.game.dialogue.story.CharacterCreation) Util(com.lilithsthrone.utils.Util) FXML(javafx.fxml.FXML) List(java.util.List) CharacterChangeEventListener(com.lilithsthrone.game.character.CharacterChangeEventListener) Covering(com.lilithsthrone.game.character.body.Covering) PerkCategory(com.lilithsthrone.game.character.effects.PerkCategory) TFEssence(com.lilithsthrone.game.inventory.enchanting.TFEssence) DialogueNodeOld(com.lilithsthrone.game.dialogue.DialogueNodeOld) InventoryInteraction(com.lilithsthrone.game.dialogue.utils.InventoryInteraction) Entry(java.util.Map.Entry) EyeType(com.lilithsthrone.game.character.body.types.EyeType) AbstractWeapon(com.lilithsthrone.game.inventory.weapon.AbstractWeapon) WorldType(com.lilithsthrone.world.WorldType) WebEngine(javafx.scene.web.WebEngine) Testicle(com.lilithsthrone.game.character.body.Testicle) ListView(javafx.scene.control.ListView) EnchantmentDialogue(com.lilithsthrone.game.dialogue.utils.EnchantmentDialogue) ButtonCharactersEventListener(com.lilithsthrone.controller.eventListeners.buttons.ButtonCharactersEventListener) FetishDesire(com.lilithsthrone.game.character.fetishes.FetishDesire) HornType(com.lilithsthrone.game.character.body.types.HornType) HashMap(java.util.HashMap) WingType(com.lilithsthrone.game.character.body.types.WingType) ArmType(com.lilithsthrone.game.character.body.types.ArmType) ButtonZoomEventListener(com.lilithsthrone.controller.eventListeners.buttons.ButtonZoomEventListener) AreolaeSize(com.lilithsthrone.game.character.body.valueEnums.AreolaeSize) MapDisplay(com.lilithsthrone.game.dialogue.MapDisplay) OrificeElasticity(com.lilithsthrone.game.character.body.valueEnums.OrificeElasticity) HairStyle(com.lilithsthrone.game.character.body.valueEnums.HairStyle) State(javafx.concurrent.Worker.State) ForcedFetishTendency(com.lilithsthrone.game.settings.ForcedFetishTendency) SlaveJob(com.lilithsthrone.game.slavery.SlaveJob) Tooltip(javafx.scene.control.Tooltip) Capacity(com.lilithsthrone.game.character.body.valueEnums.Capacity) Fetish(com.lilithsthrone.game.character.fetishes.Fetish) KeyCode(javafx.scene.input.KeyCode) WebView(javafx.scene.web.WebView) StatusEffect(com.lilithsthrone.game.character.effects.StatusEffect) GenderPreference(com.lilithsthrone.game.character.gender.GenderPreference) Wetness(com.lilithsthrone.game.character.body.valueEnums.Wetness) Month(java.time.Month) Lactation(com.lilithsthrone.game.character.body.valueEnums.Lactation) AbstractClothingType(com.lilithsthrone.game.inventory.clothing.AbstractClothingType) Attribute(com.lilithsthrone.game.character.attributes.Attribute) AbstractWeaponType(com.lilithsthrone.game.inventory.weapon.AbstractWeaponType) HairType(com.lilithsthrone.game.character.body.types.HairType) PiercingType(com.lilithsthrone.game.character.body.valueEnums.PiercingType) ButtonJournalEventListener(com.lilithsthrone.controller.eventListeners.buttons.ButtonJournalEventListener) History(com.lilithsthrone.game.character.History) GenderPronoun(com.lilithsthrone.game.character.gender.GenderPronoun) ForcedTFTendency(com.lilithsthrone.game.settings.ForcedTFTendency) EyeShape(com.lilithsthrone.game.character.body.valueEnums.EyeShape) PerkEntry(com.lilithsthrone.game.character.effects.PerkEntry) CoveringPattern(com.lilithsthrone.game.character.body.valueEnums.CoveringPattern) Vector2i(com.lilithsthrone.utils.Vector2i) ContentDisplay(javafx.scene.control.ContentDisplay) BreastType(com.lilithsthrone.game.character.body.types.BreastType) CupSize(com.lilithsthrone.game.character.body.valueEnums.CupSize) Covering(com.lilithsthrone.game.character.body.Covering) Gender(com.lilithsthrone.game.character.gender.Gender) History(com.lilithsthrone.game.character.History) InventorySelectedItemEventListener(com.lilithsthrone.controller.eventListeners.InventorySelectedItemEventListener) Month(java.time.Month) Capacity(com.lilithsthrone.game.character.body.valueEnums.Capacity) AssType(com.lilithsthrone.game.character.body.types.AssType) AbstractClothingType(com.lilithsthrone.game.inventory.clothing.AbstractClothingType) TFPotency(com.lilithsthrone.game.inventory.enchanting.TFPotency) SlaveJobHours(com.lilithsthrone.game.slavery.SlaveJobHours) InventoryTooltipEventListener(com.lilithsthrone.controller.eventListeners.InventoryTooltipEventListener) SexualOrientation(com.lilithsthrone.game.character.SexualOrientation) CumProduction(com.lilithsthrone.game.character.body.valueEnums.CumProduction) FaceType(com.lilithsthrone.game.character.body.types.FaceType) NameTriplet(com.lilithsthrone.game.character.NameTriplet) TFEssence(com.lilithsthrone.game.inventory.enchanting.TFEssence) BreastShape(com.lilithsthrone.game.character.body.valueEnums.BreastShape) Perk(com.lilithsthrone.game.character.effects.Perk) AssSize(com.lilithsthrone.game.character.body.valueEnums.AssSize) HipSize(com.lilithsthrone.game.character.body.valueEnums.HipSize) PiercingType(com.lilithsthrone.game.character.body.valueEnums.PiercingType) AbstractWeaponType(com.lilithsthrone.game.inventory.weapon.AbstractWeaponType) CoveringPattern(com.lilithsthrone.game.character.body.valueEnums.CoveringPattern) NippleSize(com.lilithsthrone.game.character.body.valueEnums.NippleSize) DialogueNodeOld(com.lilithsthrone.game.dialogue.DialogueNodeOld) PenisSize(com.lilithsthrone.game.character.body.valueEnums.PenisSize) Colour(com.lilithsthrone.utils.Colour) PerkEntry(com.lilithsthrone.game.character.effects.PerkEntry) AreolaeSize(com.lilithsthrone.game.character.body.valueEnums.AreolaeSize) PenisGirth(com.lilithsthrone.game.character.body.valueEnums.PenisGirth) SexType(com.lilithsthrone.game.sex.SexType) EnchantmentEventListener(com.lilithsthrone.controller.eventListeners.EnchantmentEventListener) HairLength(com.lilithsthrone.game.character.body.valueEnums.HairLength) Personality(com.lilithsthrone.game.character.Personality) PenisType(com.lilithsthrone.game.character.body.types.PenisType) DamageType(com.lilithsthrone.game.combat.DamageType) VaginaType(com.lilithsthrone.game.character.body.types.VaginaType) AbstractItemType(com.lilithsthrone.game.inventory.item.AbstractItemType) HairType(com.lilithsthrone.game.character.body.types.HairType) OrificePlasticity(com.lilithsthrone.game.character.body.valueEnums.OrificePlasticity) WingType(com.lilithsthrone.game.character.body.types.WingType) OrificeModifier(com.lilithsthrone.game.character.body.valueEnums.OrificeModifier) CoveringModifier(com.lilithsthrone.game.character.body.valueEnums.CoveringModifier) SlavePermission(com.lilithsthrone.game.slavery.SlavePermission) BodyCoveringType(com.lilithsthrone.game.character.body.types.BodyCoveringType) TesticleSize(com.lilithsthrone.game.character.body.valueEnums.TesticleSize) ClitorisSize(com.lilithsthrone.game.character.body.valueEnums.ClitorisSize) EyeShape(com.lilithsthrone.game.character.body.valueEnums.EyeShape) PenisModifier(com.lilithsthrone.game.character.body.valueEnums.PenisModifier) Subspecies(com.lilithsthrone.game.character.race.Subspecies) TFModifier(com.lilithsthrone.game.inventory.enchanting.TFModifier) EarType(com.lilithsthrone.game.character.body.types.EarType) BodyHair(com.lilithsthrone.game.character.body.valueEnums.BodyHair) LabiaSize(com.lilithsthrone.game.character.body.valueEnums.LabiaSize) ArrayList(java.util.ArrayList) List(java.util.List) Muscle(com.lilithsthrone.game.character.body.valueEnums.Muscle) HornType(com.lilithsthrone.game.character.body.types.HornType) Cell(com.lilithsthrone.world.Cell) HairStyle(com.lilithsthrone.game.character.body.valueEnums.HairStyle) GenderPreference(com.lilithsthrone.game.character.gender.GenderPreference) KeyboardAction(com.lilithsthrone.game.settings.KeyboardAction) PlaceUpgrade(com.lilithsthrone.world.places.PlaceUpgrade) AntennaType(com.lilithsthrone.game.character.body.types.AntennaType) AbstractClothing(com.lilithsthrone.game.inventory.clothing.AbstractClothing) TailType(com.lilithsthrone.game.character.body.types.TailType) Wetness(com.lilithsthrone.game.character.body.valueEnums.Wetness) TongueModifier(com.lilithsthrone.game.character.body.valueEnums.TongueModifier) ArmType(com.lilithsthrone.game.character.body.types.ArmType) BodySize(com.lilithsthrone.game.character.body.valueEnums.BodySize) ResponseEffectsOnly(com.lilithsthrone.game.dialogue.responses.ResponseEffectsOnly) File(java.io.File) TestNPC(com.lilithsthrone.game.character.npc.dominion.TestNPC) NPC(com.lilithsthrone.game.character.npc.NPC) SlaveJobSetting(com.lilithsthrone.game.slavery.SlaveJobSetting) PerkCategory(com.lilithsthrone.game.character.effects.PerkCategory) LipSize(com.lilithsthrone.game.character.body.valueEnums.LipSize) LegType(com.lilithsthrone.game.character.body.types.LegType) SlaveJob(com.lilithsthrone.game.slavery.SlaveJob) Fetish(com.lilithsthrone.game.character.fetishes.Fetish) FurryPreference(com.lilithsthrone.game.character.race.FurryPreference) EyeType(com.lilithsthrone.game.character.body.types.EyeType) AbstractWeapon(com.lilithsthrone.game.inventory.weapon.AbstractWeapon) EventTarget(org.w3c.dom.events.EventTarget) InventorySlot(com.lilithsthrone.game.inventory.InventorySlot) SkinType(com.lilithsthrone.game.character.body.types.SkinType) AbstractItem(com.lilithsthrone.game.inventory.item.AbstractItem) Response(com.lilithsthrone.game.dialogue.responses.Response) SlavePermissionSetting(com.lilithsthrone.game.slavery.SlavePermissionSetting) FetishDesire(com.lilithsthrone.game.character.fetishes.FetishDesire) ItemEffect(com.lilithsthrone.game.inventory.item.ItemEffect) OrificeElasticity(com.lilithsthrone.game.character.body.valueEnums.OrificeElasticity)

Example 2 with TongueModifier

use of com.lilithsthrone.game.character.body.valueEnums.TongueModifier in project liliths-throne-public by Innoxia.

the class Body method loadFromXML.

public static Body loadFromXML(StringBuilder log, Element parentElement, Document doc) {
    // **************** Core **************** //
    Element element = (Element) parentElement.getElementsByTagName("bodyCore").item(0);
    int importedFemininity = (Integer.valueOf(element.getAttribute("femininity")));
    CharacterUtils.appendToImportLog(log, "</br>Body: Set femininity: " + Integer.valueOf(element.getAttribute("femininity")));
    int importedHeight = (Integer.valueOf(element.getAttribute("height")));
    CharacterUtils.appendToImportLog(log, "</br>Body: Set height: " + Integer.valueOf(element.getAttribute("height")));
    int importedBodySize = (Integer.valueOf(element.getAttribute("bodySize")));
    CharacterUtils.appendToImportLog(log, "</br>Body: Set body size: " + Integer.valueOf(element.getAttribute("bodySize")));
    int importedMuscle = (Integer.valueOf(element.getAttribute("muscle")));
    CharacterUtils.appendToImportLog(log, "</br>Body: Set muscle: " + Integer.valueOf(element.getAttribute("muscle")));
    // TODO export
    GenitalArrangement importedGenitalArrangement = GenitalArrangement.NORMAL;
    if (element.getAttribute("genitalArrangement") != null && !element.getAttribute("genitalArrangement").isEmpty()) {
        importedGenitalArrangement = GenitalArrangement.valueOf(element.getAttribute("genitalArrangement"));
    }
    BodyMaterial importedBodyMaterial = BodyMaterial.FLESH;
    if (element.getAttribute("bodyMaterial") != null && !element.getAttribute("bodyMaterial").isEmpty()) {
        importedBodyMaterial = BodyMaterial.valueOf(element.getAttribute("bodyMaterial"));
    }
    // **************** Antenna **************** //
    Element antennae = (Element) parentElement.getElementsByTagName("antennae").item(0);
    Antenna importedAntenna = new Antenna(AntennaType.valueOf(antennae.getAttribute("type")));
    CharacterUtils.appendToImportLog(log, "</br></br>Body: Antennae:" + "</br>type: " + importedAntenna.getType());
    importedAntenna.rows = Integer.valueOf(antennae.getAttribute("rows"));
    CharacterUtils.appendToImportLog(log, "</br>rows: " + importedAntenna.getAntennaRows());
    // **************** Arm **************** //
    Element arm = (Element) parentElement.getElementsByTagName("arm").item(0);
    Arm importedArm = new Arm(ArmType.valueOf(arm.getAttribute("type")), Integer.valueOf(arm.getAttribute("rows")));
    CharacterUtils.appendToImportLog(log, "</br></br>Body: Arm:" + "</br>type: " + importedArm.getType());
    CharacterUtils.appendToImportLog(log, "</br>rows: " + importedArm.getArmRows());
    try {
        importedArm.underarmHair = BodyHair.valueOf(arm.getAttribute("underarmHair"));
        CharacterUtils.appendToImportLog(log, "</br>underarm hair: " + importedArm.getUnderarmHair());
    } catch (IllegalArgumentException e) {
        importedArm.underarmHair = BodyHair.ZERO_NONE;
        CharacterUtils.appendToImportLog(log, "</br>underarm hair: OLD_VALUE - Set to NONE");
    }
    // **************** Ass **************** //
    Element ass = (Element) parentElement.getElementsByTagName("ass").item(0);
    Element anus = (Element) parentElement.getElementsByTagName("anus").item(0);
    Ass importedAss = new Ass(AssType.valueOf(ass.getAttribute("type")), Integer.valueOf(ass.getAttribute("assSize")), Integer.valueOf(anus.getAttribute("wetness")), Float.valueOf(anus.getAttribute("capacity")), Integer.valueOf(anus.getAttribute("elasticity")), Integer.valueOf(anus.getAttribute("plasticity")), Boolean.valueOf(anus.getAttribute("virgin")));
    importedAss.hipSize = Integer.valueOf(ass.getAttribute("hipSize"));
    importedAss.anus.orificeAnus.stretchedCapacity = (Float.valueOf(anus.getAttribute("stretchedCapacity")));
    importedAss.anus.bleached = (Boolean.valueOf(anus.getAttribute("bleached")));
    try {
        importedAss.anus.assHair = (BodyHair.valueOf(anus.getAttribute("assHair")));
    } catch (IllegalArgumentException e) {
        importedAss.anus.assHair = BodyHair.ZERO_NONE;
        CharacterUtils.appendToImportLog(log, "</br>ass hair: OLD_VALUE - Set to NONE");
    }
    CharacterUtils.appendToImportLog(log, "</br></br>Body: Ass:" + "</br>type: " + importedAss.getType() + "</br>assSize: " + importedAss.getAssSize() + "</br>hipSize: " + importedAss.getHipSize());
    if (anus != null) {
        CharacterUtils.appendToImportLog(log, "</br></br>Anus:" + "</br>wetness: " + importedAss.anus.orificeAnus.wetness + "</br>elasticity: " + importedAss.anus.orificeAnus.elasticity + "</br>elasticity: " + importedAss.anus.orificeAnus.plasticity + "</br>capacity: " + importedAss.anus.orificeAnus.capacity + "</br>stretchedCapacity: " + importedAss.anus.orificeAnus.stretchedCapacity + "</br>virgin: " + importedAss.anus.orificeAnus.virgin + "</br>bleached: " + importedAss.anus.bleached + "</br>assHair: " + importedAss.anus.assHair + "</br>Modifiers:");
        Element anusModifiers = (Element) anus.getElementsByTagName("anusModifiers").item(0);
        importedAss.anus.orificeAnus.orificeModifiers.clear();
        for (OrificeModifier om : OrificeModifier.values()) {
            if (Boolean.valueOf(anusModifiers.getAttribute(om.toString()))) {
                importedAss.anus.orificeAnus.orificeModifiers.add(om);
                CharacterUtils.appendToImportLog(log, "</br>" + om.toString() + ":true");
            } else {
                CharacterUtils.appendToImportLog(log, "</br>" + om.toString() + ":false");
            }
        }
    }
    // **************** Breasts **************** //
    Element breasts = (Element) parentElement.getElementsByTagName("breasts").item(0);
    Element nipples = (Element) parentElement.getElementsByTagName("nipples").item(0);
    BreastShape breastShape = BreastShape.ROUND;
    try {
        breastShape = BreastShape.valueOf(breasts.getAttribute("shape"));
    } catch (Exception e) {
    }
    int milkStorage = 0;
    try {
        if (!breasts.getAttribute("lactation").isEmpty()) {
            milkStorage = Integer.valueOf(breasts.getAttribute("lactation"));
        } else {
            milkStorage = Integer.valueOf(breasts.getAttribute("milkStorage"));
        }
    } catch (Exception ex) {
    }
    Breast importedBreast = new Breast(BreastType.valueOf(breasts.getAttribute("type")), breastShape, Integer.valueOf(breasts.getAttribute("size")), milkStorage, Integer.valueOf(breasts.getAttribute("rows")), Integer.valueOf(nipples.getAttribute("nippleSize")), NippleShape.valueOf(nipples.getAttribute("nippleShape")), Integer.valueOf(nipples.getAttribute("areolaeSize")), Integer.valueOf(breasts.getAttribute("nippleCountPerBreast")), Float.valueOf(nipples.getAttribute("capacity")), Integer.valueOf(nipples.getAttribute("elasticity")), Integer.valueOf(nipples.getAttribute("plasticity")), Boolean.valueOf(nipples.getAttribute("virgin")));
    try {
        importedBreast.milkStored = Integer.valueOf(breasts.getAttribute("storedMilk"));
        importedBreast.milkRegeneration = Integer.valueOf(breasts.getAttribute("milkRegeneration"));
    } catch (Exception ex) {
    }
    importedBreast.nipples.orificeNipples.stretchedCapacity = (Float.valueOf(nipples.getAttribute("stretchedCapacity")));
    importedBreast.nipples.pierced = (Boolean.valueOf(nipples.getAttribute("pierced")));
    importedBreast.nipples.areolaeShape = (AreolaeShape.valueOf(nipples.getAttribute("areolaeShape")));
    CharacterUtils.appendToImportLog(log, "</br></br>Body: Breasts:" + "</br>type: " + importedBreast.getType() + "</br>size: " + importedBreast.getSize() + "</br>rows: " + importedBreast.getRows() + "</br>lactation: " + importedBreast.getRawMilkStorageValue() + "</br>nippleCountPer: " + importedBreast.getNippleCountPerBreast() + "</br></br>Nipples:" + "</br>elasticity: " + importedBreast.nipples.orificeNipples.getElasticity() + "</br>plasticity: " + importedBreast.nipples.orificeNipples.getPlasticity() + "</br>capacity: " + importedBreast.nipples.orificeNipples.getRawCapacityValue() + "</br>stretchedCapacity: " + importedBreast.nipples.orificeNipples.getStretchedCapacity() + "</br>virgin: " + importedBreast.nipples.orificeNipples.isVirgin() + "</br>pierced: " + importedBreast.nipples.isPierced() + "</br>nippleSize: " + importedBreast.nipples.getNippleSize() + "</br>nippleShape: " + importedBreast.nipples.getNippleShape() + "</br>areolaeSize: " + importedBreast.nipples.getAreolaeSize() + "</br>areolaeShape: " + importedBreast.nipples.getAreolaeShape() + "</br>Modifiers:");
    Element nippleModifiers = (Element) nipples.getElementsByTagName("nippleModifiers").item(0);
    importedBreast.nipples.orificeNipples.orificeModifiers.clear();
    for (OrificeModifier om : OrificeModifier.values()) {
        if (Boolean.valueOf(nippleModifiers.getAttribute(om.toString()))) {
            importedBreast.nipples.orificeNipples.orificeModifiers.add(om);
            CharacterUtils.appendToImportLog(log, "</br>" + om.toString() + ":true");
        } else {
            CharacterUtils.appendToImportLog(log, "</br>" + om.toString() + ":false");
        }
    }
    CharacterUtils.appendToImportLog(log, "</br></br>Milk:");
    Element milk = (Element) parentElement.getElementsByTagName("milk").item(0);
    importedBreast.milk.flavour = (FluidFlavour.valueOf(milk.getAttribute("flavour")));
    CharacterUtils.appendToImportLog(log, " flavour: " + importedBreast.milk.getFlavour() + "</br>Modifiers:");
    Element milkModifiers = (Element) milk.getElementsByTagName("milkModifiers").item(0);
    for (FluidModifier fm : FluidModifier.values()) {
        if (Boolean.valueOf(milkModifiers.getAttribute(fm.toString()))) {
            importedBreast.milk.fluidModifiers.add(fm);
            CharacterUtils.appendToImportLog(log, "</br>" + fm.toString() + ":true");
        } else {
            CharacterUtils.appendToImportLog(log, "</br>" + fm.toString() + ":false");
        }
    }
    // **************** Ear **************** //
    Element ear = (Element) parentElement.getElementsByTagName("ear").item(0);
    Ear importedEar = new Ear(EarType.valueOf(ear.getAttribute("type")));
    importedEar.pierced = (Boolean.valueOf(ear.getAttribute("pierced")));
    CharacterUtils.appendToImportLog(log, "</br></br>Body: Ear:" + "</br>type: " + importedEar.getType() + "</br>pierced: " + importedEar.isPierced());
    // **************** Eye **************** //
    Element eye = (Element) parentElement.getElementsByTagName("eye").item(0);
    String eyeTypeFromSave = eye.getAttribute("type");
    Map<String, String> eyeTypeConverterMap = new HashMap<>();
    eyeTypeConverterMap.put("EYE_HUMAN", "HUMAN");
    eyeTypeConverterMap.put("EYE_ANGEL", "ANGEL");
    eyeTypeConverterMap.put("EYE_DEMON_COMMON", "DEMON_COMMON");
    eyeTypeConverterMap.put("EYE_DOG_MORPH", "DOG_MORPH");
    eyeTypeConverterMap.put("EYE_LYCAN", "LYCAN");
    eyeTypeConverterMap.put("EYE_FELINE", "CAT_MORPH");
    eyeTypeConverterMap.put("EYE_SQUIRREL", "SQUIRREL_MORPH");
    eyeTypeConverterMap.put("EYE_HORSE_MORPH", "HORSE_MORPH");
    eyeTypeConverterMap.put("EYE_HARPY", "HARPY");
    eyeTypeConverterMap.put("EYE_SLIME", "SLIME");
    if (eyeTypeConverterMap.containsKey(eyeTypeFromSave)) {
        eyeTypeFromSave = eyeTypeConverterMap.get(eyeTypeFromSave);
    }
    Eye importedEye = new Eye(EyeType.valueOf(eyeTypeFromSave));
    importedEye.eyePairs = (Integer.valueOf(eye.getAttribute("eyePairs")));
    importedEye.irisShape = (EyeShape.valueOf(eye.getAttribute("irisShape")));
    importedEye.pupilShape = (EyeShape.valueOf(eye.getAttribute("pupilShape")));
    CharacterUtils.appendToImportLog(log, "</br></br>Body: Eye:" + "</br>type: " + importedEye.getType() + "</br>pairs: " + importedEye.getEyePairs() + "</br>iris shape: " + importedEye.getIrisShape() + "</br>pupil shape: " + importedEye.getPupilShape());
    // **************** Face **************** //
    Element face = (Element) parentElement.getElementsByTagName("face").item(0);
    Element mouth = (Element) parentElement.getElementsByTagName("mouth").item(0);
    Face importedFace = new Face(FaceType.valueOf(face.getAttribute("type")), Integer.valueOf(mouth.getAttribute("lipSize")));
    importedFace.piercedNose = (Boolean.valueOf(face.getAttribute("piercedNose")));
    try {
        importedFace.facialHair = (BodyHair.valueOf(face.getAttribute("facialHair")));
    } catch (IllegalArgumentException e) {
        importedFace.facialHair = BodyHair.ZERO_NONE;
        CharacterUtils.appendToImportLog(log, "</br>facial hair: OLD_VALUE - Set to NONE");
    }
    CharacterUtils.appendToImportLog(log, "</br></br>Body: Face: " + "</br>type: " + importedFace.getType() + "</br>piercedNose: " + importedFace.isPiercedNose() + "</br>facial hair: " + importedFace.getFacialHair() + "</br></br>Mouth: ");
    importedFace.mouth.orificeMouth.elasticity = (Integer.valueOf(mouth.getAttribute("elasticity")));
    importedFace.mouth.orificeMouth.plasticity = (Integer.valueOf(mouth.getAttribute("plasticity")));
    importedFace.mouth.orificeMouth.capacity = (Float.valueOf(mouth.getAttribute("capacity")));
    importedFace.mouth.orificeMouth.stretchedCapacity = (Float.valueOf(mouth.getAttribute("stretchedCapacity")));
    importedFace.mouth.orificeMouth.virgin = (Boolean.valueOf(mouth.getAttribute("virgin")));
    importedFace.mouth.piercedLip = (Boolean.valueOf(mouth.getAttribute("piercedLip")));
    CharacterUtils.appendToImportLog(log, "</br>elasticity: " + importedFace.mouth.orificeMouth.getElasticity() + "</br>plasticity: " + importedFace.mouth.orificeMouth.getPlasticity() + "</br>capacity: " + importedFace.mouth.orificeMouth.getCapacity() + "</br>stretchedCapacity: " + importedFace.mouth.orificeMouth.getStretchedCapacity() + "</br>virgin: " + importedFace.mouth.orificeMouth.isVirgin() + "</br>piercedLip: " + importedFace.mouth.isPiercedLip() + "</br>lipSize: " + importedFace.mouth.getLipSize() + "</br>Modifiers: ");
    Element mouthModifiers = (Element) mouth.getElementsByTagName("mouthModifiers").item(0);
    importedFace.mouth.orificeMouth.orificeModifiers.clear();
    for (OrificeModifier om : OrificeModifier.values()) {
        if (Boolean.valueOf(mouthModifiers.getAttribute(om.toString()))) {
            importedFace.mouth.orificeMouth.orificeModifiers.add(om);
            CharacterUtils.appendToImportLog(log, "</br>" + om.toString() + ":true");
        } else {
            CharacterUtils.appendToImportLog(log, "</br>" + om.toString() + ":false");
        }
    }
    Element tongue = (Element) parentElement.getElementsByTagName("tongue").item(0);
    importedFace.tongue.pierced = (Boolean.valueOf(tongue.getAttribute("piercedTongue")));
    importedFace.tongue.tongueLength = (Integer.valueOf(tongue.getAttribute("tongueLength")));
    CharacterUtils.appendToImportLog(log, "</br></br>Tongue: " + "</br>piercedTongue: " + importedFace.tongue.isPierced() + "</br>tongueLength: " + importedFace.tongue.getTongueLength() + "</br>Modifiers: ");
    Element tongueModifiers = (Element) tongue.getElementsByTagName("tongueModifiers").item(0);
    importedFace.tongue.tongueModifiers.clear();
    for (TongueModifier tm : TongueModifier.values()) {
        if (Boolean.valueOf(tongueModifiers.getAttribute(tm.toString()))) {
            importedFace.tongue.tongueModifiers.add(tm);
            CharacterUtils.appendToImportLog(log, "</br>" + tm.toString() + ":true");
        } else {
            CharacterUtils.appendToImportLog(log, "</br>" + tm.toString() + ":false");
        }
    }
    // **************** Hair **************** //
    Element hair = (Element) parentElement.getElementsByTagName("hair").item(0);
    String hairTypeFromSave = hair.getAttribute("type");
    Map<String, String> hairTypeConverterMap = new HashMap<>();
    hairTypeConverterMap.put("HAIR_HUMAN", "HUMAN");
    hairTypeConverterMap.put("HAIR_ANGEL", "ANGEL");
    hairTypeConverterMap.put("HAIR_DEMON", "DEMON_COMMON");
    hairTypeConverterMap.put("HAIR_CANINE_FUR", "DOG_MORPH");
    hairTypeConverterMap.put("HAIR_LYCAN_FUR", "LYCAN");
    hairTypeConverterMap.put("HAIR_FELINE_FUR", "CAT_MORPH");
    hairTypeConverterMap.put("HAIR_HORSE_HAIR", "HORSE_MORPH");
    hairTypeConverterMap.put("HAIR_SQUIRREL_FUR", "SQUIRREL_MORPH");
    hairTypeConverterMap.put("SLIME", "SLIME");
    hairTypeConverterMap.put("HAIR_HARPY", "HARPY");
    if (hairTypeConverterMap.containsKey(hairTypeFromSave)) {
        hairTypeFromSave = hairTypeConverterMap.get(hairTypeFromSave);
    }
    Hair importedHair = new Hair(HairType.valueOf(hairTypeFromSave), Integer.valueOf(hair.getAttribute("length")), HairStyle.valueOf(hair.getAttribute("hairStyle")));
    CharacterUtils.appendToImportLog(log, "</br></br>Body: Hair: " + "</br>type: " + importedHair.getType() + "</br>length: " + importedHair.getLength() + "</br>hairStyle: " + importedHair.getStyle());
    // **************** Horn **************** //
    Element horn = (Element) parentElement.getElementsByTagName("horn").item(0);
    Horn importedHorn = new Horn(HornType.NONE, 0);
    int rows = (Integer.valueOf(horn.getAttribute("rows")));
    String hornType = horn.getAttribute("type");
    if (hornType.equals("DEMON")) {
        hornType = "";
    }
    if (hornType.equals("BOVINE")) {
        hornType = "";
    }
    int length = 0;
    if (!hornType.equals("NONE")) {
        length = HornLength.TWO_LONG.getMedianValue();
    }
    if (!horn.getAttribute("length").isEmpty()) {
        try {
            length = Integer.valueOf(horn.getAttribute("length"));
        } catch (IllegalArgumentException e) {
        }
    }
    try {
        importedHorn = new Horn(HornType.valueOf(hornType), length);
        importedHorn.rows = rows;
        CharacterUtils.appendToImportLog(log, "</br></br>Body: Horn: " + "</br>type: " + importedHorn.getType() + "</br>length: " + length + "</br>rows: " + importedHorn.getHornRows());
    } catch (IllegalArgumentException e) {
        if (horn.getAttribute("type").startsWith("DEMON")) {
            importedHorn = new Horn(HornType.SWEPT_BACK, length);
            importedHorn.rows = rows;
        } else if (horn.getAttribute("type").startsWith("BOVINE")) {
            importedHorn = new Horn(HornType.CURVED, length);
            importedHorn.rows = rows;
        }
        CharacterUtils.appendToImportLog(log, "</br></br>Body: Horn: " + "</br>type NOT FOUND, defaulted to: " + importedHorn.getType() + "</br>rows: " + importedHorn.getHornRows());
    }
    // **************** Leg **************** //
    Element leg = (Element) parentElement.getElementsByTagName("leg").item(0);
    Leg importedLeg = new Leg(LegType.valueOf(leg.getAttribute("type")));
    CharacterUtils.appendToImportLog(log, "</br></br>Body: Leg: " + "</br>type: " + importedLeg.getType());
    // **************** Penis **************** //
    Element penis = (Element) parentElement.getElementsByTagName("penis").item(0);
    Element testicles = (Element) parentElement.getElementsByTagName("testicles").item(0);
    int girth = 2;
    if (penis.getAttribute("girth") != null && !penis.getAttribute("girth").isEmpty()) {
        girth = Integer.valueOf(penis.getAttribute("girth"));
    }
    Penis importedPenis = new Penis(PenisType.valueOf(penis.getAttribute("type")), Integer.valueOf(penis.getAttribute("size")), girth, Integer.valueOf(testicles.getAttribute("testicleSize")), Integer.valueOf(testicles.getAttribute("cumProduction")), Integer.valueOf(testicles.getAttribute("numberOfTesticles")));
    importedPenis.pierced = (Boolean.valueOf(penis.getAttribute("pierced")));
    if (!penis.getAttribute("virgin").isEmpty()) {
        importedPenis.virgin = (Boolean.valueOf(penis.getAttribute("virgin")));
    }
    CharacterUtils.appendToImportLog(log, "</br></br>Body: Penis: " + "</br>type: " + importedPenis.getType() + "</br>size: " + importedPenis.getRawSizeValue() + "</br>pierced: " + importedPenis.isPierced() + "</br>Penis Modifiers: ");
    Element penisModifiers = (Element) penis.getElementsByTagName("penisModifiers").item(0);
    importedPenis.penisModifiers.clear();
    for (PenisModifier pm : PenisModifier.values()) {
        if (penisModifiers != null && Boolean.valueOf(penisModifiers.getAttribute(pm.toString()))) {
            importedPenis.penisModifiers.add(pm);
            CharacterUtils.appendToImportLog(log, "</br>" + pm.toString() + ":true");
        } else {
            CharacterUtils.appendToImportLog(log, "</br>" + pm.toString() + ":false");
        }
    }
    importedPenis.orificeUrethra.elasticity = (Integer.valueOf(penis.getAttribute("elasticity")));
    importedPenis.orificeUrethra.plasticity = (Integer.valueOf(penis.getAttribute("plasticity")));
    importedPenis.orificeUrethra.capacity = (Float.valueOf(penis.getAttribute("capacity")));
    importedPenis.orificeUrethra.stretchedCapacity = (Float.valueOf(penis.getAttribute("stretchedCapacity")));
    if (!penis.getAttribute("urethraVirgin").isEmpty()) {
        importedPenis.orificeUrethra.virgin = (Boolean.valueOf(penis.getAttribute("urethraVirgin")));
    } else {
        importedPenis.orificeUrethra.virgin = true;
    }
    CharacterUtils.appendToImportLog(log, "</br>elasticity: " + importedPenis.orificeUrethra.getElasticity() + "</br>plasticity: " + importedPenis.orificeUrethra.getPlasticity() + "</br>capacity: " + importedPenis.orificeUrethra.getCapacity() + "</br>stretchedCapacity: " + importedPenis.orificeUrethra.getStretchedCapacity() + "</br>virgin: " + importedPenis.orificeUrethra.isVirgin() + "</br>Urethra Modifiers:");
    Element urethraModifiers = (Element) penis.getElementsByTagName("urethraModifiers").item(0);
    importedPenis.orificeUrethra.orificeModifiers.clear();
    for (OrificeModifier om : OrificeModifier.values()) {
        if (Boolean.valueOf(urethraModifiers.getAttribute(om.toString()))) {
            importedPenis.orificeUrethra.orificeModifiers.add(om);
            CharacterUtils.appendToImportLog(log, "</br>" + om.toString() + ":true");
        } else {
            CharacterUtils.appendToImportLog(log, "</br>" + om.toString() + ":false");
        }
    }
    importedPenis.testicle.internal = (Boolean.valueOf(testicles.getAttribute("internal")));
    CharacterUtils.appendToImportLog(log, "</br></br>Testicles: " + "</br>cumProduction: " + importedPenis.testicle.getRawCumProductionValue() + "</br>numberOfTesticles: " + importedPenis.testicle.getTesticleCount() + "</br>testicleSize: " + importedPenis.testicle.getTesticleSize() + "</br>internal: " + importedPenis.testicle.isInternal());
    CharacterUtils.appendToImportLog(log, "</br></br>Cum:");
    Element cum = (Element) parentElement.getElementsByTagName("cum").item(0);
    importedPenis.testicle.cum.flavour = (FluidFlavour.valueOf(cum.getAttribute("flavour")));
    CharacterUtils.appendToImportLog(log, " flavour: " + importedPenis.testicle.cum.getFlavour() + "</br>Modifiers:");
    Element cumModifiers = (Element) cum.getElementsByTagName("cumModifiers").item(0);
    for (FluidModifier fm : FluidModifier.values()) {
        if (Boolean.valueOf(cumModifiers.getAttribute(fm.toString()))) {
            importedPenis.testicle.cum.fluidModifiers.add(fm);
            CharacterUtils.appendToImportLog(log, "</br>" + fm.toString() + ":true");
        } else {
            CharacterUtils.appendToImportLog(log, "</br>" + fm.toString() + ":false");
        }
    }
    // **************** Skin **************** //
    Element skin = (Element) parentElement.getElementsByTagName("skin").item(0);
    String skinTypeFromSave = skin.getAttribute("type");
    Map<String, String> skinTypeConverterMap = new HashMap<>();
    skinTypeConverterMap.put("HUMAN", "HUMAN");
    skinTypeConverterMap.put("ANGEL", "ANGEL");
    skinTypeConverterMap.put("DEMON_COMMON", "DEMON_COMMON");
    skinTypeConverterMap.put("CANINE_FUR", "DOG_MORPH");
    skinTypeConverterMap.put("LYCAN_FUR", "LYCAN");
    skinTypeConverterMap.put("FELINE_FUR", "CAT_MORPH");
    skinTypeConverterMap.put("SQUIRREL_FUR", "SQUIRREL_MORPH");
    skinTypeConverterMap.put("HORSE_HAIR", "HORSE_MORPH");
    skinTypeConverterMap.put("SLIME", "SLIME");
    skinTypeConverterMap.put("FEATHERS", "HARPY");
    if (skinTypeConverterMap.containsKey(skinTypeFromSave)) {
        skinTypeFromSave = skinTypeConverterMap.get(skinTypeFromSave);
    }
    Skin importedSkin = new Skin(SkinType.valueOf(skinTypeFromSave));
    CharacterUtils.appendToImportLog(log, "</br></br>Body: Skin: " + "</br>type: " + importedSkin.getType());
    // **************** Tail **************** //
    Element tail = (Element) parentElement.getElementsByTagName("tail").item(0);
    Tail importedTail = new Tail(TailType.valueOf(tail.getAttribute("type")));
    importedTail.tailCount = (Integer.valueOf(tail.getAttribute("count")));
    CharacterUtils.appendToImportLog(log, "</br></br>Body: Tail: " + "</br>type: " + importedTail.getType() + "</br>count: " + importedTail.getTailCount());
    // **************** Vagina **************** //
    Element vagina = (Element) parentElement.getElementsByTagName("vagina").item(0);
    Vagina importedVagina = new Vagina(VaginaType.valueOf(vagina.getAttribute("type")), (vagina.getAttribute("labiaSize").isEmpty() ? 1 : Integer.valueOf(vagina.getAttribute("labiaSize"))), Integer.valueOf(vagina.getAttribute("clitSize")), Integer.valueOf(vagina.getAttribute("wetness")), Float.valueOf(vagina.getAttribute("capacity")), Integer.valueOf(vagina.getAttribute("elasticity")), Integer.valueOf(vagina.getAttribute("plasticity")), Boolean.valueOf(vagina.getAttribute("virgin")));
    importedVagina.pierced = (Boolean.valueOf(vagina.getAttribute("pierced")));
    importedVagina.orificeVagina.stretchedCapacity = (Float.valueOf(vagina.getAttribute("stretchedCapacity")));
    try {
        importedVagina.orificeVagina.squirter = (Boolean.valueOf(vagina.getAttribute("squirter")));
    } catch (Exception ex) {
    }
    CharacterUtils.appendToImportLog(log, "</br></br>Body: Vagina: " + "</br>type: " + importedVagina.getType() + "</br>clitSize: " + importedVagina.getClitorisSize() + "</br>pierced: " + importedVagina.isPierced() + "</br>wetness: " + importedVagina.orificeVagina.wetness + "</br>elasticity: " + importedVagina.orificeVagina.getElasticity() + "</br>plasticity: " + importedVagina.orificeVagina.getPlasticity() + "</br>capacity: " + importedVagina.orificeVagina.getCapacity() + "</br>stretchedCapacity: " + importedVagina.orificeVagina.getStretchedCapacity() + "</br>virgin: " + importedVagina.orificeVagina.isVirgin());
    Element vaginaModifiers = (Element) vagina.getElementsByTagName("vaginaModifiers").item(0);
    importedVagina.orificeVagina.orificeModifiers.clear();
    if (vaginaModifiers != null) {
        for (OrificeModifier om : OrificeModifier.values()) {
            if (Boolean.valueOf(vaginaModifiers.getAttribute(om.toString()))) {
                importedVagina.orificeVagina.orificeModifiers.add(om);
                CharacterUtils.appendToImportLog(log, "</br>" + om.toString() + ":true");
            } else {
                CharacterUtils.appendToImportLog(log, "</br>" + om.toString() + ":false");
            }
        }
    }
    CharacterUtils.appendToImportLog(log, "</br></br>Girlcum:");
    Element girlcum = (Element) parentElement.getElementsByTagName("girlcum").item(0);
    importedVagina.girlcum.flavour = (FluidFlavour.valueOf(girlcum.getAttribute("flavour")));
    CharacterUtils.appendToImportLog(log, " flavour: " + importedVagina.girlcum.getFlavour() + "</br>Modifiers:");
    Element girlcumModifiers = (Element) girlcum.getElementsByTagName("girlcumModifiers").item(0);
    for (FluidModifier fm : FluidModifier.values()) {
        if (Boolean.valueOf(girlcumModifiers.getAttribute(fm.toString()))) {
            importedVagina.girlcum.fluidModifiers.add(fm);
            CharacterUtils.appendToImportLog(log, "</br>" + fm.toString() + ":true");
        } else {
            CharacterUtils.appendToImportLog(log, "</br>" + fm.toString() + ":false");
        }
    }
    // **************** Wing **************** //
    Element wing = (Element) parentElement.getElementsByTagName("wing").item(0);
    int wingSize = 0;
    if (!wing.getAttribute("size").isEmpty()) {
        wingSize = Integer.valueOf(wing.getAttribute("size"));
    }
    Wing importedWing = new Wing(WingType.valueOf(wing.getAttribute("type")), wingSize);
    CharacterUtils.appendToImportLog(log, "</br></br>Body: Wing: " + "</br>type: " + importedWing.getType() + "</br>" + "</br>size: " + importedWing.getSizeValue() + "</br>");
    Body body = new Body.BodyBuilder(importedArm, importedAss, importedBreast, importedFace, importedEye, importedEar, importedHair, importedLeg, importedSkin, importedBodyMaterial, importedGenitalArrangement, importedHeight, importedFemininity, importedBodySize, importedMuscle).vagina(importedVagina).penis(importedPenis).horn(importedHorn).antenna(importedAntenna).tail(importedTail).wing(importedWing).build();
    body.setPiercedStomach(Boolean.valueOf(element.getAttribute("piercedStomach")));
    CharacterUtils.appendToImportLog(log, "</br>Body: Set piercedStomach: " + Boolean.valueOf(element.getAttribute("piercedStomach")));
    if (element.getAttribute("pubicHair") != null && !element.getAttribute("pubicHair").isEmpty()) {
        try {
            body.setPubicHair(BodyHair.valueOf(element.getAttribute("pubicHair")));
            CharacterUtils.appendToImportLog(log, "</br>Body: Set pubicHair: " + body.getPubicHair());
        } catch (IllegalArgumentException e) {
            body.pubicHair = BodyHair.ZERO_NONE;
            CharacterUtils.appendToImportLog(log, "</br>pubic hair: OLD_VALUE - Set to NONE");
        }
    }
    for (int i = 0; i < element.getElementsByTagName("bodyCovering").getLength(); i++) {
        Element e = ((Element) element.getElementsByTagName("bodyCovering").item(i));
        String type = e.getAttribute("type");
        if (type.equals("HORN_COW") || type.equals("HORN_DEMON")) {
            type = "HORN";
        }
        try {
            String colourPrimary = e.getAttribute("colourPrimary");
            String colourSecondary = e.getAttribute("colourSecondary");
            if (type.startsWith("HAIR_")) {
                if (colourPrimary.equals("COVERING_TAN")) {
                    colourPrimary = "COVERING_DIRTY_BLONDE";
                }
                if (colourSecondary.equals("COVERING_TAN")) {
                    colourSecondary = "COVERING_DIRTY_BLONDE";
                }
            }
            if (e.getAttribute("modifier").isEmpty()) {
                body.setBodyCoveringForXMLImport(BodyCoveringType.valueOf(type), CoveringPattern.valueOf(e.getAttribute("pattern")), Colour.valueOf(colourPrimary), !e.getAttribute("glowPrimary").isEmpty() ? Boolean.valueOf(e.getAttribute("glowPrimary")) : false, Colour.valueOf(colourSecondary), !e.getAttribute("glowSecondary").isEmpty() ? Boolean.valueOf(e.getAttribute("glowSecondary")) : false);
            } else {
                BodyCoveringType coveringType = BodyCoveringType.valueOf(type);
                CoveringModifier modifier = CoveringModifier.valueOf(e.getAttribute("modifier"));
                body.setBodyCoveringForXMLImport(coveringType, CoveringPattern.valueOf(e.getAttribute("pattern")), coveringType.getNaturalModifiers().contains(modifier) || coveringType.getExtraModifiers().contains(modifier) ? modifier : coveringType.getNaturalModifiers().get(0), Colour.valueOf(colourPrimary), !e.getAttribute("glowPrimary").isEmpty() ? Boolean.valueOf(e.getAttribute("glowPrimary")) : false, Colour.valueOf(colourSecondary), !e.getAttribute("glowSecondary").isEmpty() ? Boolean.valueOf(e.getAttribute("glowSecondary")) : false);
            }
            if (!e.getAttribute("discovered").isEmpty() && Boolean.valueOf(e.getAttribute("discovered"))) {
                body.getBodyCoveringTypesDiscovered().add(BodyCoveringType.valueOf(type));
            }
            CharacterUtils.appendToImportLog(log, "</br>Body: Set bodyCovering: " + e.getAttribute("type") + " pattern:" + CoveringPattern.valueOf(e.getAttribute("pattern")) + " " + Colour.valueOf(e.getAttribute("colourPrimary")) + " glow:" + Boolean.valueOf(e.getAttribute("glowPrimary")) + " | " + Colour.valueOf(e.getAttribute("colourSecondary")) + " glow:" + Boolean.valueOf(e.getAttribute("glowSecondary")) + " (discovered: " + e.getAttribute("discovered") + ")");
        } catch (Exception ex) {
        }
    }
    body.calculateRace();
    return body;
}
Also used : HashMap(java.util.HashMap) CoveringModifier(com.lilithsthrone.game.character.body.valueEnums.CoveringModifier) Element(org.w3c.dom.Element) BodyCoveringType(com.lilithsthrone.game.character.body.types.BodyCoveringType) PenisModifier(com.lilithsthrone.game.character.body.valueEnums.PenisModifier) BodyHair(com.lilithsthrone.game.character.body.valueEnums.BodyHair) GenitalArrangement(com.lilithsthrone.game.character.body.valueEnums.GenitalArrangement) BodyMaterial(com.lilithsthrone.game.character.body.valueEnums.BodyMaterial) BreastShape(com.lilithsthrone.game.character.body.valueEnums.BreastShape) FluidModifier(com.lilithsthrone.game.character.body.valueEnums.FluidModifier) TongueModifier(com.lilithsthrone.game.character.body.valueEnums.TongueModifier) OrificeModifier(com.lilithsthrone.game.character.body.valueEnums.OrificeModifier)

Example 3 with TongueModifier

use of com.lilithsthrone.game.character.body.valueEnums.TongueModifier in project liliths-throne-public by Innoxia.

the class CharacterUtils method generateBody.

public static Body generateBody(Gender startingGender, GameCharacter mother, GameCharacter father) {
    RacialBody startingBodyType = RacialBody.HUMAN;
    RacialBody motherBody = RacialBody.valueOfRace(mother.getSubspecies().getOffspringSubspecies().getRace());
    RacialBody fatherBody = RacialBody.valueOfRace(father.getSubspecies().getOffspringSubspecies().getRace());
    Subspecies raceTakesAfter = mother.getSubspecies();
    RaceStage stage = RaceStage.HUMAN;
    boolean takesAfterMother = true;
    boolean raceFromMother = true;
    boolean feminineGender = startingGender.isFeminine();
    NPC blankNPC = Main.game.getGenericAndrogynousNPC();
    GameCharacter parentTakesAfter = mother;
    // Core body type is random:
    if (Math.random() <= 0.5) {
        startingBodyType = motherBody;
        stage = mother.getRaceStage();
    } else {
        startingBodyType = fatherBody;
        stage = father.getRaceStage();
        raceTakesAfter = father.getSubspecies();
        raceFromMother = false;
    }
    switch(startingGender.isFeminine() ? Main.getProperties().subspeciesFeminineFurryPreferencesMap.get(raceTakesAfter) : Main.getProperties().subspeciesMasculineFurryPreferencesMap.get(raceTakesAfter)) {
        case HUMAN:
            stage = RaceStage.HUMAN;
            break;
        case MINIMUM:
            if (stage != RaceStage.HUMAN || stage != RaceStage.PARTIAL) {
                stage = RaceStage.PARTIAL;
            }
            break;
        case REDUCED:
            if (stage != RaceStage.HUMAN || stage != RaceStage.PARTIAL || stage != RaceStage.LESSER) {
                stage = RaceStage.LESSER;
            }
            break;
        case NORMAL:
            break;
        case MAXIMUM:
            stage = RaceStage.GREATER;
            break;
    }
    Body body = generateBody(startingGender, startingBodyType, stage);
    if (mother.getBodyMaterial() == BodyMaterial.SLIME) {
        body.setBodyMaterial(BodyMaterial.SLIME);
    }
    // Takes other features from the parent closest to their femininity:
    if (Math.abs(mother.getFemininityValue() - body.getFemininity()) > Math.abs(father.getFemininityValue() - body.getFemininity())) {
        takesAfterMother = false;
        parentTakesAfter = father;
    }
    float takesAfterMotherChance = takesAfterMother ? 0.75f : 0.25f;
    List<BodyCoveringType> typesToInfluence = new ArrayList<>();
    // Skin & fur colours:
    for (BodyPartInterface bp : body.getAllBodyParts()) {
        if (bp.getType().getBodyCoveringType(body) != null && bp.getType().getBodyCoveringType(body).getRace() != null && !(bp instanceof Eye)) {
            typesToInfluence.add(bp.getType().getBodyCoveringType(body));
        }
    }
    typesToInfluence.add(BodyCoveringType.ANUS);
    typesToInfluence.add(BodyCoveringType.NIPPLES);
    typesToInfluence.add(BodyCoveringType.MOUTH);
    typesToInfluence.add(BodyCoveringType.TONGUE);
    if (raceFromMother) {
        typesToInfluence = setCoveringColours(body, mother, typesToInfluence);
        setCoveringColours(body, father, typesToInfluence);
    } else {
        typesToInfluence = setCoveringColours(body, father, typesToInfluence);
        setCoveringColours(body, mother, typesToInfluence);
    }
    body.updateCoverings(false, false, true, false);
    // Iris colour:
    if (Math.random() >= 0.9f) {
        if (Math.random() >= takesAfterMotherChance) {
            body.getCoverings().put(body.getEye().getType().getBodyCoveringType(body), new Covering(body.getEye().getType().getBodyCoveringType(body), mother.getCovering(mother.getEyeType().getBodyCoveringType(mother)).getPattern(), mother.getCovering(mother.getEyeType().getBodyCoveringType(mother)).getPrimaryColour(), mother.getCovering(mother.getEyeType().getBodyCoveringType(mother)).isPrimaryGlowing(), mother.getCovering(mother.getEyeType().getBodyCoveringType(mother)).getPrimaryColour(), mother.getCovering(mother.getEyeType().getBodyCoveringType(mother)).isPrimaryGlowing()));
        } else {
            body.getCoverings().put(body.getEye().getType().getBodyCoveringType(body), new Covering(body.getEye().getType().getBodyCoveringType(body), father.getCovering(father.getEyeType().getBodyCoveringType(father)).getPattern(), father.getCovering(father.getEyeType().getBodyCoveringType(father)).getPrimaryColour(), father.getCovering(father.getEyeType().getBodyCoveringType(father)).isPrimaryGlowing(), father.getCovering(father.getEyeType().getBodyCoveringType(father)).getPrimaryColour(), father.getCovering(father.getEyeType().getBodyCoveringType(father)).isPrimaryGlowing()));
        }
    }
    // Pupil colour:
    if (Math.random() >= 0.4f) {
        if (Math.random() >= takesAfterMotherChance) {
            body.getCoverings().put(BodyCoveringType.EYE_PUPILS, new Covering(body.getEye().getType().getBodyCoveringType(body), mother.getCovering(BodyCoveringType.EYE_PUPILS).getPattern(), mother.getCovering(BodyCoveringType.EYE_PUPILS).getPrimaryColour(), mother.getCovering(BodyCoveringType.EYE_PUPILS).isPrimaryGlowing(), mother.getCovering(BodyCoveringType.EYE_PUPILS).getPrimaryColour(), mother.getCovering(BodyCoveringType.EYE_PUPILS).isPrimaryGlowing()));
        } else {
            body.getCoverings().put(BodyCoveringType.EYE_PUPILS, new Covering(body.getEye().getType().getBodyCoveringType(body), father.getCovering(BodyCoveringType.EYE_PUPILS).getPattern(), father.getCovering(BodyCoveringType.EYE_PUPILS).getPrimaryColour(), father.getCovering(BodyCoveringType.EYE_PUPILS).isPrimaryGlowing(), father.getCovering(BodyCoveringType.EYE_PUPILS).getPrimaryColour(), father.getCovering(BodyCoveringType.EYE_PUPILS).isPrimaryGlowing()));
        }
    }
    // Body core:
    // Height:
    body.setHeight(getSizeFromGenetics(body.getHeightValue(), (body.isFeminine() ? mother.isFeminine() : !mother.isFeminine()), mother.getHeightValue(), (body.isFeminine() ? father.isFeminine() : !father.isFeminine()), father.getHeightValue()));
    // Femininity:
    switch(startingGender.getType()) {
        case FEMININE:
            if (takesAfterMother) {
                if (mother.getFemininityValue() >= Femininity.FEMININE.getMinimumFemininity()) {
                    body.setFemininity(mother.getFemininityValue());
                }
            } else {
                if (father.getFemininityValue() >= Femininity.FEMININE.getMinimumFemininity()) {
                    body.setFemininity(father.getFemininityValue());
                }
            }
            break;
        case NEUTRAL:
            if (takesAfterMother) {
                if (mother.getFemininity() == Femininity.ANDROGYNOUS) {
                    body.setFemininity(mother.getFemininityValue());
                }
            } else {
                if (father.getFemininity() == Femininity.ANDROGYNOUS) {
                    body.setFemininity(father.getFemininityValue());
                }
            }
            break;
        case MASCULINE:
            if (takesAfterMother) {
                if (mother.getFemininityValue() < Femininity.ANDROGYNOUS.getMinimumFemininity()) {
                    body.setFemininity(mother.getFemininityValue());
                }
            } else {
                if (father.getFemininityValue() < Femininity.ANDROGYNOUS.getMinimumFemininity()) {
                    body.setFemininity(father.getFemininityValue());
                }
            }
            break;
    }
    // Body size:
    int minimumSize = Math.min(mother.getBodySizeValue(), father.getBodySizeValue()) - Util.random.nextInt(5);
    int maximumSize = Math.min(mother.getBodySizeValue(), father.getBodySizeValue()) + Util.random.nextInt(5);
    if (takesAfterMother) {
        minimumSize = Math.max(minimumSize, (feminineGender ? motherBody.getFemaleBodySize() - 30 : motherBody.getMaleBodySize() - 30));
        maximumSize = Math.max(maximumSize, (feminineGender ? motherBody.getFemaleBodySize() + 30 : motherBody.getMaleBodySize() + 30));
    } else {
        minimumSize = Math.max(minimumSize, (feminineGender ? fatherBody.getFemaleBodySize() - 30 : fatherBody.getMaleBodySize() - 30));
        maximumSize = Math.max(maximumSize, (feminineGender ? fatherBody.getFemaleBodySize() + 30 : fatherBody.getMaleBodySize() + 30));
    }
    int variance = (maximumSize == minimumSize ? 0 : Util.random.nextInt(maximumSize - minimumSize));
    body.setBodySize(minimumSize + variance);
    // Muscle:
    int minimumMuscle = Math.min(mother.getMuscleValue(), father.getMuscleValue()) - Util.random.nextInt(5);
    int maximumMuscle = Math.min(mother.getMuscleValue(), father.getMuscleValue()) + Util.random.nextInt(5);
    if (takesAfterMother) {
        minimumMuscle = Math.max(minimumMuscle, (feminineGender ? motherBody.getFemaleMuscle() - 30 : motherBody.getMaleMuscle() - 30));
        maximumMuscle = Math.max(maximumMuscle, (feminineGender ? motherBody.getFemaleMuscle() + 30 : motherBody.getMaleMuscle() + 30));
    } else {
        minimumMuscle = Math.max(minimumMuscle, (feminineGender ? fatherBody.getFemaleMuscle() - 30 : fatherBody.getMaleMuscle() - 30));
        maximumMuscle = Math.max(maximumMuscle, (feminineGender ? fatherBody.getFemaleMuscle() + 30 : fatherBody.getMaleMuscle() + 30));
    }
    variance = (maximumMuscle == minimumMuscle ? 0 : Util.random.nextInt(maximumMuscle - minimumMuscle));
    body.setMuscle(minimumMuscle + variance);
    // Body parts:
    boolean inheritsFromMotherFemininity = mother.isFeminine() == body.isFeminine();
    boolean inheritsFromFatherFemininity = father.isFeminine() == body.isFeminine();
    // Arm:
    if (Math.random() > 0.75) {
        body.getArm().setArmRows(blankNPC, parentTakesAfter.getArmRows());
    }
    // Ass:
    // Ass size:
    body.getAss().setAssSize(blankNPC, getSizeFromGenetics(body.getAss().getAssSize().getValue(), inheritsFromMotherFemininity, mother.getAssSize().getValue(), inheritsFromFatherFemininity, father.getAssSize().getValue()));
    // Hip size:
    body.getAss().setHipSize(blankNPC, getSizeFromGenetics(body.getAss().getHipSize().getValue(), inheritsFromMotherFemininity, mother.getHipSize().getValue(), inheritsFromFatherFemininity, father.getHipSize().getValue()));
    // Breasts:
    boolean inheritsFromMotherBreasts = mother.hasBreasts();
    boolean inheritsFromFatherBreasts = father.hasBreasts();
    if (body.getBreast().getRawSizeValue() > 0) {
        // Breast shape:
        if (Math.random() >= 0.8f) {
            if (inheritsFromMotherBreasts && inheritsFromFatherBreasts) {
                if (Math.random() >= takesAfterMotherChance) {
                    body.getBreast().setShape(blankNPC, mother.getBreastShape());
                } else {
                    body.getBreast().setShape(blankNPC, father.getBreastShape());
                }
            } else if (inheritsFromMotherBreasts) {
                body.getBreast().setShape(blankNPC, mother.getBreastShape());
            } else if (inheritsFromFatherBreasts) {
                body.getBreast().setShape(blankNPC, father.getBreastShape());
            }
        }
        // Breast size:
        body.getBreast().setSize(blankNPC, getSizeFromGenetics(body.getBreast().getSize().getMeasurement(), inheritsFromMotherBreasts, mother.getBreastSize().getMeasurement(), inheritsFromFatherBreasts, father.getBreastSize().getMeasurement()));
        // Breast rows:
        if (Math.random() >= 0.75) {
            if (Math.random() >= takesAfterMotherChance) {
                body.getBreast().setRows(blankNPC, mother.getBreastRows());
            } else {
                body.getBreast().setRows(blankNPC, father.getBreastRows());
            }
        }
        // Modifiers:
        for (OrificeModifier om : OrificeModifier.values()) {
            if (Math.random() >= 0.5) {
                if (inheritsFromMotherBreasts && inheritsFromFatherBreasts) {
                    if (Math.random() >= takesAfterMotherChance) {
                        if (mother.hasNippleOrificeModifier(om)) {
                            body.getBreast().getNipples().getOrificeNipples().addOrificeModifier(blankNPC, om);
                        }
                    } else {
                        if (father.hasNippleOrificeModifier(om)) {
                            body.getBreast().getNipples().getOrificeNipples().addOrificeModifier(blankNPC, om);
                        }
                    }
                } else if (inheritsFromMotherBreasts) {
                    if (mother.hasNippleOrificeModifier(om)) {
                        body.getBreast().getNipples().getOrificeNipples().addOrificeModifier(blankNPC, om);
                    }
                } else if (inheritsFromFatherBreasts) {
                    if (father.hasNippleOrificeModifier(om)) {
                        body.getBreast().getNipples().getOrificeNipples().addOrificeModifier(blankNPC, om);
                    }
                }
            }
        }
    }
    // Nipple count:
    if (Math.random() > 0.75f) {
        if (Math.random() >= takesAfterMotherChance) {
            body.getBreast().setNippleCountPerBreast(blankNPC, mother.getNippleCountPerBreast());
        } else {
            body.getBreast().setNippleCountPerBreast(blankNPC, father.getNippleCountPerBreast());
        }
    }
    // Nipple shape:
    if (Math.random() >= 0.75f) {
        if (Math.random() >= takesAfterMotherChance) {
            body.getBreast().getNipples().setNippleShape(blankNPC, mother.getNippleShape());
        } else {
            body.getBreast().getNipples().setNippleShape(blankNPC, father.getNippleShape());
        }
    }
    // Areolae shape:
    if (Math.random() >= 0.75f) {
        if (Math.random() >= takesAfterMotherChance) {
            body.getBreast().getNipples().setAreolaeShape(blankNPC, mother.getAreolaeShape());
        } else {
            body.getBreast().getNipples().setAreolaeShape(blankNPC, father.getAreolaeShape());
        }
    }
    // Nipple size:
    body.getBreast().getNipples().setNippleSize(blankNPC, getSizeFromGenetics(body.getBreast().getNipples().getNippleSizeValue(), inheritsFromMotherBreasts, mother.getNippleSize().getValue(), inheritsFromFatherBreasts, father.getNippleSize().getValue()));
    // Areolae size:
    body.getBreast().getNipples().setAreolaeSize(blankNPC, getSizeFromGenetics(body.getBreast().getNipples().getAreolaeSizeValue(), inheritsFromMotherBreasts, mother.getAreolaeSize().getValue(), inheritsFromFatherBreasts, father.getAreolaeSize().getValue()));
    // Face:
    // Lip size:
    body.getFace().getMouth().setLipSize(blankNPC, getSizeFromGenetics(body.getFace().getMouth().getLipSizeValue(), inheritsFromMotherFemininity, mother.getLipSizeValue(), inheritsFromFatherFemininity, father.getLipSizeValue()));
    // Mouth modifiers:
    for (OrificeModifier om : OrificeModifier.values()) {
        if (Math.random() >= 0.5) {
            if (Math.random() >= takesAfterMotherChance) {
                if (mother.hasFaceOrificeModifier(om)) {
                    body.getFace().getMouth().getOrificeMouth().addOrificeModifier(blankNPC, om);
                }
            } else {
                if (father.hasFaceOrificeModifier(om)) {
                    body.getFace().getMouth().getOrificeMouth().addOrificeModifier(blankNPC, om);
                }
            }
        }
    }
    // Tongue modifiers:
    for (TongueModifier tm : TongueModifier.values()) {
        if (Math.random() >= 0.5) {
            if (Math.random() >= takesAfterMotherChance) {
                if (mother.hasTongueModifier(tm)) {
                    body.getFace().getTongue().addTongueModifier(blankNPC, tm);
                }
            } else {
                if (father.hasTongueModifier(tm)) {
                    body.getFace().getTongue().addTongueModifier(blankNPC, tm);
                }
            }
        }
    }
    // Eye pairs:
    if (Math.random() >= 0.75) {
        if (Math.random() >= takesAfterMotherChance) {
            body.getEye().setEyePairs(blankNPC, mother.getEyePairs());
        } else {
            body.getEye().setEyePairs(blankNPC, father.getEyePairs());
        }
    }
    // Iris shape:
    if (Math.random() >= 0.75) {
        if (Math.random() >= takesAfterMotherChance) {
            body.getEye().setIrisShape(blankNPC, mother.getIrisShape());
        } else {
            body.getEye().setIrisShape(blankNPC, father.getIrisShape());
        }
    }
    // Pupil shape:
    if (Math.random() >= 0.75) {
        if (Math.random() >= takesAfterMotherChance) {
            body.getEye().setPupilShape(blankNPC, mother.getPupilShape());
        } else {
            body.getEye().setPupilShape(blankNPC, father.getPupilShape());
        }
    }
    // Horn rows:
    if (Math.random() >= 0.75) {
        if (Math.random() >= takesAfterMotherChance) {
            body.getHorn().setHornRows(blankNPC, mother.getHornRows());
        } else {
            body.getHorn().setHornRows(blankNPC, father.getHornRows());
        }
    }
    // Penis:
    boolean inheritsFromMotherPenis = mother.hasPenis();
    boolean inheritsFromFatherPenis = father.hasPenis();
    if (body.getPenis().getType() != PenisType.NONE) {
        // Penis size:
        body.getPenis().setPenisSize(blankNPC, getSizeFromGenetics(body.getPenis().getRawSizeValue(), inheritsFromMotherPenis, mother.getPenisRawSizeValue(), inheritsFromFatherPenis, father.getPenisRawSizeValue()));
        // Penis modifiers:
        for (PenisModifier pm : PenisModifier.values()) {
            if (Math.random() >= 0.5) {
                if (inheritsFromMotherPenis && inheritsFromFatherPenis) {
                    if (Math.random() >= takesAfterMotherChance) {
                        if (mother.hasPenisModifier(pm)) {
                            body.getPenis().addPenisModifier(blankNPC, pm);
                        }
                    } else {
                        if (father.hasPenisModifier(pm)) {
                            body.getPenis().addPenisModifier(blankNPC, pm);
                        }
                    }
                } else if (inheritsFromMotherPenis) {
                    if (mother.hasPenisModifier(pm)) {
                        body.getPenis().addPenisModifier(blankNPC, pm);
                    }
                } else if (inheritsFromFatherPenis) {
                    if (father.hasPenisModifier(pm)) {
                        body.getPenis().addPenisModifier(blankNPC, pm);
                    }
                }
            }
        }
        // Urethra modifiers:
        for (OrificeModifier om : OrificeModifier.values()) {
            if (Math.random() >= 0.5) {
                if (inheritsFromMotherPenis && inheritsFromFatherPenis) {
                    if (Math.random() >= takesAfterMotherChance) {
                        if (mother.hasUrethraOrificeModifier(om)) {
                            body.getPenis().getOrificeUrethra().addOrificeModifier(blankNPC, om);
                        }
                    } else {
                        if (father.hasUrethraOrificeModifier(om)) {
                            body.getPenis().getOrificeUrethra().addOrificeModifier(blankNPC, om);
                        }
                    }
                } else if (inheritsFromMotherPenis) {
                    if (mother.hasUrethraOrificeModifier(om)) {
                        body.getPenis().getOrificeUrethra().addOrificeModifier(blankNPC, om);
                    }
                } else if (inheritsFromFatherPenis) {
                    if (father.hasUrethraOrificeModifier(om)) {
                        body.getPenis().getOrificeUrethra().addOrificeModifier(blankNPC, om);
                    }
                }
            }
        }
        // Testicles:
        // Testicle size:
        body.getPenis().getTesticle().setTesticleSize(blankNPC, getSizeFromGenetics(body.getPenis().getTesticle().getTesticleSize().getValue(), inheritsFromMotherPenis, mother.getTesticleSize().getValue(), inheritsFromFatherPenis, father.getTesticleSize().getValue()));
        // Testicle count:
        if (Math.random() >= 0.75) {
            if (inheritsFromMotherPenis && inheritsFromFatherPenis) {
                if (Math.random() >= takesAfterMotherChance) {
                    body.getPenis().getTesticle().setTesticleCount(blankNPC, mother.getTesticleCount());
                } else {
                    body.getPenis().getTesticle().setTesticleCount(blankNPC, father.getTesticleCount());
                }
            } else if (inheritsFromMotherPenis) {
                body.getPenis().getTesticle().setTesticleCount(blankNPC, mother.getTesticleCount());
            } else if (inheritsFromFatherPenis) {
                body.getPenis().getTesticle().setTesticleCount(blankNPC, father.getTesticleCount());
            }
        }
        // Internal testicles:
        if (Math.random() >= 0.75) {
            if (inheritsFromMotherPenis && inheritsFromFatherPenis) {
                if (Math.random() >= takesAfterMotherChance) {
                    if (mother.isInternalTesticles()) {
                        body.getPenis().getTesticle().setInternal(blankNPC, true);
                    }
                } else {
                    if (father.isInternalTesticles()) {
                        body.getPenis().getTesticle().setInternal(blankNPC, true);
                    }
                }
            } else if (inheritsFromMotherPenis) {
                if (mother.isInternalTesticles()) {
                    body.getPenis().getTesticle().setInternal(blankNPC, true);
                }
            } else if (inheritsFromFatherPenis) {
                if (father.isInternalTesticles()) {
                    body.getPenis().getTesticle().setInternal(blankNPC, true);
                }
            }
        }
        // Cum Production:
        body.getPenis().getTesticle().setCumProduction(blankNPC, getSizeFromGenetics(body.getPenis().getTesticle().getRawCumProductionValue(), inheritsFromMotherPenis, mother.getPenisRawCumProductionValue(), inheritsFromFatherPenis, father.getPenisRawCumProductionValue()));
    }
    // Tail:
    if (Math.random() > 0.75) {
        if (Math.random() >= takesAfterMotherChance) {
            body.getTail().setTailCount(blankNPC, mother.getTailCount());
        } else {
            body.getTail().setTailCount(blankNPC, father.getTailCount());
        }
    }
    // Vagina:
    boolean inheritsFromMotherVagina = mother.hasVagina();
    boolean inheritsFromFatherVagina = father.hasVagina();
    if (body.getVagina().getType() != VaginaType.NONE) {
        // Clitoris size:
        body.getVagina().setClitorisSize(blankNPC, getSizeFromGenetics(body.getVagina().getRawClitorisSizeValue(), inheritsFromMotherVagina, mother.getVaginaRawClitorisSizeValue(), inheritsFromFatherVagina, father.getVaginaRawClitorisSizeValue()));
        // Labia size:
        body.getVagina().setLabiaSize(blankNPC, getSizeFromGenetics(body.getVagina().getRawLabiaSizeValue(), inheritsFromMotherVagina, mother.getVaginaRawLabiaSizeValue(), inheritsFromFatherVagina, father.getVaginaRawLabiaSizeValue()));
        // // Capacity:
        // body.getVagina().getOrificeVagina().setCapacity(blankNPC, getSizeFromGenetics(
        // (int) body.getVagina().getOrificeVagina().getRawCapacityValue(),
        // inheritsFromMotherVagina, (int) mother.getVaginaRawCapacityValue(),
        // inheritsFromFatherVagina, (int) father.getVaginaRawCapacityValue()));
        // Wetness:
        body.getVagina().getOrificeVagina().setWetness(blankNPC, getSizeFromGenetics(body.getVagina().getOrificeVagina().getWetness(blankNPC).getValue(), inheritsFromMotherVagina, mother.getVaginaWetness().getValue(), inheritsFromFatherVagina, father.getVaginaWetness().getValue()));
        // Modifiers:
        for (OrificeModifier om : OrificeModifier.values()) {
            if (Math.random() >= 0.5) {
                if (inheritsFromMotherVagina && inheritsFromFatherVagina) {
                    if (Math.random() >= takesAfterMotherChance) {
                        if (mother.hasVaginaOrificeModifier(om)) {
                            body.getVagina().getOrificeVagina().addOrificeModifier(blankNPC, om);
                        }
                    } else {
                        if (father.hasVaginaOrificeModifier(om)) {
                            body.getVagina().getOrificeVagina().addOrificeModifier(blankNPC, om);
                        }
                    }
                } else if (inheritsFromMotherVagina) {
                    if (mother.hasVaginaOrificeModifier(om)) {
                        body.getVagina().getOrificeVagina().addOrificeModifier(blankNPC, om);
                    }
                } else if (inheritsFromFatherVagina) {
                    if (father.hasVaginaOrificeModifier(om)) {
                        body.getVagina().getOrificeVagina().addOrificeModifier(blankNPC, om);
                    }
                }
            }
        }
    }
    return body;
}
Also used : NPC(com.lilithsthrone.game.character.npc.NPC) ArrayList(java.util.ArrayList) Covering(com.lilithsthrone.game.character.body.Covering) RaceStage(com.lilithsthrone.game.character.race.RaceStage) BodyCoveringType(com.lilithsthrone.game.character.body.types.BodyCoveringType) RacialBody(com.lilithsthrone.game.character.race.RacialBody) Subspecies(com.lilithsthrone.game.character.race.Subspecies) PenisModifier(com.lilithsthrone.game.character.body.valueEnums.PenisModifier) Eye(com.lilithsthrone.game.character.body.Eye) TongueModifier(com.lilithsthrone.game.character.body.valueEnums.TongueModifier) BodyPartInterface(com.lilithsthrone.game.character.body.BodyPartInterface) Body(com.lilithsthrone.game.character.body.Body) RacialBody(com.lilithsthrone.game.character.race.RacialBody) OrificeModifier(com.lilithsthrone.game.character.body.valueEnums.OrificeModifier)

Example 4 with TongueModifier

use of com.lilithsthrone.game.character.body.valueEnums.TongueModifier in project liliths-throne-public by Innoxia.

the class Body method saveAsXML.

@Override
public Element saveAsXML(Element parentElement, Document doc) {
    // Core:
    Element bodyCore = doc.createElement("bodyCore");
    parentElement.appendChild(bodyCore);
    CharacterUtils.addAttribute(doc, bodyCore, "piercedStomach", String.valueOf(this.isPiercedStomach()));
    CharacterUtils.addAttribute(doc, bodyCore, "height", String.valueOf(this.getHeightValue()));
    CharacterUtils.addAttribute(doc, bodyCore, "femininity", String.valueOf(this.getFemininity()));
    CharacterUtils.addAttribute(doc, bodyCore, "bodySize", String.valueOf(this.getBodySize()));
    CharacterUtils.addAttribute(doc, bodyCore, "muscle", String.valueOf(this.getMuscle()));
    CharacterUtils.addAttribute(doc, bodyCore, "pubicHair", String.valueOf(this.getPubicHair()));
    CharacterUtils.addAttribute(doc, bodyCore, "bodyMaterial", String.valueOf(this.getBodyMaterial()));
    CharacterUtils.addAttribute(doc, bodyCore, "genitalArrangement", String.valueOf(this.getGenitalArrangement()));
    for (BodyCoveringType bct : BodyCoveringType.values()) {
        Element element = doc.createElement("bodyCovering");
        bodyCore.appendChild(element);
        CharacterUtils.addAttribute(doc, element, "type", bct.toString());
        CharacterUtils.addAttribute(doc, element, "pattern", this.coverings.get(bct).getPattern().toString());
        CharacterUtils.addAttribute(doc, element, "modifier", this.coverings.get(bct).getModifier().toString());
        CharacterUtils.addAttribute(doc, element, "colourPrimary", this.coverings.get(bct).getPrimaryColour().toString());
        if (this.coverings.get(bct).isPrimaryGlowing()) {
            CharacterUtils.addAttribute(doc, element, "glowPrimary", String.valueOf(this.coverings.get(bct).isPrimaryGlowing()));
        }
        CharacterUtils.addAttribute(doc, element, "colourSecondary", this.coverings.get(bct).getSecondaryColour().toString());
        if (this.coverings.get(bct).isSecondaryGlowing()) {
            CharacterUtils.addAttribute(doc, element, "glowSecondary", String.valueOf(this.coverings.get(bct).isSecondaryGlowing()));
        }
        if (this.getBodyCoveringTypesDiscovered().contains(bct)) {
            CharacterUtils.addAttribute(doc, element, "discovered", String.valueOf(this.getBodyCoveringTypesDiscovered().contains(bct)));
        }
    }
    // Antennae:
    Element bodyAntennae = doc.createElement("antennae");
    parentElement.appendChild(bodyAntennae);
    CharacterUtils.addAttribute(doc, bodyAntennae, "type", this.antenna.getType().toString());
    CharacterUtils.addAttribute(doc, bodyAntennae, "rows", String.valueOf(this.antenna.getAntennaRows()));
    // Arm:
    Element bodyArm = doc.createElement("arm");
    parentElement.appendChild(bodyArm);
    CharacterUtils.addAttribute(doc, bodyArm, "type", this.arm.getType().toString());
    CharacterUtils.addAttribute(doc, bodyArm, "rows", String.valueOf(this.arm.getArmRows()));
    CharacterUtils.addAttribute(doc, bodyArm, "underarmHair", this.arm.getUnderarmHair().toString());
    // Ass:
    Element bodyAss = doc.createElement("ass");
    parentElement.appendChild(bodyAss);
    CharacterUtils.addAttribute(doc, bodyAss, "type", this.ass.getType().toString());
    CharacterUtils.addAttribute(doc, bodyAss, "assSize", String.valueOf(this.ass.getAssSize().getValue()));
    CharacterUtils.addAttribute(doc, bodyAss, "hipSize", String.valueOf(this.ass.getHipSize().getValue()));
    Element bodyAnus = doc.createElement("anus");
    parentElement.appendChild(bodyAnus);
    CharacterUtils.addAttribute(doc, bodyAnus, "wetness", String.valueOf(this.ass.anus.orificeAnus.wetness));
    CharacterUtils.addAttribute(doc, bodyAnus, "elasticity", String.valueOf(this.ass.anus.orificeAnus.elasticity));
    CharacterUtils.addAttribute(doc, bodyAnus, "plasticity", String.valueOf(this.ass.anus.orificeAnus.plasticity));
    CharacterUtils.addAttribute(doc, bodyAnus, "capacity", String.valueOf(this.ass.anus.orificeAnus.capacity));
    CharacterUtils.addAttribute(doc, bodyAnus, "stretchedCapacity", String.valueOf(this.ass.anus.orificeAnus.stretchedCapacity));
    CharacterUtils.addAttribute(doc, bodyAnus, "virgin", String.valueOf(this.ass.anus.orificeAnus.virgin));
    CharacterUtils.addAttribute(doc, bodyAnus, "bleached", String.valueOf(this.ass.anus.bleached));
    CharacterUtils.addAttribute(doc, bodyAnus, "assHair", this.ass.anus.assHair.toString());
    Element anusModifiers = doc.createElement("anusModifiers");
    bodyAnus.appendChild(anusModifiers);
    for (OrificeModifier om : OrificeModifier.values()) {
        CharacterUtils.addAttribute(doc, anusModifiers, om.toString(), String.valueOf(this.ass.anus.orificeAnus.hasOrificeModifier(om)));
    }
    // Breasts:
    Element bodyBreast = doc.createElement("breasts");
    parentElement.appendChild(bodyBreast);
    CharacterUtils.addAttribute(doc, bodyBreast, "type", this.breast.type.toString());
    CharacterUtils.addAttribute(doc, bodyBreast, "shape", this.breast.shape.toString());
    CharacterUtils.addAttribute(doc, bodyBreast, "size", String.valueOf(this.breast.size));
    CharacterUtils.addAttribute(doc, bodyBreast, "rows", String.valueOf(this.breast.rows));
    CharacterUtils.addAttribute(doc, bodyBreast, "milkStorage", String.valueOf(this.breast.milkStorage));
    CharacterUtils.addAttribute(doc, bodyBreast, "storedMilk", String.valueOf(this.breast.milkStored));
    CharacterUtils.addAttribute(doc, bodyBreast, "milkRegeneration", String.valueOf(this.breast.milkRegeneration));
    CharacterUtils.addAttribute(doc, bodyBreast, "nippleCountPerBreast", String.valueOf(this.breast.nippleCountPerBreast));
    Element bodyNipple = doc.createElement("nipples");
    parentElement.appendChild(bodyNipple);
    CharacterUtils.addAttribute(doc, bodyNipple, "elasticity", String.valueOf(this.breast.nipples.orificeNipples.elasticity));
    CharacterUtils.addAttribute(doc, bodyNipple, "plasticity", String.valueOf(this.breast.nipples.orificeNipples.plasticity));
    CharacterUtils.addAttribute(doc, bodyNipple, "capacity", String.valueOf(this.breast.nipples.orificeNipples.capacity));
    CharacterUtils.addAttribute(doc, bodyNipple, "stretchedCapacity", String.valueOf(this.breast.nipples.orificeNipples.stretchedCapacity));
    CharacterUtils.addAttribute(doc, bodyNipple, "virgin", String.valueOf(this.breast.nipples.orificeNipples.virgin));
    CharacterUtils.addAttribute(doc, bodyNipple, "pierced", String.valueOf(this.breast.nipples.pierced));
    CharacterUtils.addAttribute(doc, bodyNipple, "nippleSize", String.valueOf(this.breast.nipples.nippleSize));
    CharacterUtils.addAttribute(doc, bodyNipple, "nippleShape", this.breast.nipples.nippleShape.toString());
    CharacterUtils.addAttribute(doc, bodyNipple, "areolaeSize", String.valueOf(this.breast.nipples.areolaeSize));
    CharacterUtils.addAttribute(doc, bodyNipple, "areolaeShape", this.breast.nipples.areolaeShape.toString());
    Element nippleModifiers = doc.createElement("nippleModifiers");
    bodyNipple.appendChild(nippleModifiers);
    for (OrificeModifier om : OrificeModifier.values()) {
        CharacterUtils.addAttribute(doc, nippleModifiers, om.toString(), String.valueOf(this.breast.nipples.orificeNipples.hasOrificeModifier(om)));
    }
    Element bodyMilk = doc.createElement("milk");
    parentElement.appendChild(bodyMilk);
    CharacterUtils.addAttribute(doc, bodyMilk, "flavour", this.breast.milk.getFlavour().toString());
    Element milkModifiers = doc.createElement("milkModifiers");
    bodyMilk.appendChild(milkModifiers);
    for (FluidModifier fm : FluidModifier.values()) {
        CharacterUtils.addAttribute(doc, milkModifiers, fm.toString(), String.valueOf(this.breast.milk.hasFluidModifier(fm)));
    }
    // TODO transformativeEffects;
    // Ear:
    Element bodyEar = doc.createElement("ear");
    parentElement.appendChild(bodyEar);
    CharacterUtils.addAttribute(doc, bodyEar, "type", this.ear.type.toString());
    CharacterUtils.addAttribute(doc, bodyEar, "pierced", String.valueOf(this.ear.pierced));
    // Eye:
    Element bodyEye = doc.createElement("eye");
    parentElement.appendChild(bodyEye);
    CharacterUtils.addAttribute(doc, bodyEye, "type", this.eye.type.toString());
    CharacterUtils.addAttribute(doc, bodyEye, "eyePairs", String.valueOf(this.eye.eyePairs));
    CharacterUtils.addAttribute(doc, bodyEye, "irisShape", this.eye.irisShape.toString());
    CharacterUtils.addAttribute(doc, bodyEye, "pupilShape", this.eye.pupilShape.toString());
    // Face:
    Element bodyFace = doc.createElement("face");
    parentElement.appendChild(bodyFace);
    CharacterUtils.addAttribute(doc, bodyFace, "type", this.face.type.toString());
    CharacterUtils.addAttribute(doc, bodyFace, "piercedNose", String.valueOf(this.face.piercedNose));
    CharacterUtils.addAttribute(doc, bodyFace, "facialHair", this.face.facialHair.toString());
    Element bodyMouth = doc.createElement("mouth");
    parentElement.appendChild(bodyMouth);
    CharacterUtils.addAttribute(doc, bodyMouth, "elasticity", String.valueOf(this.face.mouth.orificeMouth.elasticity));
    CharacterUtils.addAttribute(doc, bodyMouth, "plasticity", String.valueOf(this.face.mouth.orificeMouth.plasticity));
    CharacterUtils.addAttribute(doc, bodyMouth, "capacity", String.valueOf(this.face.mouth.orificeMouth.capacity));
    CharacterUtils.addAttribute(doc, bodyMouth, "stretchedCapacity", String.valueOf(this.face.mouth.orificeMouth.stretchedCapacity));
    CharacterUtils.addAttribute(doc, bodyMouth, "virgin", String.valueOf(this.face.mouth.orificeMouth.virgin));
    CharacterUtils.addAttribute(doc, bodyMouth, "piercedLip", String.valueOf(this.face.mouth.piercedLip));
    CharacterUtils.addAttribute(doc, bodyMouth, "lipSize", String.valueOf(this.face.mouth.lipSize));
    Element mouthModifiers = doc.createElement("mouthModifiers");
    bodyMouth.appendChild(mouthModifiers);
    for (OrificeModifier om : OrificeModifier.values()) {
        CharacterUtils.addAttribute(doc, mouthModifiers, om.toString(), String.valueOf(this.face.mouth.orificeMouth.hasOrificeModifier(om)));
    }
    Element bodyTongue = doc.createElement("tongue");
    parentElement.appendChild(bodyTongue);
    CharacterUtils.addAttribute(doc, bodyTongue, "piercedTongue", String.valueOf(this.face.tongue.pierced));
    CharacterUtils.addAttribute(doc, bodyTongue, "tongueLength", String.valueOf(this.face.tongue.tongueLength));
    Element tongueModifiers = doc.createElement("tongueModifiers");
    bodyTongue.appendChild(tongueModifiers);
    for (TongueModifier tm : TongueModifier.values()) {
        CharacterUtils.addAttribute(doc, tongueModifiers, tm.toString(), String.valueOf(this.face.tongue.hasTongueModifier(tm)));
    }
    // Hair:
    Element bodyHair = doc.createElement("hair");
    parentElement.appendChild(bodyHair);
    CharacterUtils.addAttribute(doc, bodyHair, "type", this.hair.type.toString());
    CharacterUtils.addAttribute(doc, bodyHair, "length", String.valueOf(this.hair.length));
    CharacterUtils.addAttribute(doc, bodyHair, "hairStyle", this.hair.style.toString());
    // Horn:
    Element bodyHorn = doc.createElement("horn");
    parentElement.appendChild(bodyHorn);
    CharacterUtils.addAttribute(doc, bodyHorn, "type", this.horn.type.toString());
    CharacterUtils.addAttribute(doc, bodyHorn, "length", String.valueOf(this.horn.length));
    CharacterUtils.addAttribute(doc, bodyHorn, "rows", String.valueOf(this.horn.rows));
    // Leg:
    Element bodyLeg = doc.createElement("leg");
    parentElement.appendChild(bodyLeg);
    CharacterUtils.addAttribute(doc, bodyLeg, "type", this.leg.type.toString());
    // Penis:
    Element bodyPenis = doc.createElement("penis");
    parentElement.appendChild(bodyPenis);
    CharacterUtils.addAttribute(doc, bodyPenis, "type", this.penis.type.toString());
    CharacterUtils.addAttribute(doc, bodyPenis, "size", String.valueOf(this.penis.size));
    CharacterUtils.addAttribute(doc, bodyPenis, "girth", String.valueOf(this.penis.girth));
    CharacterUtils.addAttribute(doc, bodyPenis, "pierced", String.valueOf(this.penis.pierced));
    CharacterUtils.addAttribute(doc, bodyPenis, "virgin", String.valueOf(this.penis.virgin));
    Element penisModifiers = doc.createElement("penisModifiers");
    bodyPenis.appendChild(penisModifiers);
    for (PenisModifier pm : PenisModifier.values()) {
        CharacterUtils.addAttribute(doc, penisModifiers, pm.toString(), String.valueOf(this.penis.hasPenisModifier(pm)));
    }
    CharacterUtils.addAttribute(doc, bodyPenis, "elasticity", String.valueOf(this.penis.orificeUrethra.elasticity));
    CharacterUtils.addAttribute(doc, bodyPenis, "plasticity", String.valueOf(this.penis.orificeUrethra.plasticity));
    CharacterUtils.addAttribute(doc, bodyPenis, "capacity", String.valueOf(this.penis.orificeUrethra.capacity));
    CharacterUtils.addAttribute(doc, bodyPenis, "stretchedCapacity", String.valueOf(this.penis.orificeUrethra.stretchedCapacity));
    CharacterUtils.addAttribute(doc, bodyPenis, "urethraVirgin", String.valueOf(this.penis.orificeUrethra.virgin));
    Element urethraModifiers = doc.createElement("urethraModifiers");
    bodyPenis.appendChild(urethraModifiers);
    for (OrificeModifier om : OrificeModifier.values()) {
        CharacterUtils.addAttribute(doc, urethraModifiers, om.toString(), String.valueOf(this.penis.orificeUrethra.hasOrificeModifier(om)));
    }
    Element bodyTesticle = doc.createElement("testicles");
    parentElement.appendChild(bodyTesticle);
    CharacterUtils.addAttribute(doc, bodyTesticle, "testicleSize", String.valueOf(this.penis.testicle.testicleSize));
    CharacterUtils.addAttribute(doc, bodyTesticle, "cumProduction", String.valueOf(this.penis.testicle.cumStorage));
    CharacterUtils.addAttribute(doc, bodyTesticle, "numberOfTesticles", String.valueOf(this.penis.testicle.testicleCount));
    CharacterUtils.addAttribute(doc, bodyTesticle, "internal", String.valueOf(this.penis.testicle.internal));
    Element bodyCum = doc.createElement("cum");
    parentElement.appendChild(bodyCum);
    CharacterUtils.addAttribute(doc, bodyCum, "flavour", this.penis.testicle.cum.flavour.toString());
    Element cumModifiers = doc.createElement("cumModifiers");
    bodyCum.appendChild(cumModifiers);
    for (FluidModifier fm : FluidModifier.values()) {
        CharacterUtils.addAttribute(doc, cumModifiers, fm.toString(), String.valueOf(this.penis.testicle.cum.hasFluidModifier(fm)));
    }
    // TODO transformativeEffects;
    // Skin:
    Element bodySkin = doc.createElement("skin");
    parentElement.appendChild(bodySkin);
    CharacterUtils.addAttribute(doc, bodySkin, "type", this.skin.type.toString());
    // Tail:
    Element bodyTail = doc.createElement("tail");
    parentElement.appendChild(bodyTail);
    CharacterUtils.addAttribute(doc, bodyTail, "type", this.tail.type.toString());
    CharacterUtils.addAttribute(doc, bodyTail, "count", String.valueOf(this.tail.tailCount));
    // Vagina
    Element bodyVagina = doc.createElement("vagina");
    parentElement.appendChild(bodyVagina);
    CharacterUtils.addAttribute(doc, bodyVagina, "type", this.vagina.type.toString());
    CharacterUtils.addAttribute(doc, bodyVagina, "labiaSize", String.valueOf(this.vagina.labiaSize));
    CharacterUtils.addAttribute(doc, bodyVagina, "clitSize", String.valueOf(this.vagina.clitSize));
    CharacterUtils.addAttribute(doc, bodyVagina, "pierced", String.valueOf(this.vagina.pierced));
    CharacterUtils.addAttribute(doc, bodyVagina, "wetness", String.valueOf(this.vagina.orificeVagina.wetness));
    CharacterUtils.addAttribute(doc, bodyVagina, "elasticity", String.valueOf(this.vagina.orificeVagina.elasticity));
    CharacterUtils.addAttribute(doc, bodyVagina, "plasticity", String.valueOf(this.vagina.orificeVagina.plasticity));
    CharacterUtils.addAttribute(doc, bodyVagina, "capacity", String.valueOf(this.vagina.orificeVagina.capacity));
    CharacterUtils.addAttribute(doc, bodyVagina, "stretchedCapacity", String.valueOf(this.vagina.orificeVagina.stretchedCapacity));
    CharacterUtils.addAttribute(doc, bodyVagina, "virgin", String.valueOf(this.vagina.orificeVagina.virgin));
    CharacterUtils.addAttribute(doc, bodyVagina, "squirter", String.valueOf(this.vagina.orificeVagina.squirter));
    Element vaginaModifiers = doc.createElement("vaginaModifiers");
    bodyVagina.appendChild(vaginaModifiers);
    for (OrificeModifier om : OrificeModifier.values()) {
        CharacterUtils.addAttribute(doc, vaginaModifiers, om.toString(), String.valueOf(this.vagina.orificeVagina.hasOrificeModifier(om)));
    }
    Element bodyGirlcum = doc.createElement("girlcum");
    parentElement.appendChild(bodyGirlcum);
    CharacterUtils.addAttribute(doc, bodyGirlcum, "flavour", this.vagina.girlcum.flavour.toString());
    Element girlcumModifiers = doc.createElement("girlcumModifiers");
    bodyGirlcum.appendChild(girlcumModifiers);
    for (FluidModifier fm : FluidModifier.values()) {
        CharacterUtils.addAttribute(doc, girlcumModifiers, fm.toString(), String.valueOf(this.vagina.girlcum.hasFluidModifier(fm)));
    }
    // TODO transformativeEffects;
    // Wing:
    Element bodyWing = doc.createElement("wing");
    parentElement.appendChild(bodyWing);
    CharacterUtils.addAttribute(doc, bodyWing, "type", this.wing.type.toString());
    CharacterUtils.addAttribute(doc, bodyWing, "size", String.valueOf(this.wing.size));
    return parentElement;
}
Also used : FluidModifier(com.lilithsthrone.game.character.body.valueEnums.FluidModifier) TongueModifier(com.lilithsthrone.game.character.body.valueEnums.TongueModifier) Element(org.w3c.dom.Element) BodyCoveringType(com.lilithsthrone.game.character.body.types.BodyCoveringType) PenisModifier(com.lilithsthrone.game.character.body.valueEnums.PenisModifier) OrificeModifier(com.lilithsthrone.game.character.body.valueEnums.OrificeModifier)

Example 5 with TongueModifier

use of com.lilithsthrone.game.character.body.valueEnums.TongueModifier in project liliths-throne-public by Innoxia.

the class Body method getDescription.

/**
 * @param owner
 * @param playerKnowledgeOfThroat
 * @param playerKnowledgeOfBreasts
 * @param playerKnowledgeOfGroin
 * @return
 */
public String getDescription(GameCharacter owner) {
    StringBuilder sb = new StringBuilder();
    // Describe race:
    if (owner.isPlayer()) {
        sb.append("<p>" + "You are [pc.name], <span style='color:" + getGender().getColour().toWebHexString() + ";'>[pc.a_gender]</span> [pc.raceStage] [pc.race]. " + owner.getAppearsAsGenderDescription() + " Standing at full height, you measure [pc.heightFeetInches] ([pc.heightCm]cm).");
    } else {
        if (owner.getPlayerKnowsAreas().contains(CoverableArea.PENIS) && owner.getPlayerKnowsAreas().contains(CoverableArea.VAGINA)) {
            sb.append("<p>" + "[npc.Name] is <span style='color:" + getGender().getColour().toWebHexString() + ";'>[npc.a_gender]</span> [npc.raceStage] [npc.race]. " + owner.getAppearsAsGenderDescription() + " Standing at full height, [npc.she] measures [npc.heightFeetInches] ([npc.heightCm]cm).");
        } else {
            if (Main.game.getPlayer().hasTrait(Perk.OBSERVANT, true)) {
                sb.append("<p>" + "Thanks to your observant perk, you can detect that [npc.name] is <span style='color:" + getGender().getColour().toWebHexString() + ";'>[npc.a_gender]</span> [npc.raceStage] [npc.race]. " + owner.getAppearsAsGenderDescription() + " Standing at full height, [npc.she] measures [npc.heightFeetInches] ([npc.heightCm]cm).");
            } else {
                sb.append("<p>" + "[npc.Name] is a [npc.raceStage] [npc.race]. " + owner.getAppearsAsGenderDescription() + " Standing at full height, [npc.she] measures [npc.heightFeetInches] ([npc.heightCm]cm).");
            }
        }
    }
    sb.append("</p>");
    switch(this.getBodyMaterial()) {
        case FIRE:
            if (owner.isPlayer()) {
                sb.append("<p>" + "Your entire body, save for a small obsidian sphere in the place where your heart should be, is made out of <b style='color:" + this.getBodyMaterial().getColour().toWebHexString() + ";'>fire and smoke</b>!" + "</p>");
            } else {
                sb.append("<p>" + "[npc.Name]'s entire body, save for a small obsidian sphere in the place where [npc.her] heart should be, is made out of <b style='color:" + this.getBodyMaterial().getColour().toWebHexString() + ";'>fire and smoke</b>!" + "</p>");
            }
            break;
        case FLESH:
            break;
        case ICE:
            if (owner.isPlayer()) {
                sb.append("<p>" + "Your entire body, save for a small obsidian sphere in the place where your heart should be, is made out of <b style='color:" + this.getBodyMaterial().getColour().toWebHexString() + ";'>ice</b>!" + "</p>");
            } else {
                sb.append("<p>" + "[npc.Name]'s entire body, save for a small obsidian sphere in the place where [npc.her] heart should be, is made out of <b style='color:" + this.getBodyMaterial().getColour().toWebHexString() + ";'>ice</b>!" + "</p>");
            }
            break;
        case RUBBER:
            if (owner.isPlayer()) {
                sb.append("<p>" + "Your entire body, save for a small obsidian sphere in the place where your heart should be, is made out of <b style='color:" + this.getBodyMaterial().getColour().toWebHexString() + ";'>rubber</b>!" + "</p>");
            } else {
                sb.append("<p>" + "[npc.Name]'s entire body, save for a small obsidian sphere in the place where [npc.her] heart should be, is made out of <b style='color:" + this.getBodyMaterial().getColour().toWebHexString() + ";'>rubber</b>!" + "</p>");
            }
            break;
        case SLIME:
            if (owner.isPlayer()) {
                sb.append("<p>" + "Your entire body, save for a small, glowing sphere in the place where your heart should be, is made out of [pc.skinFullDescription(true)]!" + "</p>");
            } else {
                sb.append("<p>" + "[npc.Name]'s entire body, save for a small, glowing sphere in the place where [npc.her] heart should be, is made out of [npc.skinFullDescription(true)]!" + "</p>");
            }
            break;
    }
    // Femininity:
    if (owner.isPlayer()) {
        sb.append("<p>" + "You have ");
    } else {
        sb.append("<p>" + "[npc.She] has ");
    }
    if (Femininity.valueOf(femininity) == Femininity.MASCULINE_STRONG) {
        sb.append(UtilText.returnStringAtRandom("a <span style='color:" + Colour.MASCULINE_PLUS.toWebHexString() + ";'>very masculine</span>", "an <span style='color:" + Colour.MASCULINE_PLUS.toWebHexString() + ";'>extremely handsome</span>"));
    } else if (Femininity.valueOf(femininity) == Femininity.MASCULINE) {
        sb.append(UtilText.returnStringAtRandom("a <span style='color:" + Colour.MASCULINE.toWebHexString() + ";'>masculine</span>", "a <span style='color:" + Colour.MASCULINE.toWebHexString() + ";'>handsome</span>"));
    } else if (Femininity.valueOf(femininity) == Femininity.ANDROGYNOUS) {
        sb.append("an <span style='color:" + Colour.ANDROGYNOUS.toWebHexString() + ";'>androgynous</span>");
    } else if (Femininity.valueOf(femininity) == Femininity.FEMININE) {
        sb.append(UtilText.returnStringAtRandom("a <span style='color:" + Colour.FEMININE.toWebHexString() + ";'>pretty</span>", "a <span style='color:" + Colour.FEMININE.toWebHexString() + ";'>feminine</span>", "a <span style='color:" + Colour.FEMININE.toWebHexString() + ";'>cute</span>"));
    } else {
        sb.append(UtilText.returnStringAtRandom("a <span style='color:" + Colour.FEMININE_PLUS.toWebHexString() + ";'>very feminine</span>", "a <span style='color:" + Colour.FEMININE_PLUS.toWebHexString() + ";'>beautiful</span>", "a <span style='color:" + Colour.FEMININE_PLUS.toWebHexString() + ";'>gorgeous</span>"));
    }
    // Face and eyes:
    switch(face.getType()) {
        case HUMAN:
            sb.append(" face.");
            break;
        case ANGEL:
            sb.append(", perfectly proportioned face.");
            break;
        case DEMON_COMMON:
            sb.append(", perfectly proportioned face.");
            break;
        case IMP:
            sb.append(", impish face.");
            break;
        case DOG_MORPH:
            sb.append(", anthropomorphic dog-like face, complete with a canine muzzle.");
            break;
        case LYCAN:
            sb.append(", anthropomorphic wolf-like face, complete with a lupine muzzle.");
            break;
        case CAT_MORPH:
            sb.append(", anthropomorphic cat-like face, with a cute little feline muzzle.");
            break;
        case ALLIGATOR_MORPH:
            sb.append(", anthropomorphic alligator-like face, with a long flat muzzle.");
            break;
        case COW_MORPH:
            sb.append(", anthropomorphic cow-like face, with a cute little bovine muzzle.");
            break;
        case SQUIRREL_MORPH:
            sb.append(", anthropomorphic squirrel-like face, with a cute little muzzle.");
            break;
        case HORSE_MORPH:
            sb.append(", anthropomorphic horse-like face, with a long, equine muzzle.");
            break;
        case REINDEER_MORPH:
            sb.append(", anthropomorphic reindeer-like face, with a long, reindeer-like muzzle.");
            break;
        case HARPY:
            sb.append(", anthropomorphic bird-like face, complete with beak.");
            break;
    }
    if (owner.getBlusher().getPrimaryColour() != Colour.COVERING_NONE) {
        if (owner.isPlayer()) {
            sb.append(" You are wearing " + owner.getBlusher().getColourDescriptor(owner, true, false) + " blusher.");
        } else {
            sb.append(" [npc.She] is wearing " + owner.getBlusher().getColourDescriptor(owner, true, false) + " blusher.");
        }
    }
    if (owner.isPlayer() && hair.getRawLengthValue() == 0) {
        sb.append(" You are completely bald.");
    } else if (!owner.isPlayer() && hair.getRawLengthValue() == 0) {
        sb.append(" [npc.She] is completely bald.");
    } else {
        if (owner.isPlayer()) {
            sb.append(" You have [pc.hairLength], [pc.hairColour(true)]");
        } else {
            sb.append(" [npc.She] has [npc.hairLength], [npc.hairColour(true)]");
        }
        switch(hair.getType()) {
            case HUMAN:
                sb.append(" hair");
                break;
            case DEMON_COMMON:
                sb.append(", silken hair");
                break;
            case IMP:
                sb.append(", silken hair");
                break;
            case ANGEL:
                sb.append(", silken hair");
                break;
            case DOG_MORPH:
                sb.append(", fur-like hair");
                break;
            case LYCAN:
                sb.append(", fur-like hair");
                break;
            case CAT_MORPH:
                sb.append(", fur-like hair");
                break;
            case COW_MORPH:
                sb.append(", fur-like hair");
                break;
            case ALLIGATOR_MORPH:
                sb.append(", coarse hair");
                break;
            case SQUIRREL_MORPH:
                sb.append(", fur-like hair");
                break;
            case HORSE_MORPH:
                sb.append(", horse-like hair");
                break;
            case REINDEER_MORPH:
                sb.append(", reindeer-like hair");
                break;
            case HARPY:
                sb.append(" feathers in place of hair");
                break;
        }
        switch(hair.getStyle()) {
            case BRAIDED:
                sb.append(", which " + (hair.getType().isDefaultPlural() ? "have" : "has") + " been woven into a long braid.");
                break;
            case CURLY:
                sb.append(", which " + (hair.getType().isDefaultPlural() ? "have" : "has") + " been curled and left loose.");
                break;
            case LOOSE:
                sb.append(", which " + (hair.getType().isDefaultPlural() ? "are" : "is") + " left loose and unstyled.");
                break;
            case NONE:
                sb.append(", which " + (hair.getType().isDefaultPlural() ? "are" : "is") + " unstyled.");
                break;
            case PONYTAIL:
                sb.append(", which " + (hair.getType().isDefaultPlural() ? "have" : "has") + " been styled into a ponytail.");
                break;
            case STRAIGHT:
                sb.append(", which " + (hair.getType().isDefaultPlural() ? "have" : "has") + " been straightened and left loose.");
                break;
            case TWIN_TAILS:
                sb.append(", which " + (hair.getType().isDefaultPlural() ? "have" : "has") + " been styled into twin tails.");
                break;
            case WAVY:
                sb.append(", which " + (hair.getType().isDefaultPlural() ? "have" : "has") + " been styled into waves and left loose.");
                break;
            case MOHAWK:
                sb.append(", which " + (hair.getType().isDefaultPlural() ? "have" : "has") + " been styled into a mohawk.");
                break;
            case AFRO:
                sb.append(", which " + (hair.getType().isDefaultPlural() ? "have" : "has") + " been styled into an afro.");
                break;
            case SIDECUT:
                sb.append(", which " + (hair.getType().isDefaultPlural() ? "have" : "has") + " been styled into a sidecut.");
                break;
            case BOB_CUT:
                sb.append(", which " + (hair.getType().isDefaultPlural() ? "have" : "has") + " been styled into a bob cut.");
                break;
            case PIXIE:
                sb.append(", which " + (hair.getType().isDefaultPlural() ? "have" : "has") + " been styled into a pixie-cut.");
                break;
            case SLICKED_BACK:
                sb.append(", which " + (hair.getType().isDefaultPlural() ? "have" : "has") + " been slicked back.");
                break;
            case MESSY:
                sb.append(", which " + (hair.getType().isDefaultPlural() ? "are" : "is") + " unstyled and very messy.");
                break;
            case HIME_CUT:
                sb.append(", which " + (hair.getType().isDefaultPlural() ? "have" : "has") + " been straightened and styled into a hime cut.");
                break;
            case CHONMAGE:
                sb.append(", which " + (hair.getType().isDefaultPlural() ? "have" : "has") + " been straightened, oiled and styled into a chonmage topknot.");
                break;
            case TOPKNOT:
                sb.append(", which " + (hair.getType().isDefaultPlural() ? "have" : "has") + " been styled into a topknot.");
                break;
            case DREADLOCKS:
                sb.append(", which " + (hair.getType().isDefaultPlural() ? "have" : "has") + " been styled into dreadlocks.");
                break;
            case BIRD_CAGE:
                sb.append(", which " + (hair.getType().isDefaultPlural() ? "have" : "has") + " been styled into an elaborate bird cage" + UtilText.returnStringAtRandom(".", ", birds not included."));
                break;
            case TWIN_BRAIDS:
                sb.append(", which " + (hair.getType().isDefaultPlural() ? "have" : "has") + " been woven into long twin braids.");
                break;
            case DRILLS:
                sb.append(", which " + (hair.getType().isDefaultPlural() ? "have" : "has") + " been styled into drills.");
                break;
            case LOW_PONYTAIL:
                sb.append(", which " + (hair.getType().isDefaultPlural() ? "have" : "has") + " been styled into a low ponytail.");
                break;
            case CROWN_BRAID:
                sb.append(", which " + (hair.getType().isDefaultPlural() ? "have" : "has") + " been woven into a " + UtilText.returnStringAtRandom("crown of braids.", "braided crown."));
                break;
        }
    }
    switch(horn.getType()) {
        case NONE:
            sb.append("");
            break;
        case CURLED:
            if (owner.isPlayer()) {
                sb.append(" " + Util.capitaliseSentence(horn.getDeterminer(owner)) + " " + horn.getHornLength().getDescriptor() + ", [pc.hornColour(true)], circular-curling horns protrude from the upper sides of your forehead.");
            } else {
                sb.append(" " + Util.capitaliseSentence(horn.getDeterminer(owner)) + " " + horn.getHornLength().getDescriptor() + ", [npc.hornColour(true)], circular-curling horns protrude from the upper sides of [npc.her] forehead.");
            }
            break;
        case CURVED:
        case BOVINE_CURVED:
            if (owner.isPlayer()) {
                sb.append(" " + Util.capitaliseSentence(horn.getDeterminer(owner)) + " " + horn.getHornLength().getDescriptor() + ", [pc.hornColour(true)], curved horns protrude from the upper sides of your forehead.");
            } else {
                sb.append(" " + Util.capitaliseSentence(horn.getDeterminer(owner)) + " " + horn.getHornLength().getDescriptor() + ", [npc.hornColour(true)], curved horns protrude from the upper sides of [npc.her] forehead.");
            }
            break;
        case REINDEER_RACK:
            if (owner.isPlayer()) {
                sb.append(" " + Util.capitaliseSentence(horn.getDeterminer(owner)) + " " + horn.getHornLength().getDescriptor() + ", [pc.hornColour(true)], multi-branched antlers protrude from the upper sides of your forehead.");
            } else {
                sb.append(" " + Util.capitaliseSentence(horn.getDeterminer(owner)) + " " + horn.getHornLength().getDescriptor() + ", [npc.hornColour(true)], multi-branched antlers protrude from the upper sides of [npc.her] forehead.");
            }
            break;
        case SPIRAL:
            if (owner.isPlayer()) {
                sb.append(" " + Util.capitaliseSentence(horn.getDeterminer(owner)) + " " + horn.getHornLength().getDescriptor() + ", [pc.hornColour(true)], spiralling horns protrude from the upper sides of your forehead.");
            } else {
                sb.append(" " + Util.capitaliseSentence(horn.getDeterminer(owner)) + " " + horn.getHornLength().getDescriptor() + ", [npc.hornColour(true)], spiralling horns protrude from the upper sides of [npc.her] forehead.");
            }
            break;
        case STRAIGHT:
        case BOVINE_STRAIGHT:
            if (owner.isPlayer()) {
                sb.append(" " + Util.capitaliseSentence(horn.getDeterminer(owner)) + " " + horn.getHornLength().getDescriptor() + ", [pc.hornColour(true)], straight horns protrude from the upper sides of your forehead.");
            } else {
                sb.append(" " + Util.capitaliseSentence(horn.getDeterminer(owner)) + " " + horn.getHornLength().getDescriptor() + ", [npc.hornColour(true)], straight horns protrude from the upper sides of [npc.her] forehead.");
            }
            break;
        case SWEPT_BACK:
            if (owner.isPlayer()) {
                sb.append(" " + Util.capitaliseSentence(horn.getDeterminer(owner)) + " " + horn.getHornLength().getDescriptor() + ", [pc.hornColour(true)], swept-back horns protrude from the upper sides of your forehead.");
            } else {
                sb.append(" " + Util.capitaliseSentence(horn.getDeterminer(owner)) + " " + horn.getHornLength().getDescriptor() + ", [npc.hornColour(true)], swept-back horns protrude from the upper sides of [npc.her] forehead.");
            }
            break;
    }
    switch(antenna.getType()) {
        case NONE:
            sb.append("");
            break;
        default:
            if (owner.isPlayer())
                sb.append(" [pc.A_antennae+] protrude from your upper forehead.");
            else
                sb.append(" [npc.A_antennae+] protrude from [npc.her] upper forehead.");
    }
    if (face.isPiercedNose()) {
        if (owner.isPlayer()) {
            sb.append(" Your [pc.nose] has been pierced.");
        } else {
            sb.append(" [npc.Her] [npc.nose] has been pierced.");
        }
    }
    if (owner.isPlayer()) {
        sb.append(" You have [pc.eyePairs] ");
    } else {
        sb.append(" [npc.She] has [npc.eyePairs] ");
    }
    switch(eye.getType()) {
        case ANGEL:
            sb.append(" angelic eyes");
            break;
        case CAT_MORPH:
            sb.append(" cat-like eyes");
            break;
        case COW_MORPH:
            sb.append(" cow-like eyes");
            break;
        case DEMON_COMMON:
            sb.append(" demonic eyes");
            break;
        case IMP:
            sb.append(" impish eyes");
            break;
        case DOG_MORPH:
            sb.append(" dog-like eyes");
            break;
        case ALLIGATOR_MORPH:
            sb.append(" reptilian eyes");
            break;
        case HARPY:
            sb.append(" bird-like eyes");
            break;
        case HORSE_MORPH:
            sb.append(" horse-like eyes");
            break;
        case REINDEER_MORPH:
            sb.append(" reindeer-like eyes");
            break;
        case HUMAN:
            sb.append(" normal, human eyes");
            break;
        case LYCAN:
            sb.append(" wolf-like eyes");
            break;
        case SQUIRREL_MORPH:
            sb.append(" squirrel-like eyes");
            break;
    }
    if (owner.isPlayer()) {
        if (owner.getCovering(owner.getEyeType().getBodyCoveringType(owner)).getPattern() == CoveringPattern.EYE_IRISES_HETEROCHROMATIC) {
            sb.append(", with [pc.irisShape], heterochromatic [pc.irisPrimaryColour(true)]-and-[pc.irisSecondaryColour(true)] irises ");
        } else {
            sb.append(", with [pc.irisShape], [pc.irisPrimaryColour(true)] irises ");
        }
        if (owner.getCovering(BodyCoveringType.EYE_PUPILS).getPattern() == CoveringPattern.EYE_PUPILS_HETEROCHROMATIC) {
            sb.append("and [pc.pupilShape], heterochromatic [pc.pupilPrimaryColour(true)]-and-[pc.pupilSecondaryColour(true)] pupils.");
        } else {
            sb.append("and [pc.pupilShape], [pc.pupilPrimaryColour(true)] pupils.");
        }
    } else {
        if (owner.getCovering(owner.getEyeType().getBodyCoveringType(owner)).getPattern() == CoveringPattern.EYE_IRISES_HETEROCHROMATIC) {
            sb.append(", with [npc.irisShape], heterochromatic [npc.irisPrimaryColour(true)]-and-[npc.irisSecondaryColour(true)] irises, ");
        } else {
            sb.append(", with [npc.irisShape], [npc.irisPrimaryColour(true)] irises ");
        }
        if (owner.getCovering(BodyCoveringType.EYE_PUPILS).getPattern() == CoveringPattern.EYE_PUPILS_HETEROCHROMATIC) {
            sb.append("and [npc.pupilShape], heterochromatic [npc.pupilPrimaryColour(true)]-and-[npc.pupilSecondaryColour(true)] pupils.");
        } else {
            sb.append("and [npc.pupilShape], [npc.pupilPrimaryColour(true)] pupils.");
        }
    }
    // Eye makeup:
    if (owner.getEyeLiner().getPrimaryColour() != Colour.COVERING_NONE) {
        if (owner.isPlayer()) {
            sb.append(" Around your [pc.eyes], you've got a layer of " + owner.getEyeLiner().getColourDescriptor(owner, true, false) + " eye liner.");
        } else {
            sb.append(" Around [npc.her] [npc.eyes], [npc.she]'s got a layer of " + owner.getEyeLiner().getColourDescriptor(owner, true, false) + " eye liner.");
        }
    }
    if (owner.getEyeShadow().getPrimaryColour() != Colour.COVERING_NONE) {
        if (owner.isPlayer()) {
            sb.append(" You're wearing a tasteful amount of " + owner.getEyeShadow().getFullDescription(owner, true) + ".");
        } else {
            sb.append(" [npc.She]'s wearing a tasteful amount of " + owner.getEyeShadow().getFullDescription(owner, true) + ".");
        }
    }
    // Ear:
    switch(ear.getType()) {
        case ANGEL:
            if (owner.isPlayer())
                sb.append(" You have a pair of perfectly-formed angelic ears, which are " + getCoveredInDescriptor(owner) + " [pc.earFullDescription(true)]" + (ear.isPierced() ? ", and which have been pierced" : "") + ".");
            else
                sb.append(" [npc.She] has a pair of perfectly-formed angelic ears, which are " + getCoveredInDescriptor(owner) + " [npc.earFullDescription(true)]" + (ear.isPierced() ? ", and which have been pierced" : "") + ".");
            break;
        case HUMAN:
            if (owner.isPlayer())
                sb.append(" You have a pair of normal, human ears, which are " + getCoveredInDescriptor(owner) + " [pc.earFullDescription(true)]" + (ear.isPierced() ? ", and which have been pierced" : "") + ".");
            else
                sb.append(" [npc.She] has a pair of normal, human ears, which are " + getCoveredInDescriptor(owner) + " [npc.earFullDescription(true)]" + (ear.isPierced() ? ", and which have been pierced" : "") + ".");
            break;
        case DEMON_COMMON:
            if (owner.isPlayer())
                sb.append(" You have a pair of pointed, demonic ears, which are " + getCoveredInDescriptor(owner) + " [pc.earFullDescription(true)]" + (ear.isPierced() ? ", and which have been pierced" : "") + ".");
            else
                sb.append(" [npc.She] has a pair of pointed, demonic ears, which are " + getCoveredInDescriptor(owner) + " [npc.earFullDescription(true)]" + (ear.isPierced() ? ", and which have been pierced" : "") + ".");
            break;
        case IMP:
            if (owner.isPlayer())
                sb.append(" You have a pair of pointed, impish ears, which are " + getCoveredInDescriptor(owner) + " [pc.earFullDescription(true)]" + (ear.isPierced() ? ", and which have been pierced" : "") + ".");
            else
                sb.append(" [npc.She] has a pair of pointed, impish ears, which are " + getCoveredInDescriptor(owner) + " [npc.earFullDescription(true)]" + (ear.isPierced() ? ", and which have been pierced" : "") + ".");
            break;
        case DOG_MORPH:
            if (owner.isPlayer())
                sb.append(" You have a pair of floppy, " + (ear.isPierced() ? "pierced, " : "") + "dog-like ears, which are positioned high up on your head and are are " + getCoveredInDescriptor(owner) + " [pc.earFullDescription(true)].");
            else
                sb.append(" [npc.She] has a pair of floppy, " + (ear.isPierced() ? "pierced, " : "") + "dog-like ears, which are positioned high up on [npc.her] head and are " + getCoveredInDescriptor(owner) + " [npc.earFullDescription(true)].");
            break;
        case DOG_MORPH_POINTED:
            if (owner.isPlayer())
                sb.append(" You have a pair of pointed, " + (ear.isPierced() ? "pierced, " : "") + "dog-like ears, which are positioned high up on your head and are are " + getCoveredInDescriptor(owner) + " [pc.earFullDescription(true)].");
            else
                sb.append(" [npc.She] has a pair of pointed, " + (ear.isPierced() ? "pierced, " : "") + "dog-like ears, which are positioned high up on [npc.her] head and are " + getCoveredInDescriptor(owner) + " [npc.earFullDescription(true)].");
            break;
        case LYCAN:
            if (owner.isPlayer())
                sb.append(" You have a pair of " + (ear.isPierced() ? "pierced, " : "") + "upright, wolf-like ears, which are positioned high up on your head and are are " + getCoveredInDescriptor(owner) + " [pc.earFullDescription(true)].");
            else
                sb.append(" [npc.She] has a pair of " + (ear.isPierced() ? "pierced, " : "") + "upright, wolf-like ears, which are positioned high up on [npc.her] head and are " + getCoveredInDescriptor(owner) + " [npc.earFullDescription(true)].");
            break;
        case CAT_MORPH:
            if (owner.isPlayer())
                sb.append(" You have a pair of " + (ear.isPierced() ? "pierced, " : "") + "upright, cat-like ears, which are positioned high up on your head and are are " + getCoveredInDescriptor(owner) + " [pc.earFullDescription(true)].");
            else
                sb.append(" [npc.She] has a pair of " + (ear.isPierced() ? "pierced, " : "") + "upright, cat-like ears, which are positioned high up on [npc.her] head and are " + getCoveredInDescriptor(owner) + " [npc.earFullDescription(true)].");
            break;
        case COW_MORPH:
            if (owner.isPlayer())
                sb.append(" You have a pair of oval-shaped, cow-like ears, which are " + getCoveredInDescriptor(owner) + " [pc.earFullDescription(true)]" + (ear.isPierced() ? ", and which have been pierced" : "") + ".");
            else
                sb.append(" [npc.She] has a pair of oval-shaped, cow-like ears, which are " + getCoveredInDescriptor(owner) + " [npc.earFullDescription(true)]" + (ear.isPierced() ? ", and which have been pierced" : "") + ".");
            break;
        case ALLIGATOR_MORPH:
            if (owner.isPlayer())
                sb.append(" Your ears are an internal part of your head, and are covered by a fan of <span style='color:[pc.earColourHex];'>[pc.earColour] scales</span>." + (ear.isPierced() ? " They have been cleverly pierced so as to allow you to wear ear-specific jewellery." : ""));
            else
                sb.append(" [npc.Her] ears are an internal part of [npc.her] head, and are covered by a fan of <span style='color:[npc.earColourHex];'>[npc.earColour] scales</span>." + (ear.isPierced() ? " They have been cleverly pierced so as to allow [npc.herHim] to wear ear-specific jewellery." : ""));
            break;
        case SQUIRREL_MORPH:
            if (owner.isPlayer())
                sb.append(" You have a pair of " + (ear.isPierced() ? "pierced, " : "") + "rounded, squirrel-like ears, which are positioned high up on your head and are are " + getCoveredInDescriptor(owner) + " [pc.earFullDescription(true)].");
            else
                sb.append(" [npc.She] has a pair of " + (ear.isPierced() ? "pierced, " : "") + "rounded, squirrel-like ears, which are positioned high up on [npc.her] head and are " + getCoveredInDescriptor(owner) + " [npc.earFullDescription(true)].");
            break;
        case HORSE_MORPH:
            if (owner.isPlayer())
                sb.append(" You have a pair of " + (ear.isPierced() ? "pierced, " : "") + "upright, horse-like ears, which are positioned high up on your head and are are " + getCoveredInDescriptor(owner) + " [pc.earFullDescription(true)].");
            else
                sb.append(" [npc.She] has a pair of " + (ear.isPierced() ? "pierced, " : "") + "upright, horse-like ears, which are positioned high up on [npc.her] head and are " + getCoveredInDescriptor(owner) + " [npc.earFullDescription(true)].");
            break;
        case REINDEER_MORPH:
            if (owner.isPlayer())
                sb.append(" You have a pair of oval-shaped, reindeer-like ears, which are " + getCoveredInDescriptor(owner) + " [pc.earFullDescription(true)]" + (ear.isPierced() ? ", and which have been pierced" : "") + ".");
            else
                sb.append(" [npc.She] has a pair of oval-shaped, reindeer-like ears, which are " + getCoveredInDescriptor(owner) + " [npc.earFullDescription(true)]" + (ear.isPierced() ? ", and which have been pierced" : "") + ".");
            break;
        case HARPY:
            if (owner.isPlayer())
                sb.append(" Your ears are an internal part of your head, and are covered by a fan of <span style='color:[pc.earColourHex];'>[pc.earColour] feathers</span>." + (ear.isPierced() ? " They have been cleverly pierced so as to allow you to wear ear-specific jewellery." : ""));
            else
                sb.append(" [npc.Her] ears are an internal part of [npc.her] head, and are covered by a fan of <span style='color:[npc.earColourHex];'>[npc.earColour] feathers</span>." + (ear.isPierced() ? " They have been cleverly pierced so as to allow [npc.herHim] to wear ear-specific jewellery." : ""));
            break;
    }
    sb.append("</p>" + "<p>");
    if (Main.game.isFacialHairEnabled()) {
        if (owner.isPlayer()) {
            if (owner.getFacialHairType().getType() == BodyCoveringType.BODY_HAIR_SCALES_ALLIGATOR) {
                switch(owner.getFacialHair()) {
                    case ZERO_NONE:
                        if (!owner.isFeminine()) {
                            sb.append(" You don't have any trace of rough, stubbly " + owner.getFacialHairType().getName(owner) + " growing on your [pc.face].");
                        }
                        break;
                    case ONE_STUBBLE:
                        sb.append(" You have a stubbly patch of rough " + owner.getFacialHairType().getFullDescription(owner, true) + " growing on your [pc.face].");
                        break;
                    case TWO_MANICURED:
                        sb.append(" You have a small amount of rough " + owner.getFacialHairType().getFullDescription(owner, true) + " growing on your [pc.face], which resembles a beard.");
                        break;
                    case THREE_TRIMMED:
                        sb.append(" You have a rough patch of " + owner.getFacialHairType().getFullDescription(owner, true) + " growing on your [pc.face], which resembles a beard.");
                        break;
                    case FOUR_NATURAL:
                        sb.append(" You have a natural-looking rough patch of " + owner.getFacialHairType().getFullDescription(owner, true) + " growing on your [pc.face], which resembles a beard.");
                        break;
                    case FIVE_UNKEMPT:
                        sb.append(" You have an unkempt, rough patch of " + owner.getFacialHairType().getFullDescription(owner, true) + " growing on your [pc.face], which resembles a beard.");
                        break;
                    case SIX_BUSHY:
                        sb.append(" You have a thick, rough patch of " + owner.getFacialHairType().getFullDescription(owner, true) + " growing on your [pc.face], which resembles a beard.");
                        break;
                    case SEVEN_WILD:
                        sb.append(" You have a wild, rough patch of " + owner.getFacialHairType().getFullDescription(owner, true) + " growing on your [pc.face], which resembles a beard.");
                        break;
                }
            } else {
                switch(owner.getFacialHair()) {
                    case ZERO_NONE:
                        if (!owner.isFeminine()) {
                            sb.append(" You don't have any trace of facial " + owner.getFacialHairType().getName(owner) + ".");
                        }
                        break;
                    case ONE_STUBBLE:
                        sb.append(" You have a stubbly patch of " + owner.getFacialHairType().getFullDescription(owner, true) + " growing on your [pc.face].");
                        break;
                    case TWO_MANICURED:
                        sb.append(" You have a small amount of " + owner.getFacialHairType().getFullDescription(owner, true) + " growing on your [pc.face].");
                        break;
                    case THREE_TRIMMED:
                        sb.append(" You have a well-trimmed beard of " + owner.getFacialHairType().getFullDescription(owner, true) + " growing on your [pc.face].");
                        break;
                    case FOUR_NATURAL:
                        sb.append(" You have a natural-looking beard of " + owner.getFacialHairType().getFullDescription(owner, true) + " growing on your [pc.face].");
                        break;
                    case FIVE_UNKEMPT:
                        sb.append(" You have an unkempt, bushy beard of " + owner.getFacialHairType().getFullDescription(owner, true) + " growing on your [pc.face].");
                        break;
                    case SIX_BUSHY:
                        sb.append(" You have a thick, bushy beard of " + owner.getFacialHairType().getFullDescription(owner, true) + " growing on your [pc.face].");
                        break;
                    case SEVEN_WILD:
                        sb.append(" You have a wild, bushy beard of " + owner.getFacialHairType().getFullDescription(owner, true) + " growing on your [pc.face].");
                        break;
                }
            }
        } else {
            if (owner.getFacialHairType().getType() == BodyCoveringType.BODY_HAIR_SCALES_ALLIGATOR) {
                switch(owner.getFacialHair()) {
                    case ZERO_NONE:
                        if (!owner.isFeminine()) {
                            sb.append(" [npc.She] doesn't have any trace of rough, stubbly " + owner.getFacialHairType().getName(owner) + ".");
                        }
                        break;
                    case ONE_STUBBLE:
                        sb.append(" [npc.She] has a stubbly patch of " + owner.getFacialHairType().getFullDescription(owner, true) + " growing on [npc.her] [npc.face].");
                        break;
                    case TWO_MANICURED:
                        sb.append(" [npc.She] has a small, rough patch of " + owner.getFacialHairType().getFullDescription(owner, true) + " growing on [npc.her] [npc.face], which resembles a beard.");
                        break;
                    case THREE_TRIMMED:
                        sb.append(" [npc.She] has a rough patch of " + owner.getFacialHairType().getFullDescription(owner, true) + " growing on [npc.her] [npc.face], which resembles a beard.");
                        break;
                    case FOUR_NATURAL:
                        sb.append(" [npc.She] has a natural-looking rough patch of " + owner.getFacialHairType().getFullDescription(owner, true) + " growing on [npc.her] [npc.face], which resembles a beard.");
                        break;
                    case FIVE_UNKEMPT:
                        sb.append(" [npc.She] has a unkempt, rough patch of " + owner.getFacialHairType().getFullDescription(owner, true) + " growing on [npc.her] [npc.face], which resembles a beard.");
                        break;
                    case SIX_BUSHY:
                        sb.append(" [npc.She] has a thick, rough patch of " + owner.getFacialHairType().getFullDescription(owner, true) + " growing on [npc.her] [npc.face], which resembles a beard.");
                        break;
                    case SEVEN_WILD:
                        sb.append(" [npc.She] has a wild, rough patch of " + owner.getFacialHairType().getFullDescription(owner, true) + " growing on [npc.her] [npc.face], which resembles a beard.");
                        break;
                }
            } else {
                switch(owner.getFacialHair()) {
                    case ZERO_NONE:
                        if (!owner.isFeminine()) {
                            sb.append(" [npc.She] doesn't have any trace of facial " + owner.getFacialHairType().getName(owner) + ".");
                        }
                        break;
                    case ONE_STUBBLE:
                        sb.append(" [npc.She] has a stubbly patch of " + owner.getFacialHairType().getFullDescription(owner, true) + " growing on [npc.her] [npc.face].");
                        break;
                    case TWO_MANICURED:
                        sb.append(" [npc.She] has a small amount of " + owner.getFacialHairType().getFullDescription(owner, true) + " growing on [npc.her] [npc.face].");
                        break;
                    case THREE_TRIMMED:
                        sb.append(" [npc.She] has a well-trimmed beard of " + owner.getFacialHairType().getFullDescription(owner, true) + " growing on [npc.her] [npc.face].");
                        break;
                    case FOUR_NATURAL:
                        sb.append(" [npc.She] has a natural-looking beard of " + owner.getFacialHairType().getFullDescription(owner, true) + " growing on [npc.her] [npc.face].");
                        break;
                    case FIVE_UNKEMPT:
                        sb.append(" [npc.She] has a unkempt, bushy beard of " + owner.getFacialHairType().getFullDescription(owner, true) + " growing on [npc.her] [npc.face].");
                        break;
                    case SIX_BUSHY:
                        sb.append(" [npc.She] has a thick, bushy beard of " + owner.getFacialHairType().getFullDescription(owner, true) + " growing on [npc.her] [npc.face].");
                        break;
                    case SEVEN_WILD:
                        sb.append(" [npc.She] has a wild, bushy beard of " + owner.getFacialHairType().getFullDescription(owner, true) + " growing on [npc.her] [npc.face].");
                        break;
                }
            }
        }
    }
    // Mouth & lips:
    if (owner.isPlayer()) {
        sb.append(" You have [pc.lipSize], [pc.mouthColourPrimary(true)] [pc.lips]");
        if (owner.getLipstick().getPrimaryColour() != Colour.COVERING_NONE) {
            sb.append((owner.isPiercedLip() ? ", which have been pierced, and" : ", which") + " are currently " + getCoveredInDescriptor(owner) + " " + owner.getLipstick().getFullDescription(owner, true) + ".");
        } else {
            sb.append((owner.isPiercedLip() ? ", which have been pierced." : "."));
        }
        sb.append(" Your throat is [pc.mouthColourSecondary(true)] in colour.");
    } else {
        sb.append(" [npc.She] has [npc.lipSize], [npc.mouthColourPrimary(true)] [pc.lips]");
        if (owner.getLipstick().getPrimaryColour() != Colour.COVERING_NONE) {
            sb.append((owner.isPiercedLip() ? ", which have been pierced, and" : ", which") + " are currently " + getCoveredInDescriptor(owner) + " " + owner.getLipstick().getFullDescription(owner, true) + ".");
        } else {
            sb.append((owner.isPiercedLip() ? ", which have been pierced." : "."));
        }
        sb.append(" [npc.Her] throat is [npc.mouthColourSecondary(true)] in colour.");
    }
    // Throat modifiers:
    for (OrificeModifier om : OrificeModifier.values()) {
        if (owner.hasFaceOrificeModifier(om)) {
            if (owner.isPlayer()) {
                switch(om) {
                    case PUFFY:
                        sb.append(" Your [pc.lips] have swollen up to be far puffier than what would be considered normal.");
                        break;
                    case MUSCLE_CONTROL:
                        sb.append(" You have a series of internal muscles lining the inside of your throat, allowing you to expertly squeeze and grip down on any intruding object.");
                        break;
                    case RIBBED:
                        sb.append(" The inside of your throat is lined with sensitive, fleshy ribs, which grant you extra pleasure when stimulated.");
                        break;
                    case TENTACLED:
                        sb.append(" Your throat is filled with tiny little tentacles, which wriggle and squirm with a mind of their own.");
                        break;
                }
            } else {
                switch(om) {
                    case PUFFY:
                        sb.append(" [npc.Her] [npc.lips] have swollen up to be far puffier than what would be considered normal.");
                        break;
                    case MUSCLE_CONTROL:
                        sb.append(" [npc.She] has a series of internal muscles lining the inside of [npc.her] throat, allowing [npc.herHim] to expertly squeeze and grip down on any intruding object.");
                        break;
                    case RIBBED:
                        sb.append(" The inside of [npc.her] throat is lined with sensitive, fleshy ribs, which grant [npc.herHim] extra pleasure when stimulated.");
                        break;
                    case TENTACLED:
                        sb.append(" [npc.Her] throat is filled with tiny little tentacles, which wriggle and squirm with a mind of their own.");
                        break;
                }
            }
        }
    }
    // Tongue & blowjob:
    if (owner.isPlayer()) {
        sb.append(" Your mouth holds [pc.a_tongueLength], [pc.tongueColour(true)] [pc.tongue]" + (face.getTongue().isPierced() ? ", which has been pierced." : "."));
    } else {
        sb.append(" [npc.Her] mouth holds [npc.a_tongueLength], [npc.tongueColour(true)] [npc.tongue]" + (face.getTongue().isPierced() ? ", which has been pierced." : "."));
    }
    for (TongueModifier tm : TongueModifier.values()) {
        if (owner.hasTongueModifier(tm)) {
            if (owner.isPlayer()) {
                switch(tm) {
                    case RIBBED:
                        sb.append(" It's lined with hard, fleshy ribs, which are sure to grant extra pleasure to any orifice that they penetrate.");
                        break;
                    case TENTACLED:
                        sb.append(" A series of little tentacles coat its surface, which wriggle and squirm with a mind of their own.");
                        break;
                    case BIFURCATED:
                        sb.append(" Near the tip, it's split in two, leaving your tongue bifurcated, like a snake.");
                        break;
                }
            } else {
                switch(tm) {
                    case RIBBED:
                        sb.append(" It's lined with hard, fleshy ribs, which are sure to grant extra pleasure to any orifice that they penetrate.");
                        break;
                    case TENTACLED:
                        sb.append(" A series of little tentacles coat its surface, which wriggle and squirm with a mind of their own.");
                        break;
                    case BIFURCATED:
                        sb.append(" Near the tip, it's split in two, leaving [npc.her] tongue bifurcated, like a snake.");
                        break;
                }
            }
        }
    }
    if (owner.isPlayer()) {
        if (face.getMouth().getOrificeMouth().isVirgin()) {
            sb.append(" <span style='color:" + Colour.GENERIC_SEX.toWebHexString() + ";'>You've never given head before, so you don't know what you could fit down your throat.</span>");
        } else {
            switch(face.getMouth().getOrificeMouth().getCapacity().getMaximumSizeComfortableWithLube()) {
                // case NEGATIVE_UTILITY_VALUE:
                case ZERO_MICROSCOPIC:
                    sb.append(" [style.colourSex(You're terrible at giving head)], and struggle to fit the tip of even a tiny cock into your mouth without gagging.");
                    break;
                case ONE_TINY:
                    sb.append(" [style.colourSex(You're really bad at giving head)], and struggle to fit even a tiny cocks into your mouth without gagging.");
                    // sb.append(" You find anything larger than "+face.getRawCapacityValue()+" inches to be uncomfortable.");
                    break;
                case TWO_AVERAGE:
                    sb.append(" [style.colourSex(You're not great at giving head)], and anything larger than an average-sized human cock will cause you to gag.");
                    // sb.append(" You find anything larger than "+face.getRawCapacityValue()+" inches to be uncomfortable.");
                    break;
                case THREE_LARGE:
                    sb.append(" [style.colourSex(You're somewhat competent at giving head)], and can suppress your gag reflex enough to comfortably suck large cocks.");
                    // sb.append(" You find anything larger than "+face.getRawCapacityValue()+" inches to be uncomfortable.");
                    break;
                case FOUR_HUGE:
                    sb.append(" [style.colourSex(You're pretty good at giving head)], and can comfortably suck huge cocks without gagging.");
                    // sb.append(" You find anything larger than "+face.getRawCapacityValue()+" inches to be uncomfortable.");
                    break;
                case FIVE_ENORMOUS:
                    sb.append(" [style.colourSex(You're somewhat of an expert at giving head)], and can suck enormous cocks without too much difficulty.");
                    // sb.append(" You find anything larger than "+face.getRawCapacityValue()+" inches to be uncomfortable.");
                    break;
                case SIX_GIGANTIC:
                    sb.append(" [style.colourSex(You're amazing at giving head)], and can comfortably suck all but the most absurdly-sized of cocks with ease.");
                    // sb.append(" You find anything larger than "+face.getRawCapacityValue()+" inches to be uncomfortable.");
                    break;
                case SEVEN_STALLION:
                    sb.append(" [style.colourSex(You are)]" + " [style.colourLegendary(legendary)]" + " [style.colourSex(at giving head)]; it's almost as though your throat was purposefully designed to fit phallic objects of any size or shape.");
                    break;
                default:
                    break;
            }
            for (PenetrationType pt : PenetrationType.values()) {
                if (Main.game.getPlayer().getVirginityLoss(new SexType(SexParticipantType.CATCHER, pt, OrificeType.MOUTH)) != null && !Main.game.getPlayer().getVirginityLoss(new SexType(SexParticipantType.CATCHER, pt, OrificeType.MOUTH)).isEmpty()) {
                    sb.append(" <span style='color:" + Colour.GENERIC_ARCANE.toWebHexString() + ";'>The first time you performed oral sex was to " + Main.game.getPlayer().getVirginityLoss(new SexType(SexParticipantType.CATCHER, pt, OrificeType.MOUTH)) + ".</span>");
                    break;
                }
            }
        }
    } else {
        if (owner.getPlayerKnowsAreas().contains(CoverableArea.MOUTH)) {
            if (face.getMouth().getOrificeMouth().isVirgin()) {
                sb.append(" <span style='color:" + Colour.GENERIC_SEX.toWebHexString() + ";'>[npc.She]'s never given head before.</span>");
            } else {
                switch(face.getMouth().getOrificeMouth().getCapacity().getMaximumSizeComfortableWithLube()) {
                    // case NEGATIVE_UTILITY_VALUE:
                    case ZERO_MICROSCOPIC:
                        sb.append(" <span style='color:" + Colour.GENERIC_SEX.toWebHexString() + ";'>[npc.She]'s terrible at giving head</span>, and struggles to fit the tip of even the smallest of cocks into [npc.her] mouth without gagging.");
                        break;
                    case ONE_TINY:
                        sb.append(" <span style='color:" + Colour.GENERIC_SEX.toWebHexString() + ";'>[npc.She]'s really bad at giving head</span>, and struggles to fit even tiny cocks into [npc.her] mouth without gagging.");
                        // sb.append(" [npc.She] finds anything larger than "+face.getRawCapacityValue()+" inches to be uncomfortable.");
                        break;
                    case TWO_AVERAGE:
                        sb.append(" <span style='color:" + Colour.GENERIC_SEX.toWebHexString() + ";'>[npc.She]'s not great at giving head</span>, and anything larger than an average-sized human cock will cause [npc.her] to gag.");
                        // sb.append(" [npc.She] finds anything larger than "+face.getRawCapacityValue()+" inches to be uncomfortable.");
                        break;
                    case THREE_LARGE:
                        sb.append(" <span style='color:" + Colour.GENERIC_SEX.toWebHexString() + ";'>[npc.She]'s somewhat competent at giving head</span>, and can suppress [npc.her] gag reflex enough to comfortably suck large cocks.");
                        // sb.append(" [npc.She] finds anything larger than "+face.getRawCapacityValue()+" inches to be uncomfortable.");
                        break;
                    case FOUR_HUGE:
                        sb.append(" <span style='color:" + Colour.GENERIC_SEX.toWebHexString() + ";'>[npc.She]'s pretty good at giving head</span>, and can comfortably suck huge cocks without gagging.");
                        // sb.append(" [npc.She] finds anything larger than "+face.getRawCapacityValue()+" inches to be uncomfortable.");
                        break;
                    case FIVE_ENORMOUS:
                        sb.append(" <span style='color:" + Colour.GENERIC_SEX.toWebHexString() + ";'>[npc.She]'s somewhat of an expert at giving head</span>, and can suck enormous cocks without too much difficulty.");
                        // sb.append(" [npc.She] finds anything larger than "+face.getRawCapacityValue()+" inches to be uncomfortable.");
                        break;
                    case SIX_GIGANTIC:
                        sb.append(" <span style='color:" + Colour.GENERIC_SEX.toWebHexString() + ";'>[npc.She]'s amazing at giving head</span>, and can comfortably suck all but the most absurdly-sized of cocks with ease.");
                        // sb.append(" [npc.She] finds anything larger than "+face.getRawCapacityValue()+" inches to be uncomfortable.");
                        break;
                    case SEVEN_STALLION:
                        sb.append(" <span style='color:" + Colour.GENERIC_SEX.toWebHexString() + ";'>[npc.She] is</span>" + " <span style='color:" + Colour.GENERIC_EXCELLENT.toWebHexString() + ";'>legendary</span>" + " <span style='color:" + Colour.GENERIC_SEX.toWebHexString() + ";'>at giving head</span>;" + " it's almost as though [npc.her] throat was purposefully designed to fit phallic objects of any size or shape.");
                        break;
                    default:
                        break;
                }
            }
        } else {
            sb.append(" <span style='color:" + Colour.GENERIC_SEX.toWebHexString() + ";'>You don't know [npc.herHim] well enough to know how competent [npc.she] is at performing oral sex.</span>");
        }
    }
    sb.append("</p>");
    // Describe body:
    sb.append("<p>");
    if (owner.isPlayer()) {
        sb.append("Your torso has");
    } else {
        sb.append("[npc.Her] torso has");
    }
    if (femininity <= Femininity.MASCULINE_STRONG.getMaximumFemininity()) {
        sb.append(UtilText.returnStringAtRandom(" an <span style='color:" + Colour.MASCULINE_PLUS.toWebHexString() + ";'>extremely masculine</span> appearance", " a <span style='color:" + Colour.MASCULINE_PLUS.toWebHexString() + ";'>very masculine</span> appearance"));
    } else if (femininity <= Femininity.MASCULINE.getMaximumFemininity()) {
        sb.append(UtilText.returnStringAtRandom(" a <span style='color:" + Colour.MASCULINE.toWebHexString() + ";'>masculine</span> appearance", " a <span style='color:" + Colour.MASCULINE.toWebHexString() + ";'>boyish</span> appearance"));
    } else if (femininity <= Femininity.ANDROGYNOUS.getMaximumFemininity()) {
        sb.append(UtilText.returnStringAtRandom(" a very <span style='color:" + Colour.ANDROGYNOUS.toWebHexString() + ";'>androgynous</span> appearance"));
    } else if (femininity <= Femininity.FEMININE.getMaximumFemininity()) {
        sb.append(UtilText.returnStringAtRandom(" a <span style='color:" + Colour.FEMININE.toWebHexString() + ";'>feminine</span> appearance", " a <span style='color:" + Colour.FEMININE.toWebHexString() + ";'>pretty</span> appearance"));
    } else {
        sb.append(UtilText.returnStringAtRandom(" an <span style='color:" + Colour.FEMININE_PLUS.toWebHexString() + ";'>extremely feminine</span> appearance", " a <span style='color:" + Colour.FEMININE_PLUS.toWebHexString() + ";'>gorgeous</span> appearance", " a <span style='color:" + Colour.FEMININE_PLUS.toWebHexString() + ";'>jaw-droppingly beautiful</span> appearance"));
    }
    if (owner.isPlayer()) {
        sb.append(", and is " + getCoveredInDescriptor(owner) + " [pc.skinFullDescription(true)].");
    } else {
        sb.append(", and is " + getCoveredInDescriptor(owner) + " [npc.skinFullDescription(true)].");
    }
    if (owner.isPlayer()) {
        sb.append(" You have <span style='color:" + owner.getBodySize().getColour().toWebHexString() + ";'>[pc.a_bodySize]</span>, " + "<span style='color:" + owner.getMuscle().getColour().toWebHexString() + ";'>[pc.muscle]</span>" + " body, which gives you <span style='color:" + owner.getBodyShape().toWebHexStringColour() + ";'>[pc.a_bodyShape]</span> body shape.");
    } else {
        sb.append(" [npc.She] has <span style='color:" + BodySize.valueOf(getBodySize()).getColour().toWebHexString() + ";'>" + BodySize.valueOf(getBodySize()).getName(true) + "</span>, " + "<span style='color:" + Muscle.valueOf(getMuscle()).getColour().toWebHexString() + ";'>" + Muscle.valueOf(getMuscle()).getName(false) + "</span>" + " body, giving [npc.herHim] <span style='color:" + owner.getBodyShape().toWebHexStringColour() + ";'>[npc.a_bodyShape]</span> body shape.");
    }
    // Pregnancy:
    if (owner.hasStatusEffect(StatusEffect.PREGNANT_1)) {
        if (owner.isPlayer())
            sb.append(" Your belly is slightly swollen, and it's clear to anyone who takes a closer look that <span style='color:" + Colour.GENERIC_ARCANE.toWebHexString() + ";'>you're pregnant</span>.");
        else
            sb.append(" [npc.Her] belly is slightly swollen, and it's clear to anyone who takes a closer look that <span style='color:" + Colour.GENERIC_ARCANE.toWebHexString() + ";'>[npc.she]'s pregnant</span>.");
    } else if (owner.hasStatusEffect(StatusEffect.PREGNANT_2)) {
        if (owner.isPlayer())
            sb.append(" Your belly is heavily swollen, and it's clear to anyone who glances your way that <span style='color:" + Colour.GENERIC_ARCANE.toWebHexString() + ";'>you're pregnant</span>.");
        else
            sb.append(" [npc.Her] belly is heavily swollen, and it's clear to anyone who glances [npc.her] way that <span style='color:" + Colour.GENERIC_ARCANE.toWebHexString() + ";'>[npc.she]'s pregnant</span>.");
    } else if (owner.hasStatusEffect(StatusEffect.PREGNANT_3)) {
        if (owner.isPlayer())
            sb.append(" Your belly is massively swollen, and it's completely obvious to anyone who glances your way that" + " <span style='color:" + Colour.GENERIC_ARCANE.toWebHexString() + ";'>you're expecting to give birth very soon</span>.");
        else
            sb.append(" [npc.Her] belly is massively swollen, and it's completely obvious to anyone who glances [npc.her] way that" + " <span style='color:" + Colour.GENERIC_ARCANE.toWebHexString() + ";'>[npc.she]'s expecting to give birth very soon</span>.");
    }
    sb.append("</p>");
    // Breasts:
    sb.append("<p>");
    Breast viewedBreast = breast;
    if (Main.game.getPlayer().hasIngestedPsychoactiveFluidType(FluidTypeBase.MILK)) {
        viewedBreast = new Breast(breast.getType(), breast.getShape(), (int) (breast.getRawSizeValue() * (1.75f)), (int) ((breast.getRawMilkStorageValue() + 100) * (2.25f)), breast.getRows(), breast.getNipples().getNippleSizeValue(), breast.getNipples().getNippleShape(), breast.getNipples().getAreolaeSizeValue(), breast.getNippleCountPerBreast(), breast.getNipples().getOrificeNipples().getRawCapacityValue(), breast.getNipples().getOrificeNipples().getElasticity().getValue(), breast.getNipples().getOrificeNipples().getPlasticity().getValue(), breast.getNipples().getOrificeNipples().isVirgin());
        sb.append(" <i style='color:" + Colour.PSYCHOACTIVE.toWebHexString() + ";'>The psychoactive milk you recently ingested is causing your view of " + (owner.isPlayer() ? "your" : "[npc.name]'s") + " breasts to be distorted!</i>");
    }
    if (owner.isPlayer()) {
        if (viewedBreast.getRawSizeValue() > 0) {
            sb.append(" You have " + Util.intToString(viewedBreast.getRows()) + " pair" + (viewedBreast.getRows() == 1 ? "" : "s") + " of " + viewedBreast.getSize().getDescriptor() + " [pc.breasts]");
            if (viewedBreast.getRows() == 1) {
                if (viewedBreast.getSize().isTrainingBraSize()) {
                    sb.append(", which fit comfortably into a training bra.");
                } else {
                    sb.append(", which fit comfortably into " + UtilText.generateSingularDeterminer(viewedBreast.getSize().getCupSizeName()) + " " + viewedBreast.getSize().getCupSizeName() + "-cup bra.");
                }
            } else if (viewedBreast.getRows() == 2) {
                if (viewedBreast.getSize().isTrainingBraSize()) {
                    sb.append(", with your top pair fitting comfortably into a training bra, and the pair below being slightly smaller.");
                } else {
                    sb.append(", with your top pair fitting comfortably into " + UtilText.generateSingularDeterminer(viewedBreast.getSize().getCupSizeName()) + " " + viewedBreast.getSize().getCupSizeName() + "-cup bra, and the pair below being slightly smaller.");
                }
            } else if (viewedBreast.getRows() > 2) {
                if (viewedBreast.getSize().isTrainingBraSize()) {
                    sb.append(", with your top pair fitting comfortably into a training bra, and the pairs below each being slightly smaller than the ones above.");
                } else {
                    sb.append(", with your top pair fitting comfortably into " + UtilText.generateSingularDeterminer(viewedBreast.getSize().getCupSizeName()) + " " + viewedBreast.getSize().getCupSizeName() + "-cup bra, and the pairs below each being slightly smaller than the ones above.");
                }
            }
        } else {
            sb.append(" You have a completely flat chest");
            if (viewedBreast.getRows() == 1) {
                sb.append(", with a single pair of pecs.");
            } else {
                sb.append(", with " + Util.intToString(viewedBreast.getRows()) + " pairs of pecs.");
            }
        }
    } else {
        if (viewedBreast.getRawSizeValue() > 0) {
            sb.append(" [npc.She] has " + Util.intToString(viewedBreast.getRows()) + " pair" + (viewedBreast.getRows() == 1 ? "" : "s") + " of " + viewedBreast.getSize().getDescriptor() + " [npc.breasts]");
            if (viewedBreast.getRows() == 1) {
                if (viewedBreast.getSize().isTrainingBraSize()) {
                    sb.append(", which fit comfortably into a training bra.");
                } else {
                    sb.append(", which fit comfortably into " + UtilText.generateSingularDeterminer(viewedBreast.getSize().getCupSizeName()) + " " + viewedBreast.getSize().getCupSizeName() + "-cup bra.");
                }
            } else if (viewedBreast.getRows() == 2) {
                if (viewedBreast.getSize().isTrainingBraSize()) {
                    sb.append(", with [npc.her] top pair fitting comfortably into a training bra, and the pair below being slightly smaller.");
                } else {
                    sb.append(", with [npc.her] top pair fitting comfortably into " + UtilText.generateSingularDeterminer(viewedBreast.getSize().getCupSizeName()) + " " + viewedBreast.getSize().getCupSizeName() + "-cup bra, and the pair below being slightly smaller.");
                }
            } else if (viewedBreast.getRows() > 2) {
                if (viewedBreast.getSize().isTrainingBraSize()) {
                    sb.append(", with [npc.her] top pair fitting comfortably into a training bra, and the pairs below each being slightly smaller than the ones above.");
                } else {
                    sb.append(", with [npc.her] top pair fitting comfortably into " + UtilText.generateSingularDeterminer(viewedBreast.getSize().getCupSizeName()) + " " + viewedBreast.getSize().getCupSizeName() + "-cup bra, and the pairs below each being slightly smaller than the ones above.");
                }
            }
        } else {
            sb.append(" [npc.She] has a completely flat chest");
            if (viewedBreast.getRows() == 1) {
                sb.append(", with a single pair of pecs.");
            } else {
                sb.append(", with " + Util.intToString(viewedBreast.getRows()) + " pairs of pecs.");
            }
        }
    }
    // Nipples & piercings
    sb.append(" " + getBreastDescription(owner, viewedBreast));
    sb.append("</p>");
    // Arms and legs:
    sb.append("<p>");
    // Arms:
    String armDeterminer = "a pair of";
    if (arm.getArmRows() == 3) {
        armDeterminer = "three pairs of";
    } else if (arm.getArmRows() == 2) {
        armDeterminer = "two pairs of";
    }
    switch(arm.getType()) {
        case HUMAN:
            if (owner.isPlayer())
                sb.append("You have " + armDeterminer + " normal human arms and hands, which are " + getCoveredInDescriptor(owner) + " [pc.armFullDescription(true)].");
            else
                sb.append("[npc.She] has " + armDeterminer + " normal human arms and hands, which are " + getCoveredInDescriptor(owner) + " [npc.armFullDescription(true)].");
            break;
        case ANGEL:
            if (owner.isPlayer())
                sb.append("You have " + armDeterminer + " human-like arms and hands, which are " + getCoveredInDescriptor(owner) + " [pc.armFullDescription(true)].");
            else
                sb.append("[npc.She] has " + armDeterminer + " human-like arms and hands, which are " + getCoveredInDescriptor(owner) + " [npc.armFullDescription(true)].");
            break;
        case DEMON_COMMON:
            if (owner.isPlayer())
                sb.append("You have " + armDeterminer + " slender, human-looking arms and hands, which are " + getCoveredInDescriptor(owner) + " [pc.armFullDescription(true)].");
            else
                sb.append("[npc.She] has " + armDeterminer + " slender human-looking arms and hands, which are " + getCoveredInDescriptor(owner) + " [npc.armFullDescription(true)].");
            break;
        case DOG_MORPH:
            if (owner.isPlayer())
                sb.append("You have " + armDeterminer + " arms, which are " + getCoveredInDescriptor(owner) + " [pc.armFullDescription(true)]." + " Your hands are formed into anthropomorphic, dog-like hands, complete with little blunt claws and leathery pads.");
            else
                sb.append("[npc.She] has " + armDeterminer + " arms, which are " + getCoveredInDescriptor(owner) + " [npc.armFullDescription(true)]." + " [npc.Her] hands are formed into anthropomorphic, dog-like hands, complete with little blunt claws and leathery pads.");
            break;
        case ALLIGATOR_MORPH:
            if (owner.isPlayer())
                sb.append("You have " + armDeterminer + " arms, which are " + getCoveredInDescriptor(owner) + " [pc.armFullDescription(true)]." + " Your hands are formed into anthropomorphic, alligator-like hands, complete with little claws.");
            else
                sb.append("[npc.She] has " + armDeterminer + " arms, which are " + getCoveredInDescriptor(owner) + " [npc.armFullDescription(true)]." + " [npc.Her] hands are formed into anthropomorphic, alligator-like hands, complete with little claws.");
            break;
        case LYCAN:
            if (owner.isPlayer())
                sb.append("You have " + armDeterminer + " arms, which are " + getCoveredInDescriptor(owner) + " [pc.armFullDescription(true)]." + " Your hands are formed into anthropomorphic, wolf-like hands, complete with sharp claws and tough leathery pads.");
            else
                sb.append("[npc.She] has " + armDeterminer + " arms, which are " + getCoveredInDescriptor(owner) + " [npc.armFullDescription(true)]." + " [npc.Her] hands are formed into anthropomorphic, wolf-like hands, complete with sharp claws and tough leathery pads.");
            break;
        case CAT_MORPH:
            if (owner.isPlayer())
                sb.append("You have " + armDeterminer + " arms, which are " + getCoveredInDescriptor(owner) + " [pc.armFullDescription(true)]." + " Your hands are formed into anthropomorphic, cat-like hands, complete with retractable claws and pink pads.");
            else
                sb.append("[npc.She] has " + armDeterminer + " arms, which are " + getCoveredInDescriptor(owner) + " [npc.armFullDescription(true)]." + " [npc.Her] hands are formed into anthropomorphic, cat-like hands, complete with retractable claws and pink pads.");
            break;
        case COW_MORPH:
            if (owner.isPlayer())
                sb.append("You have " + armDeterminer + " arms, which are " + getCoveredInDescriptor(owner) + " [pc.armFullDescription(true)]." + " Your hands, while human in shape, have tough little hoof-like nails.");
            else
                sb.append("[npc.She] has " + armDeterminer + " arms, which are " + getCoveredInDescriptor(owner) + " [npc.armFullDescription(true)]." + " [npc.Her] hands, while human in shape, have tough little hoof-like nails.");
            break;
        case SQUIRREL_MORPH:
            if (owner.isPlayer())
                sb.append("You have " + armDeterminer + " arms, which are " + getCoveredInDescriptor(owner) + " [pc.armFullDescription(true)]." + " Your hands are formed into anthropomorphic, squirrel-like hands, complete with claws.");
            else
                sb.append("[npc.She] has " + armDeterminer + " arms, which are " + getCoveredInDescriptor(owner) + " [npc.armFullDescription(true)]." + " [npc.Her] hands are formed into anthropomorphic, squirrel-like hands, complete with claws.");
            break;
        case HORSE_MORPH:
            if (owner.isPlayer())
                sb.append("You have " + armDeterminer + " arms, which are " + getCoveredInDescriptor(owner) + " [pc.armFullDescription(true)]." + " Your hands, while human in shape, have tough little hoof-like nails.");
            else
                sb.append("[npc.She] has " + armDeterminer + " arms, which are " + getCoveredInDescriptor(owner) + " [npc.armFullDescription(true)]." + " [npc.Her] hands, while human in shape, have tough little hoof-like nails.");
            break;
        case REINDEER_MORPH:
            if (owner.isPlayer())
                sb.append("You have " + armDeterminer + " arms, which are " + getCoveredInDescriptor(owner) + " [pc.armFullDescription(true)]." + " Your hands, while human in shape, have tough little hoof-like nails.");
            else
                sb.append("[npc.She] has " + armDeterminer + " arms, which are " + getCoveredInDescriptor(owner) + " [npc.armFullDescription(true)]." + " [npc.Her] hands, while human in shape, have tough little hoof-like nails.");
            break;
        case HARPY:
            if (owner.isPlayer())
                sb.append("Your arms have transformed into " + armDeterminer + " huge wings, and are " + getCoveredInDescriptor(owner) + " beautiful [pc.armFullDescription(true)]." + " Where your hands should be, you have two feathered forefingers and a thumb, each of which ends in a little blunt claw." + " Although slightly less dexterous than a human hand, you're still able to use your remaining digits to form a hand-like grip.");
            else
                sb.append("In place of arms and hands, [npc.she] has " + armDeterminer + " huge wings, which are " + getCoveredInDescriptor(owner) + " beautiful [npc.armFullDescription(true)]." + " Where [npc.her] hands should be, [npc.she] has two feathered forefingers and a thumb, each of which ends in a little blunt claw." + " Although slightly less dexterous than a human hand, [npc.she]'s still able to use [npc.her] digits to form a hand-like grip.");
            break;
        default:
            break;
    }
    if (owner.isPlayer()) {
        if (owner.getHandNailPolish().getPrimaryColour() != Colour.COVERING_NONE) {
            if (owner.getArmType() == ArmType.HARPY) {
                sb.append(" The little claw on your thumb has been painted in " + owner.getCovering(BodyCoveringType.MAKEUP_NAIL_POLISH_HANDS).getFullDescription(owner, true) + ".");
            } else {
                sb.append(" Your fingernails have been painted in " + owner.getCovering(BodyCoveringType.MAKEUP_NAIL_POLISH_HANDS).getFullDescription(owner, true) + ".");
            }
        }
    } else {
        if (owner.getHandNailPolish().getPrimaryColour() != Colour.COVERING_NONE) {
            if (owner.getArmType() == ArmType.HARPY) {
                sb.append(" The little claw on [npc.her] thumb has been painted in " + owner.getCovering(BodyCoveringType.MAKEUP_NAIL_POLISH_HANDS).getFullDescription(owner, true) + ".");
            } else {
                sb.append(" [npc.Her] fingernails have been painted in " + owner.getCovering(BodyCoveringType.MAKEUP_NAIL_POLISH_HANDS).getFullDescription(owner, true) + ".");
            }
        }
    }
    if (Main.game.isBodyHairEnabled()) {
        if (owner.isPlayer()) {
            if (owner.getUnderarmHairType().getType() == BodyCoveringType.BODY_HAIR_SCALES_ALLIGATOR) {
                switch(owner.getUnderarmHair()) {
                    case ZERO_NONE:
                        sb.append(" There's no trace of any rough " + owner.getUnderarmHairType().getName(owner) + " in your armpits.");
                        break;
                    case ONE_STUBBLE:
                        sb.append(" You have a small, rough patch of " + owner.getUnderarmHairType().getFullDescription(owner, true) + " in each of your armpits.");
                        break;
                    case TWO_MANICURED:
                        sb.append(" You have a rough patch of " + owner.getUnderarmHairType().getFullDescription(owner, true) + " in each of your armpits.");
                        break;
                    case THREE_TRIMMED:
                        sb.append(" You have a rough patch of " + owner.getUnderarmHairType().getFullDescription(owner, true) + " in each of your armpits.");
                        break;
                    case FOUR_NATURAL:
                        sb.append(" You have a natural amount of rough " + owner.getUnderarmHairType().getFullDescription(owner, true) + " in each of your armpits.");
                        break;
                    case FIVE_UNKEMPT:
                        sb.append(" You have an unkempt mass of rough " + owner.getUnderarmHairType().getFullDescription(owner, true) + " in each of your armpits.");
                        break;
                    case SIX_BUSHY:
                        sb.append(" You have a thick, rough mass of " + owner.getUnderarmHairType().getFullDescription(owner, true) + " in each of your armpits.");
                        break;
                    case SEVEN_WILD:
                        sb.append(" You have a wild, rough mass of " + owner.getUnderarmHairType().getFullDescription(owner, true) + " in each of your armpits.");
                        break;
                }
            } else {
                switch(owner.getUnderarmHair()) {
                    case ZERO_NONE:
                        sb.append(" There is no trace of any " + owner.getUnderarmHairType().getName(owner) + " in your armpits.");
                        break;
                    case ONE_STUBBLE:
                        sb.append(" You have a stubbly patch of " + owner.getUnderarmHairType().getFullDescription(owner, true) + " in each of your armpits.");
                        break;
                    case TWO_MANICURED:
                        sb.append(" You have a well-manicured patch of " + owner.getUnderarmHairType().getFullDescription(owner, true) + " in each of your armpits.");
                        break;
                    case THREE_TRIMMED:
                        sb.append(" You have a trimmed patch of " + owner.getUnderarmHairType().getFullDescription(owner, true) + " in each of your armpits.");
                        break;
                    case FOUR_NATURAL:
                        sb.append(" You have a natural amount of " + owner.getUnderarmHairType().getFullDescription(owner, true) + " in each of your armpits.");
                        break;
                    case FIVE_UNKEMPT:
                        sb.append(" You have an unkempt mass of " + owner.getUnderarmHairType().getFullDescription(owner, true) + " in each of your armpits.");
                        break;
                    case SIX_BUSHY:
                        sb.append(" You have a thick, bushy mass of " + owner.getUnderarmHairType().getFullDescription(owner, true) + " in each of your armpits.");
                        break;
                    case SEVEN_WILD:
                        sb.append(" You have a wild, bushy mass of " + owner.getUnderarmHairType().getFullDescription(owner, true) + " in each of your armpits.");
                        break;
                }
            }
        } else {
            if (owner.getUnderarmHairType().getType() == BodyCoveringType.BODY_HAIR_SCALES_ALLIGATOR) {
                switch(owner.getUnderarmHair()) {
                    case ZERO_NONE:
                        sb.append(" There is no trace of any rough " + owner.getUnderarmHairType().getName(owner) + " in [npc.her] armpits.");
                        break;
                    case ONE_STUBBLE:
                        sb.append(" [npc.She] has a rough patch of " + owner.getUnderarmHairType().getFullDescription(owner, true) + " in each of [npc.her] armpits.");
                        break;
                    case TWO_MANICURED:
                        sb.append(" [npc.She] has a rough patch of " + owner.getUnderarmHairType().getFullDescription(owner, true) + " in each of [npc.her] armpits.");
                        break;
                    case THREE_TRIMMED:
                        sb.append(" [npc.She] has a rough patch of " + owner.getUnderarmHairType().getFullDescription(owner, true) + " in each of [npc.her] armpits.");
                        break;
                    case FOUR_NATURAL:
                        sb.append(" [npc.She] has a natural amount of rough " + owner.getUnderarmHairType().getFullDescription(owner, true) + " in each of [npc.her] armpits.");
                        break;
                    case FIVE_UNKEMPT:
                        sb.append(" [npc.She] has a unkempt mass of rough " + owner.getUnderarmHairType().getFullDescription(owner, true) + " in each of [npc.her] armpits.");
                        break;
                    case SIX_BUSHY:
                        sb.append(" [npc.She] has a thick, rough mass of " + owner.getUnderarmHairType().getFullDescription(owner, true) + " in each of [npc.her] armpits.");
                        break;
                    case SEVEN_WILD:
                        sb.append(" [npc.She] has a wild, rough mass of " + owner.getUnderarmHairType().getFullDescription(owner, true) + " in each of [npc.her] armpits.");
                        break;
                }
            } else {
                switch(owner.getUnderarmHair()) {
                    case ZERO_NONE:
                        sb.append(" There is no trace of any " + owner.getUnderarmHairType().getName(owner) + " in [npc.her] armpits.");
                        break;
                    case ONE_STUBBLE:
                        sb.append(" [npc.She] has a stubbly patch of " + owner.getUnderarmHairType().getFullDescription(owner, true) + " in each of [npc.her] armpits.");
                        break;
                    case TWO_MANICURED:
                        sb.append(" [npc.She] has a well-manicured patch of " + owner.getUnderarmHairType().getFullDescription(owner, true) + " in each of [npc.her] armpits.");
                        break;
                    case THREE_TRIMMED:
                        sb.append(" [npc.She] has a trimmed patch of " + owner.getUnderarmHairType().getFullDescription(owner, true) + " in each of [npc.her] armpits.");
                        break;
                    case FOUR_NATURAL:
                        sb.append(" [npc.She] has a natural amount of " + owner.getUnderarmHairType().getFullDescription(owner, true) + " in each of [npc.her] armpits.");
                        break;
                    case FIVE_UNKEMPT:
                        sb.append(" [npc.She] has a unkempt mass of " + owner.getUnderarmHairType().getFullDescription(owner, true) + " in each of [npc.her] armpits.");
                        break;
                    case SIX_BUSHY:
                        sb.append(" [npc.She] has a thick, bushy mass of " + owner.getUnderarmHairType().getFullDescription(owner, true) + " in each of [npc.her] armpits.");
                        break;
                    case SEVEN_WILD:
                        sb.append(" [npc.She] has a wild, bushy mass of " + owner.getUnderarmHairType().getFullDescription(owner, true) + " in each of [npc.her] armpits.");
                        break;
                }
            }
        }
    }
    sb.append("</br>");
    // Legs:
    switch(leg.getType()) {
        case HUMAN:
            if (owner.isPlayer())
                sb.append("You have a pair of human legs and feet, which are " + getCoveredInDescriptor(owner) + " [pc.legFullDescription(true)].");
            else
                sb.append("[npc.Her] legs and feet are human, and are " + getCoveredInDescriptor(owner) + " [npc.legFullDescription(true)].");
            break;
        case ANGEL:
            if (owner.isPlayer())
                sb.append("Your legs and feet are human in shape, but are " + getCoveredInDescriptor(owner) + " [pc.legFullDescription(true)].");
            else
                sb.append("[npc.Her] legs and feet are human in shape, but are " + getCoveredInDescriptor(owner) + " [npc.legFullDescription(true)].");
            break;
        case DEMON_COMMON:
            if (owner.isPlayer())
                sb.append("Your legs and feet are human in shape, but are " + getCoveredInDescriptor(owner) + " [pc.legFullDescription(true)].");
            else
                sb.append("[npc.Her] legs and feet are human in shape, but are " + getCoveredInDescriptor(owner) + " [npc.legFullDescription(true)].");
            break;
        case DOG_MORPH:
            if (owner.isPlayer())
                sb.append("Your legs are " + getCoveredInDescriptor(owner) + " [pc.legFullDescription(true)]," + " and your feet are formed into anthropomorphic dog-like paws, complete with little blunt claws and leathery pads.");
            else
                sb.append("[npc.Her] legs are " + getCoveredInDescriptor(owner) + " [npc.legFullDescription(true)]," + " and [npc.her] feet are formed into anthropomorphic dog-like paws, complete with little blunt claws and leathery pads.");
            break;
        case LYCAN:
            if (owner.isPlayer())
                sb.append("Your legs are " + getCoveredInDescriptor(owner) + " [pc.legFullDescription(true)]," + " and your feet are formed into anthropomorphic wolf-like paws, complete with sharp claws and tough leathery pads.");
            else
                sb.append("[npc.Her] legs are " + getCoveredInDescriptor(owner) + " [npc.legFullDescription(true)]," + " and [npc.her] feet are formed into anthropomorphic wolf-like paws, complete with sharp claws and tough leathery pads.");
            break;
        case ALLIGATOR_MORPH:
            if (owner.isPlayer())
                sb.append("Your legs are " + getCoveredInDescriptor(owner) + " [pc.legFullDescription(true)]," + " and your feet are formed into anthropomorphic alligator-like feet, complete with sharp claws.");
            else
                sb.append("[npc.Her] legs are " + getCoveredInDescriptor(owner) + " [npc.legFullDescription(true)]," + " and [npc.her] feet are formed into anthropomorphic alligator-like feet, complete with sharp claws.");
            break;
        case CAT_MORPH:
            if (owner.isPlayer())
                sb.append("Your legs are " + getCoveredInDescriptor(owner) + " [pc.legFullDescription(true)]," + " and your feet are formed into anthropomorphic cat-like paws, complete with retractable claws and pink pads.");
            else
                sb.append("[npc.Her] legs are " + getCoveredInDescriptor(owner) + " [npc.legFullDescription(true)]," + " and [npc.her] feet are formed into anthropomorphic cat-like paws, complete with retractable claws and pink pads.");
            break;
        case SQUIRREL_MORPH:
            if (owner.isPlayer())
                sb.append("Your legs are " + getCoveredInDescriptor(owner) + " [pc.legFullDescription(true)]," + " and your feet are formed into anthropomorphic squirrel-like paws, complete with claws and pink pads.");
            else
                sb.append("[npc.Her] legs are " + getCoveredInDescriptor(owner) + " [npc.legFullDescription(true)]," + " and [npc.her] feet are formed into anthropomorphic squirrel-like paws, complete with claws and pink pads.");
            break;
        case HORSE_MORPH:
            if (owner.isPlayer())
                sb.append("Your legs are " + getCoveredInDescriptor(owner) + " [pc.legFullDescription(true)]," + " and your feet are formed into anthropomorphic horse-like hooves.");
            else
                sb.append("[npc.Her] legs are " + getCoveredInDescriptor(owner) + " [npc.legFullDescription(true)]," + " and [npc.her] feet are formed into anthropomorphic horse-like hooves.");
            break;
        case REINDEER_MORPH:
            if (owner.isPlayer())
                sb.append("Your legs are " + getCoveredInDescriptor(owner) + " <span style='color:[pc.legColourHex];'>[pc.legColour] [pc.legSkin]</span>," + " and your feet are formed into anthropomorphic reindeer-like hooves.");
            else
                sb.append("[npc.Her] legs are " + getCoveredInDescriptor(owner) + " <span style='color:[npc.legColourHex];'>[npc.legColour] [npc.legSkin]</span>," + " and [npc.her] feet are formed into anthropomorphic reindeer-like hooves.");
            break;
        case COW_MORPH:
            if (owner.isPlayer())
                sb.append("Your legs are " + getCoveredInDescriptor(owner) + " [pc.legFullDescription(true)]," + " and your feet are formed into anthropomorphic cow-like hooves.");
            else
                sb.append("[npc.Her] legs are " + getCoveredInDescriptor(owner) + " [npc.legFullDescription(true)]," + " and [npc.her] feet are formed into anthropomorphic cow-like hooves.");
            break;
        case HARPY:
            if (owner.isPlayer())
                sb.append("Your upper thighs are " + getCoveredInDescriptor(owner) + " [pc.legFullDescription(true)], which transition into leathery bird-like skin just above your knee." + " While your legs still retain a human-like shape, your feet have transformed into bird-like talons.");
            else
                sb.append("[npc.Her] upper thighs are " + getCoveredInDescriptor(owner) + " [npc.legFullDescription(true)], which transition into leathery bird-like skin just above [npc.her] knee." + " While [npc.her] legs still retain a human-like shape, [npc.her] feet have transformed into bird-like talons.");
            break;
        default:
            break;
    }
    if (owner.isPlayer()) {
        if (owner.getFootNailPolish().getPrimaryColour() != Colour.COVERING_NONE) {
            if (owner.getLegType() == LegType.HARPY) {
                sb.append(" The claws on your talons have been painted in " + owner.getCovering(BodyCoveringType.MAKEUP_NAIL_POLISH_FEET).getFullDescription(owner, true) + ".");
            } else if (owner.getLegType() == LegType.HORSE_MORPH) {
                sb.append(" Your hooves have been painted in " + owner.getCovering(BodyCoveringType.MAKEUP_NAIL_POLISH_FEET).getFullDescription(owner, true) + ".");
            } else if (owner.getLegType() == LegType.COW_MORPH) {
                sb.append(" Your hooves have been painted in " + owner.getCovering(BodyCoveringType.MAKEUP_NAIL_POLISH_FEET).getFullDescription(owner, true) + ".");
            } else {
                sb.append(" Your toenails have been painted in " + owner.getCovering(BodyCoveringType.MAKEUP_NAIL_POLISH_FEET).getFullDescription(owner, true) + ".");
            }
        }
    } else {
        if (owner.getFootNailPolish().getPrimaryColour() != Colour.COVERING_NONE) {
            if (owner.getLegType() == LegType.HARPY) {
                sb.append(" The claws on [npc.her] talons have been painted in " + owner.getCovering(BodyCoveringType.MAKEUP_NAIL_POLISH_FEET).getFullDescription(owner, true) + ".");
            } else if (owner.getLegType() == LegType.HORSE_MORPH) {
                sb.append(" [npc.Her] hooves have been painted in " + owner.getCovering(BodyCoveringType.MAKEUP_NAIL_POLISH_FEET).getFullDescription(owner, true) + ".");
            } else if (owner.getLegType() == LegType.COW_MORPH) {
                sb.append(" [npc.Her] hooves have been painted in " + owner.getCovering(BodyCoveringType.MAKEUP_NAIL_POLISH_FEET).getFullDescription(owner, true) + ".");
            } else {
                sb.append(" [npc.Her] toenails have been painted in " + owner.getCovering(BodyCoveringType.MAKEUP_NAIL_POLISH_FEET).getFullDescription(owner, true) + ".");
            }
        }
    }
    sb.append("</br>");
    if (owner.isPlayer()) {
        sb.append(" All of your limbs ");
    } else {
        sb.append(" All of [npc.her] limbs ");
    }
    if (femininity <= Femininity.MASCULINE_STRONG.getMaximumFemininity()) {
        sb.append(UtilText.returnStringAtRandom("<span style='color:" + Colour.MASCULINE_PLUS.toWebHexString() + ";'>have a very masculine shape to them</span>."));
    } else if (femininity <= Femininity.MASCULINE.getMaximumFemininity()) {
        sb.append(UtilText.returnStringAtRandom("<span style='color:" + Colour.MASCULINE.toWebHexString() + ";'>have a masculine shape to them</span>."));
    } else if (femininity <= Femininity.ANDROGYNOUS.getMaximumFemininity()) {
        sb.append("<span style='color:" + Colour.ANDROGYNOUS.toWebHexString() + ";'>look quite androgynous, and could easily belong to either a male or female</span>.");
    } else if (femininity <= Femininity.FEMININE.getMaximumFemininity()) {
        sb.append(UtilText.returnStringAtRandom("<span style='color:" + Colour.FEMININE.toWebHexString() + ";'>are slender and feminine-looking</span>."));
    } else {
        sb.append(UtilText.returnStringAtRandom("<span style='color:" + Colour.FEMININE_PLUS.toWebHexString() + ";'>have an extremely feminine shape to them</span>."));
    }
    sb.append("</p>");
    // Tail, wings & ass:
    if (wing.getType() != WingType.NONE || tail.getType() != TailType.NONE) {
        sb.append("<p>");
        // Wing:
        switch(wing.getType()) {
            case DEMON_COMMON:
                if (owner.isPlayer()) {
                    sb.append("Growing from your shoulder-blades, you have a pair of [pc.wingSize] bat-like wings.");
                } else {
                    sb.append("Growing from [npc.her] shoulder-blades, [npc.she] has a pair of [npc.wingSize] bat-like wings.");
                }
                break;
            case ANGEL:
                if (owner.isPlayer()) {
                    sb.append("Growing from your shoulder-blades, you have [pc.a_wingSize] pair of white feathered wings.");
                } else {
                    sb.append("Growing from [npc.her] shoulder-blades, [npc.she] has [pc.a_wingSize] pair of white feathered wings.");
                }
                break;
            default:
                break;
        }
        if (wing.getType().allowsFlight()) {
            if (wing.getSizeValue() >= WingSize.TWO_AVERAGE.getValue()) {
                if (owner.isPlayer()) {
                    sb.append(" They are large enough that they can be used to allow you to fly.");
                } else {
                    sb.append(" They are large enough that they can be used to allow [npc.her] to fly.");
                }
            } else {
                if (owner.isPlayer()) {
                    sb.append(" They aren't large enough to allow you to fly.");
                } else {
                    sb.append(" They aren't large enough to allow [npc.her] to fly.");
                }
            }
        } else if (wing.getType() != WingType.NONE) {
            sb.append(" They are entirely incapable of flight.");
        }
        if (tail.getType() != TailType.NONE) {
            if (owner.isPlayer()) {
                sb.append(" Growing out from just above your ass, you have ");
            } else {
                sb.append(" Growing out from just above [npc.her] ass, [npc.she] has ");
            }
        }
        if (owner.getTailCount() == 1) {
            switch(owner.getTailType()) {
                case CAT_MORPH:
                    if (owner.isPlayer()) {
                        sb.append("a furry, [pc.tailColour(true)] cat-like tail, which you can control well enough to grant you significantly improved balance.");
                    } else {
                        sb.append("a furry, [npc.tailColour(true)] cat-like tail, which [npc.she] can control well enough to grant [npc.herHim] significantly improved balance.");
                    }
                    break;
                case DEMON_COMMON:
                    if (owner.isPlayer()) {
                        sb.append("a spaded, [pc.tailColour(true)] demonic tail, over which you have complete control, and you can easily use it to grip and hold objects.");
                    } else {
                        sb.append("a spaded, [npc.tailColour(true)] demonic tail, over which [npc.she] has complete control, and [npc.she] can easily use it to grip and hold objects.");
                    }
                    break;
                case IMP:
                    if (owner.isPlayer()) {
                        sb.append("a spaded, [pc.tailColour(true)] impish tail, over which you have complete control, and you can easily use it to grip and hold objects.");
                    } else {
                        sb.append("a spaded, [npc.tailColour(true)] impish tail, over which [npc.she] has complete control, and [npc.she] can easily use it to grip and hold objects.");
                    }
                    break;
                case DOG_MORPH:
                    if (owner.isPlayer()) {
                        sb.append("a furry, [pc.tailColour(true)] dog-like tail, which wags uncontrollably when you get excited.");
                    } else {
                        sb.append("a furry, [npc.tailColour(true)] dog-like tail, which wags uncontrollably when [npc.she] gets excited.");
                    }
                    break;
                case DOG_MORPH_STUBBY:
                    if (owner.isPlayer()) {
                        sb.append("a stubby, [pc.tailColour(true)] dog-like tail, which wags uncontrollably when you get excited.");
                    } else {
                        sb.append("a stubby, [npc.tailColour(true)] dog-like tail, which wags uncontrollably when [npc.she] gets excited.");
                    }
                    break;
                case ALLIGATOR_MORPH:
                    if (owner.isPlayer()) {
                        sb.append("a long, [pc.tailColour(true)] alligator-like tail, which you can swipe from side to side with considerable force.");
                    } else {
                        sb.append("a long, [npc.tailColour(true)] alligator-like tail, which [npc.she] can swipe from side to side with considerable force.");
                    }
                    break;
                case HARPY:
                    if (owner.isPlayer()) {
                        sb.append("a plume of beautiful, [pc.tailColour(true)] tail-feathers, which you can rapidly move up and down to help you keep your balance and to control your path when in flight.");
                    } else {
                        sb.append("a plume of beautiful, [npc.tailColour(true)] tail-feathers, which [npc.she] can rapidly move up and down to help [npc.herHim] keep [npc.her] balance and to control [npc.her] path when in flight.");
                    }
                    break;
                case HORSE_MORPH:
                    if (owner.isPlayer()) {
                        sb.append("a long, [pc.tailColour(true)] horse-like tail, which you can swipe from side to side, but other than that, you don't have much control over it.");
                    } else {
                        sb.append("a long, [npc.tailColour(true)] horse-like tail, which [npc.she] can swipe from side to side, but other than that, [npc.she] doesn't have much control over it.");
                    }
                    break;
                case REINDEER_MORPH:
                    if (owner.isPlayer()) {
                        sb.append("a short, [pc.tailColour(true)] reindeer-like tail.");
                    } else {
                        sb.append("a short, [npc.tailColour(true)] reindeer-like tail.");
                    }
                    break;
                case COW_MORPH:
                    if (owner.isPlayer()) {
                        sb.append("a long, [pc.tailColour(true)] cow-like tail, which you can swipe from side to side, but other than that, you don't have much control over it.");
                    } else {
                        sb.append("a long, [npc.tailColour(true)] cow-like tail, which [npc.she] can swipe from side to side, but other than that, [npc.she] doesn't have much control over it.");
                    }
                    break;
                case LYCAN:
                    if (owner.isPlayer()) {
                        sb.append("a furry, [pc.tailColour(true)] wolf-like tail.");
                    } else {
                        sb.append("a furry, [npc.tailColour(true)] wolf-like tail.");
                    }
                    break;
                case SQUIRREL_MORPH:
                    if (owner.isPlayer()) {
                        sb.append("a fluffy, [pc.tailColour(true)] squirrel-like tail, which you can control well enough to grant you significantly improved balance.");
                    } else {
                        sb.append("a fluffy, [npc.tailColour(true)] squirrel-like tail, which [npc.she] can control well enough to grant [npc.herHim] significantly improved balance.");
                    }
                    break;
                case NONE:
                    break;
            }
        } else {
            sb.append(Util.intToString(owner.getTailCount()) + " ");
            switch(owner.getTailType()) {
                case CAT_MORPH:
                    if (owner.isPlayer()) {
                        sb.append("furry, [pc.tailColour(true)] cat-like tails, which you can control well enough to grant you significantly improved balance.");
                    } else {
                        sb.append("furry, [npc.tailColour(true)] cat-like tails, which [npc.she] can control well enough to grant [npc.herHim] significantly improved balance.");
                    }
                    break;
                case DEMON_COMMON:
                    if (owner.isPlayer()) {
                        sb.append("spaded, [pc.tailColour(true)] demonic tails, over which you have complete control, and you can easily use them to grip and hold objects.");
                    } else {
                        sb.append("spaded, [npc.tailColour(true)] demonic tails, over which [npc.she] has complete control, and [npc.she] can easily use them to grip and hold objects.");
                    }
                    break;
                case IMP:
                    if (owner.isPlayer()) {
                        sb.append("spaded, [pc.tailColour(true)] impish tails, over which you have complete control, and you can easily use them to grip and hold objects.");
                    } else {
                        sb.append("spaded, [npc.tailColour(true)] impish tails, over which [npc.she] has complete control, and [npc.she] can easily use them to grip and hold objects.");
                    }
                    break;
                case DOG_MORPH:
                    if (owner.isPlayer()) {
                        sb.append("furry, [pc.tailColour(true)] dog-like tails, which wag uncontrollably when you get excited.");
                    } else {
                        sb.append("furry, [npc.tailColour(true)] dog-like tails, which wag uncontrollably when [npc.she] gets excited.");
                    }
                    break;
                case DOG_MORPH_STUBBY:
                    if (owner.isPlayer()) {
                        sb.append("stubby, [pc.tailColour(true)] dog-like tails, which wag uncontrollably when you get excited.");
                    } else {
                        sb.append("stubby, [npc.tailColour(true)] dog-like tails, which wag uncontrollably when [npc.she] gets excited.");
                    }
                    break;
                case ALLIGATOR_MORPH:
                    if (owner.isPlayer()) {
                        sb.append("long, [pc.tailColour(true)] alligator-like tails, which you can swipe from side to side with considerable force.");
                    } else {
                        sb.append("long, [npc.tailColour(true)] alligator-like tails, which [npc.she] can swipe from side to side with considerable force.");
                    }
                    break;
                case HARPY:
                    if (owner.isPlayer()) {
                        sb.append("plumes of beautiful, [pc.tailColour(true)] tail-feathers, which you can rapidly move up and down to help you keep your balance and to control your path when in flight.");
                    } else {
                        sb.append("plumes of beautiful, [npc.tailColour(true)] tail-feathers, which [npc.she] can rapidly move up and down to help [npc.herHim] keep [npc.her] balance and to control [npc.her] path when in flight.");
                    }
                    break;
                case HORSE_MORPH:
                    if (owner.isPlayer()) {
                        sb.append("long, [pc.tailColour(true)] horse-like tails, which you can swipe from side to side, but other than that, you don't have much control over them.");
                    } else {
                        sb.append("long, [npc.tailColour(true)] horse-like tails, which [npc.she] can swipe from side to side, but other than that, [npc.she] doesn't have much control over them.");
                    }
                    break;
                case REINDEER_MORPH:
                    if (owner.isPlayer()) {
                        sb.append("short, [pc.tailColour(true)] reindeer-like tails.");
                    } else {
                        sb.append("short, [npc.tailColour(true)] reindeer-like tails.");
                    }
                    break;
                case COW_MORPH:
                    if (owner.isPlayer()) {
                        sb.append("long, [pc.tailColour(true)] cow-like tails, which you can swipe from side to side, but other than that, you don't have much control over them.");
                    } else {
                        sb.append("long, [npc.tailColour(true)] cow-like tails, which [npc.she] can swipe from side to side, but other than that, [npc.she] doesn't have much control over them.");
                    }
                    break;
                case LYCAN:
                    if (owner.isPlayer()) {
                        sb.append("furry, [pc.tailColour(true)] wolf-like tails.");
                    } else {
                        sb.append("furry, [npc.tailColour(true)] wolf-like tails.");
                    }
                    break;
                case SQUIRREL_MORPH:
                    if (owner.isPlayer()) {
                        sb.append("fluffy, [pc.tailColour(true)] squirrel-like tails, which you can control well enough to grant you significantly improved balance.");
                    } else {
                        sb.append("fluffy, [npc.tailColour(true)] squirrel-like tails, which [npc.she] can control well enough to grant [npc.herHim] significantly improved balance.");
                    }
                    break;
                case NONE:
                    break;
            }
        }
        sb.append("</p>");
    }
    sb.append("<p>");
    // Ass & hips:
    if (owner.isPlayer()) {
        sb.append("Your [pc.hips+] and [pc.assSize] [pc.ass] are " + getCoveredInDescriptor(owner) + " [pc.assFullDescription(true)].");
    } else {
        sb.append("[npc.Her] [npc.hips+] and [npc.assSize] [npc.ass] are " + getCoveredInDescriptor(owner) + " [npc.assFullDescription(true)].");
    }
    if (owner.getPlayerKnowsAreas().contains(CoverableArea.ANUS)) {
        sb.append(" " + getAssDescription(owner));
        sb.append("</p>");
    } else {
        sb.append(" <span style='color:" + Colour.GENERIC_SEX.toWebHexString() + ";'>You haven't seen [npc.her] naked ass before, so you don't know what [npc.her] asshole looks like.</span>");
        sb.append("</p>");
    }
    // TODO pubic hair
    if (owner.getPlayerKnowsAreas().contains(CoverableArea.VAGINA) && owner.getPlayerKnowsAreas().contains(CoverableArea.PENIS)) {
        // Vagina, virgin/capacity, wetness:
        if (vagina.getType() == VaginaType.NONE && penis.getType() == PenisType.NONE) {
            sb.append("<p>" + getMoundDescription(owner) + "</p>");
        }
    }
    if (owner.getPlayerKnowsAreas().contains(CoverableArea.PENIS)) {
        // Penises, cum production, testicle size, capacity:
        if (penis.getType() != PenisType.NONE) {
            sb.append("<p>" + getPenisDescription(owner) + "</p>");
        }
    } else {
        sb.append(" <p>" + "<span style='color:" + Colour.GENERIC_SEX.toWebHexString() + ";'>You haven't seen [npc.her] naked groin before, so you don't know what [npc.her] cock looks like, or even if [npc.she] has one.</span>" + "</p>");
    }
    if (owner.getPlayerKnowsAreas().contains(CoverableArea.VAGINA)) {
        // Vagina, virgin/capacity, wetness:
        if (vagina.getType() != VaginaType.NONE) {
            sb.append("<p>" + getVaginaDescription(owner) + "</p>");
        }
    } else {
        sb.append(" <p>" + "<span style='color:" + Colour.GENERIC_SEX.toWebHexString() + ";'>You haven't seen [npc.her] naked groin before, so you don't know what [npc.her] pussy looks like, or even if [npc.she] has one.</span>" + "</p>");
    }
    if (!owner.isPlayer()) {
        sb.append(getSexDetails(owner));
        sb.append(getPregnancyDetails(owner));
    }
    return UtilText.parse(owner, sb.toString());
}
Also used : SexType(com.lilithsthrone.game.sex.SexType) TongueModifier(com.lilithsthrone.game.character.body.valueEnums.TongueModifier) PenetrationType(com.lilithsthrone.game.sex.PenetrationType) OrificeModifier(com.lilithsthrone.game.character.body.valueEnums.OrificeModifier)

Aggregations

TongueModifier (com.lilithsthrone.game.character.body.valueEnums.TongueModifier)6 OrificeModifier (com.lilithsthrone.game.character.body.valueEnums.OrificeModifier)5 BodyCoveringType (com.lilithsthrone.game.character.body.types.BodyCoveringType)4 PenisModifier (com.lilithsthrone.game.character.body.valueEnums.PenisModifier)4 ArrayList (java.util.ArrayList)3 Covering (com.lilithsthrone.game.character.body.Covering)2 BodyHair (com.lilithsthrone.game.character.body.valueEnums.BodyHair)2 BreastShape (com.lilithsthrone.game.character.body.valueEnums.BreastShape)2 CoveringModifier (com.lilithsthrone.game.character.body.valueEnums.CoveringModifier)2 NPC (com.lilithsthrone.game.character.npc.NPC)2 Subspecies (com.lilithsthrone.game.character.race.Subspecies)2 HashMap (java.util.HashMap)2 EnchantmentEventListener (com.lilithsthrone.controller.eventListeners.EnchantmentEventListener)1 InventorySelectedItemEventListener (com.lilithsthrone.controller.eventListeners.InventorySelectedItemEventListener)1 InventoryTooltipEventListener (com.lilithsthrone.controller.eventListeners.InventoryTooltipEventListener)1 SetContentEventListener (com.lilithsthrone.controller.eventListeners.SetContentEventListener)1 TooltipHideEventListener (com.lilithsthrone.controller.eventListeners.TooltipHideEventListener)1 TooltipInformationEventListener (com.lilithsthrone.controller.eventListeners.TooltipInformationEventListener)1 TooltipMoveEventListener (com.lilithsthrone.controller.eventListeners.TooltipMoveEventListener)1 TooltipResponseDescriptionEventListener (com.lilithsthrone.controller.eventListeners.TooltipResponseDescriptionEventListener)1