code:
package com.lilithsthrone.game.character.body.valueEnums;

import java.util.List;

import com.lilithsthrone.game.character.GameCharacter;
import com.lilithsthrone.game.character.body.Anus;
import com.lilithsthrone.game.character.body.Ass;
import com.lilithsthrone.game.character.body.BodyPartInterface;
import com.lilithsthrone.game.character.body.BreastCrotch;
import com.lilithsthrone.game.character.body.Clitoris;
import com.lilithsthrone.game.character.body.Leg;
import com.lilithsthrone.game.character.body.Penis;
import com.lilithsthrone.game.character.body.Tail;
import com.lilithsthrone.game.character.body.Tentacle;
import com.lilithsthrone.game.character.body.Testicle;
import com.lilithsthrone.game.character.body.Vagina;
import com.lilithsthrone.game.character.body.types.LegType;
import com.lilithsthrone.game.character.body.types.WingType;
import com.lilithsthrone.game.inventory.InventorySlot;
import com.lilithsthrone.game.inventory.ItemTag;
import com.lilithsthrone.game.inventory.clothing.BodyPartClothingBlock;
import com.lilithsthrone.utils.Util;

/**
 * @since 0.3.1
 * @version 0.3.1
 * @author Innoxia
 */
public enum LegConfiguration {

	/**
	 * This LegConfiguration is the standard for humans, demons, angels, and the vast majority of animal-morphs.
	 */
	BIPEDAL("bipedal",
			0,
			0,
			true,
			true,
			WingSize.THREE_LARGE,
			false,
			2,
			0,
			"The most common type of lower body; the character's legs and groin are in the same configuration as that of a regular human.",
			"Above [npc.her] groin, occupying the lower region of [npc.her] abdomen,") {
		@Override
		public boolean isGenitalConfigurationTransformable() {
			return true;
		}
		@Override
		public List<Class<? extends BodyPartInterface>> getBestialParts() {
			return Util.newArrayListOfValues();
		}
		@Override
		public BodyPartClothingBlock getBodyPartClothingBlock(GameCharacter character) {
			return null; // Bipedal configuration doesn't block any slots by default.
		}
		@Override
		public void setLegsToDemon(GameCharacter character) {
			character.setLegType(LegType.DEMON_COMMON);
		}
	},

	/**
	 * This LegConfiguration is available for almost every mammalian race, with some notable exceptions being humans, demons, and angels.
	 */
	TAUR("taur",
			-50,
			0,
			false,
			false,
			WingSize.FOUR_HUGE,
			true,
			4,
			0,
			"A configuration in which the character's legs and groin are replaced by the quadrupedal, bestial body of the associated animal-morph, with their genitals shifting to be found in the same place as their animal equivalent."
				+ " The most common example of this is the 'centaur', in which the character's legs and groin are replaced by the body and genitals of a horse.",
			"Down beneath the groin on [npc.her] animal body,") {

			@Override
			public BodyPartClothingBlock getBodyPartClothingBlock(GameCharacter character) {
				return new BodyPartClothingBlock(
						Util.newArrayListOfValues(
								InventorySlot.LEG,
								InventorySlot.GROIN),
						character.getLegType().getRace(),
						"Due to the fact that [npc.nameHasFull] the lower body of [npc.a_legRace], only taur-suitable clothing can be worn in this slot.",
						Util.newArrayListOfValues(
								ItemTag.FITS_NON_BIPED_BODY_HUMANOID,
								ItemTag.FITS_TAUR_BODY));
			}
			@Override
			public void setLegsToDemon(GameCharacter character) {
				character.setLegType(LegType.DEMON_HOOFED);
			}
	},

//	/**
//	 * This LegConfiguration is available for almost every mammalian race, with some notable exceptions being humans, demons, and angels.
//	 */
//	TAUR_WINGED("winged taur",
//			true,
//			true,
//			false,
//			"A configuration in which the character's legs and groin are replaced by the quadrupedal, winged, bestial body of the associated animal-morph, with their genitals shifting to be found in the same place as their animal equivalent."
//				+ " The most common example of this is the 'pegatuar', in which the character's legs and groin are replaced by the body and genitals of a winged horse.",
//			"Down beneath the groin on [npc.her] animal body,") {
//
//		@Override
//		public BodyPartClothingBlock getBodyPartClothingBlock(GameCharacter character) {
//			return new BodyPartClothingBlock(
//					Util.newArrayListOfValues(
//							InventorySlot.LEG,
//							InventorySlot.GROIN),
//					character.getLegType().getRace(),
//					"Due to the fact that [npc.nameHasFull] the lower body of [npc.a_legRace], only taur-suitable clothing can be worn in this slot.",
//					Util.newArrayListOfValues(
//							ItemTag.FITS_NON_BIPED_BODY_HUMANOID,
//							ItemTag.FITS_TAUR_BODY));
//		}
//	},

	/**
	 * This LegConfiguration is available for snakes and eels.
	 */
	TAIL_LONG("long-tailed",
			0,
			0,
			true,
			true,
			WingSize.FOUR_HUGE,
			false,
			0,
			0,
			"A configuration in which the character's legs and groin are replaced by an extremely long tail of the associated animal-morph, with their genitals shifting to be located within a cloaca."
				+ " The most common example of this is the 'lamia', in which the character's legs and groin are replaced by the body and genitals of a snake.",
			"Above [npc.her] groin, occupying the lower region of [npc.her] humanoid abdomen,") {

		@Override
		public BodyPartClothingBlock getBodyPartClothingBlock(GameCharacter character) {
			return new BodyPartClothingBlock(
					Util.newArrayListOfValues(
							InventorySlot.LEG,
							InventorySlot.GROIN),
					character.getLegType().getRace(),
					"Due to the fact that [npc.nameHasFull] the lower body of [npc.a_legRace], only long-tail-suitable clothing can be worn in this slot.",
					Util.newArrayListOfValues(
							ItemTag.FITS_NON_BIPED_BODY_HUMANOID,
							ItemTag.FITS_LONG_TAIL_BODY));
		}
	},

	/**
	 * This LegConfiguration is available for fish.
	 */
	TAIL("tailed",
			200,
			-90,
			true,
			true,
			WingSize.THREE_LARGE,
			false,
			0,
			0,
			"A configuration in which the character's legs and groin are replaced by a tail of the associated animal-morph, with their genitals shifting to be located within a cloaca."
					+ " The most common example of this is the 'mermaid', in which the character's legs and groin are replaced by the body and genitals of a fish.",
			"Above [npc.her] groin, occupying the lower region of [npc.her] humanoid abdomen,") {

		@Override
		public BodyPartClothingBlock getBodyPartClothingBlock(GameCharacter character) {
			return new BodyPartClothingBlock(
					Util.newArrayListOfValues(
							InventorySlot.LEG,
							InventorySlot.GROIN),
					character.getLegType().getRace(),
					"Due to the fact that [npc.nameHasFull] the lower body of [npc.a_legRace], only tail-suitable clothing can be worn in this slot.",
					Util.newArrayListOfValues(
							ItemTag.FITS_NON_BIPED_BODY_HUMANOID,
							ItemTag.FITS_TAIL_BODY));
		}
	},

