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

import java.util.ArrayList;
import java.util.List;

import com.lilithsthrone.game.character.GameCharacter;
import com.lilithsthrone.game.character.fetishes.Fetish;
import com.lilithsthrone.game.character.fetishes.FetishDesire;
import com.lilithsthrone.game.character.gender.Gender;
import com.lilithsthrone.game.character.npc.NPC;
import com.lilithsthrone.game.character.npc.dominion.Angel;
import com.lilithsthrone.game.character.npc.dominion.Bunny;
import com.lilithsthrone.game.character.npc.dominion.Loppy;
import com.lilithsthrone.game.character.npc.misc.GenericSexualPartner;
import com.lilithsthrone.game.character.persona.SexualOrientation;
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.ResponseEffectsOnly;
import com.lilithsthrone.game.dialogue.responses.ResponseSex;
import com.lilithsthrone.game.dialogue.responses.ResponseTag;
import com.lilithsthrone.game.dialogue.utils.UtilText;
import com.lilithsthrone.game.sex.Sex;
import com.lilithsthrone.game.sex.SexPace;
import com.lilithsthrone.game.sex.managers.universal.SMGeneric;
import com.lilithsthrone.main.Main;
import com.lilithsthrone.utils.Util;
import com.lilithsthrone.utils.Vector2i;
import com.lilithsthrone.world.Cell;
import com.lilithsthrone.world.Weather;
import com.lilithsthrone.world.WorldType;
import com.lilithsthrone.world.places.PlaceType;

/**
 * @since 0.2.2
 * @version 0.2.2
 * @author Innoxia
 */
public class RedLightDistrict {

	public static boolean isSpaceForMoreProstitutes() {
		Cell[][] grid = Main.game.getWorlds().get(WorldType.ANGELS_KISS_GROUND_FLOOR).getGrid();

		for(int i=0; i<grid.length; i++) {
			for(int j=0; j<grid[0].length; j++) {
				if(grid[i][j].getPlace().getPlaceType().equals(PlaceType.ANGELS_KISS_BEDROOM)
						&& Main.game.getCharactersPresent(WorldType.ANGELS_KISS_GROUND_FLOOR, new Vector2i(i, j)).isEmpty()) {
					return true;
				}
			}
		}

		return false;
	}

	public static final DialogueNode OUTSIDE = new DialogueNode("Red-light District", "Red-light District", false) {

		@Override
		public int getSecondsPassed() {
			return CityPlaces.TRAVEL_TIME_STREET;
		}

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

			UtilText.nodeContentSB.append(UtilText.parseFromXMLFile("places/dominion/redLightDistrict/redLightDistrict", "OUTSIDE"));

			if(Main.game.getCurrentWeather()==Weather.MAGIC_STORM) {
				UtilText.nodeContentSB.append(UtilText.parseFromXMLFile("places/dominion/redLightDistrict/redLightDistrict", "OUTSIDE_STORM"));
			} else {
				UtilText.nodeContentSB.append(UtilText.parseFromXMLFile("places/dominion/redLightDistrict/redLightDistrict", "OUTSIDE_NO_STORM"));
			}

			UtilText.nodeContentSB.append(UtilText.parseFromXMLFile("places/dominion/redLightDistrict/redLightDistrict", "OUTSIDE_FINAL"));

			return UtilText.nodeContentSB.toString();
		}

