code:
package com.lilithsthrone.game.dialogue.npcDialogue.submission;

import com.lilithsthrone.game.character.GameCharacter;
import com.lilithsthrone.game.character.attributes.CorruptionLevel;
import com.lilithsthrone.game.character.body.valueEnums.BodyMaterial;
import com.lilithsthrone.game.character.fetishes.Fetish;
import com.lilithsthrone.game.character.npc.NPC;
import com.lilithsthrone.game.character.npc.NPCFlagValue;
import com.lilithsthrone.game.dialogue.DialogueNode;
import com.lilithsthrone.game.dialogue.responses.Response;
import com.lilithsthrone.game.dialogue.responses.ResponseCombat;
import com.lilithsthrone.game.dialogue.responses.ResponseEffectsOnly;
import com.lilithsthrone.game.dialogue.responses.ResponseSex;
import com.lilithsthrone.game.dialogue.responses.ResponseTag;
import com.lilithsthrone.game.dialogue.utils.BodyChanging;
import com.lilithsthrone.game.dialogue.utils.InventoryInteraction;
import com.lilithsthrone.game.dialogue.utils.UtilText;
import com.lilithsthrone.game.sex.Sex;
import com.lilithsthrone.game.sex.SexControl;
import com.lilithsthrone.game.sex.SexPace;
import com.lilithsthrone.game.sex.managers.universal.SMGeneric;
import com.lilithsthrone.game.sex.managers.universal.SMLyingDown;
import com.lilithsthrone.game.sex.positions.slots.SexSlotLyingDown;
import com.lilithsthrone.main.Main;
import com.lilithsthrone.utils.Colour;
import com.lilithsthrone.utils.Util;
import com.lilithsthrone.utils.Util.Value;

/**
 * @since 0.2.5
 * @version 0.3.4
 * @author Innoxia
 */
public class TunnelSlimeDialogue {

	private static NPC getSlime() {
		return Main.game.getActiveNPC();
	}

	public static final DialogueNode ATTACK = new DialogueNode("Assaulted!", "", true) {

		@Override
		public String getContent() {
			UtilText.nodeContentSB.setLength(0);

			UtilText.nodeContentSB.append(UtilText.parseFromXMLFile("places/submission/tunnelSlime", "ATTACK_INTRO"));

			if(getSlime().hasFetish(Fetish.FETISH_TRANSFORMATION_GIVING)) {
				if(Main.game.getPlayer().getBodyMaterial()==BodyMaterial.SLIME) {

					UtilText.nodeContentSB.append(UtilText.parseFromXMLFile("places/submission/tunnelSlime", "ATTACK_TRANSFORMER_PLAYER_SLIME"));
					if(getSlime().isAttractedTo(Main.game.getPlayer())) {
						UtilText.nodeContentSB.append(UtilText.parseFromXMLFile("places/submission/tunnelSlime", "TRANSFORMER_PLAYER_SLIME_OFFER_SEX"));
					} else {
						UtilText.nodeContentSB.append(UtilText.parseFromXMLFile("places/submission/tunnelSlime", "TRANSFORMER_PLAYER_SLIME_NO_SEX"));
					}

				}
				// Slime transformation descriptions are appended in SubmissionAttacker getEncounterDialogue() method.

			} else {
				UtilText.nodeContentSB.append(UtilText.parseFromXMLFile("places/submission/tunnelSlime", "ATTACK"));
			}

			return UtilText.nodeContentSB.toString();
		}

		@Override
		public Response getResponse(int responseTab, int index) {
			if(getSlime().hasFetish(Fetish.FETISH_TRANSFORMATION_GIVING)) {
				if(Main.game.getPlayer().getBodyMaterial()==BodyMaterial.SLIME) {
					if (index == 1) {
						return new ResponseCombat("Fight",
								"You aren't going to stand for [npc.name] transforming people into slimes. Teach [npc.herHim] a lesson!", Main.game.getActiveNPC(),
								Util.newHashMapOfValues(
										new Value<>(Main.game.getPlayer(), "[pc.speech(You aren't going to be stalking these tunnels on my watch!)] you shout, launching into an attack!"),
										new Value<>(getSlime(), "[npc.speech(Traitor! You'll pay for this!)] [npc.Name] cries out as [npc.she] prepares to defend [npc.herself].")));

					} else if (index == 2) {
						return new Response("Leave", "Continue on your journey.", ATTACK) {
							@Override
							public void effects(){
								if(getSlime().isAttractedTo(Main.game.getPlayer())) {
									Main.game.getTextStartStringBuilder().append(UtilText.parseFromXMLFile("places/submission/tunnelSlime", "ATTACK_TRANSFORMER_PLAYER_SLIME_TURN_DOWN_SEX"));
								} else {
									Main.game.getTextStartStringBuilder().append(UtilText.parseFromXMLFile("places/submission/tunnelSlime", "ATTACK_TRANSFORMER_PLAYER_SLIME_LEAVE"));
								}
							}
							@Override
							public DialogueNode getNextDialogue(){
								return Main.game.getDefaultDialogueNoEncounter();
							}
						};

					} else if (index == 3) {
						if(!getSlime().isAttractedTo(Main.game.getPlayer())) {
							return new Response("Dominant Sex", "[npc.Name] isn't attracted to you!", null);

						} else if(getSlime().hasFetish(Fetish.FETISH_DOMINANT) && !getSlime().hasFetish(Fetish.FETISH_SUBMISSIVE)) {
							return new Response("Dominant Sex", "[npc.Name] isn't willing to let you be the dominant partner.", null);

						} else {
							return new ResponseSex("Dominant Sex", "Take the dominant role and have sex with [npc.name].",
									null, null, null,
									null, null, null,
									true, true,
									new SMGeneric(
											Util.newArrayListOfValues(Main.game.getPlayer()),
											Util.newArrayListOfValues(getSlime()),
									null,
									null), AFTER_SLIME_SEX_AS_DOM, UtilText.parseFromXMLFile("places/submission/tunnelSlime", "SLIME_SEX_AS_DOM"));
						}

					} else if (index == 4) {
						if(!getSlime().isAttractedTo(Main.game.getPlayer())) {
							return new Response("Submissive Sex", "[npc.Name] isn't attracted to you!", null);

						} else if(getSlime().hasFetish(Fetish.FETISH_SUBMISSIVE) && !getSlime().hasFetish(Fetish.FETISH_DOMINANT)) {
							return new Response("Submissive Sex", "[npc.Name] isn't willing to let you be the submissive partner.", null);

						} else {
							return new ResponseSex("Submissive Sex", "Take the submissive role and have sex with [npc.name].",
									null, null, null,
									null, null, null,
									true, true,
									new SMGeneric(
											Util.newArrayListOfValues(getSlime()),
											Util.newArrayListOfValues(Main.game.getPlayer()),
									null,
									null), AFTER_SLIME_SEX_AS_SUB, UtilText.parseFromXMLFile("places/submission/tunnelSlime", "SLIME_SEX_AS_SUB"));
						}

					} else {
						return null;
					}

				} else {
					if (index == 1) {
						return new ResponseCombat("Fight",
								"Stand up for yourself and fight [npc.name]!", Main.game.getActiveNPC(),
								Util.newHashMapOfValues(
										new Value<>(Main.game.getPlayer(), ""),
										new Value<>(getSlime(), "")));

					} else if (index == 2) {
						return new Response("Offer Money", "[npc.Name] isn't interested in your money! All [npc.she] wants to do is turn you into a slime!", null);

					} else if (index == 3) {
						return new Response("Submit", "Allow [npc.name] to transform you into a slime!", TRANSFORMED) {
							@Override
							public Colour getHighlightColour() {
								return Colour.TRANSFORMATION_GENERIC;
							}
							@Override
							public void effects() {
								Main.game.getTextEndStringBuilder().append(Main.game.getPlayer().setBodyMaterial(BodyMaterial.SLIME));

								if(getSlime().isAttractedTo(Main.game.getPlayer())) {
									Main.game.getTextEndStringBuilder().append(UtilText.parseFromXMLFile("places/submission/tunnelSlime", "TRANSFORMED_SLIME_OFFER_SEX"));
								} else {
									Main.game.getTextEndStringBuilder().append(UtilText.parseFromXMLFile("places/submission/tunnelSlime", "TRANSFORMED_SLIME_NO_SEX"));
								}
							}
						};

					} else {
						return null;
					}
				}

			} else {
				if (index == 1) {
					return new ResponseCombat("Fight",
							"Stand up for yourself and fight [npc.name]!", Main.game.getActiveNPC(),
							Util.newHashMapOfValues(
									new Value<>(Main.game.getPlayer(), ""),
									new Value<>(getSlime(), "")));

				} else if (index == 2) {
					if(Main.game.getPlayer().getMoney()<250) {
						return new Response("Offer money ("+UtilText.formatAsMoney(250, "span")+")", "You don't have enough money to offer to pay [npc.name] off. You'll have to either fight [npc.herHim] or offer [npc.herHim] your body!", null);
					} else {
						return new Response("Offer money ("+UtilText.formatAsMoney(250, "span")+")", "Offer to pay [npc.name] 250 flames to leave you alone.", OFFER_MONEY) {
							@Override
							public void effects() {
								Main.game.getPlayer().incrementMoney(-250);
							}
						};
					}

				} else if (index == 3) {
					if(Main.game.getActiveNPC().isAttractedTo(Main.game.getPlayer())) {
						return new ResponseSex("Offer body", "Offer your body to [npc.name] so that you can avoid a violent confrontation.",
								Util.newArrayListOfValues(Fetish.FETISH_SUBMISSIVE), null, Fetish.FETISH_SUBMISSIVE.getAssociatedCorruptionLevel(),
								null, null, null,
								true, true,
								new SMGeneric(
										Util.newArrayListOfValues(getSlime()),
										Util.newArrayListOfValues(Main.game.getPlayer()),
										null,
										null) {
									@Override
									public SexControl getSexControl(GameCharacter character) {
										if(character.isPlayer()) {
											return SexControl.ONGOING_PLUS_LIMITED_PENETRATIONS;
										}
										return super.getSexControl(character);
									}
								},
								AFTER_SLIME_SEX_AS_SUB,
								UtilText.parseFromXMLFile("places/submission/tunnelSlime", "OFFER_BODY"));
					} else {
						return new Response("Offer body", "You can tell that [npc.name] isn't at all interested in having sex with you. You'll either have to offer [npc.herHim] some money, or prepare for a fight!", null);
					}

				} else {
					return null;
				}

			}

		}
	};