	/**
	 * This LegConfiguration is available for spiders and scorpions.
	 */
	ARACHNID("arachnid",
			-25,
			100,
			false,
			true,
			WingSize.FOUR_HUGE,
			true,
			8,
			0,
			"A configuration in which the character's legs and groin are replaced by the eight-legged, bestial body of the associated arachnid-morph, with their genitals shifting to be found in the same place as their animal equivalent."
					+ " The most common example of this is the 'arachne', in which the character's legs and groin are replaced by the body and genitals of a spider.",
			"Occupying the lower region of [npc.her] humanoid abdomen,") {

		@Override
		public BodyPartClothingBlock getBodyPartClothingBlock(GameCharacter character) {
			return new BodyPartClothingBlock(
					Util.newArrayListOfValues(
							InventorySlot.LEG,
							InventorySlot.GROIN),
					character.getLegType().getRace(),
					"Due to the fact that [npc.nameHasFull] the lower body of [npc.a_legRace], only arachnid-suitable clothing can be worn in this slot.",
					Util.newArrayListOfValues(
							ItemTag.FITS_NON_BIPED_BODY_HUMANOID,
							ItemTag.FITS_ARACHNID_BODY));
		}

		@Override
		public boolean isGenitalsExposed(GameCharacter character) { // When genitals are in a cloaca (i.e. beneath the arachnid body), they are not visible.
			return character.getGenitalArrangement()==GenitalArrangement.NORMAL;
		}
	},

	/**
	 * This LegConfiguration is available for octopuses and squids.

	 *

	 * Below the thunders of the upper deep;

	 * Far far beneath in the abysmal sea,

	 * His ancient, dreamless, uninvaded sleep

	 * The Kraken sleepeth: faintest sunlights flee

	 * About his shadowy sides; above him swell

	 * Huge sponges of millennial growth and height;

	 * And far away into the sickly light,

	 * From many a wondrous grot and secret cell

	 * Unnumber'd and enormous polypi

	 * Winnow with giant arms the slumbering green.

	 * There hath he lain for ages, and will lie

	 * Battening upon huge seaworms in his sleep,

	 * Until the latter fire shall heat the deep;

	 * Then once by man and angels to be seen,

	 * In roaring he shall rise and on the surface die.
	 */
	CEPHALOPOD("cephalopod",
			50,
			-75,
			true,
			true,
			WingSize.THREE_LARGE,
			false,
			0,
			8,
			// I believe that "tentacled" is technically incorrect as a catch-all term for cephalopods, as octopuses have eight 'arms', while squids have eight arms plus two tentacles. Oh well.
			"A configuration in which the character's legs and groin are replaced by the tentacled, bestial body of the associated cephalopod-morph, with their genitals shifting to be found in the same place as their animal equivalent."
					+ " The most common example of this is the 'kraken', in which the character's legs and groin are replaced by the body and genitals of a squid.",
			"Above [npc.her] groin, occupying the lower region of [npc.her] humanoid abdomen,") {

		@Override
		public BodyPartClothingBlock getBodyPartClothingBlock(GameCharacter character) {
			return new BodyPartClothingBlock(
					Util.newArrayListOfValues(
							InventorySlot.LEG,
							InventorySlot.GROIN),
					character.getLegType().getRace(),
					"Due to the fact that [npc.nameHasFull] the lower body of [npc.a_legRace], only cephalopod-suitable clothing can be worn in this slot.",
					Util.newArrayListOfValues(
							ItemTag.FITS_NON_BIPED_BODY_HUMANOID,
							ItemTag.FITS_CEPHALOPOD_BODY));
		}

		@Override
		public boolean isGenitalsExposed(GameCharacter character) { // Genitals are under tentacles, so are not visible even when naked.
			return false;
		}
	};

	private String name;
	private int landSpeedModifier;
	private int waterSpeedModifier;
	private boolean bipedalPositionedGenitals;
	private boolean bipedalPositionedCrotchBoobs;

	private WingSize minimumWingSizeForFlight;
	private boolean wingsOnLegConfiguration;

	int numberOfLegs;
	int numberOfTentacles;

	private String genericDescription;
	private String crotchBoobLocationDescription;

	private LegConfiguration(
			String name,
			int landSpeedModifier,
			int waterSpeedModifier,
			boolean bipedalPositionedGenitals,
			boolean bipedalPositionedCrotchBoobs,
			WingSize minimumWingSizeForFlight,
			boolean wingsOnLegConfiguration,
			int numberOfLegs,
			int numberOfTentacles,
			String genericDescription,
			String crotchBoobLocationDescription) {

		this.name = name;

		this.landSpeedModifier = landSpeedModifier;
		this.waterSpeedModifier = waterSpeedModifier;

		this.bipedalPositionedGenitals = bipedalPositionedGenitals;
		this.bipedalPositionedCrotchBoobs = bipedalPositionedCrotchBoobs;

		this.minimumWingSizeForFlight=minimumWingSizeForFlight;
		this.wingsOnLegConfiguration=wingsOnLegConfiguration;

		this.numberOfLegs = numberOfLegs;
		this.numberOfTentacles = numberOfTentacles;

		this.genericDescription = genericDescription;
		this.crotchBoobLocationDescription = crotchBoobLocationDescription;
	}

	// I didn't implement this in the end, as upon further reflection, I came to the conclusion that blocking the player's choices for the sake of more 'realistic' taur bodies is a bad idea.
	// All of the pre-generated ones will be accurate anyway, so all this would do is limit the player unnecessarily.
//	/**
//	 * @return A list of BodyPartInterface classes of whose type cannot be transformed outside of the LegType's Race while the character has this LegConfiguration.
//	 *  Their other modifiers can still be freely transformed. Penis and Vagina can still be set to NONE.
//	 */
//	public List<Class<? extends BodyPartInterface>> getBlockedTransformations() {
//		return getBestialParts();
//	}

	/**
	 * @return A list of BodyPartInterface classes which are considered to be fully animalistic as part of this LegConfiguration. e.g. A taur's Tail, Ass, BreastCrotch, Penis, and Vagina are all animalistic.
	 */
	public List<Class<? extends BodyPartInterface>> getBestialParts() {
		return Util.newArrayListOfValues(Ass.class, Anus.class, BreastCrotch.class, Leg.class, Tail.class, Tentacle.class, Penis.class, Testicle.class, Vagina.class, Clitoris.class);
	}

	public String getName() {
		return name;
	}

	public int getLandSpeedModifier() {
		return landSpeedModifier;
	}

	public int getWaterSpeedModifier() {
		return waterSpeedModifier;
	}

	/**
	 * @return true If this leg configuration blocks flight from the usual arms or wings.
	 */
	public WingSize getMinimumWingSizeForFlight() {
		return minimumWingSizeForFlight;
	}

	public boolean isWingsOnLegConfiguration() {
		return wingsOnLegConfiguration;
	}

	/**
	 * @return true If this leg configuration has genitals in roughly the same place as on a biped.
	 */
	public boolean isBipedalPositionedGenitals() {
		return bipedalPositionedGenitals;
	}

	/**
	 * @return true If this leg configuration has crotch-boobs in roughly the same place as on a biped.
	 */
	public boolean isBipedalPositionedCrotchBoobs() {
		return bipedalPositionedCrotchBoobs;
	}

	public int getNumberOfLegs() {
		return numberOfLegs;
	}

	public int getNumberOfTentacles() {
		return numberOfTentacles;
	}

	public boolean isGenitalsExposed(GameCharacter character) {
		return true;
	}

	public boolean isGenitalConfigurationTransformable() {
		return false;
	}

	public String getGenericDescription() {
		return genericDescription;
	}

	public String getCrotchBoobLocationDescription() {
		return crotchBoobLocationDescription;
	}

	public void setLegsToDemon(GameCharacter character) {
		throw new IllegalArgumentException("Demon legs for this leg configuration is not yet implemented!");
	}

	public void setWingsToDemon(GameCharacter character) {
		character.setWingType(WingType.DEMON_COMMON);
		character.setWingSize(this.minimumWingSizeForFlight.getValue());
	}

	/**
	 * @return A BodyPartClothingBlock object which defines how this LegConfiguration is blocking InventorySlots. Returns null if it doesn't affect inventorySlots in any way.
	 */
	public abstract BodyPartClothingBlock getBodyPartClothingBlock(GameCharacter character);
}