		@Override
		public Response getResponse(int responseTab, int index) {
			if (index == 1) {
				return new ResponseEffectsOnly("Angel's Kiss", "Step inside the large brothel named 'Angel's Kiss'."){
					@Override
					public void effects() {
						if(!Main.game.getDialogueFlags().hasFlag(DialogueFlagValue.angelIntroduced)) {
							Main.game.getNpc(Angel.class).setLocation(WorldType.ANGELS_KISS_GROUND_FLOOR, PlaceType.ANGELS_KISS_ENTRANCE, false);
						}
						Main.mainController.moveGameWorld(WorldType.ANGELS_KISS_GROUND_FLOOR, PlaceType.ANGELS_KISS_ENTRANCE, true);
					}
				};

			} else {
				return null;
			}
		}
	};

	public static final DialogueNode ANGELS_KISS_ENTRANCE = new DialogueNode("Entrance", ".", false) {

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

		@Override
		public boolean isTravelDisabled() {
			return !Main.game.getDialogueFlags().hasFlag(DialogueFlagValue.angelIntroduced);
		}

		@Override
		public String getContent() {
			if(!Main.game.getDialogueFlags().hasFlag(DialogueFlagValue.angelIntroduced)) {
				return UtilText.parseFromXMLFile("places/dominion/redLightDistrict/angelsKiss", "ENTRANCE");

			} else {
				UtilText.nodeContentSB.setLength(0);

				UtilText.nodeContentSB.append(UtilText.parseFromXMLFile("places/dominion/redLightDistrict/angelsKiss", "ENTRANCE_REPEAT"));

				List<NPC> charactersPresent = new ArrayList<>(Main.game.getCharactersPresent());
				charactersPresent.removeIf((npc) -> Main.game.getPlayer().getCompanions().contains(npc));

				if(charactersPresent.isEmpty()) {
					UtilText.nodeContentSB.append(UtilText.parseFromXMLFile("places/dominion/redLightDistrict/angelsKiss", "ENTRANCE_REPEAT_EMPTY"));
				}else {
					UtilText.nodeContentSB.append(UtilText.parse(charactersPresent.get(0), UtilText.parseFromXMLFile("places/dominion/redLightDistrict/angelsKiss", "ENTRANCE_REPEAT_STAFFED")));
				}

				return UtilText.nodeContentSB.toString();
			}
		}

		@Override
		public Response getResponse(int responseTab, int index) {
			if(!Main.game.getDialogueFlags().hasFlag(DialogueFlagValue.angelIntroduced)) {
				if (index == 1) {
					return new Response("Continue", "Angel leaves you alone to explore Angel's Kiss by yourself...", ANGELS_KISS_ENTRANCE){
						@Override
						public void effects() {
							Main.game.getNpc(Angel.class).setLocation(WorldType.ANGELS_KISS_GROUND_FLOOR, PlaceType.ANGELS_KISS_OFFICE, false);
							Main.game.getDialogueFlags().setFlag(DialogueFlagValue.angelIntroduced, true);
						}
					};
				} else {
					return null;
				}

			} else {
				if (index == 1) {
					return new ResponseEffectsOnly("Exit", "Exit the brothel and head back out into Dominion."){
						@Override
						public void effects() {
							Main.mainController.moveGameWorld(WorldType.DOMINION, PlaceType.DOMINION_RED_LIGHT_DISTRICT, true);
						}
					};
				} else {
					return null;
				}
			}
		}
	};

	public static final DialogueNode ANGELS_KISS_CORRIDOR = new DialogueNode("Corridor", ".", false) {

		@Override
		public int getSecondsPassed() {
			return 20;
		}

		@Override
		public String getContent() {
			return UtilText.parseFromXMLFile("places/dominion/redLightDistrict/angelsKiss", "CORRIDOR");
		}

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

	public static final DialogueNode ANGELS_KISS_STAIRS_UP = new DialogueNode("Staircase Up", ".", false) {

		@Override
		public int getSecondsPassed() {
			return 20;
		}

		@Override
		public String getContent() {
			return UtilText.parseFromXMLFile("places/dominion/redLightDistrict/angelsKiss", "STAIRS_UP");
		}

		@Override
		public Response getResponse(int responseTab, int index) {
			if (index == 1) {
				return new ResponseEffectsOnly("Upstairs", "Go up the staircase to the first floor of the brothel."){
					@Override
					public void effects() {
						Main.mainController.moveGameWorld(WorldType.ANGELS_KISS_FIRST_FLOOR, PlaceType.ANGELS_KISS_STAIRCASE_DOWN, true);
					}
				};

			} else {
				return null;
			}
		}
	};

	public static final DialogueNode ANGELS_KISS_STAIRS_DOWN = new DialogueNode("Staircase Down", ".", false) {

		@Override
		public int getSecondsPassed() {
			return 20;
		}

		@Override
		public String getContent() {
			return UtilText.parseFromXMLFile("places/dominion/redLightDistrict/angelsKiss", "STAIRS_DOWN");
		}

		@Override
		public Response getResponse(int responseTab, int index) {
			if (index == 1) {
				return new ResponseEffectsOnly("Downstairs", "Go down the staircase to the ground floor of the brothel."){
					@Override
					public void effects() {
						Main.mainController.moveGameWorld(WorldType.ANGELS_KISS_GROUND_FLOOR, PlaceType.ANGELS_KISS_STAIRCASE_UP, true);
					}
				};

			} else {
				return null;
			}
		}
	};

	public static final DialogueNode ANGELS_KISS_BEDROOM = new DialogueNode("Bedroom", ".", false) {

		@Override
		public int getSecondsPassed() {
			return 20;
		}

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

			UtilText.nodeContentSB.append(UtilText.parseFromXMLFile("places/dominion/redLightDistrict/angelsKiss", "BEDROOM"));

			List<NPC> charactersPresent = Main.game.getCharactersPresent();
			charactersPresent.removeIf((npc) -> Main.game.getPlayer().getCompanions().contains(npc));

			if(charactersPresent.size()>1){
				NPC prostitute = charactersPresent.get(0);
				NPC client = charactersPresent.get(1);
				for(NPC npc : charactersPresent) {
					if(npc instanceof GenericSexualPartner) {
						client = npc;
					} else {
						prostitute = npc;
						Main.game.setActiveNPC(npc);
					}
				}

				if(prostitute.isSlave() && prostitute.getOwner().isPlayer()) {
					//TODO append description of sex type
//					SlaveryEventLogEntry currentSex = null;
//					long time = 0;
//					for(SlaveryEventLogEntry entry : Main.game.getSlaveryEventLog().get(Main.game.getDayNumber())) {
//						if(entry.getSlaveID().equals(prostitute.getId()) && entry.getTime()>time) {
//							currentSex = entry;
//						}
//					}
//					System.out.println(currentSex.getTags().get(0));

					return UtilText.parseFromXMLFile("places/dominion/redLightDistrict/angelsKiss", "BEDROOM_OCCUPIED_SLAVE_SEX", Util.newArrayListOfValues(prostitute, client)); //TODO need obedience/affection variations

				} else {
					return UtilText.parseFromXMLFile("places/dominion/redLightDistrict/angelsKiss", "BEDROOM_OCCUPIED_SEX", Util.newArrayListOfValues(prostitute, client));
				}

			} else if(charactersPresent.isEmpty()) {
				if(Main.game.getDialogueFlags().hasFlag(DialogueFlagValue.prostitutionLicenseObtained)) {
					if(Main.game.getPlayer().getWorldLocation()==WorldType.ANGELS_KISS_GROUND_FLOOR) {
						UtilText.nodeContentSB.append(UtilText.parseFromXMLFile("places/dominion/redLightDistrict/angelsKiss", "BEDROOM_EMPTY_WHORE_SELF_GROUND_FLOOR"));
					} else {
						UtilText.nodeContentSB.append(UtilText.parseFromXMLFile("places/dominion/redLightDistrict/angelsKiss", "BEDROOM_EMPTY_WHORE_SELF"));
					}
				} else {
					UtilText.nodeContentSB.append(UtilText.parseFromXMLFile("places/dominion/redLightDistrict/angelsKiss", "BEDROOM_EMPTY"));
				}

			} else {
				Main.game.setActiveNPC(charactersPresent.get(0));
				if(charactersPresent.get(0).isSlave() && charactersPresent.get(0).getOwner().isPlayer()) {
					UtilText.nodeContentSB.append(UtilText.parseFromXMLFile("places/dominion/redLightDistrict/angelsKiss", "BEDROOM_OCCUPIED_SLAVE", Util.newArrayListOfValues(charactersPresent.get(0)))); //TODO need obedience/affection variations
				} else {
					UtilText.nodeContentSB.append(UtilText.parseFromXMLFile("places/dominion/redLightDistrict/angelsKiss", "BEDROOM_OCCUPIED", Util.newArrayListOfValues(charactersPresent.get(0))));
				}
			}

			return UtilText.nodeContentSB.toString();
		}

		@Override
		public Response getResponse(int responseTab, int index) {
			List<NPC> charactersPresent = Main.game.getCharactersPresent();
			charactersPresent.removeIf((npc) -> Main.game.getPlayer().getCompanions().contains(npc));

			if(!charactersPresent.isEmpty()) {
				int cost = 300;
				NPC npc = charactersPresent.get(0);

				if(charactersPresent.size()<=1){
					if(charactersPresent.get(0).isSlave() && charactersPresent.get(0).getOwner().isPlayer()) {
						if (index == 1) {
								return new ResponseSex("Sex",
										UtilText.parse(npc, "Have sex with [npc.name], with you as the dominant partner."),
										true, false,
										new SMGeneric(
												Util.newArrayListOfValues(Main.game.getPlayer()),
												Util.newArrayListOfValues(npc),
										null,
										null) {
											public SexPace getStartingSexPaceModifier(GameCharacter character) {
												if(!character.isPlayer()) {
													return SexPace.SUB_NORMAL;
												}
												return super.getStartingSexPaceModifier(character);
											}
										},
										AFTER_SEX_PROSTITUTE,
										UtilText.parseFromXMLFile("places/dominion/redLightDistrict/angelsKiss", "BEDROOM_PROSTITUTE_SLAVE_SEX"));

						} else if (index == 2) {
								return new ResponseSex("Submissive Sex",
										UtilText.parse(npc, "Let [npc.name] take charge, allowing you to have submissive sex with [npc.herHim]."),
										true, false,
										new SMGeneric(
												Util.newArrayListOfValues(npc),
												Util.newArrayListOfValues(Main.game.getPlayer()),
										null,
										null){
											public SexPace getStartingSexPaceModifier(GameCharacter character) {
												if(!character.isPlayer()) {
													return SexPace.DOM_NORMAL;
												}
												return super.getStartingSexPaceModifier(character);
											}
										},
										AFTER_SEX_PROSTITUTE,
										UtilText.parseFromXMLFile("places/dominion/redLightDistrict/angelsKiss", "BEDROOM_PROSTITUTE_SLAVE_SEX_SUB"));

						}

					} else {
						if (index == 1) {
							if(Main.game.getPlayer().getMoney()<cost) {
								return new Response("Sex ("+UtilText.formatAsMoney(cost, "span")+")",
										UtilText.parse(npc, "You don't have "+cost+" flames, so you can't afford to have sex with [npc.name]."), null);

							} else {
								return new ResponseSex("Sex ("+UtilText.formatAsMoney(cost, "span")+")",
										UtilText.parse(npc, "Pay "+cost+" flames to have sex with [npc.name], with you as the dominant partner."),
										true, false,
										new SMGeneric(
												Util.newArrayListOfValues(Main.game.getPlayer()),
												Util.newArrayListOfValues(npc),
										null,
										null){
											public SexPace getStartingSexPaceModifier(GameCharacter character) {
												if(!character.isPlayer()) {
													return SexPace.SUB_NORMAL;
												}
												return super.getStartingSexPaceModifier(character);
											}
										},
										AFTER_SEX_PROSTITUTE,
										UtilText.parseFromXMLFile("places/dominion/redLightDistrict/angelsKiss", "BEDROOM_PROSTITUTE_SEX")) {
									@Override
									public void effects() {
										Main.game.getPlayer().incrementMoney(-cost);
									}
								};
							}

						} else if (index == 2) {
							if(Main.game.getPlayer().getMoney()<cost) {
								return new Response("Submissive Sex ("+UtilText.formatAsMoney(cost, "span")+")",
										UtilText.parse(npc, "You don't have "+cost+" flames, so you can't afford to have submissive sex with [npc.name]."), null);

							} else {
								return new ResponseSex("Submissive Sex ("+UtilText.formatAsMoney(cost, "span")+")",
										UtilText.parse(npc, "Pay "+cost+" flames to let [npc.name] take charge, allowing you to have submissive sex with [npc.herHim]."),
										true, false,
										new SMGeneric(
												Util.newArrayListOfValues(npc),
												Util.newArrayListOfValues(Main.game.getPlayer()),
										null,
										null){
											public SexPace getStartingSexPaceModifier(GameCharacter character) {
												if(!character.isPlayer()) {
													return SexPace.DOM_NORMAL;
												}
												return super.getStartingSexPaceModifier(character);
											}
										},
										AFTER_SEX_PROSTITUTE,
										UtilText.parseFromXMLFile("places/dominion/redLightDistrict/angelsKiss", "BEDROOM_PROSTITUTE_SEX_SUB")) {
									@Override
									public void effects() {
										Main.game.getPlayer().incrementMoney(-cost);
									}
								};
							}

						}
					}
				}

			} else if(Main.game.getDialogueFlags().hasFlag(DialogueFlagValue.prostitutionLicenseObtained) && Main.game.getPlayer().getWorldLocation()==WorldType.ANGELS_KISS_FIRST_FLOOR) {
				if(index==1) {
					return new Response("Sell body (Sub)", "Tell Angel that you've like to act as the submissive partner, and then wait around for a client to show up.", ANGELS_KISS_SELL_SELF_SUB){
						@Override
						public void effects() {
							NPC npc = new GenericSexualPartner(Gender.getGenderFromUserPreferences(false, false), Main.game.getPlayer().getWorldLocation(), Main.game.getPlayer().getLocation(), false);
							if(Math.random()<0.4f) {
								npc.setSexualOrientation(SexualOrientation.AMBIPHILIC);
							} else {
								if(Main.game.getPlayer().isFeminine()) {
									npc.setSexualOrientation(SexualOrientation.GYNEPHILIC);
								} else {
									npc.setSexualOrientation(SexualOrientation.ANDROPHILIC);
								}
							}
							npc.removeFetish(Fetish.FETISH_SUBMISSIVE);
							npc.setFetishDesire(Fetish.FETISH_DOMINANT, FetishDesire.THREE_LIKE);
							try {
								Main.game.addNPC(npc, false);
								Main.game.setActiveNPC(npc);
							} catch (Exception e) {
								e.printStackTrace();
							}
						}
					};

				} else if(index==2) {
					return new Response("Sell body (Dom)", "Tell Angel that you've like to act as the dominant partner, and then wait around for a client to show up.", ANGELS_KISS_SELL_SELF_DOM){
						@Override
						public void effects() {
							NPC npc = new GenericSexualPartner(Gender.getGenderFromUserPreferences(false, false), Main.game.getPlayer().getWorldLocation(), Main.game.getPlayer().getLocation(), false);
							if(Math.random()<0.4f) {
								npc.setSexualOrientation(SexualOrientation.AMBIPHILIC);
							} else {
								if(Main.game.getPlayer().isFeminine()) {
									npc.setSexualOrientation(SexualOrientation.GYNEPHILIC);
								} else {
									npc.setSexualOrientation(SexualOrientation.ANDROPHILIC);
								}
							}
							npc.removeFetish(Fetish.FETISH_DOMINANT);
							npc.setFetishDesire(Fetish.FETISH_SUBMISSIVE, FetishDesire.THREE_LIKE);
							try {
								Main.game.addNPC(npc, false);
								Main.game.setActiveNPC(npc);
							} catch (Exception e) {
								e.printStackTrace();
							}
						}
					};
				}
			}
			return null;
		}
	};

	public static final DialogueNode AFTER_SEX_PROSTITUTE = new DialogueNode("Bedroom", "Disentangle yourself from [npc.namePos] clutches.", false) {

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

		@Override
		public String getContent() {
			List<NPC> charactersPresent = new ArrayList<>(Main.game.getCharactersPresent());
			charactersPresent.removeIf((npc) -> Main.game.getPlayer().getCompanions().contains(npc));

			if(Sex.getNumberOfOrgasms(charactersPresent.get(0))==0) {
				return UtilText.parseFromXMLFile("places/dominion/redLightDistrict/angelsKiss", "PROSTITUTE_AFTER_SEX_NO_ORGASM");
			} else {
				return UtilText.parseFromXMLFile("places/dominion/redLightDistrict/angelsKiss", "PROSTITUTE_AFTER_SEX");
			}
		}

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

	public static final DialogueNode ANGELS_KISS_SELL_SELF_SUB = new DialogueNode("Bedroom", ".", true) {

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

		@Override
		public String getContent() {
			return UtilText.parseFromXMLFile("places/dominion/redLightDistrict/angelsKiss", "SELL_SELF_SUB");
		}

		@Override
		public Response getResponse(int responseTab, int index) {
			int payment = 2000;

			if (index == 1) {
				return new ResponseSex("Sex ("+UtilText.formatAsMoney(2000, "span")+")",
						"Accept the price of "+2000+" flames to have sex with [npc.name].",
						true, false,
						new SMGeneric(
								Util.newArrayListOfValues(Main.game.getActiveNPC()),
								Util.newArrayListOfValues(Main.game.getPlayer()),
						null,
						null),
						AFTER_SEX_SELL_SELF_SUB,
						UtilText.parseFromXMLFile("places/dominion/redLightDistrict/angelsKiss", "SELL_SELF_SUB_START")) {
					@Override
					public void effects() {
						Main.game.getPlayer().incrementMoney(payment);
					}
				};

			} else if(index == 2) {
				return new Response("Decline", "Tell [npc.name] that you're not interested in what [npc.she] has in mind...", ANGELS_KISS_SELL_SELF_DECLINE){
					@Override
					public void effects() {
						Main.game.getTextStartStringBuilder().append(
								UtilText.parseFromXMLFile("places/dominion/redLightDistrict/angelsKiss", "SELL_SELF_DECLINE")
								+UtilText.parseFromXMLFile("places/dominion/redLightDistrict/angelsKiss", "SELL_SELF_DECLINE_SUB"));
						Main.game.banishNPC(Main.game.getActiveNPC());
					}
				};

			} else {
				return null;
			}
		}
	};

	public static final DialogueNode ANGELS_KISS_SELL_SELF_DOM = new DialogueNode("Bedroom", ".", true) {

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

		@Override
		public String getContent() {
			return UtilText.parseFromXMLFile("places/dominion/redLightDistrict/angelsKiss", "SELL_SELF_DOM");
		}

		@Override
		public Response getResponse(int responseTab, int index) {
			int payment = 2000;

			if (index == 1) {
				return new ResponseSex("Sex ("+UtilText.formatAsMoney(2000, "span")+")",
						"Accept the price of "+2000+" flames to have sex with [npc.name].",
						true, false,
						new SMGeneric(
								Util.newArrayListOfValues(Main.game.getPlayer()),
								Util.newArrayListOfValues(Main.game.getActiveNPC()),
						null,
						null), AFTER_SEX_SELL_SELF_DOM, UtilText.parseFromXMLFile("places/dominion/redLightDistrict/angelsKiss", "SELL_SELF_DOM_START")) {
					@Override
					public void effects() {
						Main.game.getPlayer().incrementMoney(payment);
					}
				};

			} else if(index == 2) {
				return new Response("Decline", "Tell [npc.name] that you're not interested in what [npc.she] has in mind...", ANGELS_KISS_SELL_SELF_DECLINE){
					@Override
					public void effects() {
						Main.game.getTextStartStringBuilder().append(
								UtilText.parseFromXMLFile("places/dominion/redLightDistrict/angelsKiss", "SELL_SELF_DECLINE")
								+UtilText.parseFromXMLFile("places/dominion/redLightDistrict/angelsKiss", "SELL_SELF_DECLINE_DOM"));
						Main.game.banishNPC(Main.game.getActiveNPC());
					}
				};

			} else {
				return null;
			}
		}
	};

	public static final DialogueNode ANGELS_KISS_SELL_SELF_DECLINE = new DialogueNode("Bedroom", ".", false, true) {

		@Override
		public int getSecondsPassed() {
			return 20;
		}

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

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

	public static final DialogueNode AFTER_SEX_SELL_SELF_DOM = new DialogueNode("Bedroom", "Disentangle yourself from [npc.namePos] clutches.", true) {

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

		@Override
		public String getContent() {
			return UtilText.parseFromXMLFile("places/dominion/redLightDistrict/angelsKiss", "SELL_SELF_DOM_AFTER_SEX");
		}

		@Override
		public Response getResponse(int responseTab, int index) {
			if (index == 1) {
				return new Response("Recover", "Recover from the exhausting sex you've just had.", ANGELS_KISS_BEDROOM){
					@Override
					public void effects() {
						Main.game.banishNPC(Main.game.getActiveNPC());
					}
				};

			} else {
				return null;
			}
		}
	};

	public static final DialogueNode AFTER_SEX_SELL_SELF_SUB = new DialogueNode("Bedroom", "Disentangle yourself from [npc.namePos] clutches.", true) {

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

		@Override
		public String getContent() {
			return UtilText.parseFromXMLFile("places/dominion/redLightDistrict/angelsKiss", "SELL_SELF_SUB_AFTER_SEX");
		}

		@Override
		public Response getResponse(int responseTab, int index) {
			if (index == 1) {
				return new Response("Recover", "Recover from the exhausting sex you've just had.", ANGELS_KISS_BEDROOM){
					@Override
					public void effects() {
						Main.game.banishNPC(Main.game.getActiveNPC());
					}
				};

			} else {
				return null;
			}
		}
	};

	public static final DialogueNode ANGELS_KISS_BEDROOM_BUNNY = new DialogueNode("Bunny's Bedroom", ".", false) {

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

		@Override
		public boolean isTravelDisabled() {
			return !Main.game.getDialogueFlags().hasFlag(DialogueFlagValue.bunnyIntroduced);
		}

		@Override
		public String getContent() {
			if(!Main.game.getDialogueFlags().hasFlag(DialogueFlagValue.bunnyIntroduced)) {
				return UtilText.parseFromXMLFile("places/dominion/redLightDistrict/angelsKiss", "BEDROOM_BUNNY");
			} else {
				return UtilText.parseFromXMLFile("places/dominion/redLightDistrict/angelsKiss", "BEDROOM_BUNNY_REPEAT");
			}
		}

		@Override
		public Response getResponse(int responseTab, int index) {
			int cost = 1500;
			int threesomeCost = 5000;

			if (index == 1) {
				if(Main.game.getPlayer().getMoney()<cost) {
					return new Response("Sex ("+UtilText.formatAsMoney(cost, "span")+")", "You don't have "+cost+" flames, so you can't afford to have sex with Bunny.", null);

				} else {
					return new ResponseSex("Sex ("+UtilText.formatAsMoney(cost, "span")+")",
							"Pay "+cost+" flames to have sex with Bunny.",
							true, false,
							new SMGeneric(
									Util.newArrayListOfValues(Main.game.getPlayer()),
									Util.newArrayListOfValues(Main.game.getNpc(Bunny.class)),
							null,
							null), AFTER_SEX_BUNNY, UtilText.parseFromXMLFile("places/dominion/redLightDistrict/angelsKiss", "BEDROOM_BUNNY_SEX")) {
						@Override
						public void effects() {
							Main.game.getDialogueFlags().setFlag(DialogueFlagValue.bunnyIntroduced, true);
							Main.game.getPlayer().incrementMoney(-cost);
						}
					};
				}

			} else if (index == 2) {
				if(Main.game.getPlayer().getMoney()<threesomeCost) {
					return new Response("Threesome ("+UtilText.formatAsMoney(threesomeCost, "span")+")", "You don't have "+threesomeCost+" flames, so you can't afford to have sex with both Bunny and Loppy at the same time.", null);

				} else {
					return new ResponseSex("Threesome ("+UtilText.formatAsMoney(threesomeCost, "span")+")",
							"Pay "+threesomeCost+" flames to have sex with both Bunny and Loppy at the same time.",
							true, false,
							new SMGeneric(
									Util.newArrayListOfValues(Main.game.getPlayer()),
									Util.newArrayListOfValues(Main.game.getNpc(Bunny.class), Main.game.getNpc(Loppy.class)),
									null,
									null,
									ResponseTag.PREFER_DOGGY),
							AFTER_SEX_BUNNY_THREESOME,
							UtilText.parseFromXMLFile("places/dominion/redLightDistrict/angelsKiss", "BEDROOM_BUNNY_THREESOME")
							+(Main.game.getDialogueFlags().hasFlag(DialogueFlagValue.loppyIntroduced)
									?UtilText.parseFromXMLFile("places/dominion/redLightDistrict/angelsKiss", "BEDROOM_BUNNY_THREESOME_LOPPY_INTRODUCED")
									:UtilText.parseFromXMLFile("places/dominion/redLightDistrict/angelsKiss", "BEDROOM_BUNNY_THREESOME_LOPPY_NOT_INTRODUCED"))) {
						@Override
						public void effects() {
							Main.game.getDialogueFlags().setFlag(DialogueFlagValue.bunnyIntroduced, true);
//							Main.game.getDialogueFlags().setFlag(DialogueFlagValue.loppyIntroduced, true);
							Main.game.getNpc(Loppy.class).setLocation(WorldType.ANGELS_KISS_FIRST_FLOOR, PlaceType.ANGELS_KISS_BEDROOM_BUNNY, false);
							Main.game.getPlayer().incrementMoney(-threesomeCost);
						}
					};
				}

			} else if (!Main.game.getDialogueFlags().hasFlag(DialogueFlagValue.bunnyIntroduced) && index == 3) {
				return new Response("Decline", "You're not really interested in paying for sex with Bunny right now...", ANGELS_KISS_BEDROOM_BUNNY){
					@Override
					public void effects() {
						Main.game.getDialogueFlags().setFlag(DialogueFlagValue.bunnyIntroduced, true);
						Main.game.getTextEndStringBuilder().append(UtilText.parseFromXMLFile("places/dominion/redLightDistrict/angelsKiss", "BEDROOM_BUNNY_DECLINE"));
					}
				};

			} else {
				return null;
			}
		}
	};

	public static final DialogueNode AFTER_SEX_BUNNY = new DialogueNode("Bunny's Bedroom", "Disentangle yourself from Bunny's clutches.", false) {

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

		@Override
		public String getContent() {
			if(Sex.getNumberOfOrgasms(Main.game.getNpc(Bunny.class)) == 0) {
				return UtilText.parseFromXMLFile("places/dominion/redLightDistrict/angelsKiss", "BEDROOM_BUNNY_AFTER_SEX_NO_ORGASM");
			} else {
				return UtilText.parseFromXMLFile("places/dominion/redLightDistrict/angelsKiss", "BEDROOM_BUNNY_AFTER_SEX");
			}
		}

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

	public static final DialogueNode AFTER_SEX_BUNNY_THREESOME = new DialogueNode("Bunny's Bedroom", "Disentangle yourself from Bunny's clutches.", false) {

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

		@Override
		public String getContent() {
			return UtilText.parseFromXMLFile("places/dominion/redLightDistrict/angelsKiss", "BEDROOM_BUNNY_AFTER_THREESOME");
		}

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

	public static final DialogueNode ANGELS_KISS_BEDROOM_LOPPY = new DialogueNode("Loppy's Bedroom", ".", false) {

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

		@Override
		public boolean isTravelDisabled() {
			return !Main.game.getDialogueFlags().hasFlag(DialogueFlagValue.loppyIntroduced);
		}

		@Override
		public String getContent() {
			if(!Main.game.getDialogueFlags().hasFlag(DialogueFlagValue.loppyIntroduced)) {
				return UtilText.parseFromXMLFile("places/dominion/redLightDistrict/angelsKiss", "BEDROOM_LOPPY");
			} else {
				return UtilText.parseFromXMLFile("places/dominion/redLightDistrict/angelsKiss", "BEDROOM_LOPPY_REPEAT");
			}
		}

		@Override
		public Response getResponse(int responseTab, int index) {
			int cost = 2000;
			int dominantCost = 2500;
			int threesomeCost = 5000;

			if (index == 1) {
				if(Main.game.getPlayer().getMoney()<cost) {
					return new Response("Sex ("+UtilText.formatAsMoney(cost, "span")+")", "You don't have "+cost+" flames, so you can't afford to have sex with Loppy.", null);

				} else {
					return new ResponseSex("Sex ("+UtilText.formatAsMoney(cost, "span")+")",
							"Pay "+cost+" flames to have sex with Loppy.",
							true, false,
							new SMGeneric(
									Util.newArrayListOfValues(Main.game.getPlayer()),
									Util.newArrayListOfValues(Main.game.getNpc(Loppy.class)),
							null,
							null), AFTER_SEX_LOPPY, UtilText.parseFromXMLFile("places/dominion/redLightDistrict/angelsKiss", "BEDROOM_LOPPY_SEX")) {
						@Override
						public void effects() {
							Main.game.getDialogueFlags().setFlag(DialogueFlagValue.loppyIntroduced, true);
							Main.game.getPlayer().incrementMoney(-cost);
						}
					};
				}

			} else if (index == 2) {
				if(Main.game.getPlayer().getMoney()<dominantCost) {
					return new Response("Submissive Sex ("+UtilText.formatAsMoney(dominantCost, "span")+")", "You don't have "+dominantCost+" flames, so you can't afford to have submissive sex with Loppy.", null);

				} else {
					return new ResponseSex("Submissive Sex ("+UtilText.formatAsMoney(dominantCost, "span")+")",
							"Pay "+dominantCost+" flames to let Loppy take charge and fuck you.",
							true, true,
							new SMGeneric(
									Util.newArrayListOfValues(Main.game.getNpc(Loppy.class)),
									Util.newArrayListOfValues(Main.game.getPlayer()),
							null,
							null), AFTER_SEX_LOPPY, UtilText.parseFromXMLFile("places/dominion/redLightDistrict/angelsKiss", "BEDROOM_LOPPY_SEX_SUBMISSIVE")) {
						@Override
						public void effects() {
							Main.game.getDialogueFlags().setFlag(DialogueFlagValue.loppyIntroduced, true);
							Main.game.getPlayer().incrementMoney(-dominantCost);
						}
					};
				}

			} else if (index == 3) {
				if(Main.game.getPlayer().getMoney()<threesomeCost) {
					return new Response("Threesome ("+UtilText.formatAsMoney(threesomeCost, "span")+")", "You don't have "+threesomeCost+" flames, so you can't afford to have sex with both Loppy and Bunny at the same time.", null);

				} else {
					return new ResponseSex("Threesome ("+UtilText.formatAsMoney(threesomeCost, "span")+")",
							"Pay "+threesomeCost+" flames to have sex with both Loppy and Bunny at the same time.",
							true, false,
							new SMGeneric(
									Util.newArrayListOfValues(Main.game.getPlayer()),
									Util.newArrayListOfValues(Main.game.getNpc(Loppy.class), Main.game.getNpc(Bunny.class)),
									null,
									null,
									ResponseTag.PREFER_DOGGY),
							AFTER_SEX_LOPPY_THREESOME,
							UtilText.parseFromXMLFile("places/dominion/redLightDistrict/angelsKiss", "BEDROOM_LOPPY_THREESOME")
							+(Main.game.getDialogueFlags().hasFlag(DialogueFlagValue.bunnyIntroduced)
									?UtilText.parseFromXMLFile("places/dominion/redLightDistrict/angelsKiss", "BEDROOM_LOPPY_THREESOME_BUNNY_INTRODUCED")
									:UtilText.parseFromXMLFile("places/dominion/redLightDistrict/angelsKiss", "BEDROOM_LOPPY_THREESOME_BUNNY_NOT_INTRODUCED"))) {
						@Override
						public void effects() {
//							Main.game.getDialogueFlags().setFlag(DialogueFlagValue.bunnyIntroduced, true);
							Main.game.getDialogueFlags().setFlag(DialogueFlagValue.loppyIntroduced, true);
							Main.game.getNpc(Bunny.class).setLocation(WorldType.ANGELS_KISS_FIRST_FLOOR, PlaceType.ANGELS_KISS_BEDROOM_LOPPY, false);
							Main.game.getPlayer().incrementMoney(-threesomeCost);
						}
					};
				}

			} else if (!Main.game.getDialogueFlags().hasFlag(DialogueFlagValue.loppyIntroduced) && index == 4) {
				return new Response("Decline", "You're not really interested in paying for sex with Loppy right now...", ANGELS_KISS_BEDROOM_LOPPY){
					@Override
					public void effects() {
						Main.game.getDialogueFlags().setFlag(DialogueFlagValue.loppyIntroduced, true);
						Main.game.getTextEndStringBuilder().append(UtilText.parseFromXMLFile("places/dominion/redLightDistrict/angelsKiss", "BEDROOM_LOPPY_DECLINE"));
					}
				};

			} else {
				return null;
			}
		}
	};

	public static final DialogueNode AFTER_SEX_LOPPY = new DialogueNode("Loppy's Bedroom", "Disentangle yourself from Loppy's clutches.", false) {

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

		@Override
		public String getContent() {
			if(Sex.getNumberOfOrgasms(Main.game.getNpc(Loppy.class)) == 0) {
				return UtilText.parseFromXMLFile("places/dominion/redLightDistrict/angelsKiss", "BEDROOM_LOPPY_AFTER_SEX_NO_ORGASM");
			} else {
				return UtilText.parseFromXMLFile("places/dominion/redLightDistrict/angelsKiss", "BEDROOM_LOPPY_AFTER_SEX");
			}
		}

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

	public static final DialogueNode AFTER_SEX_LOPPY_THREESOME = new DialogueNode("Loppy's Bedroom", "Disentangle yourself from Loppy's clutches.", false) {

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

		@Override
		public String getContent() {
			return UtilText.parseFromXMLFile("places/dominion/redLightDistrict/angelsKiss", "BEDROOM_LOPPY_AFTER_THREESOME");
		}

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

	public static final DialogueNode ANGELS_KISS_OFFICE = new DialogueNode("Angel's Office", ".", false) {

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

		@Override
		public boolean isTravelDisabled() {
			return !Main.game.getDialogueFlags().hasFlag(DialogueFlagValue.angelsOfficeIntroduced);
		}

		@Override
		public String getContent() {
			if(!Main.game.getDialogueFlags().hasFlag(DialogueFlagValue.angelsOfficeIntroduced)) {
				return UtilText.parseFromXMLFile("places/dominion/redLightDistrict/angelsKiss", "OFFICE");
			} else {
				if(!Main.game.getDialogueFlags().hasFlag(DialogueFlagValue.prostitutionLicenseObtained)) {
					return UtilText.parseFromXMLFile("places/dominion/redLightDistrict/angelsKiss", "OFFICE_REPEAT");
				} else {
					return UtilText.parseFromXMLFile("places/dominion/redLightDistrict/angelsKiss", "OFFICE_REPEAT_WITH_LICENSE");
				}
			}
		}

		@Override
		public Response getResponse(int responseTab, int index) {
			if(!Main.game.getDialogueFlags().hasFlag(DialogueFlagValue.angelsOfficeIntroduced)) {
				if (index == 1) {
					return new Response("Continue", "Now that Angel's offered you her deal, you could ask some other questions...", ANGELS_KISS_OFFICE_CONTINUE) {
						@Override
						public void effects() {
							Main.game.getDialogueFlags().setFlag(DialogueFlagValue.angelsOfficeIntroduced, true);
							Main.game.updateResponses();
						}
					};

				} else {
					return null;
				}

			} else {
				if (index == 1) {
					return new Response("Prostitution", "Ask Angel about the laws and regulations regarding prostitution in Dominion.", ANGELS_KISS_OFFICE_PROSTITUTION);

				} else if (index == 2) {
					return new Response("Background", "Ask Angel about her background, and how she ended up owning Angel's Kiss.", ANGELS_KISS_OFFICE_BACKGROUND);

				} else if (index == 3 && !Main.game.getDialogueFlags().hasFlag(DialogueFlagValue.prostitutionLicenseObtained)) {
					if(Main.game.getPlayer().getMoney()<5000) {
						return new Response("License ("+UtilText.formatAsMoney(5000, "span")+")", "You don't have enough money to purchase a prostitution license!", null);
					} else {
						return new Response("License ("+UtilText.formatAsMoney(5000, "span")+")", "Agree to Angel's deal and purchase a prostitution license.", ANGELS_KISS_OFFICE_LICENSE_PURCHASE) {
							@Override
							public void effects() {
								Main.game.getDialogueFlags().setFlag(DialogueFlagValue.prostitutionLicenseObtained, true);
								Main.game.getPlayer().incrementMoney(-5000);
							}
						};
					}

				} else {
					return null;
				}
			}
		}
	};

	public static final DialogueNode ANGELS_KISS_OFFICE_CONTINUE = new DialogueNode("Angel's Office", ".", false, true) {

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

		@Override
		public String getContent() {
			return UtilText.parseFromXMLFile("places/dominion/redLightDistrict/angelsKiss", "OFFICE_CONTINUE");
		}

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

	public static final DialogueNode ANGELS_KISS_OFFICE_PROSTITUTION = new DialogueNode("Angel's Office", ".", false) {

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

		@Override
		public String getContent() {
			return UtilText.parseFromXMLFile("places/dominion/redLightDistrict/angelsKiss", "OFFICE_PROSTITUTION");
		}

		@Override
		public Response getResponse(int responseTab, int index) {
			if (index == 1) {
				return new Response("Prostitution", "You are already talking to Angel about prostitution.", null);

			} else {
				return ANGELS_KISS_OFFICE.getResponse(responseTab, index);
			}
		}
	};

	public static final DialogueNode ANGELS_KISS_OFFICE_BACKGROUND = new DialogueNode("Angel's Office", ".", false) {

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

		@Override
		public String getContent() {
			return UtilText.parseFromXMLFile("places/dominion/redLightDistrict/angelsKiss", "OFFICE_BACKGROUND");
		}

		@Override
		public Response getResponse(int responseTab, int index) {
			if (index == 2) {
				return new Response("Background", "You are already talking to Angel about her background.", null);

			} else {
				return ANGELS_KISS_OFFICE.getResponse(responseTab, index);
			}
		}
	};

	public static final DialogueNode ANGELS_KISS_OFFICE_LICENSE_PURCHASE = new DialogueNode("Angel's Office", ".", false) {

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

		@Override
		public String getContent() {
			return UtilText.parseFromXMLFile("places/dominion/redLightDistrict/angelsKiss", "OFFICE_LICENSE_PURCHASE");
		}

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

}


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

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

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

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

		@Override
		public int getSecondsPassed() {
			return CityPlaces.TRAVEL_TIME_STREET;
		}

		@Override
		public String getContent() {
			return UtilText.parseFromXMLFile("places/dominion/cityHall/generic", "OUTSIDE");
		}

		@Override
		public Response getResponse(int responseTab, int index) {
			if (index == 1) {
				if(Main.game.getHourOfDay()>=9 && Main.game.getHourOfDay()<=16) {
					return new Response("Enter", "Dominion's city hall is currently open to the public, so you could head inside if you wanted to.", CITY_HALL_FOYER) {
						@Override
						public void effects() {
							Main.mainController.moveGameWorld(WorldType.CITY_HALL, PlaceType.CITY_HALL_ENTRANCE, true);

							Main.game.getTextStartStringBuilder().append(UtilText.parseFromXMLFile("places/dominion/cityHall/generic", "ENTRY"));
						}
					};

				} else {
					return new Response("Enter", "Dominion's city hall is currently closed to the public, so if you had any business to conduct, you'll have to return between the hours of nine in the morning, and four in the afternoon.", null);
				}

			} else {
				return null;
			}
		}
	};

	public static final DialogueNode CITY_HALL_FOYER = new DialogueNode("Foyer", "-", false) {

		@Override
		public int getSecondsPassed() {
			return 30;
		}

		@Override
		public String getContent() {
			return UtilText.parseFromXMLFile("places/dominion/cityHall/generic", "CITY_HALL_FOYER");
		}

		@Override
		public Response getResponse(int responseTab, int index) {
			if (index == 1) {
				return new Response("Exit", "Head out through the revolving glass doors back into Dominion.", OUTSIDE) {
					@Override
					public void effects() {
						Main.mainController.moveGameWorld(WorldType.DOMINION, PlaceType.DOMINION_CITY_HALL, true);
					}
				};

			} else {
				return null;
			}
		}
	};

	public static final DialogueNode CITY_HALL_INFORMATION_DESK = new DialogueNode("Information Desk", "-", false) {

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

		@Override
		public String getContent() {
			return UtilText.parseFromXMLFile("places/dominion/cityHall/generic", "CITY_HALL_INFORMATION_DESK");
		}

		@Override
		public Response getResponse(int responseTab, int index) {
			if(index == 1) {
				return new Response("Name change", "Ask one of the receptionists about changing your name.", CITY_HALL_INFORMATION_DESK_NAME_CHANGE);

			} else if(index == 2) {
				return new Response("Property", "Ask one of the receptionists about buying or renting property in Dominion.", CITY_HALL_INFORMATION_DESK_PROPERTY);

			} else {
				return null;
			}
		}
	};

	public static final DialogueNode CITY_HALL_INFORMATION_DESK_NAME_CHANGE = new DialogueNode("Information Desk", "-", false) {

		@Override
		public int getSecondsPassed() {
			return 30;
		}

		@Override
		public String getContent() {
			return UtilText.parseFromXMLFile("places/dominion/cityHall/generic", "CITY_HALL_INFORMATION_DESK_NAME_CHANGE");
		}

		@Override
		public Response getResponse(int responseTab, int index) {
			if(index == 1) {
				return new Response("Name change", "You've just asked about changing your name.", null);

			} else if(index == 2) {
				return new Response("Property", "Ask one of the receptionists about buying or renting property in Dominion.", CITY_HALL_INFORMATION_DESK_PROPERTY);

			} else {
				return null;
			}
		}
	};

	public static final DialogueNode CITY_HALL_INFORMATION_DESK_PROPERTY = new DialogueNode("Information Desk", "-", false) {

		@Override
		public int getSecondsPassed() {
			return 30;
		}

		@Override
		public String getContent() {
			return UtilText.parseFromXMLFile("places/dominion/cityHall/generic", "CITY_HALL_INFORMATION_DESK_PROPERTY");
		}

		@Override
		public Response getResponse(int responseTab, int index) {
			if(index == 1) {
				return new Response("Name change", "Ask one of the receptionists about changing your name.", CITY_HALL_INFORMATION_DESK_NAME_CHANGE);

			} else if(index == 2) {
				return new Response("Property", "You've just asked about buying or renting property in Dominion.", null);

			} else {
				return null;
			}
		}
	};

	public static final DialogueNode CITY_HALL_CORRIDOR = new DialogueNode("Corridor", "-", false) {

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

		@Override
		public String getContent() {
			return UtilText.parseFromXMLFile("places/dominion/cityHall/generic", "CITY_HALL_CORRIDOR");
		}

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

	public static final DialogueNode CITY_HALL_WAITING_AREA = new DialogueNode("Waiting Room", "-", false) {

		@Override
		public int getSecondsPassed() {
			return 30;
		}

		@Override
		public String getContent() {
			return UtilText.parseFromXMLFile("places/dominion/cityHall/generic", "CITY_HALL_WAITING_AREA");
		}

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

	public static final DialogueNode CITY_HALL_OFFICE = new DialogueNode("Private Office", "-", false) {

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

		@Override
		public String getContent() {
			return UtilText.parseFromXMLFile("places/dominion/cityHall/generic", "CITY_HALL_OFFICE");
		}

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

	public static final DialogueNode CITY_HALL_STAIRS = new DialogueNode("Staircase", "-", false) {

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

		@Override
		public String getContent() {
			return UtilText.parseFromXMLFile("places/dominion/cityHall/generic", "CITY_HALL_STAIRS");
		}

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

}

repo_name: klorpa/Pedo

license: unknown


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

import java.util.List;

import com.lilithsthrone.game.character.GameCharacter;
import com.lilithsthrone.game.character.body.CoverableArea;
import com.lilithsthrone.game.character.npc.NPC;
import com.lilithsthrone.game.character.npc.dominion.Vanessa;
import com.lilithsthrone.game.character.persona.NameTriplet;
import com.lilithsthrone.game.character.persona.Relationship;
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.ResponseEffectsOnly;
import com.lilithsthrone.game.dialogue.responses.ResponseSex;
import com.lilithsthrone.game.dialogue.utils.UtilText;
import com.lilithsthrone.game.inventory.InventorySlot;
import com.lilithsthrone.game.inventory.item.AbstractItemType;
import com.lilithsthrone.game.inventory.item.ItemType;
import com.lilithsthrone.game.sex.InitialSexActionInformation;
import com.lilithsthrone.game.sex.Sex;
import com.lilithsthrone.game.sex.managers.dominion.vanessa.SMVanessaOral;
import com.lilithsthrone.game.sex.managers.dominion.vanessa.SMVanessaSex;
import com.lilithsthrone.game.sex.positions.SexPosition;
import com.lilithsthrone.game.sex.positions.slots.SexSlotAllFours;
import com.lilithsthrone.game.sex.positions.slots.SexSlotDesk;
import com.lilithsthrone.game.sex.positions.slots.SexSlotSitting;
import com.lilithsthrone.game.sex.positions.slots.SexSlotStanding;
import com.lilithsthrone.game.sex.sexActions.baseActions.PenisVagina;
import com.lilithsthrone.game.sex.sexActions.baseActions.TongueVagina;
import com.lilithsthrone.main.Main;
import com.lilithsthrone.utils.Colour;
import com.lilithsthrone.utils.Util;
import com.lilithsthrone.utils.Util.Value;
import com.lilithsthrone.world.WorldType;
import com.lilithsthrone.world.places.PlaceType;

/**
 * @since 0.3.2
 * @version 0.3.2
 * @author Innoxia
 */
public class CityHallDemographics {

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

		@Override
		public String getContent() {
			return UtilText.parseFromXMLFile("places/dominion/cityHall/demographics", "CITY_HALL_DEMOGRAPHICS_ENTRANCE");
		}

		@Override
		public Response getResponse(int responseTab, int index) {
			if (index == 1) {
				return new Response("Ring bell",
						Main.game.getPlayer().hasCompanions()
							?UtilText.parse(Main.game.getPlayer().getMainCompanion(), "Tell [npc.name] to wait outside, before ringing the little bell on [vanessa.namePos] desk and waiting for her to appear.")
							:"Ring the little bell on [vanessa.namePos] desk and wait for her to appear.",
						CITY_HALL_DEMOGRAPHICS_MAIN) {
					@Override
					public void effects() {
						Main.game.getNpc(Vanessa.class).setLocation(WorldType.CITY_HALL, PlaceType.CITY_HALL_BUREAU_OF_DEMOGRAPHICS);
						Main.game.getTextStartStringBuilder().append(UtilText.parseFromXMLFile("places/dominion/cityHall/demographics", "CITY_HALL_DEMOGRAPHICS_RING_BELL"));
						Main.game.getDialogueFlags().setFlag(DialogueFlagValue.vanessaIntroduced, true);

						for(GameCharacter character : Main.game.getPlayer().getCompanions()) {
							character.setNearestLocation(WorldType.CITY_HALL, PlaceType.CITY_HALL_CORRIDOR, false);
						}
					}
				};

			} else if (index == 0) {
				return new Response("Leave", "Decide against bothering [vanessa.name], and head back out into the corridor.", CityHall.CITY_HALL_CORRIDOR) {
					@Override
					public void effects() {
						Main.game.getPlayer().setNearestLocation(WorldType.CITY_HALL, PlaceType.CITY_HALL_CORRIDOR, false);
						Main.game.getTextStartStringBuilder().append(UtilText.parseFromXMLFile("places/dominion/cityHall/demographics", "CITY_HALL_DEMOGRAPHICS_ENTRANCE_TURN_BACK"));
					}
				};

			} else {
				return null;
			}
		}
	};

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

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

		@Override
		public Response getResponse(int responseTab, int index) {
			if (index == 1) {
				return new Response("Name change", "Ask [vanessa.name] about getting your name changed.", NAME_CHANGE);

			} else if (index == 2) {
				if(Main.game.getPlayer().hasItemType(ItemType.OFFSPRING_MAP)) {
					return new Response("Offspring map", "You've already purchased an offspring map from [vanessa.name], and do not need another one.", null);

				} else {
					return new Response("Offspring map", "Ask [vanessa.name] about obtaining a map of where any offspring of yours live.", OFFSPRING_MAP);
				}

			} else if (index == 3) {
				if(Main.game.getDialogueFlags().hasFlag(DialogueFlagValue.vanessaDailyHelped)) {
					return new Response("Offer help", "You've already helped [vanessa.name] with her work today.", null);
				}
				return new Response("Offer help", "Ask [vanessa.name] if she needs any help.", OFFER_HELP) {
					@Override
					public void effects() {
						Main.game.getDialogueFlags().setFlag(DialogueFlagValue.vanessaDailyHelped, true);
						Main.game.getNpc(Vanessa.class).setLocation(WorldType.CITY_HALL, PlaceType.CITY_HALL_ARCHIVES);
						Main.game.getPlayer().setLocation(WorldType.CITY_HALL, PlaceType.CITY_HALL_ARCHIVES);

						for(GameCharacter character : Main.game.getPlayer().getCompanions()) {
							character.setNearestLocation(WorldType.CITY_HALL, PlaceType.CITY_HALL_CORRIDOR, false);
						}
					}
				};

			} else if (index == 4 && (Main.game.getDialogueFlags().hasFlag(DialogueFlagValue.vanessaDailyHelped) || Main.game.getDialogueFlags().hasFlag(DialogueFlagValue.vanessaMassaged))) {
				if(Main.game.getDialogueFlags().hasFlag(DialogueFlagValue.vanessaDailyMassage)) {
					return new Response("Foot massage", "You've already given [vanessa.name] a foot massage today. She won't want another one until tomorrow.", null);
				}

				return new Response("Foot massage", "Offer [vanessa.name] a foot massage.", FOOT_MASSAGE) {
					@Override
					public void effects() {
						Main.game.getDialogueFlags().setFlag(DialogueFlagValue.vanessaDailyMassage, true);

						try {
							Main.game.getNpc(Vanessa.class).unequipClothingIntoVoid(Main.game.getNpc(Vanessa.class).getClothingInSlot(InventorySlot.FOOT), true, Main.game.getNpc(Vanessa.class));
						} catch(Exception ex) { System.err.println("Vanessa is not wearing any shoes!"); }

						Main.game.getTextStartStringBuilder().append(UtilText.parseFromXMLFile("places/dominion/cityHall/demographics", "FOOT_MASSAGE"));
						Main.game.getTextStartStringBuilder().append(UtilText.parseFromXMLFile("places/dominion/cityHall/demographics", "FOOT_MASSAGE_CORE"));

						Main.game.getTextEndStringBuilder().append(Main.game.getNpc(Vanessa.class).incrementAffection(Main.game.getPlayer(), 5));
					}
				};

			} else if (index == 5
					&& Main.game.getDialogueFlags().hasFlag(DialogueFlagValue.vanessaDailyHelped)
					&& Main.game.getDialogueFlags().hasFlag(DialogueFlagValue.vanessaFucked)
					&& !Main.game.getDialogueFlags().hasFlag(DialogueFlagValue.vanessaDailyMassage)) {
				return new Response("Make her beg", "Get [vanessa.name] to beg you for a foot massage.", FOOT_MASSAGE) {
					@Override
					public void effects() {
						Main.game.getDialogueFlags().setFlag(DialogueFlagValue.vanessaDailyMassage, true);

						try {
							Main.game.getNpc(Vanessa.class).unequipClothingIntoVoid(Main.game.getNpc(Vanessa.class).getClothingInSlot(InventorySlot.FOOT), true, Main.game.getNpc(Vanessa.class));
						} catch(Exception ex) { System.err.println("Vanessa is not wearing any shoes!"); }

						Main.game.getTextStartStringBuilder().append(UtilText.parseFromXMLFile("places/dominion/cityHall/demographics", "FOOT_MASSAGE_BEG"));
						Main.game.getTextStartStringBuilder().append(UtilText.parseFromXMLFile("places/dominion/cityHall/demographics", "FOOT_MASSAGE_CORE"));

						Main.game.getTextEndStringBuilder().append(Main.game.getNpc(Vanessa.class).incrementAffection(Main.game.getPlayer(), 5));
					}
				};

			} else if (index == 6) {
				return new Response("Cataloguing", "Ask [vanessa.name] about what sort of cataloguing work she's responsible for.", QUESTION_CATALOGUING) {
					@Override
					public void effects() {
						Main.game.getTextStartStringBuilder().append(UtilText.parseFromXMLFile("places/dominion/cityHall/demographics", "QUESTION_CATALOGUING"));
						Main.game.getDialogueFlags().setFlag(DialogueFlagValue.vanessaAskedAboutCatalogue, true);
					}
				};

			} else if (index == 7) {
				return new Response("Solitary", "Ask [vanessa.name] why she's the only person working in this department.", QUESTION_SOLITARY) {
					@Override
					public void effects() {
						Main.game.getTextStartStringBuilder().append(UtilText.parseFromXMLFile("places/dominion/cityHall/demographics", "QUESTION_SOLITARY"));
						Main.game.getDialogueFlags().setFlag(DialogueFlagValue.vanessaAskedAboutSolitary, true);
					}
				};

			} else if(index==10 && Main.game.getDialogueFlags().hasFlag(DialogueFlagValue.vanessaHelped)) {
				return new ResponseEffectsOnly("Calling her: [vanessa.Name]", "Cycle between calling the elderly fox-girl 'Ms. Cunningham' and 'Vanessa'.") {
					@Override
					public void effects() {
						Main.game.getNpc(Vanessa.class).setPlayerKnowsName(!Main.game.getNpc(Vanessa.class).isPlayerKnowsName());
					}
				};

			} if (index == 0) {
				return new Response("Leave", "Decide against bothering [vanessa.name], and head back out into the corridor.", CityHall.CITY_HALL_CORRIDOR) {
					@Override
					public void effects() {
						Main.game.getPlayer().setNearestLocation(WorldType.CITY_HALL, PlaceType.CITY_HALL_CORRIDOR, false);
						Main.game.getNpc(Vanessa.class).setLocation(WorldType.CITY_HALL, PlaceType.CITY_HALL_ARCHIVES);
					}
				};

			} else {
				return null;
			}
		}
	};

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

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

		@Override
		public Response getResponse(int responseTab, int index) {
			if(index==6) {
				return new Response("Cataloguing", "You just asked [vanessa.name] how name cataloguing works.", null);
			}
			return CITY_HALL_DEMOGRAPHICS_MAIN.getResponse(responseTab, index);
		}
	};

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

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

		@Override
		public Response getResponse(int responseTab, int index) {
			if(index==7) {
				return new Response("Solitary", "You just asked [vanessa.name] why she's the only person working in this department.", null);
			}
			return CITY_HALL_DEMOGRAPHICS_MAIN.getResponse(responseTab, index);
		}
	};

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

		@Override
		public String getContent() {
			return UtilText.parseFromXMLFile("places/dominion/cityHall/demographics", "OFFER_HELP");
		}

		@Override
		public Response getResponse(int responseTab, int index) {
			if(Main.game.getDialogueFlags().hasFlag(DialogueFlagValue.vanessaHelped)) {
				if (index == 1) {
					return new Response("Work", "Get to work alongside [vanessa.name] cataloguing these papers.", OFFER_HELP_FINISH) {
						@Override
						public void effects() {
							Main.game.getNpc(Vanessa.class).setLocation(WorldType.CITY_HALL, PlaceType.CITY_HALL_BUREAU_OF_DEMOGRAPHICS);
							Main.game.getPlayer().setLocation(WorldType.CITY_HALL, PlaceType.CITY_HALL_BUREAU_OF_DEMOGRAPHICS);
							Main.game.getTextEndStringBuilder().append(Main.game.getNpc(Vanessa.class).incrementAffection(Main.game.getPlayer(), 10));

							for(GameCharacter character : Main.game.getPlayer().getCompanions()) {
								character.setNearestLocation(WorldType.CITY_HALL, PlaceType.CITY_HALL_CORRIDOR, false);
							}
						}
					};

				}

			} else {
				if (index == 1) {
					return new Response("Vanessa", "Tell the elderly fox-girl that you'd be happy to call her 'Vanessa', before getting to work on cataloguing papers.", OFFER_HELP_FINISH) {
						@Override
						public void effects() {
							Main.game.getTextStartStringBuilder().append(UtilText.parseFromXMLFile("places/dominion/cityHall/demographics", "OFFER_HELP_VANESSA"));

							Main.game.getNpc(Vanessa.class).setLocation(WorldType.CITY_HALL, PlaceType.CITY_HALL_BUREAU_OF_DEMOGRAPHICS);
							Main.game.getPlayer().setLocation(WorldType.CITY_HALL, PlaceType.CITY_HALL_BUREAU_OF_DEMOGRAPHICS);
							Main.game.getTextEndStringBuilder().append(Main.game.getNpc(Vanessa.class).incrementAffection(Main.game.getPlayer(), 15));

							for(GameCharacter character : Main.game.getPlayer().getCompanions()) {
								character.setNearestLocation(WorldType.CITY_HALL, PlaceType.CITY_HALL_CORRIDOR, false);
							}
							Main.game.getNpc(Vanessa.class).setPlayerKnowsName(true);
							Main.game.getDialogueFlags().setFlag(DialogueFlagValue.vanessaHelped, true);
						}
					};

				} else if(index==2) {
					return new Response("Ms. Cunningham", "Tell the elderly fox-girl that you prefer to call her 'Ms. Cunningham', before getting to work on cataloguing papers.", OFFER_HELP_FINISH) {
						@Override
						public void effects() {
							Main.game.getTextStartStringBuilder().append(UtilText.parseFromXMLFile("places/dominion/cityHall/demographics", "OFFER_HELP_MS_CUNNINGHAM"));

							Main.game.getNpc(Vanessa.class).setLocation(WorldType.CITY_HALL, PlaceType.CITY_HALL_BUREAU_OF_DEMOGRAPHICS);
							Main.game.getPlayer().setLocation(WorldType.CITY_HALL, PlaceType.CITY_HALL_BUREAU_OF_DEMOGRAPHICS);
							Main.game.getTextEndStringBuilder().append(Main.game.getNpc(Vanessa.class).incrementAffection(Main.game.getPlayer(), 10));

							for(GameCharacter character : Main.game.getPlayer().getCompanions()) {
								character.setNearestLocation(WorldType.CITY_HALL, PlaceType.CITY_HALL_CORRIDOR, false);
							}
							Main.game.getNpc(Vanessa.class).setPlayerKnowsName(false);
							Main.game.getDialogueFlags().setFlag(DialogueFlagValue.vanessaHelped, true);
						}
					};
				}
			}

			return null;
		}
	};

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

		@Override
		public String getContent() {
			return UtilText.parseFromXMLFile("places/dominion/cityHall/demographics", "OFFER_HELP_FINISH");
		}

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

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

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

		@Override
		public Response getResponse(int responseTab, int index) {
			if (index == 1) {
				return new Response("Bare feet", "Pull off [vanessa.namePos] pantyhose so that you can massage her bare feet.", BARE_FOOT_MASSAGE) {
					@Override
					public void effects() {
						Main.game.getDialogueFlags().setFlag(DialogueFlagValue.vanessaMassaged, true);
						try {
							Main.game.getNpc(Vanessa.class).unequipClothingIntoVoid(Main.game.getNpc(Vanessa.class).getClothingInSlot(InventorySlot.SOCK), true, Main.game.getNpc(Vanessa.class));
						} catch(Exception ex) { System.err.println("Vanessa is not wearing pantyhose!"); }

						Main.game.getTextEndStringBuilder().append(Main.game.getNpc(Vanessa.class).incrementAffection(Main.game.getPlayer(), 5));
					}
				};

			} else if (index == 2) {
				return new Response("Stop", "Stop giving [vanessa.name] a foot massage.", CITY_HALL_DEMOGRAPHICS_MAIN) {
					@Override
					public void effects() {
						Main.game.getDialogueFlags().setFlag(DialogueFlagValue.vanessaMassaged, true);
						Main.game.getNpc(Vanessa.class).endSex(); // Cleans & replaces clothing
						Main.game.getTextStartStringBuilder().append(UtilText.parseFromXMLFile("places/dominion/cityHall/demographics", "FOOT_MASSAGE_STOP"));
					}
				};

			} else {
				return null;
			}
		}
	};

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

		@Override
		public String getContent() {
			return UtilText.parseFromXMLFile("places/dominion/cityHall/demographics", "BARE_FOOT_MASSAGE");
		}

		@Override
		public Response getResponse(int responseTab, int index) {
			if (index == 1) {
				if(!Main.game.getPlayer().isAbleToAccessCoverableArea(CoverableArea.MOUTH, true)) {
					return new Response("Perform cunnilingus", "You are unable to access your mouth, so cannot perform cunnilingus on [vanessa.name]!", null);
				}
				return new ResponseSex("Perform cunnilingus",
						"Shuffle forwards between [vanessa.namePos] legs and start eating her out.",
						true, true,
						new SMVanessaOral(
								SexPosition.SITTING,
								Util.newHashMapOfValues(new Value<>(Main.game.getNpc(Vanessa.class), SexSlotSitting.SITTING)),
								Util.newHashMapOfValues(new Value<>(Main.game.getPlayer(), SexSlotSitting.PERFORMING_ORAL))),
						null,
						null,
						END_ORAL_SEX,
						UtilText.parseFromXMLFile("places/dominion/cityHall/demographics", "START_ORAL")) {
					@Override
					public List<InitialSexActionInformation> getInitialSexActions() {
						return Util.newArrayListOfValues(new InitialSexActionInformation(Main.game.getPlayer(), Main.game.getNpc(Vanessa.class), TongueVagina.CUNNILINGUS_START, false, true));
					}
					@Override
					public void effects() {
						Main.game.getDialogueFlags().setFlag(DialogueFlagValue.vanessaFucked, true);
					}
				};

			} else if (index == 2) {
				return new Response("Stop", "Stop giving [vanessa.name] a foot massage.", CITY_HALL_DEMOGRAPHICS_MAIN) {
					@Override
					public void effects() {
						Main.game.getNpc(Vanessa.class).endSex(); // Cleans & replaces clothing
						Main.game.getTextStartStringBuilder().append(UtilText.parseFromXMLFile("places/dominion/cityHall/demographics", "BARE_FOOT_MASSAGE_STOP"));
					}
				};

			} else {
				return null;
			}
		}
	};

	public static final DialogueNode END_ORAL_SEX = new DialogueNode("Pushed back", "[vanessa.Name] pushes you away from her pussy and grins down at you...", true) {

		@Override
		public String getContent() {
			if(Sex.getNumberOfOrgasms(Main.game.getPlayer())>0) {
				return UtilText.parseFromXMLFile("places/dominion/cityHall/demographics", "END_ORAL_SEX");
			} else {
				return UtilText.parseFromXMLFile("places/dominion/cityHall/demographics", "END_ORAL_SEX_NO_ORGASM");
			}
		}

		@Override
		public Response getResponse(int responseTab, int index) {
			if(index==1) {
				if(Main.game.getPlayer().hasPenis() && (Main.game.getPlayer().isAbleToAccessCoverableArea(CoverableArea.PENIS, true) || !Main.game.getPlayer().hasVagina())) {
					if(Main.game.getPlayer().isAbleToAccessCoverableArea(CoverableArea.PENIS, true)) {
						boolean biped = !Main.game.getPlayer().isTaur();
						return new ResponseSex("Sex",
								biped
									?"Push [vanessa.name] back onto her desk and fuck her."
									:"Mount [vanessa.name] and start fucking her.",
								true, true,
								biped
									?new SMVanessaSex(
											SexPosition.OVER_DESK,
											Util.newHashMapOfValues(new Value<>(Main.game.getPlayer(), SexSlotDesk.BETWEEN_LEGS)),
											Util.newHashMapOfValues(new Value<>(Main.game.getNpc(Vanessa.class), SexSlotDesk.OVER_DESK_ON_BACK)))
									:new SMVanessaSex(
											SexPosition.ALL_FOURS,
											Util.newHashMapOfValues(new Value<>(Main.game.getPlayer(), SexSlotAllFours.BEHIND)),
											Util.newHashMapOfValues(new Value<>(Main.game.getNpc(Vanessa.class), SexSlotAllFours.ALL_FOURS))),
								null,
								null,
								END_SEX,
								UtilText.parseFromXMLFile("places/dominion/cityHall/demographics", "START_SEX_FUCKING_VANESSA")){
							@Override
							public List<InitialSexActionInformation> getInitialSexActions() {
								return Util.newArrayListOfValues(new InitialSexActionInformation(Main.game.getPlayer(), Main.game.getNpc(Vanessa.class), PenisVagina.PENIS_FUCKING_START, false, true));
							}
							@Override
							public void effects() {
								Main.game.getDialogueFlags().setFlag(DialogueFlagValue.vanessaFucked, true);
							}
						};

					} else {
						return new Response("Sex", "As you cannot get access to your cock, [vanessa.name] cannot have sex with you...", null);
					}

				} else if(Main.game.getPlayer().hasVagina()) {
					if(Main.game.getPlayer().isAbleToAccessCoverableArea(CoverableArea.VAGINA, true)) {
						boolean biped = !Main.game.getPlayer().isTaur();
						return new ResponseSex("Receive cunnilingus",
								biped
									?"Allow [vanessa.name] to swap places with you so that she can eat you out."
									:"Allow [vanessa.name] to kneel behind you so that she can eat you out.",
								true, true,
								biped
									?new SMVanessaOral(
											SexPosition.SITTING,
											Util.newHashMapOfValues(new Value<>(Main.game.getPlayer(), SexSlotSitting.SITTING)),
											Util.newHashMapOfValues(new Value<>(Main.game.getNpc(Vanessa.class), SexSlotSitting.PERFORMING_ORAL)))
									:new SMVanessaOral(
											SexPosition.STANDING,
											Util.newHashMapOfValues(new Value<>(Main.game.getPlayer(), SexSlotStanding.STANDING_DOMINANT)),
											Util.newHashMapOfValues(new Value<>(Main.game.getNpc(Vanessa.class), SexSlotStanding.PERFORMING_ORAL_BEHIND))),
								null,
								null,
								END_SEX_ORAL_RECEIVING,
								UtilText.parseFromXMLFile("places/dominion/cityHall/demographics", "START_SEX_EATEN_OUT")){
							@Override
							public List<InitialSexActionInformation> getInitialSexActions() {
								return Util.newArrayListOfValues(new InitialSexActionInformation(Main.game.getNpc(Vanessa.class), Main.game.getPlayer(), TongueVagina.CUNNILINGUS_START, false, true));
							}
							@Override
							public void effects() {
								Main.game.getDialogueFlags().setFlag(DialogueFlagValue.vanessaFucked, true);
							}
						};

					} else {
						return new Response("Receive cunnilingus", "As you cannot get access to your pussy, [vanessa.name] cannot have sex with you...", null);
					}

				} else {
					if(Main.game.getPlayer().isAbleToAccessCoverableArea(CoverableArea.VAGINA, true)) {
						boolean biped = !Main.game.getPlayer().isTaur();
						return new ResponseSex("Receive oral",
								biped
									?"Allow [vanessa.name] to swap places with you so that she can perform oral on your genderless mound."
									:"Allow [vanessa.name] to kneel behind you so that she can perform oral on your genderless mound.",
								true, true,
								biped
									?new SMVanessaOral(
											SexPosition.SITTING,
											Util.newHashMapOfValues(new Value<>(Main.game.getPlayer(), SexSlotSitting.SITTING)),
											Util.newHashMapOfValues(new Value<>(Main.game.getNpc(Vanessa.class), SexSlotSitting.PERFORMING_ORAL)))
									:new SMVanessaOral(
											SexPosition.STANDING,
											Util.newHashMapOfValues(new Value<>(Main.game.getPlayer(), SexSlotStanding.STANDING_DOMINANT)),
											Util.newHashMapOfValues(new Value<>(Main.game.getNpc(Vanessa.class), SexSlotStanding.PERFORMING_ORAL_BEHIND))),
								null,
								null,
								END_SEX_ORAL_RECEIVING,
								UtilText.parseFromXMLFile("places/dominion/cityHall/demographics", "START_SEX_EATEN_OUT_MOUND")){
							@Override
							public void effects() {
								Main.game.getDialogueFlags().setFlag(DialogueFlagValue.vanessaFucked, true);
							}
						};

					} else {
						return new Response("Receive oral", "As you cannot get access to your genderless mound, [vanessa.name] cannot have sex with you...", null);
					}
				}

			} else if(index==2) {
				return new Response("Decline", "Tell [vanessa.name] that you've had enough for now.", CITY_HALL_DEMOGRAPHICS_MAIN) {
					@Override
					public void effects() {
						Main.game.getNpc(Vanessa.class).endSex(); // Cleans & replaces clothing
						Main.game.getTextStartStringBuilder().append(UtilText.parseFromXMLFile("places/dominion/cityHall/demographics", "END_ORAL_SEX_DECLINE_MORE"));
					}
				};
			}

			return null;
		}
	};

	public static final DialogueNode END_SEX = new DialogueNode("Finished", "Having had enough sex for now, the two of you start to get your clothing back in order...", true) {

		@Override
		public String getContent() {
			if(Sex.getNumberOfOrgasms(Main.game.getPlayer())>0) {
				return UtilText.parseFromXMLFile("places/dominion/cityHall/demographics", "END_SEX");
			} else {
				return UtilText.parseFromXMLFile("places/dominion/cityHall/demographics", "END_SEX_NO_PLAYER_ORGASM");
			}
		}

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

	public static final DialogueNode END_SEX_ORAL_RECEIVING = new DialogueNode("Finished", "Having had enough sex for now, the two of you start to get your clothing back in order...", true) {

		@Override
		public String getContent() {
			if(Sex.getNumberOfOrgasms(Main.game.getPlayer())>0) {
				return UtilText.parseFromXMLFile("places/dominion/cityHall/demographics", "END_SEX");
			} else {
				return UtilText.parseFromXMLFile("places/dominion/cityHall/demographics", "END_SEX_NO_PLAYER_ORGASM");
			}
		}

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

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

		@Override
		public String getContent() {
			return UtilText.parseFromXMLFile("places/dominion/cityHall/demographics", "OFFSPRING_MAP");
		}

		@Override
		public Response getResponse(int responseTab, int index) {
			if (index == 1) {
				if(Main.game.getPlayer().getMoney()>=ItemType.OFFSPRING_MAP.getValue(null)) {
					return new Response("Purchase ("+UtilText.formatAsMoney(ItemType.OFFSPRING_MAP.getValue(null), "span")+")", "Tell [vanessa.name] that you want to buy an arcane offspring map.", OFFSPRING_MAP_PURCHASE) {
						@Override
						public void effects() {
							Main.game.getTextEndStringBuilder().append(Main.game.getPlayer().incrementMoney(-ItemType.OFFSPRING_MAP.getValue(null)));
							Main.game.getTextEndStringBuilder().append(Main.game.getPlayer().addItem(AbstractItemType.generateItem(ItemType.OFFSPRING_MAP), false));
						}
					};

				} else {
					return new Response("Purchase ("+UtilText.formatAsMoneyUncoloured(ItemType.OFFSPRING_MAP.getValue(null), "span")+")", "You don't have enough money for this...", null);
				}

			} else if (index == 2) {
				return new Response("Change mind", "Decide against buying an offspring map.", CITY_HALL_DEMOGRAPHICS_MAIN) {
					@Override
					public void effects() {
						Main.game.getTextStartStringBuilder().append(UtilText.parseFromXMLFile("places/dominion/cityHall/demographics", "OFFSPRING_MAP_BACK"));
					}
				};

			} else {
				return null;
			}
		}
	};

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

		@Override
		public String getContent() {
			return UtilText.parseFromXMLFile("places/dominion/cityHall/demographics", "OFFSPRING_MAP_PURCHASE");
		}

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

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

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

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

			UtilText.nodeContentSB.append(UtilText.parseFromXMLFile("places/dominion/cityHall/demographics", "NAME_CHANGE"));

			UtilText.nodeContentSB.append("<br/>"
					+ "<div class='container-full-width' style='text-align:center;'>"
						+ "<div style='position:relative; display:inline-block; padding-bottom:0; margin 0 auto; vertical-align:middle; width:100%; text-align:center;'>"
							+ "<p style='display:inline-block; padding:0; margin:0; height:32px; line-height:32px; width:100px;'>First name: </p>"
							+ "<form style='display:inline-block; padding:0; margin:0; text-align:center;'><input type='text' id='nameInput' value='"+ UtilText.parseForHTMLDisplay(Main.game.getPlayer().getName(false))+ "'></form>"
							+ "<br/>"
							+ "<p style='display:inline-block; padding:0; margin:0; height:32px; line-height:32px; width:100px;'>Surname: </p>"
							+ "<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>"
						+ "</div>"
						+ "<br/>"
						+ "<i>Your name must be between 2 and 32 characters long. You cannot use the square bracket characters or full stops. (Surname may be left blank.)</i>"
						+ (unsuitableName ? "<p style='text-align:center;padding-top:0;'><b style=' color:"+ Colour.GENERIC_BAD.toWebHexString()+ ";'>Invalid name.</b></p>" : "")
						+ (unsuitableSurname ? "<p style='text-align:center;padding-top:0;'><b style=' color:"+ Colour.GENERIC_BAD.toWebHexString()+ ";'>Invalid Surname.</b></p>" : "")
					+ "</div>"

					+ "<p id='hiddenFieldName' style='display:none;'></p>"
					+ "<p id='hiddenFieldSurname' style='display:none;'></p>");

			return UtilText.nodeContentSB.toString();
		}

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

				} else {
					return new ResponseEffectsOnly("Confirm ("+UtilText.formatAsMoney(100, "span")+")", "Have your name changed.<br/>This will cost "+UtilText.formatAsMoney(100)+"."){
						@Override
						public int getSecondsPassed() {
							return 10*60;
						}
						@Override
						public void effects() {
							applyNameChange(false);
						}
					};
				}

			} else if(index==2) {
				if(Main.game.getPlayer().getAllCharactersOfRelationType(Relationship.Parent).isEmpty()) {
					return new Response("Offspring ("+UtilText.formatAsMoneyUncoloured(5000, "span")+")",
							"Change your name, and also have all lines of your offspring update their surnames to your surname.<br/>[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.formatAsMoneyUncoloured(5000, "span")+")",
							"Change your name, and also have all lines of your offspring update their surnames to your surname.<br/>[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.<br/>This will cost "+UtilText.formatAsMoney(5000)+"."){
						@Override
						public int getSecondsPassed() {
							return 10*60;
						}
						@Override
						public void effects() {
							applyNameChange(true);
						}
					};
				}

			} else if (index == 0) {
				return new Response("Back", "Decide not to change your name.", CITY_HALL_DEMOGRAPHICS_MAIN) {
					@Override
					public void effects() {
						Main.game.getTextStartStringBuilder().append(UtilText.parseFromXMLFile("places/dominion/cityHall/demographics", "NAME_CHANGE_BACK"));
					}
				};

			} 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()>=1
					&& (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()<1) {
			unsuitableSurname = true;
		}

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

		} 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(
						"<p style='text-align:center;'>"
							+ "You fill out the forms and hand over the required fee, officially changing your name to:<br/>"
							+ "<b>[pc.Name]"+(!Main.game.getPlayer().getSurname().isEmpty()?" [pc.Surname]":"")+"</b><br/>"
							+ "All of your offspring, all the way down your family tree, have had their surnames legally changed to:<br/>"
							+ "<b>[pc.Surname]</b><br/>"
						+ "</p>"
						+Main.game.getPlayer().incrementMoney(-5000));
			} else {
				Main.game.getTextEndStringBuilder().append(
						"<p style='text-align:center;'>"
							+ "You fill out the forms and hand over the required fee, officially changing your name to:<br/>"
							+ "<b>[pc.Name]"+(!Main.game.getPlayer().getSurname().isEmpty()?" [pc.Surname]":"")+"</b>"
						+ "</p>"
						+Main.game.getPlayer().incrementMoney(-100));
			}
			Main.game.setContent(new Response("" ,"", NAME_CHANGE));
		}
	}
}


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

import com.lilithsthrone.game.dialogue.DialogueNode;
import com.lilithsthrone.game.dialogue.responses.Response;
import com.lilithsthrone.game.dialogue.utils.UtilText;

/**
 * @since 0.3.2
 * @version 0.3.2
 * @author Innoxia
 */
public class CityHallProperty {

	public static final DialogueNode CITY_HALL_PROPERTY_ENTRANCE = new DialogueNode("Bureau of Property and Commerce", "-", false) {

		@Override
		public String getContent() {
			return UtilText.parseFromXMLFile("places/dominion/cityHall/property", "CITY_HALL_PROPERTY_ENTRANCE");
		}

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