	public static final DialogueNode ATTACK_REPEAT = new DialogueNode("Assaulted!", "", true) {

		@Override
		public String getContent() {
			if(getSlime().hasFetish(Fetish.FETISH_TRANSFORMATION_GIVING)) {
				if(Main.game.getPlayer().getBodyMaterial()==BodyMaterial.SLIME) {
					UtilText.nodeContentSB.setLength(0);

					UtilText.nodeContentSB.append(UtilText.parseFromXMLFile("places/submission/tunnelSlime", "ATTACK_REPEAT_TRANSFORMER_PLAYER_SLIME"));
					if(getSlime().isAttractedTo(Main.game.getPlayer())) {
						UtilText.nodeContentSB.append(UtilText.parseFromXMLFile("places/submission/tunnelSlime", "TRANSFORMER_PLAYER_SLIME_OFFER_SEX"));
					} else {
						UtilText.nodeContentSB.append(UtilText.parseFromXMLFile("places/submission/tunnelSlime", "TRANSFORMER_PLAYER_SLIME_NO_SEX"));
					}
					return UtilText.nodeContentSB.toString();

				} else {
					return UtilText.parseFromXMLFile("places/submission/tunnelSlime", "ATTACK_REPEAT_TRANSFORMER");
				}

			} else {
				return UtilText.parseFromXMLFile("places/submission/tunnelSlime", "ATTACK_REPEAT");
			}
		}

		@Override
		public Response getResponse(int responseTab, int index) {
			return ATTACK.getResponse(responseTab, index);
		}
	};

	public static final DialogueNode ATTACK_PREGNANCY_REVEAL = new DialogueNode("Assaulted!", "", true) {

		@Override
		public String getContent() {
			if(getSlime().hasFetish(Fetish.FETISH_TRANSFORMATION_GIVING)) {
				if(Main.game.getPlayer().getBodyMaterial()==BodyMaterial.SLIME) {
					UtilText.nodeContentSB.setLength(0);

					UtilText.nodeContentSB.append(UtilText.parseFromXMLFile("places/submission/tunnelSlime", "ATTACK_PREGNANCY_REVEAL_TRANSFORMER_PLAYER_SLIME"));
					if(getSlime().isAttractedTo(Main.game.getPlayer())) {
						UtilText.nodeContentSB.append(UtilText.parseFromXMLFile("places/submission/tunnelSlime", "TRANSFORMER_PLAYER_SLIME_OFFER_SEX"));
					} else {
						UtilText.nodeContentSB.append(UtilText.parseFromXMLFile("places/submission/tunnelSlime", "TRANSFORMER_PLAYER_SLIME_NO_SEX"));
					}
					return UtilText.nodeContentSB.toString();

				} else {
					return UtilText.parseFromXMLFile("places/submission/tunnelSlime", "ATTACK_PREGNANCY_REVEAL_TRANSFORMER");
				}

			} else {
				return UtilText.parseFromXMLFile("places/submission/tunnelSlime", "ATTACK_PREGNANCY_REVEAL");
			}
		}

		@Override
		public Response getResponse(int responseTab, int index) {
			return ATTACK.getResponse(responseTab, index);
		}
	};

	public static final DialogueNode AFTER_SLIME_SEX_AS_DOM = new DialogueNode("Step back", "", true) {

		@Override
		public String getDescription(){
			return "Now that you've had your fun, you can step back and leave [npc.name] to recover.";
		}

		@Override
		public String getContent() {
			if(Sex.getNumberOfOrgasms(getSlime()) >= getSlime().getOrgasmsBeforeSatisfied()) {
				return UtilText.parseFromXMLFile("places/submission/tunnelSlime", "AFTER_SLIME_SEX_AS_DOM");
			} else {
				return UtilText.parseFromXMLFile("places/submission/tunnelSlime", "AFTER_SLIME_SEX_AS_DOM_NO_ORGASM");
			}
		}

		@Override
		public Response getResponse(int responseTab, int index) {
			if (index == 1) {
				return new Response("Continue", "Carry on your way.", AFTER_SLIME_SEX_AS_DOM){
					@Override
					public DialogueNode getNextDialogue(){
						return Main.game.getDefaultDialogueNoEncounter();
					}
				};

			} else {
				return null;
			}
		}
	};

	public static final DialogueNode AFTER_SLIME_SEX_AS_SUB = new DialogueNode("Used", "", true) {

		@Override
		public int getSecondsPassed() {
			return 15*60;
		}

		@Override
		public String getDescription(){
			return "[npc.Name] has had enough fun with you for now.";
		}

		@Override
		public String getContent() {
			if(Sex.getNumberOfOrgasms(getSlime()) >= getSlime().getOrgasmsBeforeSatisfied()) {
				return UtilText.parseFromXMLFile("places/submission/tunnelSlime", "AFTER_SLIME_SEX_AS_SUB");
			} else {
				return UtilText.parseFromXMLFile("places/submission/tunnelSlime", "AFTER_SLIME_SEX_AS_SUB_NO_ORGASM");
			}
		}

		@Override
		public Response getResponse(int responseTab, int index) {
			if (index == 1) {
				return new Response("Continue", "Carry on your way.", AFTER_SLIME_SEX_AS_SUB){
					@Override
					public DialogueNode getNextDialogue(){
						return Main.game.getDefaultDialogueNoEncounter();
					}
				};

			} else {
				return null;
			}
		}
	};

	public static final DialogueNode TRANSFORMED = new DialogueNode("", "", true, true) {

		@Override
		public int getSecondsPassed() {
			return 10*60;
		}

		@Override
		public String getContent() {
			return UtilText.parseFromXMLFile("places/submission/tunnelSlime", "TRANSFORMED");
		}

		@Override
		public Response getResponse(int responseTab, int index) {
			if (index == 1) {
				return new Response("Leave", "Continue on your journey.", TRANSFORMED) {
					@Override
					public void effects(){
						if(getSlime().isAttractedTo(Main.game.getPlayer())) {
							Main.game.getTextStartStringBuilder().append(UtilText.parseFromXMLFile("places/submission/tunnelSlime", "ATTACK_TRANSFORMER_PLAYER_SLIME_TURN_DOWN_SEX"));
						}
					}
					@Override
					public DialogueNode getNextDialogue(){
						return Main.game.getDefaultDialogueNoEncounter();
					}
				};

			} else if (index == 2) {
				if(!getSlime().isAttractedTo(Main.game.getPlayer())) {
					return new Response("Dominant Sex", "[npc.Name] isn't attracted to you!", null);

				} else if(getSlime().hasFetish(Fetish.FETISH_DOMINANT) && !getSlime().hasFetish(Fetish.FETISH_SUBMISSIVE)) {
					return new Response("Dominant Sex", "[npc.Name] isn't willing to let you be the dominant partner.", null);

				} else {
					return new ResponseSex("Dominant Sex", "Take the dominant role and have sex with [npc.name].",
							null, null, null,
							null, null, null,
							true, true,
							new SMGeneric(
									Util.newArrayListOfValues(Main.game.getPlayer()),
									Util.newArrayListOfValues(getSlime()),
							null,
							null), AFTER_SLIME_SEX_AS_DOM, UtilText.parseFromXMLFile("places/submission/tunnelSlime", "SLIME_SEX_AS_DOM"));
				}

			} else if (index == 3) {
				if(!getSlime().isAttractedTo(Main.game.getPlayer())) {
					return new Response("Submissive Sex", "[npc.Name] isn't attracted to you!", null);

				} else if(getSlime().hasFetish(Fetish.FETISH_SUBMISSIVE) && !getSlime().hasFetish(Fetish.FETISH_DOMINANT)) {
					return new Response("Submissive Sex", "[npc.Name] isn't willing to let you be the submissive partner.", null);

				} else {
					return new ResponseSex("Submissive Sex", "Take the submissive role and have sex with [npc.name].",
							null, null, null,
							null, null, null,
							true, true,
							new SMGeneric(
									Util.newArrayListOfValues(getSlime()),
									Util.newArrayListOfValues(Main.game.getPlayer()),
							null,
							null), AFTER_SLIME_SEX_AS_SUB, UtilText.parseFromXMLFile("places/submission/tunnelSlime", "SLIME_SEX_AS_SUB"));
				}

			} else {
				return null;
			}
		}
	};