code:
package com.lilithsthrone.game.character.body.valueEnums;

import com.lilithsthrone.utils.Colour;

/**
 * @since 0.1.83
 * @version 0.3.2
 * @author Innoxia
 */
public enum LipSize {

	ZERO_THIN(0, "thin", Colour.GENERIC_SIZE_ONE, false),
	ONE_AVERAGE(1, "average-sized", Colour.GENERIC_SIZE_TWO, false),
	TWO_FULL(2, "full", Colour.GENERIC_SIZE_THREE, false),
	THREE_PLUMP(3, "plump", Colour.GENERIC_SIZE_FOUR, false),
	FOUR_HUGE(4, "huge", Colour.GENERIC_SIZE_FIVE, false),
	FIVE_MASSIVE(5, "massive", Colour.GENERIC_SIZE_SIX, true),
	SIX_GIGANTIC(6, "gigantic", Colour.GENERIC_SIZE_SEVEN, true),
	SEVEN_ABSURD(7, "absurdly colossal", Colour.GENERIC_SIZE_EIGHT, true);

	private int value;
	private String descriptor;
	private Colour colour;
	private boolean impedesSpeech;

	private LipSize(int value, String descriptor, Colour colour, boolean impedesSpeech) {
		this.value = value;
		this.descriptor = descriptor;
		this.colour = colour;
		this.impedesSpeech = impedesSpeech;
	}

	public int getValue() {
		return value;
	}

	public String getName() {
		return descriptor;
	}

	public static LipSize getLipSizeFromInt(int index) {
		for(LipSize ls : LipSize.values()) {
			if(index == ls.getValue()) {
				return ls;
			}
		}
		return ZERO_THIN;
	}

	public static int getLargest() {
		int largest = ZERO_THIN.value;
		for(LipSize ls : LipSize.values()) {
			largest = Math.max(largest, ls.value);
		}
		return largest;
	}

	public Colour getColour() {
		return colour;
	}

	public boolean isImpedesSpeech() {
		return impedesSpeech;
	}
}

repo_name: klorpa/Pedo

license: unknown


code:
package com.lilithsthrone.game.character.body.valueEnums;

import com.lilithsthrone.game.dialogue.utils.UtilText;
import com.lilithsthrone.utils.Colour;

/**
 * @since 0.1.83
 * @version 0.1.83
 * @author Innoxia
 */
public enum Muscle {

	ZERO_SOFT("soft", 0, 20, Colour.MUSCLE_ZERO),
	ONE_LIGHTLY_MUSCLED("lightly muscled", 20, 40, Colour.MUSCLE_ONE),
	TWO_TONED("toned", 40, 60, Colour.MUSCLE_TWO),
	THREE_MUSCULAR("muscular", 60, 80, Colour.MUSCLE_THREE),
	FOUR_RIPPED("ripped", 80, 100, Colour.MUSCLE_FOUR);

	private String name;
	private int minimumMuscle, maximumMuscle;
	private Colour colour;

	private Muscle(String name, int minimumMuscle, int maximumMuscle, Colour colour) {
		this.name = name;
		this.minimumMuscle = minimumMuscle;
		this.maximumMuscle = maximumMuscle;
		this.colour = colour;
	}

	public int getMinimumValue() {
		return minimumMuscle;
	}

	public int getMaximumValue() {
		return maximumMuscle;
	}

	public int getMedianValue() {
		return minimumMuscle + (maximumMuscle - minimumMuscle) / 2;
	}

	public static Muscle valueOf(int muscle) {
		for(Muscle f : Muscle.values()) {
			if(muscle>=f.getMinimumValue() && muscle<f.getMaximumValue()) {
				return f;
			}
		}
		return FOUR_RIPPED;
	}

	public String getName(boolean withDeterminer) {
		if(withDeterminer) {
			return UtilText.generateSingularDeterminer(name) + " " + name;
		} else {
			return name;
		}
	}

	public Colour getColour() {
		return colour;
	}
}


code:
package com.lilithsthrone.game.character.body.valueEnums;

/**
 * @since 0.1.83
 * @version 0.1.83
 * @author Innoxia
 */
public enum NippleShape {

	NORMAL("normal"),
	VAGINA("nipple-cunts"),
	LIPS("lipples");

	private String descriptor;

	private NippleShape(String descriptor) {
		this.descriptor = descriptor;
	}

	public String getName() {
		return descriptor;
	}
}


code:
package com.lilithsthrone.game.character.body.valueEnums;

import com.lilithsthrone.utils.Colour;

/**
 * @since 0.1.83
 * @version 0.1.83
 * @author Innoxia
 */
public enum NippleSize {

	ZERO_TINY(0, "tiny", Colour.GENERIC_SIZE_ONE),
	ONE_SMALL(1, "small", Colour.GENERIC_SIZE_TWO),
	TWO_BIG(2, "big", Colour.GENERIC_SIZE_THREE),
	THREE_LARGE(3, "large", Colour.GENERIC_SIZE_FOUR),
	FOUR_MASSIVE(4, "massive", Colour.GENERIC_SIZE_FIVE);

	private int value;
	private String descriptor;
	private Colour colour;

	private NippleSize(int value, String descriptor, Colour colour) {
		this.value = value;
		this.descriptor = descriptor;
		this.colour=colour;
	}

	public int getValue() {
		return value;
	}

	public String getName() {
		return descriptor;
	}

	public static NippleSize getNippleSizeFromInt(int index) {
		for(NippleSize as : NippleSize.values()) {
			if(index == as.getValue()) {
				return as;
			}
		}
		return ZERO_TINY;
	}

	public Colour getColour() {
		return colour;
	}
}


code:
package com.lilithsthrone.game.character.body.valueEnums;

import com.lilithsthrone.utils.Colour;

/**
 * Arbitrary measurements in increments of 1, going from 0 to 7.
 *
 * @since 0.1.64
 * @version 0.1.90
 * @author Innoxia
 */
public enum OrificeElasticity {

	/*-------RIGID:---------*/

	/**Is extremely resistant to being stretched out.*/
	ZERO_UNYIELDING("rigid", 0, 0.05f, Colour.GENERIC_SIZE_ONE),

	/**Is very resistant to being stretched out.*/
	ONE_RIGID("stiff", 1, 0.1f, Colour.GENERIC_SIZE_TWO),

	/**Is resistant to being stretched out.*/
	TWO_FIRM("firm", 2, 0.15f, Colour.GENERIC_SIZE_THREE),

	/*-------NORMAL:---------*/

	/**Normal value, along with FOUR_LIMBER. Is quite resistant to being stretched out.*/
	THREE_FLEXIBLE("flexible", 3, 0.2f, Colour.GENERIC_SIZE_FOUR),

	/**Normal value, along with THREE_FLEXIBLE. Is somewhat resistant to being stretched out.*/
	FOUR_LIMBER("limber", 4, 0.25f, Colour.GENERIC_SIZE_FIVE),

	/*-------STRETCHY:---------*/

	/**Stretches out fairly quickly.*/
	FIVE_STRETCHY("stretchy", 5, 0.3f, Colour.GENERIC_SIZE_SIX),

	/**Easily stretches out.*/
	SIX_SUPPLE("supple", 6, 0.4f, Colour.GENERIC_SIZE_SEVEN),

	/**Very quickly stretches out.*/
	SEVEN_ELASTIC("elastic", 7, 0.5f, Colour.GENERIC_SIZE_EIGHT);

	private String descriptor;
	private int value;
	private float stretchModifier;
	private Colour colour;

	private OrificeElasticity(String descriptor, int value, float stretchModifier, Colour colour) {
		this.descriptor = descriptor;
		this.value = value;
		this.stretchModifier = stretchModifier;
		this.colour = colour;
	}

	public static OrificeElasticity getElasticityFromInt(int value) {
		for(OrificeElasticity oe : OrificeElasticity.values()) {
			if(value == oe.getValue()) {
				return oe;
			}
		}
		return SEVEN_ELASTIC;
	}

	/**
	 * To fit into a sentence: "You have a "+getDescriptor()+" ass."
	 */
	public String getDescriptor() {
		return descriptor;
	}

	public int getValue() {
		return value;
	}

	public float getStretchModifier() {
		return stretchModifier;
	}

	public Colour getColour() {
		return colour;
	}

}


code:
package com.lilithsthrone.game.character.body.valueEnums;

/**
 * @since 0.1.83
 * @version 0.1.83
 * @author Innoxia
 */
public enum OrificeModifier {

	PUFFY("puffy"),
	RIBBED("internally-ribbed"),
	TENTACLED("tentacled"),
	MUSCLE_CONTROL("internally-muscled");

	private String descriptor;

	private OrificeModifier(String descriptor) {
		this.descriptor = descriptor;
	}

	public String getName() {
		return descriptor;
	}
}


code:
package com.lilithsthrone.game.character.body.valueEnums;

import com.lilithsthrone.utils.Colour;

/**
 * Arbitrary measurements in increments of 1, going from 0 to 7.
 *
 * @since 0.1.83
 * @version 0.3.1
 * @author Innoxia
 */
public enum OrificePlasticity {

	/*-------MOULDABLE:---------*/

	/**Instantly returns to starting value after sex.*/
	ZERO_RUBBERY("rubbery",
			"[style.colourPlasticity(instantly recovers all of its original capacity)]",
			"[style.colourPlasticity(instantly return to their original capacity)]",
			0, 0, 100, Colour.GENERIC_SIZE_ONE),

	/**Quickly returns to starting value after sex, at a rate of 2 cm per 30 minutes.*/
	ONE_SPRINGY("springy",
			"[style.colourPlasticity(very rapidly recovers all of its original capacity)]",
			"[style.colourPlasticity(very rapidly recover all of their original capacity)]",
			1, 0, 2/(60*30f), Colour.GENERIC_SIZE_TWO),

	/**Returns to starting value after sex, at a rate of 2 cm per hour.*/
	TWO_TENSILE("tensile",
			"[style.colourPlasticity(recovers all of its original capacity at a modest rate)]",
			"[style.colourPlasticity(recover all of their original capacity at a modest rate)]",
			2, 0, 2/(60*60f), Colour.GENERIC_SIZE_THREE),

	/*-------NORMAL:---------*/

	/**Normal value, along with FOUR_ACCOMMODATING. Will slowly return to starting value after sex, at a rate of 2 cm per 3 hours.*/
	THREE_RESILIENT("resilient",
			"[style.colourPlasticity(slowly recovers all of its original capacity)]",
			"[style.colourPlasticity(slowly recover all of their original capacity)]",
			3, 0, 2/(60*60f*4), Colour.GENERIC_SIZE_FOUR),

	/**Normal value, along with THREE_RESILIENT. Will very slowly return to starting value after sex, at a rate of 2 cm per 12 hours.*/
	FOUR_ACCOMMODATING("accommodating",
			"[style.colourPlasticity(very slowly recovers all of its original capacity)]",
			"[style.colourPlasticity(very slowly recover all of their original capacity)]",
			4, 0, 2/(60*60f*12), Colour.GENERIC_SIZE_FIVE),

	/*-------STRETCHY:---------*/

	/**Will recover about 80% of its original size after sex, at a rate of 2 cm per 24 hours.*/
	FIVE_YIELDING("yielding",
			"[style.colourPlasticity(very slowly recovers [style.italicsMinorBad(most, not all)], of its original capacity)]",
			"[style.colourPlasticity(very slowly recover [style.italicsMinorBad(most, not all)], of their original capacity)]",
			5, 0.2f, 2/(60*60f*24), Colour.GENERIC_SIZE_SIX),

	/**Will only recover about 40% of its original size after sex, at a rate of 2 cm per 24 hours.*/
	SIX_MALLEABLE("malleable",
			"[style.colourPlasticity(very slowly recovers [style.italicsBad(only a fraction)] of its original capacity)]",
			"[style.colourPlasticity(very slowly recover [style.italicsBad(only a fraction)] of their original capacity)]",
			6, 0.6f, 2/(60*60f*24), Colour.GENERIC_SIZE_SEVEN),

	/**Will recover none of its original size after sex.*/
	SEVEN_MOULDABLE("mouldable",
			"remains [style.italicsTerrible(permanently stretched)] [style.colourPlasticity(and recovers none of its original capacity)]",
			"remains [style.italicsTerrible(permanently stretched)] [style.colourPlasticity(and recovers none of their original capacity)]",
			7, 1, 2/(60*60f*24), Colour.GENERIC_SIZE_EIGHT);

	private String descriptor;
	private String description;
	private String descriptionPlural;
	private int value;
	private float capacityIncreaseModifier;
	private float recoveryModifier;
	private Colour colour;

	private OrificePlasticity(String descriptor, String description, String descriptionPlural, int value, float capacityIncreaseModifier, float recoveryModifier, Colour colour) {
		this.descriptor = descriptor;
		this.description = description;
		this.descriptionPlural = descriptionPlural;
		this.value = value;
		this.capacityIncreaseModifier = capacityIncreaseModifier;
		this.recoveryModifier = recoveryModifier;
		this.colour = colour;
	}

	public static OrificePlasticity getElasticityFromInt(int value) {
		for(OrificePlasticity oe : OrificePlasticity.values()) {
			if(value == oe.getValue()) {
				return oe;
			}
		}
		return SEVEN_MOULDABLE;
	}

	/**
	 * To fit into a sentence: "You have a "+getDescriptor()+" ass."
	 */
	public String getDescriptor() {
		return descriptor;
	}
	public String getDescription() {
		return description;
	}
	public String getDescriptionPlural() {
		return descriptionPlural;
	}

	public int getValue() {
		return value;
	}

	public float getRecoveryModifier() {
		return recoveryModifier;
	}

	public float getCapacityIncreaseModifier() {
		return capacityIncreaseModifier;
	}

	public Colour getColour() {
		return colour;
	}
}


code:
package com.lilithsthrone.game.character.body.valueEnums;

/**
 * @since 0.1.83
 * @version 0.1.95
 * @author Innoxia
 */
public enum PenetrationModifier {

	SHEATHED("sheathed"),
	RIBBED("ribbed"),
	TENTACLED("tentacled"),
	KNOTTED("knotted"),
	TAPERED("tapered"),
	BLUNT("blunt"),
	FLARED("flared"),
	BARBED("barbed"),
	VEINY("veiny"),
	PREHENSILE("prehensile");

	private String descriptor;

	private PenetrationModifier(String descriptor) {
		this.descriptor = descriptor;
	}

	public String getName() {
		return descriptor;
	}
}


code:
package com.lilithsthrone.game.character.body.valueEnums;

import com.lilithsthrone.utils.Colour;

/**
 * @since 0.2.1
 * @version 0.2.1
 * @author Innoxia
 */
public enum PenisGirth {

	ZERO_SLENDER(0, "slender", Colour.GENERIC_SIZE_ONE),
	ONE_THIN(1, "thin", Colour.GENERIC_SIZE_TWO),
	TWO_AVERAGE(2, "averagely-girthed", Colour.GENERIC_SIZE_THREE),
	THREE_THICK(3, "thick", Colour.GENERIC_SIZE_FOUR),
	FOUR_FAT(4, "fat", Colour.GENERIC_SIZE_FIVE);

	private int value;
	private String descriptor;
	private Colour colour;