	public static final DialogueNode RESIST_TRANSFORMED = new DialogueNode("", "", true, true) {

		@Override
		public int getSecondsPassed() {
			return 10*60;
		}

		@Override
		public String getContent() {
			UtilText.nodeContentSB.setLength(0);

			UtilText.nodeContentSB.append(UtilText.parseFromXMLFile("places/submission/tunnelSlime", "RESIST_TRANSFORMED"));

			if(getSlime().isAttractedTo(Main.game.getPlayer()) && getSlime().isWillingToRape() && Main.game.isNonConEnabled()) {
				UtilText.nodeContentSB.append(UtilText.parseFromXMLFile("places/submission/tunnelSlime", "RESIST_TRANSFORMED_RAPE"));
			} else {
				UtilText.nodeContentSB.append(UtilText.parseFromXMLFile("places/submission/tunnelSlime", "RESIST_TRANSFORMED_NO_RAPE"));
			}

			return UtilText.nodeContentSB.toString();
		}

		@Override
		public Response getResponse(int responseTab, int index) {
			if(Main.game.getActiveNPC().isAttractedTo(Main.game.getPlayer()) && Main.game.getActiveNPC().isWillingToRape() && Main.game.isNonConEnabled()) {
				if (index == 1) {
					return new ResponseSex("Sex",
							"[npc.Name] forces [npc.herself] on you...",
							false, false,
							new SMLyingDown(
									Util.newHashMapOfValues(new Value<>(Main.game.getActiveNPC(), SexSlotLyingDown.MISSIONARY)),
									Util.newHashMapOfValues(new Value<>(Main.game.getPlayer(), SexSlotLyingDown.LYING_DOWN))),
							null,
							null, AFTER_SLIME_SEX_AS_SUB, "
"
								+ "You surrender yourself to [npc.name], lying back and offering no resistance as [npc.she] tongue-fucks your throat."
								+ " After a moment, [npc.she] sits back up, leaving a wet pool of slime all over your [pc.lips]."
								+ " [npc.speech(Good bitch! You know your place already! Now be a good [pc.girl] and try to enjoy this...)]"
							+ "
");

				} else if (index == 2) {
					return new ResponseSex("Eager Sex",
							"[npc.Name] forces [npc.herself] on you...",
							false, false,
							new SMLyingDown(
									Util.newHashMapOfValues(new Value<>(Main.game.getActiveNPC(), SexSlotLyingDown.MISSIONARY)),
									Util.newHashMapOfValues(new Value<>(Main.game.getPlayer(), SexSlotLyingDown.LYING_DOWN))) {
								@Override
								public SexPace getStartingSexPaceModifier(GameCharacter character) {
									if(character.isPlayer()) {
										return SexPace.SUB_EAGER;
									}
									return null;
								}
							},
							null,
							null, AFTER_SLIME_SEX_AS_SUB, "
"
								+ "You eagerly surrender yourself to [npc.name], raising your head to help [npc.herHim] tongue-fuck your throat."
								+ " After a moment, [npc.she] sits back up, leaving a wet pool of slime all over your [pc.lips]."
								+ " [npc.speech(Good bitch! You know your place already! Now be a good [pc.girl] and try to enjoy this...)]"
							+ "
");

				} else if (index == 3 && Main.game.isNonConEnabled()) {
					return new ResponseSex("Resist Sex",
							"[npc.Name] forces [npc.herself] on you...",
							false, false,
							new SMLyingDown(
									Util.newHashMapOfValues(new Value<>(Main.game.getActiveNPC(), SexSlotLyingDown.MISSIONARY)),
									Util.newHashMapOfValues(new Value<>(Main.game.getPlayer(), SexSlotLyingDown.LYING_DOWN))) {
								@Override
								public SexPace getStartingSexPaceModifier(GameCharacter character) {
									if(character.isPlayer()) {
										return SexPace.SUB_RESISTING;
									}
									return null;
								}
							},
							null,
							null, AFTER_SLIME_SEX_AS_SUB, "
"
								+ "You try to turn your face away, but [npc.name] simply reaches up to grip both sides of your head, holding you still as [npc.she] tongue-fucks your throat."
								+ " After a moment, [npc.she] sits back up, leaving a wet pool of slime all over your [pc.lips]."
								+ " [npc.speech(Stupid bitch! You can resist as much as you want! I'm not going to stop until I'm satisfied!)]"
							+ "
");

				} else {
					return null;
				}

			} else {
				if (index == 1) {
					return new Response("Continue", "Carry on your way.", AFTER_COMBAT_PLAYER_DEFEAT){
						@Override
						public DialogueNode getNextDialogue() {
							return Main.game.getDefaultDialogueNoEncounter();
						}
					};

				} else {
					return null;
				}
			}
		}
	};

	public static final DialogueNode OFFER_MONEY = new DialogueNode("", "", true, true) {

		@Override
		public int getSecondsPassed() {
			return 10*60;
		}

		@Override
		public String getContent() {
			return UtilText.parseFromXMLFile("places/submission/tunnelSlime", "OFFER_MONEY");
		}

		@Override
		public Response getResponse(int responseTab, int index) {
			if (index == 1) {
				return new Response("Continue", "Carry on your way.", OFFER_MONEY){
					@Override
					public DialogueNode getNextDialogue(){
						return Main.game.getDefaultDialogueNoEncounter();
					}
				};

			} else {
				return null;
			}
		}
	};

	// Standard combat:

	public static final DialogueNode AFTER_COMBAT_PLAYER_VICTORY = new DialogueNode("Victory", "", true) {

		@Override
		public String getDescription() {
			return "You have defeated [npc.name]!";
		}

		@Override
		public String getContent() {
			if(Main.game.getActiveNPC().isAttractedTo(Main.game.getPlayer()) || !Main.game.isNonConEnabled()) {
				return UtilText.parseFromXMLFile("places/submission/tunnelSlime", "AFTER_COMBAT_VICTORY_ENEMY_WANTS_SEX");

			} else {
				return UtilText.parseFromXMLFile("places/submission/tunnelSlime", "AFTER_COMBAT_VICTORY");
			}
		}

		@Override
		public Response getResponse(int responseTab, int index) {

			if (index == 1) {
				return new Response("Continue", "Carry on your way...", Main.game.getDefaultDialogueNoEncounter()){
					@Override
					public void effects() {
						if(getSlime().hasFlag(NPCFlagValue.genericNPCBetrayedByPlayer)) {
							Main.game.banishNPC(getSlime());
						}
					}
				};

			} else if (index == 2) {
				if(!getSlime().isAttractedTo(Main.game.getPlayer()) && !Main.game.isNonConEnabled()) {
					return new Response("Sex", "[npc.Name] has no interest in having sex with you!", null);

				} else if(getSlime().isAttractedTo(Main.game.getPlayer())) {
					return new ResponseSex("Sex",
							"Well, [npc.she] is asking for it!",
							true, false,
							new SMGeneric(
									Util.newArrayListOfValues(Main.game.getPlayer()),
									Util.newArrayListOfValues(getSlime()),
							null,
							null),
							AFTER_SEX_VICTORY,
							UtilText.parseFromXMLFile("places/submission/tunnelSlime", "AFTER_COMBAT_VICTORY_SEX", getSlime()));

				} else {
					return new ResponseSex(
							"Rape [npc.herHim]",
							"[npc.She] needs to be punished for attacking you like that...",
							Util.newArrayListOfValues(Fetish.FETISH_NON_CON_DOM), null, Fetish.FETISH_NON_CON_DOM.getAssociatedCorruptionLevel(), null, null, null,
							false, false,
							new SMGeneric(
									Util.newArrayListOfValues(Main.game.getPlayer()),
									Util.newArrayListOfValues(getSlime()),
							null,
							null),
							AFTER_SEX_VICTORY,
							UtilText.parseFromXMLFile("places/submission/tunnelSlime", "AFTER_COMBAT_VICTORY_RAPE", getSlime()));
				}

			} else if (index == 3) {
				if(!getSlime().isAttractedTo(Main.game.getPlayer()) && !Main.game.isNonConEnabled()) {
					return new Response("Gentle Sex", "[npc.Name] has no interest in having sex with you!", null);

				} else if(getSlime().isAttractedTo(Main.game.getPlayer())){
					return new ResponseSex("Gentle sex",
							"Well, [npc.she] is asking for it! (Start the sex scene in the 'gentle' pace.)",
							true, false,
							new SMGeneric(
									Util.newArrayListOfValues(Main.game.getPlayer()),
									Util.newArrayListOfValues(getSlime()),
									null,
									null,
									ResponseTag.START_PACE_PLAYER_DOM_GENTLE),
							AFTER_SEX_VICTORY,
							UtilText.parseFromXMLFile("places/submission/tunnelSlime", "AFTER_COMBAT_VICTORY_SEX_GENTLE", getSlime()));

				} else {
					return new ResponseSex("Rape [npc.herHim] (gentle)", "[npc.She] needs to be punished for attacking you like that... (Start the sex scene in the 'gentle' pace.)",
							Util.newArrayListOfValues(Fetish.FETISH_NON_CON_DOM), null, Fetish.FETISH_NON_CON_DOM.getAssociatedCorruptionLevel(), null, null, null,
							false, false,
							new SMGeneric(
									Util.newArrayListOfValues(Main.game.getPlayer()),
									Util.newArrayListOfValues(getSlime()),
									null,
									null,
									ResponseTag.START_PACE_PLAYER_DOM_GENTLE),
							AFTER_SEX_VICTORY,
							UtilText.parseFromXMLFile("places/submission/tunnelSlime", "AFTER_COMBAT_VICTORY_RAPE_GENTLE", getSlime()));
				}

			} else if (index == 4) {
				if(!getSlime().isAttractedTo(Main.game.getPlayer()) && !Main.game.isNonConEnabled()) {
					return new Response("Rough Sex", "[npc.Name] has no interest in having sex with you!", null);

				} else if(getSlime().isAttractedTo(Main.game.getPlayer())){
					return new ResponseSex("Rough sex",
							"Well, [npc.she] is asking for it! (Start the sex scene in the 'rough' pace.)",
							true, false,
							new SMGeneric(
									Util.newArrayListOfValues(Main.game.getPlayer()),
									Util.newArrayListOfValues(getSlime()),
									null,
									null,
									ResponseTag.START_PACE_PLAYER_DOM_ROUGH),
							AFTER_SEX_VICTORY,
							UtilText.parseFromXMLFile("places/submission/tunnelSlime", "AFTER_COMBAT_VICTORY_SEX_ROUGH", getSlime()));

				} else {
					return new ResponseSex("Rape [npc.herHim] (rough)", "[npc.She] needs to be punished for attacking you like that... (Start the sex scene in the 'rough' pace.)",
							Util.newArrayListOfValues(Fetish.FETISH_NON_CON_DOM), null, Fetish.FETISH_NON_CON_DOM.getAssociatedCorruptionLevel(), null, null, null,
							false, false,
							new SMGeneric(
									Util.newArrayListOfValues(Main.game.getPlayer()),
									Util.newArrayListOfValues(getSlime()),
									null,
									null,
									ResponseTag.START_PACE_PLAYER_DOM_ROUGH),
							AFTER_SEX_VICTORY, UtilText.parseFromXMLFile("places/submission/tunnelSlime", "AFTER_COMBAT_VICTORY_RAPE_ROUGH", getSlime()));
				}

			} else if (index == 5) {
				if(!getSlime().isAttractedTo(Main.game.getPlayer())) {
					return new Response("Submit",
							"You can't submit to [npc.name], as [npc.she] has no interest in having sex with you!",
							null);
				} else {
					return new ResponseSex("Submit",
							"You're not really sure what to do now... Perhaps it would be best to let [npc.name] choose what to do next?",
							Util.newArrayListOfValues(Fetish.FETISH_SUBMISSIVE),
							null, CorruptionLevel.THREE_DIRTY, null, null, null,
							false, false,
							new SMGeneric(
									Util.newArrayListOfValues(getSlime()),
									Util.newArrayListOfValues(Main.game.getPlayer()),
							null,
							null),
							AFTER_SLIME_SEX_AS_SUB,
							UtilText.parseFromXMLFile("places/submission/tunnelSlime", "AFTER_COMBAT_VICTORY_SEX_SUBMIT", getSlime()));
				}

			} else if (index == 6) {
				return new ResponseEffectsOnly("Inventory", "Now that you've defeated [npc.name], there's nothing stopping you from helping yourself to [npc.her] clothing and items..."){
					@Override
					public void effects() {
						Main.mainController.openInventory(getSlime(), InventoryInteraction.FULL_MANAGEMENT);
					}
				};

			}
			//TODO
//			else if (index == 7) {
//				if(slime().hasFlag(NPCFlagValue.genericNPCBetrayedByPlayer)) {
//					return new Response("Talk", "After betraying [npc.namePos] trust, [npc.she] will never want to talk to you again.", null);
//
//				} else {
//					return new Response("Talk", "Talk to [npc.name] and ask [npc.herHim] why [npc.she] attacked you.", AFTER_COMBAT_VICTORY_TALK){
//						@Override
//						public void effects() {
//							slime().setPlayerKnowsName(true);
//							Main.game.getTextEndStringBuilder().append(slime().setAffection(Main.game.getPlayer(), 10));
//						}
//					};
//				}
//
//			}
			else if (index == 8 && getSlime().isAbleToSelfTransform()) {
				return new Response("Transform [npc.herHim]",
						"Take a very detailed look at what [npc.name] can transform [npc.herself] into...",
						BodyChanging.BODY_CHANGING_CORE){
					@Override
					public void effects() {
						Main.game.saveDialogueNode();
						BodyChanging.setTarget(getSlime());
					}
				};

			} else if (index == 10 && !getSlime().hasFlag(NPCFlagValue.genericNPCBetrayedByPlayer)) {
				return new Response(
						"Remove character",
						"Scare [npc.name] away. This will remove [npc.herHim] from this area, allowing another character to move into this tile.",
						Main.game.getDefaultDialogueNoEncounter()){
					@Override
					public void effects() {
						Main.game.getTextStartStringBuilder().append(UtilText.parseFromXMLFile("places/submission/tunnelSlime", "AFTER_COMBAT_VICTORY_BANISH_NPC", getSlime()));
						Main.game.banishNPC(getSlime());
					}
				};

			} else {
				return null;
			}

		}
	};

	public static final DialogueNode AFTER_COMBAT_PLAYER_DEFEAT = new DialogueNode("Defeat", "", true) {

		@Override
		public String getDescription() {
			return "You have been defeated by [npc.name]!";
		}

		@Override
		public String getContent() {
			UtilText.nodeContentSB.setLength(0);

			UtilText.nodeContentSB.append(UtilText.parseFromXMLFile("places/submission/tunnelSlime", "AFTER_COMBAT_DEFEAT"));

			if(getSlime().hasFetish(Fetish.FETISH_TRANSFORMATION_GIVING) && Main.game.getPlayer().getBodyMaterial()!=BodyMaterial.SLIME) {
				UtilText.nodeContentSB.append(UtilText.parseFromXMLFile("places/submission/tunnelSlime", "AFTER_COMBAT_DEFEAT_TRANSFORMER"));

			} else {
				if(getSlime().isAttractedTo(Main.game.getPlayer()) && getSlime().isWillingToRape() && Main.game.isNonConEnabled()) {
					UtilText.nodeContentSB.append(UtilText.parseFromXMLFile("places/submission/tunnelSlime", "AFTER_COMBAT_DEFEAT_RAPE"));
				} else {
					UtilText.nodeContentSB.append(UtilText.parseFromXMLFile("places/submission/tunnelSlime", "AFTER_COMBAT_DEFEAT_NO_RAPE"));
				}
			}

			return UtilText.nodeContentSB.toString();
		}

		@Override
		public Response getResponse(int responseTab, int index) {
			if(getSlime().hasFetish(Fetish.FETISH_TRANSFORMATION_GIVING) && Main.game.getPlayer().getBodyMaterial()!=BodyMaterial.SLIME) {
				if (index == 1) {
					if(Main.game.isSpittingDisabled()) {
						return Response.getDisallowedSpittingResponse("Resist");
					}
					if(Main.game.getPlayer().hasFetish(Fetish.FETISH_TRANSFORMATION_RECEIVING)) {
						return new Response("Resist",
								"Due to your "+Fetish.FETISH_TRANSFORMATION_RECEIVING.getName(Main.game.getPlayer())
									+" fetish, you love being transformed so much that you can't bring yourself to resist!",
								null);
					} else {
						return new Response("Resist", "Knock the strange fluid out of [npc.namePos] hands.", RESIST_TRANSFORMED);
					}

				} else if (index == 2) {
					return new Response("Submit", "Allow [npc.name] to transform you into a slime!", TRANSFORMED) {
						@Override
						public Colour getHighlightColour() {
							return Colour.TRANSFORMATION_GENERIC;
						}
						@Override
						public void effects() {
							Main.game.getPlayer().setBodyMaterial(BodyMaterial.SLIME);
						}
					};

				} else {
					return null;
				}

			} else if(Main.game.getActiveNPC().isAttractedTo(Main.game.getPlayer()) && Main.game.getActiveNPC().isWillingToRape() && Main.game.isNonConEnabled()) {
				if (index == 1) {
					return new ResponseSex("Sex",
							"[npc.Name] forces [npc.herself] on you...",
							false, false,
							new SMGeneric(
									Util.newArrayListOfValues(Main.game.getActiveNPC()),
									Util.newArrayListOfValues(Main.game.getPlayer()),
							null,
							null), AFTER_SLIME_SEX_AS_SUB, "
"
								+ "You surrender yourself to [npc.name], lying back and offering no resistance as [npc.she] tongue-fucks your throat."
								+ " After a moment, [npc.she] sits back up, leaving a wet pool of slime all over your [pc.lips]."
								+ " [npc.speech(Good bitch! You know your place already! Now be a good [pc.girl] and try to enjoy this...)]"
							+ "
");

				} else if (index == 2) {
					return new ResponseSex("Eager Sex",
							"[npc.Name] forces [npc.herself] on you...",
							false, false,
							new SMGeneric(
									Util.newArrayListOfValues(Main.game.getActiveNPC()),
									Util.newArrayListOfValues(Main.game.getPlayer()),
									null,
									null,
									ResponseTag.START_PACE_PLAYER_SUB_EAGER), AFTER_SLIME_SEX_AS_SUB, "
"
								+ "You eagerly surrender yourself to [npc.name], raising your head to help [npc.herHim] tongue-fuck your throat."
								+ " After a moment, [npc.she] sits back up, leaving a wet pool of slime all over your [pc.lips]."
								+ " [npc.speech(Good bitch! You know your place already! Now be a good [pc.girl] and try to enjoy this...)]"
							+ "
");

				} else if (index == 3 && Main.game.isNonConEnabled()) {
					return new ResponseSex("Resist Sex",
							"[npc.Name] forces [npc.herself] on you...",
							false, false,
							new SMGeneric(
									Util.newArrayListOfValues(Main.game.getActiveNPC()),
									Util.newArrayListOfValues(Main.game.getPlayer()),
									null,
									null,
									ResponseTag.START_PACE_PLAYER_SUB_RESISTING), AFTER_SLIME_SEX_AS_SUB, "
"
								+ "You try to turn your face away, but [npc.name] simply reaches up to grip both sides of your head, holding you still as [npc.she] tongue-fucks your throat."
								+ " After a moment, [npc.she] sits back up, leaving a wet pool of slime all over your [pc.lips]."
								+ " [npc.speech(Stupid bitch! You can resist as much as you want! I'm not going to stop until I'm satisfied!)]"
							+ "
");

				} else {
					return null;
				}

			} else {
				if (index == 1) {
					return new Response("Continue", "Carry on your way.", AFTER_COMBAT_PLAYER_DEFEAT){
						@Override
						public DialogueNode getNextDialogue() {
							return Main.game.getDefaultDialogueNoEncounter();
						}
					};

				} else {
					return null;
				}
			}
		}
	};

	public static final DialogueNode AFTER_SEX_VICTORY = new DialogueNode("Step back", "", true) {

		@Override
		public String getDescription(){
			return "Now that you've had your fun, you can step back and leave [npc.name] to recover.";
		}

		@Override
		public String getContent() {
			if(Sex.getNumberOfOrgasms(getSlime()) >= getSlime().getOrgasmsBeforeSatisfied()) {
				return UtilText.parseFromXMLFile("places/submission/tunnelSlime", "AFTER_SLIME_SEX_AS_DOM");
			} else {
				return UtilText.parseFromXMLFile("places/submission/tunnelSlime", "AFTER_SLIME_SEX_AS_DOM_NO_ORGASM");
			}
		}

		@Override
		public Response getResponse(int responseTab, int index) {
			if (index == 1) {
				return new Response("Continue", "Carry on your way.", AFTER_SEX_VICTORY){
					@Override
					public DialogueNode getNextDialogue(){
						return Main.game.getDefaultDialogueNoEncounter();
					}
				};

			} else if (index == 6) {
				return new ResponseEffectsOnly("Inventory", "There's nothing stopping you from helping yourself to [npc.namePos] clothing and items..."){
					@Override
					public void effects() {
						Main.mainController.openInventory(Main.game.getActiveNPC(), InventoryInteraction.FULL_MANAGEMENT);
					}
				};

			} else if (index == 10) {
				return new Response(
						"Remove character",
						"Scare [npc.name] away. This will remove [npc.herHim] from this area, allowing another character to move into this tile.",
						AFTER_COMBAT_PLAYER_VICTORY){
					@Override
					public DialogueNode getNextDialogue() {
						return Main.game.getDefaultDialogueNoEncounter();
					}
					@Override
					public void effects() {
						Main.game.banishNPC(Main.game.getActiveNPC());
					}
				};

			} else {
				return null;
			}
		}
	};

}

repo_name: klorpa/Pedo

license: unknown


code:
package com.lilithsthrone.game.dialogue.npcDialogue.unique;

import com.lilithsthrone.game.PropertyValue;
import com.lilithsthrone.game.character.GameCharacter;
import com.lilithsthrone.game.character.npc.dominion.Lumi;
import com.lilithsthrone.game.dialogue.DialogueFlagValue;
import com.lilithsthrone.game.dialogue.DialogueNode;
import com.lilithsthrone.game.dialogue.responses.Response;
import com.lilithsthrone.game.dialogue.responses.ResponseCombat;
import com.lilithsthrone.game.dialogue.responses.ResponseEffectsOnly;
import com.lilithsthrone.game.dialogue.responses.ResponseSex;
import com.lilithsthrone.game.dialogue.utils.UtilText;
import com.lilithsthrone.game.sex.SexPace;
import com.lilithsthrone.game.sex.managers.universal.SMLyingDown;
import com.lilithsthrone.game.sex.positions.slots.SexSlotLyingDown;
import com.lilithsthrone.main.Main;
import com.lilithsthrone.utils.Util;
import com.lilithsthrone.utils.Util.Value;
import com.lilithsthrone.world.WorldType;
import com.lilithsthrone.world.places.PlaceType;

/**
 * @since 0.2.5
 * @version 0.2.6
 * @author Nnxx, Innoxia
 */
public class LumiDialogue {

	public static final DialogueNode LUMI_APPEARS = new DialogueNode("Alleyways", "", true) {

		@Override
		public String getAuthor() {
			return "Nnxx";
		}

		@Override
		public String getContent() {
			return UtilText.parseFromXMLFile("characters/dominion/lumi", "LUMI_APPEARS");
		}

		@Override
		public Response getResponse(int responseTab, int index) {
			if (index == 1) {
				if(Main.game.getDialogueFlags().hasFlag(DialogueFlagValue.lumiMet)) {
					return new Response("Stay", "Decide to stay and see who approaches.", LUMI_APPEARS_REPEAT_ENCOUNTER);
				} else {
					return new Response("Stay", "Decide to stay and see who approaches.", LUMI_APPEARS_FIRST_ENCOUNTER);
				}

			} else if (index == 2) {
				return new ResponseEffectsOnly("Evade", "Quickly duck away down a narrow passage.") {
					@Override
					public void effects() {
						Main.game.getTextStartStringBuilder().append(UtilText.parseFromXMLFile("characters/dominion/lumi", "LUMI_APPEARS_EVADE"));
						Main.game.setContent(new Response("", "", Main.game.getDefaultDialogueNoEncounter()));
					}
				};

			} else {
				return null;
			}
		}
	};

	private static int moneyStolen = 0;

	public static final DialogueNode LUMI_APPEARS_FIRST_ENCOUNTER = new DialogueNode("Alleyways", "", true, true) {

		@Override
		public String getAuthor() {
			return "Nnxx";
		}

		@Override
		public String getContent() {
			return UtilText.parseFromXMLFile("characters/dominion/lumi", "LUMI_APPEARS_FIRST_ENCOUNTER");
		}

		@Override
		public Response getResponse(int responseTab, int index) {
			if (index == 1) {
				return new Response("Wait", "Keep hiding behind the pile of junk.", LUMI_APPEARS_FIRST_ENCOUNTER_WAITING) {
					@Override
					public void effects() {
						moneyStolen = Main.game.getPlayer().getMoney()>=700?700:Main.game.getPlayer().getMoney();
						Main.game.getPlayer().incrementMoney(-moneyStolen);

						if(moneyStolen==700) {
							Main.game.getTextEndStringBuilder().append(UtilText.parseFromXMLFile("characters/dominion/lumi", "MAX_MONEY_STOLEN"));
						} else {
							Main.game.getTextEndStringBuilder().append(UtilText.parseFromXMLFile("characters/dominion/lumi", "ALL_MONEY_STOLEN"));
						}
					}
				};

			} else {
				return null;
			}
		}
	};

	public static final DialogueNode LUMI_APPEARS_FIRST_ENCOUNTER_WAITING = new DialogueNode("Alleyways", "", true, true) {

		@Override
		public String getAuthor() {
			return "Nnxx";
		}

		@Override
		public String getContent() {
			return UtilText.parseFromXMLFile("characters/dominion/lumi", "LUMI_APPEARS_FIRST_ENCOUNTER_WAITING");
		}

		@Override
		public Response getResponse(int responseTab, int index) {
			if (index == 1) {
				return new Response("Chase them", "You're not going to let this thief escape!", LUMI_CHASE);

			} else if (index == 2) {
				return new ResponseEffectsOnly("Let them go", "You don't have time to be chasing after petty thieves. Let them go.") {
					@Override
					public void effects() {
						Main.game.getTextStartStringBuilder().append(UtilText.parseFromXMLFile("characters/dominion/lumi", "LUMI_LET_THEM_ESCAPE"));
						Main.game.setContent(new Response("", "", Main.game.getDefaultDialogueNoEncounter()));
					}
				};

			} else {
				return null;
			}
		}
	};

	public static final DialogueNode LUMI_CHASE = new DialogueNode("Alleyways", "", true, true) {

		@Override
		public String getAuthor() {
			return "Nnxx";
		}

		@Override
		public String getContent() {
			return UtilText.parseFromXMLFile("characters/dominion/lumi", "LUMI_CHASE");
		}

		@Override
		public Response getResponse(int responseTab, int index) {
			if (index == 1) {
				return new Response("Continue pursuit", "You're not going to let this thief escape!", LUMI_CHASE_CONTINUE) {
					@Override
					public void effects() {
						Main.game.getNpc(Lumi.class).setLocation(Main.game.getPlayer().getWorldLocation(), Main.game.getPlayer().getLocation(), true);
					}
				};

			} else {
				return null;
			}
		}
	};

	public static final DialogueNode LUMI_CHASE_CONTINUE = new DialogueNode("Alleyways", "", true, true) {

		@Override
		public String getAuthor() {
			return "Nnxx";
		}

		@Override
		public int getSecondsPassed() {
			return 10*60;
		}

		@Override
		public String getContent() {
			return UtilText.parseFromXMLFile("characters/dominion/lumi", "LUMI_CHASE_CONTINUE");
		}

		@Override
		public Response getResponse(int responseTab, int index) {
			if (index == 1) {
				return new Response("Talk", "Decide to try talking to her. After all, violence is never the solution!", LUMI_CAUGHT_TALK);

			} else if (index == 2) {
				return new ResponseCombat("Fight",
						"You're not going to let this thief escape!",
						Main.game.getNpc(Lumi.class),
						Util.newHashMapOfValues(
								new Value<>(Main.game.getPlayer(), UtilText.parseFromXMLFile("characters/dominion/lumi", "LUMI_COMBAT_PC_OPENING")),
								new Value<>(Main.game.getNpc(Lumi.class), UtilText.parseFromXMLFile("characters/dominion/lumi", "LUMI_COMBAT_LUMI_OPENING")))) {
					@Override
					public void effects() {
						Main.game.getDialogueFlags().setFlag(DialogueFlagValue.lumiDisabled, true);
					}
				};

			} else {
				return null;
			}
		}
	};

	public static final DialogueNode COMBAT_PLAYER_LOSS = new DialogueNode("Alleyways", "", true) {

		@Override
		public String getAuthor() {
			return "Nnxx";
		}

		@Override
		public String getContent() {
			return UtilText.parseFromXMLFile("characters/dominion/lumi", "COMBAT_PLAYER_LOSS");
		}

		@Override
		public Response getResponse(int responseTab, int index) {
			if(index == 1) {
				return new Response("Continue", "Carry on your way...", null){
					@Override
					public DialogueNode getNextDialogue() {
						return Main.game.getDefaultDialogueNoEncounter();
					}
					@Override
					public void effects() {
						Main.game.getNpc(Lumi.class).setLocation(WorldType.EMPTY, PlaceType.GENERIC_EMPTY_TILE);
					}
				};

			} else {
				return null;
			}
		}
	};

	public static final DialogueNode COMBAT_PLAYER_WIN = new DialogueNode("Alleyways", "", true) {

		@Override
		public String getAuthor() {
			return "Nnxx";
		}

		@Override
		public String getContent() {
			return UtilText.parseFromXMLFile("characters/dominion/lumi", "COMBAT_PLAYER_WIN");
		}

		@Override
		public Response getResponse(int responseTab, int index) {
			if (index == 1) {
				return new Response("Recover money", "Just pick your money up and leave without making a fuss.", COMBAT_PLAYER_WIN_RECOVER_MONEY) {
					@Override
					public void effects() {
						Main.game.getPlayer().incrementMoney(moneyStolen);
					}
				};

			} else if (index == 2 && Main.getProperties().hasValue(PropertyValue.nonConContent)) {
				return new ResponseSex("Take advantage",
						"Now that she's been subdued, it's time to have some fun with this helpless wolf-girl!",
						false, false,
						new SMLyingDown(
								Util.newHashMapOfValues(new Value<>(Main.game.getPlayer(), SexSlotLyingDown.MISSIONARY)),
								Util.newHashMapOfValues(new Value<>(Main.game.getNpc(Lumi.class), SexSlotLyingDown.LYING_DOWN))) {
							@Override
							public SexPace getStartingSexPaceModifier(GameCharacter character) {
								if(character.isPlayer()) {
									return SexPace.DOM_ROUGH;
								}
								return SexPace.SUB_RESISTING;
							}
						},
						null,
						null, AFTER_SEX, UtilText.parseFromXMLFile("characters/dominion/lumi", "COMBAT_PLAYER_WIN_TAKE_ADVANTAGE")) {
					@Override
					public void effects() {
						Main.game.getPlayer().incrementKarma(-1000);
					}
				};

			} else {
				return null;
			}
		}
	};

	public static final DialogueNode AFTER_SEX = new DialogueNode("Alleyways", "", true, true) {

		@Override
		public String getAuthor() {
			return "Nnxx";
		}

		@Override
		public String getContent() {
			return UtilText.parseFromXMLFile("characters/dominion/lumi", "AFTER_SEX");
		}

		@Override
		public Response getResponse(int responseTab, int index) {
			if(index == 1) {
				return new Response("Continue", "Carry on your way...", null){
					@Override
					public DialogueNode getNextDialogue() {
						return Main.game.getDefaultDialogueNoEncounter();
					}
					@Override
					public void effects() {
						Main.game.getNpc(Lumi.class).setLocation(WorldType.EMPTY, PlaceType.GENERIC_EMPTY_TILE);
					}
				};

			} else {
				return null;
			}
		}
	};

	public static final DialogueNode COMBAT_PLAYER_WIN_RECOVER_MONEY = new DialogueNode("Alleyways", "", true, true) {

		@Override
		public String getAuthor() {
			return "Nnxx";
		}

		@Override
		public String getContent() {
			return UtilText.parseFromXMLFile("characters/dominion/lumi", "COMBAT_PLAYER_WIN_RECOVER_MONEY");
		}

		@Override
		public Response getResponse(int responseTab, int index) {
			if(index == 1) {
				return new Response("Continue", "Carry on your way...", null){
					@Override
					public DialogueNode getNextDialogue() {
						return Main.game.getDefaultDialogueNoEncounter();
					}
					@Override
					public void effects() {
						Main.game.getNpc(Lumi.class).setLocation(WorldType.EMPTY, PlaceType.GENERIC_EMPTY_TILE);
					}
				};

			} else {
				return null;
			}
		}
	};

	public static final DialogueNode COMBAT_PLAYER_WIN_TAKE_ADVANTAGE = new DialogueNode("Alleyways", "", true, true) {

		@Override
		public String getAuthor() {
			return "Nnxx";
		}

		@Override
		public String getContent() {
			return UtilText.parseFromXMLFile("characters/dominion/lumi", "COMBAT_PLAYER_WIN_TAKE_ADVANTAGE");
		}

		@Override
		public Response getResponse(int responseTab, int index) {
			if(index == 1) {
				return new Response("Continue", "Carry on your way...", null){
					@Override
					public DialogueNode getNextDialogue() {
						return Main.game.getDefaultDialogueNoEncounter();
					}
					@Override
					public void effects() {
						Main.game.getNpc(Lumi.class).setLocation(WorldType.EMPTY, PlaceType.GENERIC_EMPTY_TILE);
					}
				};

			} else {
				return null;
			}
		}
	};

	public static final DialogueNode LUMI_CAUGHT_TALK = new DialogueNode("Alleyways", "", true, true) {

		@Override
		public String getAuthor() {
			return "Nnxx";
		}

		@Override
		public String getContent() {
			return UtilText.parseFromXMLFile("characters/dominion/lumi", "LUMI_CAUGHT_TALK");
		}

		@Override
		public Response getResponse(int responseTab, int index) {
			if(index == 1) {
				return new Response("Give", "Let Lumi keep the money that she stole from you, and tell her how to make the most of it.", LUMI_CAUGHT_TALK_GIVE_MONEY) {
					@Override
					public void effects() {
						Main.game.getNpc(Lumi.class).setPlayerKnowsName(true);
						Main.game.getTextEndStringBuilder().append(Main.game.getNpc(Lumi.class).incrementAffection(Main.game.getPlayer(), 10));
					}
				};

			} else if(index == 2) {
				return new Response("Ask", "Ask Lumi to return the money that she stole from you.", LUMI_CAUGHT_TALK_ASK_FOR_MONEY_BACK) {
					@Override
					public void effects() {
						Main.game.getNpc(Lumi.class).setPlayerKnowsName(true);
						Main.game.getPlayer().incrementMoney(moneyStolen);
						Main.game.getDialogueFlags().setFlag(DialogueFlagValue.lumiPromisedDinner, true);
						Main.game.getTextEndStringBuilder().append(Main.game.getNpc(Lumi.class).incrementAffection(Main.game.getPlayer(), 5));
					}
				};

			} else if(index == 3) {
				return new Response("Threaten", "Discipline this thief! You get the feeling that if you were to do this, you'd never see her again.", LUMI_CAUGHT_TALK_THREATEN){
					@Override
					public void effects() {
						Main.game.getDialogueFlags().setFlag(DialogueFlagValue.lumiDisabled, true);
					}
				};

			} else {
				return null;
			}
		}
	};

	public static final DialogueNode LUMI_CAUGHT_TALK_GIVE_MONEY = new DialogueNode("Alleyways", "", true, true) {

		@Override
		public String getAuthor() {
			return "Nnxx";
		}

		@Override
		public String getContent() {
			return UtilText.parseFromXMLFile("characters/dominion/lumi", "LUMI_CAUGHT_TALK_GIVE_MONEY");
		}

		@Override
		public Response getResponse(int responseTab, int index) {
			if(index == 1) {
				return new Response("Continue", "Carry on your way...", null){
					@Override
					public DialogueNode getNextDialogue() {
						return Main.game.getDefaultDialogueNoEncounter();
					}
				};

			} else {
				return null;
			}
		}
	};

	public static final DialogueNode LUMI_CAUGHT_TALK_ASK_FOR_MONEY_BACK = new DialogueNode("Alleyways", "", true, true) {

		@Override
		public String getAuthor() {
			return "Nnxx";
		}

		@Override
		public String getContent() {
			return UtilText.parseFromXMLFile("characters/dominion/lumi", "LUMI_CAUGHT_TALK_ASK_FOR_MONEY_BACK");
		}

		@Override
		public Response getResponse(int responseTab, int index) {
			if(index == 1) {
				return new Response("Continue", "Carry on your way...", null){
					@Override
					public DialogueNode getNextDialogue() {
						return Main.game.getDefaultDialogueNoEncounter();
					}
				};

			} else {
				return null;
			}
		}
	};

	public static final DialogueNode LUMI_CAUGHT_TALK_THREATEN = new DialogueNode("Alleyways", "", true, true) {

		@Override
		public String getAuthor() {
			return "Nnxx";
		}

		@Override
		public String getContent() {
			return UtilText.parseFromXMLFile("characters/dominion/lumi", "LUMI_CAUGHT_TALK_THREATEN");
		}

		@Override
		public Response getResponse(int responseTab, int index) {
			if(index == 1) {
				return new Response("Continue", "Carry on your way...", null){
					@Override
					public DialogueNode getNextDialogue() {
						return Main.game.getDefaultDialogueNoEncounter();
					}
					@Override
					public void effects() {
						Main.game.getNpc(Lumi.class).setLocation(WorldType.EMPTY, PlaceType.GENERIC_EMPTY_TILE);
					}
				};

			} else {
				return null;
			}
		}
	};

	public static final DialogueNode LUMI_APPEARS_REPEAT_ENCOUNTER = new DialogueNode("Alleyways", "", true, true) {

		@Override
		public String getAuthor() {
			return "Nnxx";
		}

		@Override
		public String getContent() {
			return UtilText.parseFromXMLFile("characters/dominion/lumi", "LUMI_APPEARS_REPEAT_ENCOUNTER");
		}

		@Override
		public Response getResponse(int responseTab, int index) {
			return null;
		}
	};
}


code:
package com.lilithsthrone.game.dialogue.places;

import com.lilithsthrone.game.dialogue.DialogueNode;
import com.lilithsthrone.game.dialogue.responses.Response;
import com.lilithsthrone.main.Main;
import com.lilithsthrone.world.WorldType;
import com.lilithsthrone.world.places.PlaceType;

/**
 * @since 0.1.0
 * @version 0.1.69
 * @author Innoxia
 */
public class JunglePlaces {

	public static final DialogueNode PATH = new DialogueNode("Jungle path", "", false) {
		/**
		 *
		 */

		@Override
		public String getContent() {
			return "TODO Walking down a narrow path...";
		}

		@Override
		public Response getResponse(int responseTab, int index) {
			return null;
		}
	};

	public static final DialogueNode CLUB = new DialogueNode("Club", "A place.", false) {
		/**
		 *
		 */

		@Override
		public String getContent() {
			return "TODO";
		}

		@Override
		public Response getResponse(int responseTab, int index) {
			return null;
		}
	};

	public static final DialogueNode BROTHEL = new DialogueNode("Brothel", "A place.", false) {
		/**
		 *
		 */

		@Override
		public String getContent() {
			return "TODO";
		}

		@Override
		public Response getResponse(int responseTab, int index) {
			return null;
		}
	};

	public static final DialogueNode TENTACLE_QUEENS_LAIR = new DialogueNode("Tentacle Queen's Lair", "A place.", false) {
		/**
		 *
		 */

		@Override
		public String getContent() {
			return "TODO";
		}

		@Override
		public Response getResponse(int responseTab, int index) {
			return null;
		}
	};

	public static final DialogueNode DENSE_JUNGLE = new DialogueNode("Dense Jungle", "A place.", false) {
		/**
		 *
		 */

		@Override
		public String getContent() {
			return "TODO";
		}

		@Override
		public Response getResponse(int responseTab, int index) {
			return null;
		}
	};

	// Entrances and exits:

	public static final DialogueNode JUNGLE_ENTRANCE = new DialogueNode("", "Travel to Dominion.", false) {
		/**
		 *
		 */

		@Override
		public String getContent() {
			return "A half-overgrown sign near the road tells you that this path leads back to Dominion.";
		}
		@Override
		public Response getResponse(int responseTab, int index) {
			if (index == 1) {
				return new Response("Dominion", "Travel to Dominion. (This will be added later!)", null){
					@Override
					public void effects() {
						Main.mainController.moveGameWorld(WorldType.DOMINION, PlaceType.DOMINION_EXIT_NORTH, true);
					}
				};

			} else {
				return null;
			}
		}
	};
}


code:
package com.lilithsthrone.game.dialogue.places.dominion;

import com.lilithsthrone.game.character.GameCharacter;
import com.lilithsthrone.game.character.npc.NPC;
import com.lilithsthrone.game.character.persona.NameTriplet;
import com.lilithsthrone.game.character.persona.Relationship;
import com.lilithsthrone.game.dialogue.DialogueNode;
import com.lilithsthrone.game.dialogue.responses.Response;
import com.lilithsthrone.game.dialogue.responses.ResponseEffectsOnly;
import com.lilithsthrone.game.dialogue.utils.UtilText;
import com.lilithsthrone.main.Main;
import com.lilithsthrone.utils.Color;

/**
 * @since 0.1.0
 * @version 0.2.12
 * @author Innoxia
 */
public class CityHall {

	public static final DialogueNode OUTSIDE = new DialogueNode("City Hall", "-", false) {

		@Override
		public int getMinutesPassed() {
			return 5;
		}

		@Override
		public String getContent() {
			return "
"
					+ "Before you stands City Hall; the center of administration for the city of Dominion."
					+ " A sign near the entrance of the impressive building informs you that it's open twenty-four hours a day."
					+ "
";
		}

		@Override
		public Response getResponse(int responseTab, int index) {
			if (index == 1) {
				return new Response("Enter", "The doors are wide open, inviting you to step inside Dominion's City Hall.", CITY_HALL_ENTER);

			} else {
				return null;
			}
		}
	};
	public static final DialogueNode CITY_HALL_ENTER = new DialogueNode("City Hall ", "-", true) {

		@Override
		public String getContent() {
			return "
"
						+ "You find yourself standing in a huge entrance hall, with a polished marble floor and huge chandeliers giving the impression of obvious wealth and power."
						+ " There are a series of rich mahogany desks scattered around the place, with each one seeming to be responsible for rather specific and mundane problems."
						+ " A helpful map that you find near to the entrance shows the way to some different departments that might be of more use to you."
					+ "
";
		}

		@Override
		public Response getResponse(int responseTab, int index) {
			if (index == 1) {
				return new Response("Demographics", "Follow the map's directions to the 'Bureau of Demographics' office.", CITY_HALL_PUBLIC_ENQUIRIES);

			} else if (index == 0) {
				return new Response("Leave", "Head back outside.", OUTSIDE);

			} else {
				return null;
			}
		}
	};

	public static final DialogueNode CITY_HALL_PUBLIC_ENQUIRIES = new DialogueNode("Bureau of Demographics", "-", true) {

		@Override
		public String getContent() {
			return "
"
						+ "Following the directions you obtained from the map in the entrance hall, you soon find yourself entering the office marked 'Bureau of Demographics'."
						+ " Shelves fill the stuffy and dimly-lit room, which looks to be more of an archive than a regular office."
						+ " A bored-looking lesser cat-girl sits behind the front desk, her eyes cast down as she looks over a pile of papers and forms."
						+ " If she noticed your arrival, she doesn't show it, and seems to be content to carry on reading what's in front of her as she ignores your presence."
					+ "
";
		}

		@Override
		public Response getResponse(int responseTab, int index) {
			if (index == 1) {
				return new Response("Name change", "Ask the cat-girl about changing your name.", CITY_HALL_NAME_CHANGE_FORM);

			} else if (index == 0) {
				return new Response("Back", "Return to the entrance hall.", CITY_HALL_ENTER);

			} else {
				return null;
			}
		}
	};

	private static boolean unsuitableName = false;
	private static boolean unsuitableSurname = false;

	public static final DialogueNode CITY_HALL_NAME_CHANGE_FORM = new DialogueNode("Bureau of Demographics", "-", true) {

		@Override
		public String getContent() {
			return "
"
						+ "The cat-girl looks up as you approach her desk, and lets out a tired sigh, before asking, "
						+ "[genericFemale.speech(What can I help you with?)]"
					+ "
"
					+ "
"
						+ "You ask about changing your name, and with a sigh, she leans down and starts rummaging around under her desk."
						+ " After a moment she seems to find what she's looking for and sits back upright, handing you a pink form before looking back down at the papers on her desk."
					+ "
"
					+ "
"
						+"[genericFemale.speech(Fill in what you'd like to change your name to, then you have to pay the admin fee of one hundred flames,)]"
						+ " she drones, not bothering to look up from the papers in front of her."
						+" [genericFemale.speech(If you want all of your offspring to have their surnames changed to your new one, then that'll be five thousand flames. It's not easy tracking them all down in our records, you know.)]"
					+ "
"
					+"
"
					+ "
"
						+ "
"
							+ "
First name:
"
							+ "<form style='display:inline-block; padding:0; margin:0; text-align:center;'><input type='text' id='nameInput' value='"+ UtilText.parseForHTMLDisplay(Main.game.getPlayer().getName())+ "'></form>"
							+ "
"
							+ "
Surname:
"
							+ "<form style='display:inline-block; padding:0; margin:0; text-align:center;'><input type='text' id='surnameInput' value='"+ UtilText.parseForHTMLDisplay(Main.game.getPlayer().getSurname())+ "'></form>"
						+ "
"
						+ "
"
						+ "Your name must be between 2 and 16 characters long. You cannot use the square bracket characters or full stops. (Surname may be left blank.)"
						+ (unsuitableName ? "
Invalid name.
" : "")
						+ (unsuitableSurname ? "
Invalid Surname.
" : "")
					+ "
"

					+ "

"
					+ "

";

		}

		@Override
		public Response getResponse(int responseTab, int index) {
			if (index == 1) {
				if (Main.game.getPlayer().getMoney() < 100) {
					return new Response("Confirm ("+UtilText.formatAsMoneyUncolored(100, "span")+")",
							"Have your name changed.
[style.italicsBad(You cannot afford this!)]",
							null);

				} else {
					return new ResponseEffectsOnly("Confirm ("+UtilText.formatAsMoney(100, "span")+")", "Have your name changed.
This will cost "+UtilText.formatAsMoney(100)+"."){
						@Override
						public void effects() {
							applyNameChange(false);
						}
					};
				}

			} else if(index==2) {
				if(Main.game.getPlayer().getAllCharactersOfRelationType(Relationship.Parent).isEmpty()) {
					return new Response("Offspring ("+UtilText.formatAsMoneyUncolored(5000, "span")+")",
							"Change your name, and also have all lines of your offspring update their surnames to your surname.
[style.italicsBad(You do not have any children, so you can't do this!)]", null);

				} else if (Main.game.getPlayer().getMoney() < 5000) {
					return new Response("Offspring ("+UtilText.formatAsMoneyUncolored(5000, "span")+")",
							"Change your name, and also have all lines of your offspring update their surnames to your surname.
[style.italicsBad(You cannot afford this!)]", null);

				} else {
					return new ResponseEffectsOnly("Offspring ("+UtilText.formatAsMoney(5000, "span")+")",
							"Change your name, and also have all lines of your offspring update their surnames to your surname.
This will cost "+UtilText.formatAsMoney(5000)+"."){
						@Override
						public void effects() {
							applyNameChange(true);
						}
					};
				}

			} else if (index == 0) {
				return new Response("Back", "Decide not to change your name.", CITY_HALL_PUBLIC_ENQUIRIES);

			} else {
				return null;
			}
		}
	};

	private static void applyNameChange(boolean applyOffspringSurnames) {
		Main.mainController.getWebEngine().executeScript("document.getElementById('hiddenFieldName').innerHTML=document.getElementById('nameInput').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
					|| !Main.mainController.getWebEngine().getDocument().getElementById("hiddenFieldName").getTextContent().matches("[^\\[\\]\\.]+"))
				unsuitableName = true;
			else {
				unsuitableName = false;
			}
		}
		Main.mainController.getWebEngine().executeScript("document.getElementById('hiddenFieldSurname').innerHTML=document.getElementById('surnameInput').value;");
		if(Main.mainController.getWebEngine().getDocument()!=null) {
			if (Main.mainController.getWebEngine().getDocument().getElementById("hiddenFieldSurname").getTextContent().length()==0
					&& (Main.mainController.getWebEngine().getDocument().getElementById("hiddenFieldSurname").getTextContent().length() > 32
							|| !Main.mainController.getWebEngine().getDocument().getElementById("hiddenFieldSurname").getTextContent().matches("[^\\[\\]\\.]+")))
				unsuitableSurname = true;
			else {
				unsuitableSurname = false;
			}
		}

		if(applyOffspringSurnames && Main.mainController.getWebEngine().getDocument().getElementById("hiddenFieldSurname").getTextContent().length()==0) {
			unsuitableSurname = true;
		}

		if (unsuitableName || unsuitableSurname)  {
			Main.game.setContent(new Response("" ,"", CITY_HALL_NAME_CHANGE_FORM));

		} else {
			Main.game.getPlayer().setName(new NameTriplet(Main.mainController.getWebEngine().getDocument().getElementById("hiddenFieldName").getTextContent()));
			Main.game.getPlayer().setSurname(Main.mainController.getWebEngine().getDocument().getElementById("hiddenFieldSurname").getTextContent());

			if(applyOffspringSurnames && Main.mainController.getWebEngine().getDocument().getElementById("hiddenFieldSurname").getTextContent().length()>=1) {
				for(NPC npc : Main.game.getAllNPCs()) {
					GameCharacter mother = npc.getMother();
					if(mother!=null) {
						while(mother.getMother()!=null) {
							mother = mother.getMother();
						}
						if(mother.isPlayer()) {
							npc.setSurname(Main.game.getPlayer().getSurname());
						}
					}
				}
			}
			if(applyOffspringSurnames) {
				Main.game.getTextEndStringBuilder().append(
						"
"
							+ "You fill out the forms and hand over the required fee, officially changing your name to:
"
							+ "[pc.Name]"+(!Main.game.getPlayer().getSurname().isEmpty()?" [pc.Surname]":"")+"
"
							+ "All of your offspring, all the way down your family tree, have had their surnames legally changed to:
"
							+ "[pc.Surname]
"
						+ "
"
						+Main.game.getPlayer().incrementMoney(-5000));
			} else {
				Main.game.getTextEndStringBuilder().append(
						"
"
							+ "You fill out the forms and hand over the required fee, officially changing your name to:
"
							+ "[pc.Name]"+(!Main.game.getPlayer().getSurname().isEmpty()?" [pc.Surname]":"")+""
						+ "
"
						+Main.game.getPlayer().incrementMoney(-100));
			}
			Main.game.setContent(new Response("" ,"", CITY_HALL_NAME_CHANGE_FORM));
		}
	}

}