	private PenisGirth(int value, String descriptor, Colour colour) {
		this.value = value;
		this.descriptor = descriptor;
		this.colour = colour;
	}

	public int getValue() {
		return value;
	}

	public String getName() {
		return descriptor;
	}

	public static PenisGirth getPenisGirthFromInt(int size) {
		for(PenisGirth ls : PenisGirth.values()) {
			if(size == ls.getValue()) {
				return ls;
			}
		}
		return ZERO_SLENDER;
	}

	public static int getLargest() {
		int largest = ZERO_SLENDER.value;
		for(PenisGirth ls : PenisGirth.values()) {
			largest = Math.max(largest, ls.value);
		}
		return largest;
	}

	public Colour getColour() {
		return colour;
	}
}


code:
package com.lilithsthrone.game.character.body.valueEnums;

import com.lilithsthrone.utils.Colour;

/**
 * Sizes in cm.
 *
 * @since 0.1.0
 * @version 0.1.83
 * @author Innoxia
 */
public enum PenisSize {
	/**Utility*/
	NEGATIVE_UTILITY_VALUE("N/A", -1, -1, Colour.GENERIC_SIZE_ONE),

	/**Barely even anything there. (0-1 inches)*/
	ZERO_MICROSCOPIC("tiny", 0, 5, Colour.GENERIC_SIZE_TWO),

	/**Average size for a harpy. (2-3 inches)*/
	ONE_TINY("small", 5, 10, Colour.GENERIC_SIZE_TWO),

	/**Average size for all regular morphs. (4-7 inches)*/
	TWO_AVERAGE("average-sized", 10, 20, Colour.GENERIC_SIZE_THREE),

	/**Average size for a wolf morph. (8-11 inches)*/
	THREE_LARGE("large", 20, 30, Colour.GENERIC_SIZE_FOUR),

	/**Average size for a horse morph. (12-15 inches)*/
	FOUR_HUGE("huge", 30, 40, Colour.GENERIC_SIZE_FIVE),

	/**Straying into the bounds of "world record for a human". Large for a horse morph. (16-19 inches)*/
	FIVE_ENORMOUS("enormous", 40, 50, Colour.GENERIC_SIZE_SIX),

	/**This is just ridiculous... World record for a horse-morph. (20-23 inches)*/
	SIX_GIGANTIC("gigantic", 50, 60, Colour.GENERIC_SIZE_SEVEN),

	/**And this is for "extreme proportion" content. (24-40 inches)*/
	SEVEN_STALLION("stallion-sized", 60, 100, Colour.GENERIC_SIZE_EIGHT);

	private int minimumValue, maximumValue;
	private String descriptor;
	private Colour colour;

	private PenisSize(String descriptor, int minimumValue, int maximumValue, Colour colour) {
		this.descriptor = descriptor;
		this.minimumValue = minimumValue;
		this.maximumValue = maximumValue;
		this.colour=colour;
	}

	public int getMinimumValue() {
		return minimumValue;
	}

	public int getMaximumValue() {
		return maximumValue;
	}

	public int getMedianValue() {
		return minimumValue + ((maximumValue - minimumValue) / 2);
	}

	public static PenisSize getPenisSizeFromInt(int cm) {
		for(PenisSize ps : PenisSize.values()) {
			if(cm>=ps.getMinimumValue() && cm<ps.getMaximumValue()) {
				return ps;
			}
		}
		return SEVEN_STALLION;
	}

	/**
	 * To fit into a sentence: "Your cock is "+getDescriptor()+"." "Your "
	 * getDescriptor()+" cock is dribbling precum."
	 */
	public String getDescriptor() {
		return descriptor;
	}

	public Colour getColour() {
		return colour;
	}
}


code:
package com.lilithsthrone.game.character.body.valueEnums;

/**
 * @since 0.1.84
 * @version 0.1.84
 * @author Innoxia
 */
public enum PiercingType {

	EAR("ear"),
	NOSE("nose"),
	LIP("lip"),
	TONGUE("tongue"),
	NAVEL("navel"),
	NIPPLE("nipple"),
	VAGINA("vagina"),
	PENIS("penis");

	private String name;

	private PiercingType(String name) {
		this.name = name;
	}

	public String getName() {
		return name;
	}
}


code:
package com.lilithsthrone.game.character.body.valueEnums;

import java.util.List;

import com.lilithsthrone.utils.Colour;
import com.lilithsthrone.utils.Util;

/**
 * @since 0.2.?
 * @version 0.2.9
 * @author Pimgd
 */
public enum StartingSkinTone {

	VERY_LIGHT(Util.newArrayListOfValues(
			Colour.SKIN_PALE,
			Colour.SKIN_PINK,
			Colour.SKIN_BLUE,
			Colour.SKIN_IVORY,

			Colour.SLIME_BLUE,
			Colour.SLIME_PINK,

			Colour.COVERING_BLEACH_BLONDE,
			Colour.COVERING_GINGER,
			Colour.COVERING_LILAC,
			Colour.COVERING_PINK,
			Colour.COVERING_WHITE,

			Colour.HORN_WHITE,
			Colour.ORIFICE_INTERIOR,
			Colour.TONGUE,

			Colour.COVERING_BROWN,
			Colour.COVERING_BLONDE,
			Colour.COVERING_BLEACH_BLONDE,
			Colour.COVERING_GINGER,
			Colour.COVERING_WHITE,
			Colour.COVERING_PINK,

			Colour.COVERING_CLEAR,
			Colour.COVERING_NONE,

			Colour.EYE_BROWN,
			Colour.EYE_BLUE,
			Colour.EYE_GREEN,
			Colour.EYE_YELLOW,
			Colour.EYE_RED,
			Colour.EYE_PINK,
			Colour.EYE_ORANGE,
			Colour.EYE_BLACK)),

	LIGHT(Util.newArrayListOfValues(
			Colour.SKIN_LIGHT,
			Colour.SKIN_ROSY,
			Colour.SKIN_PINK,
			Colour.SKIN_BLUE,
			Colour.SKIN_IVORY,
			Colour.SKIN_LILAC,

			Colour.SLIME_BLUE,
			Colour.SLIME_PINK,
			Colour.SLIME_GREEN,
			Colour.SLIME_RED,

			Colour.COVERING_WHITE,
			Colour.COVERING_BLUE,
			Colour.COVERING_LILAC,
			Colour.COVERING_PINK,
			Colour.COVERING_RED,
			Colour.COVERING_GREEN,
			Colour.COVERING_YELLOW,
			Colour.COVERING_ORANGE,
			Colour.COVERING_GINGER,
			Colour.COVERING_BLEACH_BLONDE,

			Colour.HORN_WHITE,
			Colour.ORIFICE_INTERIOR,
			Colour.TONGUE,

			Colour.COVERING_BROWN,
			Colour.COVERING_BLONDE,
			Colour.COVERING_BLEACH_BLONDE,
			Colour.COVERING_GINGER,
			Colour.COVERING_RED,
			Colour.COVERING_WHITE,
			Colour.COVERING_BLUE,
			Colour.COVERING_PURPLE,
			Colour.COVERING_PINK,
			Colour.COVERING_GREEN,

			Colour.COVERING_CLEAR,
			Colour.COVERING_NONE,

			Colour.EYE_BROWN,
			Colour.EYE_BLUE,
			Colour.EYE_GREEN,
			Colour.EYE_YELLOW,
			Colour.EYE_RED,
			Colour.EYE_PINK,
			Colour.EYE_ORANGE,
			Colour.EYE_BLACK)),

	OLIVE(Util.newArrayListOfValues(
			Colour.SKIN_OLIVE,
			Colour.SKIN_TANNED,
			Colour.SKIN_RED,
			Colour.SKIN_BROWN,
			Colour.SKIN_PINK,
			Colour.SKIN_BLUE,
			Colour.SKIN_LILAC,
			Colour.SKIN_PURPLE,
			Colour.SKIN_IVORY,

			Colour.SLIME_BLUE,
			Colour.SLIME_PINK,
			Colour.SLIME_GREEN,
			Colour.SLIME_RED,
			Colour.SLIME_BLACK,

			Colour.COVERING_BLACK,
			Colour.COVERING_WHITE,
			Colour.COVERING_BLUE,
			Colour.COVERING_LILAC,
			Colour.COVERING_PINK,
			Colour.COVERING_RED,
			Colour.COVERING_GREEN,
			Colour.COVERING_YELLOW,
			Colour.COVERING_ORANGE,
			Colour.COVERING_GINGER,
			Colour.COVERING_BLEACH_BLONDE,

			Colour.HORN_WHITE,
			Colour.ORIFICE_INTERIOR,
			Colour.TONGUE,

			Colour.COVERING_BROWN,
			Colour.COVERING_BROWN_DARK,
			Colour.COVERING_BLACK,
			Colour.COVERING_BLONDE,
			Colour.COVERING_BLEACH_BLONDE,
			Colour.COVERING_RED,
			Colour.COVERING_WHITE,
			Colour.COVERING_BLUE,
			Colour.COVERING_PURPLE,
			Colour.COVERING_PINK,
			Colour.COVERING_GREEN,

			Colour.COVERING_CLEAR,
			Colour.COVERING_NONE,

			Colour.EYE_BROWN,
			Colour.EYE_BLUE,
			Colour.EYE_GREEN,
			Colour.EYE_YELLOW,
			Colour.EYE_RED,
			Colour.EYE_PINK,
			Colour.EYE_ORANGE,
			Colour.EYE_BLACK)),

	DARK(Util.newArrayListOfValues(
			Colour.SKIN_DARK,
			Colour.SKIN_RED,
			Colour.SKIN_BROWN,
			Colour.SKIN_LILAC,
			Colour.SKIN_PURPLE,

			Colour.SLIME_BLUE,
			Colour.SLIME_GREEN,
			Colour.SLIME_RED,
			Colour.SLIME_BLACK,

			Colour.COVERING_BLACK,
			Colour.COVERING_WHITE,
			Colour.COVERING_BLUE,
			Colour.COVERING_LILAC,
			Colour.COVERING_PINK,
			Colour.COVERING_RED,
			Colour.COVERING_GREEN,
			Colour.COVERING_YELLOW,
			Colour.COVERING_ORANGE,

			Colour.HORN_WHITE,
			Colour.ORIFICE_INTERIOR,
			Colour.TONGUE,

			Colour.COVERING_BROWN,
			Colour.COVERING_BROWN_DARK,
			Colour.COVERING_BLACK,
			Colour.COVERING_RED,
			Colour.COVERING_WHITE,
			Colour.COVERING_BLUE,
			Colour.COVERING_PURPLE,
			Colour.COVERING_PINK,
			Colour.COVERING_GREEN,

			Colour.COVERING_CLEAR,
			Colour.COVERING_NONE,

			Colour.EYE_BROWN,
			Colour.EYE_YELLOW,
			Colour.EYE_RED,
			Colour.EYE_PINK,
			Colour.EYE_ORANGE,
			Colour.EYE_BLACK)),

	VERY_DARK(Util.newArrayListOfValues(
			Colour.SKIN_EBONY,
			Colour.SKIN_CHOCOLATE,
			Colour.SKIN_RED,
			Colour.SKIN_BROWN,
			Colour.SKIN_PURPLE,

			Colour.SLIME_BLUE,
			Colour.SLIME_GREEN,
			Colour.SLIME_RED,
			Colour.SLIME_BLACK,

			Colour.COVERING_BLACK,
			Colour.COVERING_WHITE,
			Colour.COVERING_BLUE,
			Colour.COVERING_RED,
			Colour.COVERING_GREEN,
			Colour.COVERING_YELLOW,
			Colour.COVERING_ORANGE,

			Colour.HORN_WHITE,
			Colour.ORIFICE_INTERIOR,
			Colour.TONGUE,

			Colour.COVERING_BROWN,
			Colour.COVERING_BROWN_DARK,
			Colour.COVERING_BLACK,
			Colour.COVERING_RED,
			Colour.COVERING_WHITE,
			Colour.COVERING_BLUE,
			Colour.COVERING_PURPLE,
			Colour.COVERING_GREEN,

			Colour.COVERING_CLEAR,
			Colour.COVERING_NONE,

			Colour.EYE_BROWN,
			Colour.EYE_YELLOW,
			Colour.EYE_RED,
			Colour.EYE_PINK,
			Colour.EYE_ORANGE,
			Colour.EYE_BLACK));

	private List<Colour> associatedColours;

	private StartingSkinTone(List<Colour> associatedColours) {
		this.associatedColours = associatedColours;
	}

	public List<Colour> getAssociatedColours() {
		return associatedColours;
	}

}


code:
package com.lilithsthrone.game.character.body.valueEnums;

import com.lilithsthrone.utils.Colour;

/**
 * Arbitrary measurements in increments of 1, going from 0 to 7.
 *
 * @since 0.1.0
 * @version 0.1.83
 * @author Innoxia
 */
public enum TesticleSize {

	/**Little bumps under the skin.*/
	ZERO_VESTIGIAL("vestigial", 0, Colour.GENERIC_SIZE_ONE),

	/**Small for a human.*/
	ONE_TINY("tiny", 1, Colour.GENERIC_SIZE_TWO),

	/**Average for a human.*/
	TWO_AVERAGE("average-sized", 2, Colour.GENERIC_SIZE_THREE),

	/**Large for a human. Average for a dog or wolf-morph.*/
	THREE_LARGE("large", 3, Colour.GENERIC_SIZE_FOUR),

	/**Unrealistically large for a human. Average for a horse-morph.*/
	FOUR_HUGE("huge", 4, Colour.GENERIC_SIZE_FIVE),

	/**Large for a horse-morph.*/
	FIVE_MASSIVE("massive", 5, Colour.GENERIC_SIZE_SIX),

	/**Getting pretty absurd.*/
	SIX_GIGANTIC("gigantic", 6, Colour.GENERIC_SIZE_SEVEN),

	/**"Extreme proportion" content.*/
	SEVEN_ABSURD("absurdly enormous", 7, Colour.GENERIC_SIZE_EIGHT);

	private int value;
	private String descriptor;
	private Colour colour;

	private TesticleSize(String descriptor, int value, Colour colour) {
		this.descriptor = descriptor;
		this.value = value;
		this.colour=colour;
	}

	public int getValue() {
		return value;
	}

	public static TesticleSize getTesticleSizeFromInt(int index) {
		for(TesticleSize ts : TesticleSize.values()) {
			if(index == ts.getValue()) {
				return ts;
			}
		}
		return SEVEN_ABSURD;
	}

	/**
	 * To fit into a sentence: "Your balls are "+getDescriptor()+"."
	 */
	public String getDescriptor() {
		return descriptor;
	}

	public Colour getColour() {
		return colour;
	}
}


code:
package com.lilithsthrone.game.character.body.valueEnums;

/**
 * Sizes in cm.
 *
 * @since 0.1.83
 * @version 0.1.83
 * @author Innoxia
 */
public enum TongueLength {

	ZERO_NORMAL("normal-sized", 0, 5),

	ONE_LONG("long", 5, 10),

	TWO_VERY_LONG("very long", 10, 20),

	THREE_EXTREMELY_LONG("extremely long", 20, 30),

	FOUR_ABSURDLY_LONG("absurdly long", 30, 60);

	private int minimumValue, maximumValue;
	private String descriptor;

	private TongueLength(String descriptor, int minimumValue, int maximumValue) {
		this.descriptor = descriptor;
		this.minimumValue = minimumValue;
		this.maximumValue = maximumValue;
	}

	public int getMinimumValue() {
		return minimumValue;
	}

	public int getMaximumValue() {
		return maximumValue;
	}

	public int getMedianValue() {
		return minimumValue + ((maximumValue - minimumValue) / 2);
	}

	public static TongueLength getTongueLengthFromInt(int cm) {
		for(TongueLength ps : TongueLength.values()) {
			if(cm>=ps.getMinimumValue() && cm<ps.getMaximumValue()) {
				return ps;
			}
		}
		return FOUR_ABSURDLY_LONG;
	}

	public String getDescriptor() {
		return descriptor;
	}
}


code:
package com.lilithsthrone.game.character.body.valueEnums;

/**
 * @since 0.1.83
 * @version 0.1.83
 * @author Innoxia
 */
public enum TongueModifier {

	RIBBED("ribbed"),
	TENTACLED("tentacled"),
	BIFURCATED("bifurcated");

	private String descriptor;

	private TongueModifier(String descriptor) {
		this.descriptor = descriptor;
	}

	public String getName() {
		return descriptor;
	}
}


code:
package com.lilithsthrone.game.character.body.valueEnums;

import com.lilithsthrone.utils.Colour;

/**
 * Arbitrary measurements in increments of 1, going from 0 to 7.
 *
 * @since 0.1.0
 * @version 0.3.1
 * @author Innoxia
 */
public enum Wetness {

	ZERO_DRY("dry", 0, 101, 101, Colour.GENERIC_SIZE_ONE),

	ONE_SLIGHTLY_MOIST("slightly moist", 1, 100, 100, Colour.GENERIC_SIZE_TWO),

	TWO_MOIST("moist", 2, 50, 50, Colour.GENERIC_SIZE_THREE),

	THREE_WET("wet", 3, 25, 25, Colour.GENERIC_SIZE_FOUR),

	FOUR_SLIMY("slimy", 4, 0, 0, Colour.GENERIC_SIZE_FIVE),

	FIVE_SLOPPY("sloppy", 5, 0, 0, Colour.GENERIC_SIZE_SIX),

	SIX_SOPPING_WET("sopping wet", 6, 0, 0, Colour.GENERIC_SIZE_SEVEN),

	SEVEN_DROOLING("drooling", 7, 0, 0, Colour.GENERIC_SIZE_EIGHT);

	private int wetness;
	private int arousalNeededToGetVaginaWet;
	private int arousalNeededToGetAssWet;
	private String descriptor;
	private Colour colour;

	private Wetness(String descriptor, int wetness, int arousalNeededToGetVaginaWet, int arousalNeededToGetAssWet, Colour colour) {
		this.descriptor = descriptor;
		this.wetness = wetness;
		this.arousalNeededToGetVaginaWet = arousalNeededToGetVaginaWet;
		this.arousalNeededToGetAssWet = arousalNeededToGetAssWet;
		this.colour = colour;
	}

	public static Wetness valueOf(int wetness) {
		for(Wetness w : Wetness.values()) {
			if(wetness == w.getValue()) {
				return w;
			}
		}
		return SEVEN_DROOLING;
	}

	/**
	 * To fit into a sentence such as:

	 * "Your vagina is "+getDescriptor()+"."

	 * "Your "+getDescriptor()+" asshole is stretched wide open."
	 */
	public String getDescriptor() {
		return descriptor;
	}

	public int getValue() {
		return wetness;
	}

	public int getArousalNeededToGetVaginaWet() {
		return arousalNeededToGetVaginaWet;
	}

	public int getArousalNeededToGetAssWet() {
		return arousalNeededToGetAssWet;
	}

	public Colour getColour() {
		return colour;
	}
}


code:
package com.lilithsthrone.game.character.body.valueEnums;

import com.lilithsthrone.utils.Colour;

/**
 * @since 0.1.95
 * @version 0.3.1
 * @author Innoxia
 */
public enum WingSize {

	ZERO_TINY(0, "tiny", Colour.GENERIC_SIZE_ONE),
	ONE_SMALL(1, "small", Colour.GENERIC_SIZE_TWO),
	TWO_AVERAGE(2, "average-sized", Colour.GENERIC_SIZE_THREE),
	THREE_LARGE(3, "large", Colour.GENERIC_SIZE_FOUR),
	FOUR_HUGE(4, "huge", Colour.GENERIC_SIZE_FIVE);

	private int value;
	private String descriptor;
	private Colour colour;

	private WingSize(int value, String descriptor, Colour colour) {
		this.value = value;
		this.descriptor = descriptor;
		this.colour = colour;
	}

	public int getValue() {
		return value;
	}

	public String getName() {
		return descriptor;
	}

	public static WingSize getWingSizeFromInt(int size) {
		for(WingSize ls : WingSize.values()) {
			if(size == ls.getValue()) {
				return ls;
			}
		}
		return ZERO_TINY;
	}

	public static int getLargest() {
		int largest = ZERO_TINY.value;
		for(WingSize ls : WingSize.values()) {
			largest = Math.max(largest, ls.value);
		}
		return largest;
	}

	public Colour getColour() {
		return colour;
	}
}


code:
package com.lilithsthrone.game.character.effects;

import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map.Entry;

import com.lilithsthrone.game.character.GameCharacter;
import com.lilithsthrone.game.character.attributes.Attribute;
import com.lilithsthrone.game.character.attributes.CorruptionLevel;
import com.lilithsthrone.game.combat.Spell;
import com.lilithsthrone.game.combat.SpellSchool;
import com.lilithsthrone.game.combat.SpellUpgrade;
import com.lilithsthrone.utils.Colour;
import com.lilithsthrone.utils.SvgUtil;
import com.lilithsthrone.utils.Util;

/**
 * @since 0.1.0
 * @version 0.3.4
 * @author Innoxia
 */
public abstract class AbstractPerk {

	private int renderingPriority;
	protected String name;
	private List<Colour> colours;
	private boolean equippableTrait;

	private Spell spell;
	private SpellUpgrade spellUpgrade;
	private SpellSchool school;

	// Attributes modified by this Virtue:
	private HashMap<Attribute, Integer> attributeModifiers;

	private PerkCategory perkCategory;

	protected String pathName;
	private String SVGString;

	private List<String> extraEffects;

	private List<String> modifiersList;

	public AbstractPerk(int renderingPriority,
			boolean major,
			String name,
			PerkCategory perkCategory,
			String pathName,
			Colour colour,
			HashMap<Attribute, Integer> attributeModifiers,
			List<String> extraEffects) {
		this(renderingPriority,
				major,
				name,
				perkCategory,
				pathName,
				colour,
				attributeModifiers,
				extraEffects,
				null,
				null,
				null);
	}

	public AbstractPerk(int renderingPriority,
			boolean major,
			String name,
			PerkCategory perkCategory,
			String pathName,
			Colour colour,
			HashMap<Attribute, Integer> attributeModifiers,
			List<String> extraEffects,
			Spell spell,
			SpellUpgrade spellUpgrade,
			SpellSchool school) {
		this(renderingPriority,
				major,
				name,
				perkCategory,
				pathName,
				Util.newArrayListOfValues(colour),
				attributeModifiers,
				extraEffects,
				spell,
				spellUpgrade,
				school);
	}

	public AbstractPerk(int renderingPriority,
			boolean major,
			String name,
			PerkCategory perkCategory,
			String pathName,
			List<Colour> colours,
			HashMap<Attribute, Integer> attributeModifiers,
			List<String> extraEffects,
			Spell spell,
			SpellUpgrade spellUpgrade,
			SpellSchool school) {

		this.renderingPriority = renderingPriority;
		this.name = name;
		this.colours = colours;

		this.equippableTrait = major;

		this.perkCategory = perkCategory;

		this.attributeModifiers = attributeModifiers;

		if(extraEffects!=null) {
			this.extraEffects = extraEffects;
		} else {
			this.extraEffects = new ArrayList<>();
		}

		this.pathName = pathName;
		if(pathName!=null) {
			generateSVGImage(pathName, colours);
		}

		modifiersList = new ArrayList<>();

		this.spell = spell;
		this.spellUpgrade = spellUpgrade;
		this.school = school;
	}

	@Override
	public boolean equals(Object o) {
		if(o instanceof AbstractPerk) {
			if(((AbstractPerk)o).getName(null).equals(this.getName(null))
					&& ((AbstractPerk)o).getAttributeModifiers(null) == this.getAttributeModifiers(null)){
				return true;
			}
		}
		return false;
	}

	@Override
	public int hashCode() {
		int result = 17;
		result = 31 * result + this.getName(null).hashCode();
		if(this.getAttributeModifiers(null)!=null) {
			result = 31 * result + this.getAttributeModifiers(null).hashCode();
		}
		return result;
	}

	protected void generateSVGImage(String pathName, List<Colour> colours) {
		try {
			InputStream is = this.getClass().getResourceAsStream("/com/lilithsthrone/res/" + pathName + ".svg");
			if(is==null) {
				System.err.println("Error! Perk icon file does not exist (Trying to read from '"+pathName+"')!");
			}
			SVGString = Util.inputStreamToString(is);

			SVGString = SvgUtil.colourReplacement(name.replaceAll(" ", ""), colours.get(0), colours.size()>=2?colours.get(1):null, colours.size()>=3?colours.get(2):null, SVGString);

			is.close();

		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	public boolean isAlwaysAvailable() {
		return false;
	}

	/**
	 * Override this and return true if the perk is one that is unlock via special in-game events.
	 * @return true If this perk does not appear in the perk tree, but is otherwise obtainable through special means.
	 */
	public boolean isHiddenPerk() {
		return false;
	}

	/**
	 * @return true if this a perk that's granted as part of an NPC's background.
	 */
	public boolean isBackgroundPerk() {
		return false;
	}

	public String getName(GameCharacter owner) {
		return name;
	}

	public Colour getColour() {
		return colours.get(0);
	}

	public boolean isEquippableTrait() {
		return equippableTrait;
	}

	public abstract String getDescription(GameCharacter target);

	public List<String> getModifiersAsStringList(GameCharacter character) {
		modifiersList.clear();

		if (this.getAttributeModifiers(character) != null) {
			for (Entry<Attribute, Integer> e : this.getAttributeModifiers(character).entrySet()) {
				modifiersList.add(""+ (e.getValue() > 0 ? "+" : "")+ e.getValue()+ ""
						+ " "+ Util.capitaliseSentence(e.getKey().getAbbreviatedName())+ "");
			}
		}

		return Util.mergeLists(modifiersList, getExtraEffects());
	}

	public HashMap<Attribute, Integer> getAttributeModifiers(GameCharacter character) {
		return attributeModifiers;
	}

	public String applyPerkGained(GameCharacter character) {
		return "";
	};

	public String applyPerkLost(GameCharacter character) {
		return "";
	};

	public CorruptionLevel getAssociatedCorruptionLevel() {
		return CorruptionLevel.ZERO_PURE;
	}

	public int getRenderingPriority() {
		return renderingPriority;
	}

	public List<String> getExtraEffects() {
		return extraEffects;
	}

	public String getSVGString(GameCharacter owner) {
		return SVGString;
	}

	public PerkCategory getPerkCategory() {
		return perkCategory;
	}

	public Spell getSpell() {
		return spell;
	}

	public SpellUpgrade getSpellUpgrade() {
		return spellUpgrade;
	}

	public SpellSchool getSchool() {
		return school;
	}
}


code:
package com.lilithsthrone.game.character.effects;

import java.util.HashSet;
import java.util.Set;

import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;

import com.lilithsthrone.game.character.CharacterUtils;
import com.lilithsthrone.game.character.body.types.FluidType;
import com.lilithsthrone.utils.XMLSaving;

/**
 * @since 0.2.0
 * @version 0.3.1
 * @author Innoxia
 */
public class Addiction implements XMLSaving {

	private FluidType fluid;
	private long lastTimeSatisfied;
	private Set<String> providerIDs;

	public Addiction(FluidType fluid, long lastTimeSatisfied) {
		this.fluid = fluid;
		this.lastTimeSatisfied = lastTimeSatisfied;
		this.providerIDs = new HashSet<>();
	}

	public Addiction(FluidType fluid, long lastTimeSatisfied, String providerID) {
		this.fluid = fluid;
		this.lastTimeSatisfied = lastTimeSatisfied;
		this.providerIDs = new HashSet<>();
		this.providerIDs.add(providerID);
	}

	public Addiction(FluidType fluid, long lastTimeSatisfied, Set<String> providerIDs) {
		this.fluid = fluid;
		this.lastTimeSatisfied = lastTimeSatisfied;
		this.providerIDs = providerIDs;
	}

	@Override
	public boolean equals(Object o) {
		if(super.equals(o)) {
			return (o instanceof Addiction)
					&& ((Addiction)o).getFluid().equals(this.getFluid())
					&& ((Addiction)o).getLastTimeSatisfied() == this.getLastTimeSatisfied()
					&& ((Addiction)o).getProviderIDs().equals(this.getProviderIDs());
		} else {
			return false;
		}
	}

	@Override
	public int hashCode() {
		int result = 17;
		result = 31 * result + this.getFluid().hashCode();
		result = 31 * result + (int)this.getLastTimeSatisfied();
		result = 31 * result + this.getProviderIDs().hashCode();
		return result;
	}

	@Override
	public Element saveAsXML(Element parentElement, Document doc) {
		Element element = doc.createElement("addiction");
		parentElement.appendChild(element);

		CharacterUtils.addAttribute(doc, element, "fluid", this.getFluid().toString());
		CharacterUtils.addAttribute(doc, element, "lastTimeSatisfied", String.valueOf(this.getLastTimeSatisfied()));

		Element innerElement = doc.createElement("providerIDs");
		element.appendChild(innerElement);
		for(String id : this.getProviderIDs()) {
			Element idElement = doc.createElement("id");
			innerElement.appendChild(idElement);
			CharacterUtils.addAttribute(doc, idElement, "value", id);
		}

		return element;
	}

	public static Addiction loadFromXML(StringBuilder log, Element parentElement, Document doc) {
		Set<String> IDs = new HashSet<>();
		NodeList idList = ((Element)parentElement.getElementsByTagName("providerIDs").item(0)).getElementsByTagName("id");
		for(int i = 0; i < idList.getLength(); i++){
			IDs.add(((Element)idList.item(i)).getAttribute("value"));
		}

		return new Addiction(FluidType.getTypeFromString(parentElement.getAttribute("fluid")),
				Long.valueOf(parentElement.getAttribute("lastTimeSatisfied")),
				IDs);
	}

	public FluidType getFluid() {
		return fluid;
	}

	public void setFluid(FluidType fluid) {
		this.fluid = fluid;
	}

	public long getLastTimeSatisfied() {
		return lastTimeSatisfied;
	}

	public void setLastTimeSatisfied(long lastTimeSatisfied) {
		this.lastTimeSatisfied = lastTimeSatisfied;
	}

	public Set<String> getProviderIDs() {
		return providerIDs;
	}

	public void addProviderID(String providerID) {
		getProviderIDs().add(providerID);
	}
}