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

import com.lilithsthrone.game.character.GameCharacter;
import com.lilithsthrone.game.character.body.types.BodyCoveringType;
import com.lilithsthrone.game.character.body.types.TailType;
import com.lilithsthrone.game.character.effects.StatusEffect;
import com.lilithsthrone.game.dialogue.utils.UtilText;
import com.lilithsthrone.main.Main;
import com.lilithsthrone.utils.Util;

/**
 * @since 0.1.0
 * @version 0.3.1
 * @author Innoxia
 */
public class Tail implements BodyPartInterface {

	public static final int MAXIMUM_COUNT = 9;

	protected TailType type;
	protected int tailCount;

	public Tail(TailType type) {
		this.type = type;
		tailCount = 1;
	}

	@Override
	public TailType getType() {
		return type;
	}

	@Override
	public String getDeterminer(GameCharacter gc) {
		return type.getDeterminer(gc);
	}

	@Override
	public String getName(GameCharacter gc) {
		return type.getName(gc);
	}

	@Override
	public String getNameSingular(GameCharacter gc) {
		return type.getNameSingular(gc);
	}

	@Override
	public String getNamePlural(GameCharacter gc) {
		return type.getNamePlural(gc);
	}

	@Override
	public String getDescriptor(GameCharacter gc) {
		return type.getDescriptor(gc);
	}

	public String setType(GameCharacter owner, TailType type) {
		if(!Main.game.isStarted() || owner==null) {
			this.type = type;
			if(owner!=null) {
				owner.postTransformationCalculation();
			}
			return "";
		}

		if (type == getType()) {
			if(type == TailType.NONE) {
				return UtilText.parse(owner, "
[style.colourDisabled([npc.Name] already [npc.verb(lack)] a tail, so nothing happens...)]
");

			} else {
				return UtilText.parse(owner, "
[style.colourDisabled([npc.Name] already [npc.has] the [npc.tail] of [npc.a_tailRace], so nothing happens...)]
");
			}
		}

		UtilText.transformationContentSB.setLength(0);

		if (owner.isPlayer()) {
			if(this.type == TailType.NONE) {
				UtilText.transformationContentSB.append(
						"
"
							+ "You feel a strange bubbling sensation building up in your lower back, and after just a moment you feel something pushing out from under your [pc.skin].");
			} else {
				UtilText.transformationContentSB.append(
						"
"
							+ (owner.getTailCount()==1
								?"You feel your [pc.tail] growing hot and itchy, and after just a moment it starts to transform."
								:"You feel your [pc.tails] growing hot and itchy, and after just a moment they start to transform."));
			}

		} else {
			if(this.type == TailType.NONE) {
				UtilText.transformationContentSB.append(
						"
"
							+ "[npc.Name] rubs at [npc.her] lower back as [npc.she] feels it growing hot and sensitive, and as [npc.she] does so, something starts pushing out from under [npc.her] [npc.skin].");
			} else {
				UtilText.transformationContentSB.append(
						"
"
							+ (owner.getTailCount()==1
								?"[npc.Name] feels [npc.her] [npc.tail] growing hot and itchy, and after just a moment it starts to transform."
								:"[npc.Name] feels [npc.her] [npc.tails] growing hot and itchy, and after just a moment they start to transform."));
			}
		}

		switch (type) {
			case NONE:
				if (owner.isPlayer()) {
					UtilText.transformationContentSB.append(
							(owner.getTailCount()==1
								?" You gasp as you feel your [pc.tail] shrinking down and disappearing into your lower back."
								:" You gasp as you feel your [pc.tails] shrinking down and disappearing into your lower back")
							+ "
"
							+ "You now have [style.boldTfGeneric(no tail)]");
				} else {
					UtilText.transformationContentSB.append(
							(owner.getTailCount()==1
								?" [npc.She] gasps as [npc.she] feels [npc.her] [npc.tail] shrinking down and disappearing into [npc.her] lower back."
								:" [npc.She] gasps as [npc.she] feels [npc.her] [npc.tails] shrinking down and disappearing into [npc.her] lower back.")
							+ "
"
							+ "[npc.Name] now has [style.boldTfGeneric(no tail)]");
				}
				break;
			case CAT_MORPH: case CAT_MORPH_SHORT: case CAT_MORPH_TUFTED:
				if (owner.isPlayer()) {
					UtilText.transformationContentSB.append(
							(owner.getTailCount()==1
								?" A furry, cat-like tail sprouts from just above your ass"+(type==TailType.CAT_MORPH_SHORT?".":", rapidly growing in size until it's almost as long as one of your legs.")
									+(type==TailType.CAT_MORPH_SHORT
										?""
										: " You quickly realise that you have a decent amount of control over it, and you can twist it almost anywhere you please.")
									+(type==TailType.CAT_MORPH_TUFTED
										?" At the end of the tail there is a bunch of fur giving it a tuft."
										:"")
									+ "
"
									+ "You now have a [style.boldCatMorph(cat-like tail)]"
								:" [pc.TailCount] furry, cat-like tails sprout from just above your ass"+(type==TailType.CAT_MORPH_SHORT?".":", rapidly growing in size until they're each almost as long as one of your legs.")
									+(type==TailType.CAT_MORPH_SHORT
										?""
										: " You quickly realise that you have a decent amount of control over them, and you can twist them almost anywhere you please.")
									+(type==TailType.CAT_MORPH_TUFTED
										?" At the end of the tails there is a bunch of fur giving it a tuft."
										:"")
									+ "
"
									+ "You now have [pc.tailCount] [style.boldCatMorph(cat-like tails)]")
							);
				} else {
					UtilText.transformationContentSB.append(
							(owner.getTailCount()==1
								?" A furry, cat-like tail sprouts from just above [npc.her] ass"+(type==TailType.CAT_MORPH_SHORT?".":", rapidly growing in size until it's almost as long as one of [npc.her] legs.")
									+(type==TailType.CAT_MORPH_SHORT?"": " [npc.She] quickly realises that [npc.she] has a decent amount of control over it, and can twist it almost anywhere [npc.she] pleases.")
									+(type==TailType.CAT_MORPH_TUFTED?" At the end of the tail there is a bunch of fur giving it a tuft.":"")
									+ "
"
									+ "[npc.Name] now has a [style.boldCatMorph(cat-like tail)]"
								:" [npc.TailCount] furry, cat-like tails sprout from just above [npc.her] ass"+(type==TailType.CAT_MORPH_SHORT?".":", rapidly growing in size until they're each almost as long as one of [npc.her] legs.")
									+(type==TailType.CAT_MORPH_SHORT?"":  " [npc.She] quickly realises that [npc.she] has a decent amount of control over them, and can twist them almost anywhere [npc.she] pleases.")
									+(type==TailType.CAT_MORPH_TUFTED?" At the end of the tails there is a bunch of fur giving it a tuft.":"")
									+ "
"
									+ "[npc.Name] now has [npc.tailCount] [style.boldCatMorph(cat-like tails)]")
							);
				}
				break;
			case DEMON_COMMON:
				if (!owner.isShortStature()) {
					UtilText.transformationContentSB.append(
							(owner.getTailCount()==1
								?" A demonic, spaded tail sprouts from just above [npc.her] ass, rapidly growing in size until it's slightly longer than one of [npc.her] [npc.legs]."
									+ " [npc.She] quickly [npc.verb(realise)] that [npc.she] [npc.has] complete control over where it goes, allowing [npc.herHim] to use it like a third limb."
									+ "
"
									+ "[npc.Name] now has a [style.boldDemon(demonic tail)]"
								:" [npc.TailCount] demonic, spaded tails sprout from just above [npc.her] ass, rapidly growing in size until they're slightly longer than one of [npc.her] [npc.legs]."
									+ " [npc.She] quickly [npc.verb(realise)] that [npc.she] [npc.has] complete control over where they go, allowing [npc.herHim] to use them like extra limbs."
									+ "
"
									+ "[npc.Name] now has [npc.tailCount] [style.boldDemon(demonic tails)]")
							);
				} else {
					UtilText.transformationContentSB.append(
							(owner.getTailCount()==1
								?" A demonic, spaded tail sprouts from just above [npc.her] ass, rapidly growing in size until it's slightly longer than one of [npc.her] [npc.legs]."
									+ " [npc.She] quickly [npc.verb(realise)] that [npc.she] [npc.has] complete control over where it goes, allowing [npc.herHim] to use it like a third limb."
									+ "
"
									+ "[npc.Name] now has an [style.boldImp(impish tail)]"
								:" [npc.TailCount] demonic, spaded tails sprout from just above [npc.her] ass, rapidly growing in size until they're slightly longer than one of [npc.her] [npc.legs]."
									+ " [npc.She] quickly [npc.verb(realise)] that [npc.she] [npc.has] complete control over where they go, allowing [npc.herHim] to use them like extra limbs."
									+ "
"
									+ "[npc.Name] now has [npc.tailCount] [style.boldImp(impish tails)]")
							);
				}
				break;
			case DEMON_HAIR_TIP:
				owner.getBodyCoveringTypesDiscovered().add(BodyCoveringType.HAIR_DEMON);
				if (!owner.isShortStature()) {
					UtilText.transformationContentSB.append(
							(owner.getTailCount()==1
								?" A demonic, spaded tail sprouts from just above [npc.her] ass, rapidly growing in size until it's slightly longer than one of [npc.her] [npc.legs]."
									+ " [npc.She] quickly [npc.verb(realise)] that [npc.she] [npc.has] complete control over where it goes, allowing [npc.herHim] to use it like a third limb."
									+ "
"
									+ "[npc.Name] now [npc.has] a [style.boldDemon(demonic tail)], covered in [npc.tailFullDescription(true)] and tipped with "
										+owner.getCovering(BodyCoveringType.HAIR_DEMON).getFullDescription(owner, true)+".
"
								:" [npc.TailCount] demonic, spaded tails sprout from just above [npc.her] ass, rapidly growing in size until they're slightly longer than one of [npc.her] [npc.legs]."
									+ " [npc.She] quickly [npc.verb(realise)] that [npc.she] [npc.has] complete control over where they go, allowing [npc.herHim] to use them like extra limbs."
									+ "
"
									+ "[npc.Name] now [npc.has] [npc.tailCount] [style.boldDemon(demonic tails)], covered in [npc.tailFullDescription(true)] and tipped with "
										+owner.getCovering(BodyCoveringType.HAIR_DEMON).getFullDescription(owner, true)+".
")
							);
				} else {
					UtilText.transformationContentSB.append(
							(owner.getTailCount()==1
								?" A demonic, spaded tail sprouts from just above [npc.her] ass, rapidly growing in size until it's slightly longer than one of [npc.her] [npc.legs]."
									+ " [npc.She] quickly  [npc.verb(realise)] that [npc.she] [npc.has] complete control over where it goes, allowing [npc.herHim] to use it like a third limb."
									+ "
"
									+ "[npc.Name] now [npc.has] an [style.boldImp(impish tail)], covered in [npc.tailFullDescription(true)] and tipped with "
										+owner.getCovering(BodyCoveringType.HAIR_DEMON).getFullDescription(owner, true)+".
"
								:" [npc.TailCount] demonic, spaded tails sprout from just above [npc.her] ass, rapidly growing in size until they're slightly longer than one of [npc.her] [npc.legs]."
									+ " [npc.She] quickly [npc.verb(realise)] that [npc.she] [npc.has] complete control over where they go, allowing [npc.herHim] to use them like extra limbs."
									+ "
"
									+ "[npc.Name] now [npc.has] [npc.tailCount] [style.boldImp(impish tails)], covered in [npc.tailFullDescription(true)] and tipped with "
										+owner.getCovering(BodyCoveringType.HAIR_DEMON).getFullDescription(owner, true)+".
")
							);
				}
				break;
			case DEMON_HORSE:
				UtilText.transformationContentSB.append(
						(owner.getTailCount()==1
							?" A horse-like tail sprouts from just above [npc.her] ass, rapidly growing in length until it hangs to just over half-way down [npc.her] legs."
								+ " [npc.She] quickly [npc.verb(discover)] that [npc.her] control over it is limited to swishing it from side to side."
								+ "
"
								+ "[npc.Name] now [npc.has] a [style.boldDemon(demonic, horse-like tail)]"
							:" [npc.TailCount] horse-like tails sprout from just above [npc.her] ass, rapidly growing in length until they hang to just over half-way down [npc.her] legs."
								+ " [npc.She] quickly [npc.verb(discover)] that [npc.her] control over them is limited to swishing them from side to side."
								+ "
"
								+ "[npc.Name] now [npc.has] [npc.tailCount] [style.boldDemon(demonic, horse-like tails)]")
						);
				break;
			case DOG_MORPH: case DOG_MORPH_STUBBY:
				if (owner.isPlayer()) {
					UtilText.transformationContentSB.append(
							(owner.getTailCount()==1
								?" A furry, dog-like tail sprouts from just above your ass, rapidly growing in size until it's about half the length of one of your legs."
									+ " You quickly realise that you have little control over it, and it wags with a mind of its own whenever you get excited."
									+ "
"
									+ "You now have a [style.boldDogMorph("+(type==TailType.DOG_MORPH_STUBBY?"stubby, ":"")+"dog-like tail)]"
								:" [pc.TailCount] furry, dog-like tails sprout from just above your ass, rapidly growing in size until they're each about half the length of one of your legs."
									+ " You quickly realise that you have little control over them, and they wag with a mind of their own whenever you get excited."
									+ "
"
									+ "You now have [pc.tailCount] [style.boldDogMorph("+(type==TailType.DOG_MORPH_STUBBY?"stubby, ":"")+"dog-like tails)]")
							);
				} else {
					UtilText.transformationContentSB.append(
							(owner.getTailCount()==1
								?" A furry, dog-like tail sprouts from just above [npc.her] ass, rapidly growing in size until it's about half the length of one of [npc.her] legs."
									+ " [npc.She] quickly realises that [npc.she] has little control over it, and it wags with a mind of its own whenever [npc.she] gets excited."
									+ "
"
									+ "[npc.Name] now has a [style.boldDogMorph("+(type==TailType.DOG_MORPH_STUBBY?"stubby, ":"")+"dog-like tail)]"
								:" [npc.TailCount] furry, dog-like tails sprout from just above [npc.her] ass, rapidly growing in size until they're each about half the length of one of [npc.her] legs."
									+ " [npc.She] quickly realises that [npc.she] has little control over them, and they wag with a mind of their own whenever [npc.she] gets excited."
									+ "
"
									+ "[npc.Name] now has [npc.tailCount] [style.boldDogMorph("+(type==TailType.DOG_MORPH_STUBBY?"stubby, ":"")+"dog-like tails)]")
							);
				}
				break;
			case FOX_MORPH:
				if (owner.isPlayer()) {
					UtilText.transformationContentSB.append(
							(owner.getTailCount()==1
								?" A bushy, fox-like tail sprouts from just above your ass, rapidly growing in size until it's about half the length of one of your legs."
									+ " You quickly realise that you have a decent amount of control over it, and it retains heat more easily than other kinds of tails."
									+ "
"
									+ "You now have a [style.boldFoxMorph(fox-like tail)]"
								:" [pc.TailCount] bushy, fox-like tails sprout from just above your ass, rapidly growing in size until they're each about half the length of one of your legs."
									+ " You quickly realise that you have a decent amount of control over them, and they retain heat more easily than other kinds of tails."
									+ "
"
									+ "You now have [pc.tailCount] [style.boldFoxMorph(fox-like tails)]")
							);
				} else {
					UtilText.transformationContentSB.append(
							(owner.getTailCount()==1
								?" A bushy, fox-like tail sprouts from just above [npc.her] ass, rapidly growing in size until it's about half the length of one of [npc.her] legs."
									+ " [npc.She] quickly realises that [npc.she] has a decent amount of control over it, and it retains heat more easily than other kinds of tails."
									+ "
"
									+ "[npc.Name] now has a [style.boldFoxMorph(fox-like tail)]"
								:" [npc.TailCount] bushy, fox-like tails sprout from just above [npc.her] ass, rapidly growing in size until they're each about half the length of one of [npc.her] legs."
									+ " [npc.She] quickly realises that [npc.she] has a decent amount of control over them, and they retain heat more easily than other kinds of tails."
									+ "
"
									+ "[npc.Name] now has [npc.tailCount] [style.boldFoxMorph(fox-like tails)]")
							);
				}
				break;
			case FOX_MORPH_MAGIC:
				if (owner.isPlayer()) {
					UtilText.transformationContentSB.append(
							(owner.getTailCount()==1
								?" A bushy, fox-like tail sprouts from just above your ass, rapidly growing in size until it's about half the length of one of your legs."
									+ " Your tail quickly becomes wreathed in an arcane fire, almost as if to display your unusual magic ability."
									+ "
"
									+ "You now have a [style.boldFoxMorph(fox-like tail)]"
									+ "
"
									+ "Magic fox tails (and the ability to increase their number) will eventually be removed from transformation potions."
								:" [pc.TailCount] bushy, fox-like tails sprout from just above your ass, rapidly growing in size until they're each about half the length of one of your legs."
									+ " Your tails quickly become wreathed in an arcane fire, almost as if to display your unusual magic ability."
									+ "
"
									+ "Magic fox tails (and the ability to increase their number) will eventually be removed from transformation potions.")
							);
				} else {
					UtilText.transformationContentSB.append(
							(owner.getTailCount()==1
								?" A bushy, fox-like tail sprouts from just above [npc.her] ass, rapidly growing in size until it's about half the length of one of [npc.her] legs."
									+ " [npc.She] tail quickly becomes wreathed in an arcane fire, almost as if to display the owner's unusual magic ability."
									+ "
"
									+ "[npc.Name] now has a [style.boldFoxMorph(arcane fox-like tail)]\n"
									+ "
"
									+ "Magic fox tails (and the ability to increase their number) will eventually be removed from transformation potions."
								:" [npc.TailCount] bushy, fox-like tails sprout from just above [npc.her] ass, rapidly growing in size until they're each about half the length of one of [npc.her] legs."
									+ " [npc.HerHis] tails quickly becomes wreathed in an arcane fire, almost as if to display the owner's unusual magic ability."
									+ "
"
									+ "[npc.Name] now has [npc.tailCount] [style.boldFoxMorph(arcane fox-like tails)]"
									+ "
"
									+ "Magic fox tails (and the ability to increase their number) will eventually be removed from transformation potions.")
							);
				}
				break;
			case HARPY:
				if (owner.isPlayer()) {
					UtilText.transformationContentSB.append(
							(owner.getTailCount()==1
								?" A pretty plume of tail feathers sprouts from just above your ass, with each feather quickly growing to be about one-third the length of one of your legs."
									+ " You discover that you can quickly raise and lower your new bird-like tail, which helps you to keep your balance."
									+ "
"
									+ "You now have a [style.boldHarpy(harpy's bird-like tail)]"
								:" [pc.TailCount] pretty plumes of tail feathers sprout from just above your ass, with each feather quickly growing to be about one-third the length of one of your legs."
									+ " You discover that you can quickly raise and lower your new bird-like tails, which helps you to keep your balance."
									+ "
"
									+ "You now have [pc.tailCount] [style.boldHarpy(harpy's bird-like tails)]")
							);
				} else {
					UtilText.transformationContentSB.append(
							(owner.getTailCount()==1
								?" A pretty plume of tail feathers sprouts from just above [npc.her] ass, with each feather quickly growing to be about one-third the length of one of [npc.her] legs."
									+ " [npc.She] discovers that [npc.she] can quickly raise and lower [npc.her] new bird-like tail, which helps [npc.herHim] to keep [npc.her] balance."
									+ "
"
									+ "[npc.Name] now has a [style.boldHarpy(harpy's bird-like tail)]"
								:" [npc.TailCount] pretty plumes of tail feathers sprout from just above [npc.her] ass, with each feather quickly growing to be about one-third the length of one of [npc.her] legs."
									+ " [npc.She] discovers that [npc.she] can quickly raise and lower [npc.her] new bird-like tails, which helps [npc.herHim] to keep [npc.her] balance."
									+ "
"
									+ "[npc.Name] now has [npc.tailCount] [style.boldHarpy(harpy's bird-like tails)]")
							);
				}
				break;
			case HORSE_MORPH:
				if (owner.isPlayer()) {
					UtilText.transformationContentSB.append(
							(owner.getTailCount()==1
								?" A horse-like tail sprouts from just above your ass, rapidly growing in length until it hangs to just over half-way down your legs."
									+ " You quickly discover that your control over it is limited to swishing it from side to side."
									+ "
"
									+ "You now have a [style.boldHorseMorph(horse-like tail)]"
								:" [pc.TailCount] horse-like tails sprout from just above your ass, rapidly growing in length until they hang to just over half-way down your legs."
									+ " You quickly discover that your control over them is limited to swishing them from side to side."
									+ "
"
									+ "You now have [pc.tailCount] [style.boldHorseMorph(horse-like tails)]")
							);
				} else {
					UtilText.transformationContentSB.append(
							(owner.getTailCount()==1
								?" A horse-like tail sprouts from just above [npc.her] ass, rapidly growing in length until it hangs to just over half-way down [npc.her] legs."
									+ " [npc.She] quickly discovers that [npc.her] control over it is limited to swishing it from side to side."
									+ "
"
									+ "[npc.Name] now has a [style.boldHorseMorph(horse-like tail)]"
								:" [npc.TailCount] horse-like tails sprout from just above [npc.her] ass, rapidly growing in length until they hang to just over half-way down [npc.her] legs."
									+ " [npc.She] quickly discovers that [npc.her] control over them is limited to swishing them from side to side."
									+ "
"
									+ "[npc.Name] now has [npc.tailCount] [style.boldHorseMorph(horse-like tails)]")
							);
				}
				break;
			case HORSE_MORPH_ZEBRA:
				UtilText.transformationContentSB.append(
						(owner.getTailCount()==1
							?" A zebra-like tail sprouts from just above [npc.her] ass, rapidly growing in length until it hangs to just over half-way down [npc.her] [npc.legs]."
								+ " [npc.She] quickly [npc.verb(discover)] that [npc.her] control over it is limited to swishing it from side to side."
								+ "
"
								+ "[npc.Name] now [npc.has] a [style.boldHorseMorph(zebra-like tail)]"
							:" [npc.TailCount] horse-like tails sprout from just above [npc.her] ass, rapidly growing in length until they hang to just over half-way down [npc.her] legs."
								+ " [npc.She] quickly discovers that [npc.her] control over them is limited to swishing them from side to side."
								+ "
"
								+ "[npc.Name] now has [npc.tailCount] [style.boldHorseMorph(horse-like tails)]")
						);
				break;
			case REINDEER_MORPH:
				if (owner.isPlayer()) {
					UtilText.transformationContentSB.append(
							(owner.getTailCount()==1
								?" A reindeer-like tail sprouts from just above your ass, rapidly growing in width until it takes up about a third of your rear."
									+ " You quickly discover that your control over it is limited to simply twitching it up and down."
									+ "
"
									+ "You now have a [style.boldReindeerMorph(reindeer-like tail)]"
								:" [pc.TailCount] reindeer-like tails sprout from just above your ass, rapidly growing in width until they take up about a third of your rear."
									+ " You quickly discover that your control over them is limited to simply twitching them up and down."
									+ "
"
									+ "You now have [pc.tailCount] [style.boldReindeerMorph(reindeer-like tails)]")
							);
				} else {
					UtilText.transformationContentSB.append(
							(owner.getTailCount()==1
								?" A reindeer-like tail sprouts from just above [npc.her] ass, rapidly growing in width until it takes up about a third of [npc.her] rear."
									+ " [npc.She] quickly discovers that [npc.her] control over it is limited to simply twitching it up and down."
									+ "
"
									+ "[npc.Name] now has a [style.boldReindeerMorph(reindeer-like tail)]"
								:" [npc.TailCount] reindeer-like tails sprout from just above [npc.her] ass, rapidly growing in width until they take up about a third of [npc.her] rear."
									+ " [npc.She] quickly discovers that [npc.her] control over them is limited to simply twitching them up and down."
									+ "
"
									+ "[npc.Name] now has [npc.tailCount] [style.boldReindeerMorph(reindeer-like tails)]")
							);
				}
				break;
			case COW_MORPH:
				if (owner.isPlayer()) {
					UtilText.transformationContentSB.append(
							(owner.getTailCount()==1
								?" A cow-like tail sprouts from just above your ass, rapidly growing in length until it hangs to just over half-way down your legs."
									+ " You quickly discover that your control over it is limited to swishing it from side to side."
									+ "
"
									+ "You now have a [style.boldCowMorph(cow-like tail)]"
								:" [pc.TailCount] cow-like tails sprout from just above your ass, rapidly growing in length until they hang to just over half-way down your legs."
									+ " You quickly discover that your control over them is limited to swishing them from side to side."
									+ "
"
									+ "You now have [pc.tailCount] [style.boldCowMorph(cow-like tails)]")
							);
				} else {
					UtilText.transformationContentSB.append(
							(owner.getTailCount()==1
								?" A cow-like tail sprouts from just above [npc.her] ass, rapidly growing in length until it hangs to just over half-way down [npc.her] legs."
									+ " [npc.She] quickly discovers that [npc.her] control over it is limited to swishing it from side to side."
									+ "
"
									+ "[npc.Name] now has a [style.boldCowMorph(cow-like tail)]"
								:" [npc.TailCount] cow-like tails sprout from just above [npc.her] ass, rapidly growing in length until they hang to just over half-way down [npc.her] legs."
									+ " [npc.She] quickly discovers that [npc.her] control over them is limited to swishing them from side to side."
									+ "
"
									+ "[npc.Name] now has [npc.tailCount] [style.boldCowMorph(cow-like tails)]")
							);
				}
				break;
			case LYCAN:
				if (owner.isPlayer()) {
					UtilText.transformationContentSB.append(
							(owner.getTailCount()==1
								?" A furry, wolf-like tail sprouts from just above your ass, rapidly growing in size until it's about half the length of one of your legs."
									+ " You quickly realise that you have limited control over it, and it takes a lot of effort to stop it from betraying your emotions."
									+ "
"
									+ "You now have a [style.boldWolfMorph(wolf-like tail)]"
								:" [pc.TailCount] furry, wolf-like tails sprout from just above your ass, rapidly growing in size until they're each about half the length of one of your legs."
									+ " You quickly realise that you have limited control over them, and it takes a lot of effort to stop them from betraying your emotions."
									+ "
"
									+ "You now have [pc.tailCount] [style.boldWolfMorph(wolf-like tails)]")
							);
				} else {
					UtilText.transformationContentSB.append(
							(owner.getTailCount()==1
								?" A furry, wolf-like tail sprouts from just above [npc.her] ass, rapidly growing in size until it's about half the length of one of [npc.her] legs."
									+ " [npc.She] quickly realises that [npc.she] has limited control over it, and it takes a lot of effort to stop it from betraying [npc.her] emotions."
									+ "
"
									+ "[npc.Name] now has a [style.boldWolfMorph(wolf-like tail)]"
								:" [npc.TailCount] furry, wolf-like tails sprout from just above [npc.her] ass, rapidly growing in size until they're each about half the length of one of [npc.her] legs."
									+ " [npc.She] quickly realises that [npc.she] has limited control over them, and it takes a lot of effort to stop them from betraying [npc.her] emotions."
									+ "
"
									+ "[npc.Name] now has [npc.tailCount] [style.boldWolfMorph(wolf-like tails)]")
							);
				}
				break;
			case ALLIGATOR_MORPH:
				if (owner.isPlayer()) {
					UtilText.transformationContentSB.append(
							(owner.getTailCount()==1
								?" A scaly, alligator-like tail sprouts from just above your ass, rapidly growing in size until it's almost as long as your body."
									+ " You quickly discover that you can swish it from side to side with considerable force."
									+ "
"
									+ "You now have an [style.boldGatorMorph(alligator-like tail)]"
								:" [pc.TailCount] scaly, alligator-like tails sprout from just above your ass, rapidly growing in size until they're each almost as long as your body."
									+ " You quickly discover that you can swish them from side to side with considerable force."
									+ "
"
									+ "You now have [pc.tailCount] [style.boldGatorMorph(alligator-like tails)]")
							);
				} else {
					UtilText.transformationContentSB.append(
							(owner.getTailCount()==1
								?" A scaly, alligator-like tail sprouts from just above [npc.her] ass, rapidly growing in size until it's almost as long as [npc.her] body."
									+ " [npc.She] quickly discovers that [npc.she] can swish it from side to side with considerable force."
									+ "
"
									+ "[npc.Name] now has an [style.boldGatorMorph(alligator-like tail)]"
								:" [npc.TailCount] scaly, alligator-like tails sprout from just above [npc.her] ass, rapidly growing in size until they're each almost as long as [npc.her] body."
									+ " [npc.She] quickly discovers that [npc.she] can swish them from side to side with considerable force."
									+ "
"
									+ "[npc.Name] now has [npc.tailCount] [style.boldGatorMorph(alligator-like tails)]")
							);
				}
				break;
			case SQUIRREL_MORPH:
				if (owner.isPlayer()) {
					UtilText.transformationContentSB.append(
							(owner.getTailCount()==1
								?" A furry, squirrel-like tail sprouts from just above your ass, rapidly growing in size until it's almost as long as your body."
									+ " You quickly realise that you have a reasonable amount of control over it, and can use it to help balance you out while moving quickly."
									+ "
"
									+ "You now have a [style.boldSquirrelMorph(squirrel-like tail)]"
								:" [pc.TailCount] furry, squirrel-like tails sprout from just above your ass, rapidly growing in size until they're each almost as long as your body."
									+ " You quickly realise that you have a reasonable amount of control over them, and can use them to help balance you out while moving quickly."
									+ "
"
									+ "You now have [pc.tailCount] [style.boldSquirrelMorph(squirrel-like tails)]")
							);
				} else {
					UtilText.transformationContentSB.append(
							(owner.getTailCount()==1
								?" A furry, squirrel-like tail sprouts from just above [npc.her] ass, rapidly growing in size until it's almost as long as [npc.her] body."
									+ " [npc.She] quickly realises that [npc.she] has a reasonable amount of control over it, and can use it to help balance [npc.herHim] out while moving quickly."
									+ "
"
									+ "[npc.Name] now has a [style.boldSquirrelMorph(squirrel-like tail)]"
								:" [npc.TailCount] furry, squirrel-like tails sprout from just above [npc.her] ass, rapidly growing in size until they're each almost as long as [npc.her] body."
									+ " [npc.She] quickly realises that [npc.she] has a reasonable amount of control over them, and can use them to help balance [npc.herHim] out while moving quickly."
									+ "
"
									+ "[npc.Name] now has [npc.tailCount] [style.boldSquirrelMorph(squirrel-like tails)]")
							);
				}
				break;
			case RAT_MORPH:
				if (owner.isPlayer()) {
					UtilText.transformationContentSB.append(
							(owner.getTailCount()==1
								?" A thick, rat-like tail sprouts from just above your ass, rapidly growing in size until it's almost as long as one of your legs."
									+ " You quickly realise that you have a decent amount of control over it, and you can twist it almost anywhere you please."
									+ "
"
									+ "You now have a [style.boldRatMorph(rat-like tail)]"
								:" [pc.TailCount] thick, rat-like tails sprout from just above your ass, rapidly growing in size until they're each almost as long as one of your legs."
									+ " You quickly realise that you have a decent amount of control over them, and you can twist them almost anywhere you please."
									+ "
"
									+ "You now have [pc.tailCount] [style.boldRatMorph(rat-like tails)]")
							);
				} else {
					UtilText.transformationContentSB.append(
							(owner.getTailCount()==1
								?" A thick, rat-like tail sprouts from just above [npc.her] ass, rapidly growing in size until it's almost as long as one of [npc.her] legs."
									+ " [npc.She] quickly realises that [npc.she] has a decent amount of control over it, and can twist it almost anywhere [npc.she] pleases."
									+ "
"
									+ "[npc.Name] now has a [style.boldRatMorph(rat-like tail)]"
								:" [npc.TailCount] thick, rat-like tails sprout from just above [npc.her] ass, rapidly growing in size until they're each almost as long as one of [npc.her] legs."
									+ " [npc.She] quickly realises that [npc.she] has a decent amount of control over them, and can twist them almost anywhere [npc.she] pleases."
									+ "
"
									+ "[npc.Name] now has [npc.tailCount] [style.boldRatMorph(rat-like tails)]")
							);
				}
				break;
			case BAT_MORPH:
				UtilText.transformationContentSB.append(
						(owner.getTailCount()==1
							?" A small tail sprouts from just above [npc.her] ass, rapidly growing in size until it's about as long as one of [npc.her] forearms."
								+ " [npc.She] quickly [npc.verb(realise)] that [npc.she] [npc.has] a decent amount of control over it, and can twist it almost anywhere [npc.she] [npc.verb(please)]."
								+ "
"
								+ "[npc.Name] now [npc.has] a [style.boldBatMorph(bat-like tail)]"
							:" [npc.TailCount] small tails sprout from just above [npc.her] ass, rapidly growing in size until they're each about as long as one of [npc.her] forearms."
								+ " [npc.She] quickly [npc.verb(realise)] that [npc.she] [npc.has] a decent amount of control over them, and can twist them almost anywhere [npc.she] [npc.verb(please)]."
								+ "
"
								+ "[npc.Name] now [npc.has] [npc.tailCount] [style.boldBatMorph(bat-like tails)]")
						);
				break;
			case RABBIT_MORPH:
				if (owner.isPlayer()) {
					UtilText.transformationContentSB.append(
							(owner.getTailCount()==1
								?" A furry, round, rabbit-like tail sprouts from just above your ass, rapidly growing in size until it's about as large as a bowling ball."
									+ " You quickly realise that you have no control over it whatsoever, what with it being no more than just a ball of downy fluff."
									+ "
"
									+ "You now have a [style.boldRabbitMorph(rabbit-like tail)]"
								:" [pc.TailCount] furry, round, rabbit-like tails sprout from just above your ass, rapidly growing in size until they're each about as large as a bowling ball."
									+ " You quickly realise that you have no control over them whatsoever, what with them being no more than just balls of downy fluff."
									+ "
"
									+ "You now have [pc.tailCount] [style.boldRabbitMorph(rabbit-like tails)]")
							);
				} else {
					UtilText.transformationContentSB.append(
							(owner.getTailCount()==1
								?" A furry, round, rabbit-like tail sprouts from just above [npc.her] ass, rapidly growing in size until it's about as large as a bowling ball."
									+ " [npc.She] quickly realises that [npc.she] has no control over it whatsoever, what with it being no more than just a ball of downy fluff."
									+ "
"
									+ "[npc.Name] now has a [style.boldRabbitMorph(rabbit-like tail)]"
								:" [npc.TailCount] furry, round, rabbit-like tails sprout from just above [npc.her] ass, rapidly growing in size until they're each about as large as a bowling ball."
									+ " [npc.She] quickly realises that [npc.she] has no control over them whatsoever, what with them being no more than just balls of downy fluff."
									+ "
"
									+ "[npc.Name] now has [npc.tailCount] [style.boldRabbitMorph(rabbit-like tails)]")
							);
				}
				break;
		}

		this.type = type;

		if(type == TailType.NONE) {
			UtilText.transformationContentSB.append(".
");
		} else if(type!= TailType.DEMON_HAIR_TIP){
			if (owner.isPlayer()) {
				UtilText.transformationContentSB.append(", covered in [pc.tailFullDescription(true)].
");
			} else {
				UtilText.transformationContentSB.append(", covered in [npc.tailFullDescription(true)].
");
			}
		}

		return UtilText.parse(owner, UtilText.transformationContentSB.toString())
				+ "
"
					+ owner.postTransformationCalculation()
				+ "
";
	}

	public int getTailCount() {
		return tailCount;
	}

	public String setTailCount(GameCharacter owner, int tailCount, boolean overrideYoukoLimitations) {
		tailCount = Math.max(1, Math.min(tailCount, MAXIMUM_COUNT));

		if(owner.getTailCount() == tailCount) {
			return "
[style.colourDisabled(Nothing happens...)]
";
		}

		if(owner.getTailType().equals(TailType.FOX_MORPH_MAGIC) && !overrideYoukoLimitations) {
			return "
"
						+ "[style.colourMinorBad([npc.NamePos] arcane-infused "
							+(this.tailCount==1
								?"tail absorbs and nullifies"
								:"tails absorb and nullify")
							+" the transformative effect, preventing any alteration to the number of tails [npc.she] [npc.has]!)]"
					+ "
";
		}

		owner.removeStatusEffect(StatusEffect.SUBSPECIES_BONUS);

		boolean removingTails = owner.getTailCount() > tailCount;
		this.tailCount = tailCount;

		owner.addStatusEffect(StatusEffect.SUBSPECIES_BONUS, -1);

		if (owner.getTailType() == TailType.NONE) {
			return "
[style.colourDisabled(Nothing happens...)]
";
		}

		if(removingTails) {
			if(owner.isPlayer()) {
				return
						"
"
							+ "A tingling feeling spreads over your [pc.tails], before moving down and concentrating into your lower back."
							+ " You can't help but let out a little cry as you feel some of them [style.boldShrink(shrinking away)] and disappearing back down into your [pc.skin].
"
							+ "After a few moments, you're left with [style.boldTfGeneric("
									+(tailCount==1
										?"a single [pc.tail]"
										:Util.intToString(tailCount)+" [pc.tails]")
							+ ")]."
						+ "
";
			} else {
				return UtilText.parse(owner,
						"
"
							+ "A tingling feeling spreads over [npc.namePos] [npc.tails], before moving down and concentrating into [npc.her] lower back."
							+ " [npc.She] can't help but let out a little cry as [npc.she] feels some of them [style.boldShrink(shrinking away)] and disappearing back down into [npc.her] [npc.skin].
"
							+ "After a few moments, [npc.sheIs] left with [style.boldTfGeneric("
									+(tailCount==1
										?"a single [npc.tail]"
										:Util.intToString(tailCount)+" [npc.tails]")
							+ ")]."
						+ "
");
			}

		} else {
			if(owner.isPlayer()) {
				return
						"
"
							+ "A tingling feeling spreads over your [pc.tails], before moving down and concentrating into your lower back."
							+ " You can't help but let out a little cry as you feel new [pc.tails] [style.boldGrow(pushing up)] and growing out of your [pc.skin].
"
							+ "After a few moments, you're left with [style.boldTfGeneric("
									+(tailCount==1
										?"a single [pc.tail]"
										:Util.intToString(tailCount)+" [pc.tails]")
							+ ")]."
						+ "
";
			} else {
				return UtilText.parse(owner,
						"
"
							+ "A tingling feeling spreads over [npc.namePos] [npc.tails], before moving down and concentrating into [npc.her] lower back."
							+ " [npc.She] can't help but let out a little cry as [npc.she] feels new [npc.tails] [style.boldGrow(pushing up)] and growing out of [npc.her] [npc.skin].
"
							+ "After a few moments, [npc.sheIs] left with [style.boldTfGeneric("
									+(tailCount==1
										?"a single [npc.tail]"
										:Util.intToString(tailCount)+" [npc.tails]")
							+ ")]."
						+ "
");
			}
		}
	}

	@Override
	public boolean isBestial(GameCharacter owner) {
		if(owner==null) {
			return false;
		}
		return owner.getLegConfiguration().getBestialParts().contains(Tail.class) && getType().getRace().isBestialPartsAvailable();
	}
}


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

import com.lilithsthrone.game.character.GameCharacter;
import com.lilithsthrone.game.character.body.types.TentacleType;
import com.lilithsthrone.game.dialogue.utils.UtilText;
import com.lilithsthrone.main.Main;
import com.lilithsthrone.utils.Util;

/**
 * @since 0.2.8
 * @version 0.3.1
 * @author Innoxia
 */
public class Tentacle implements BodyPartInterface {

	protected TentacleType type;
	protected int tentacleCount;

	public Tentacle(TentacleType type) {
		this.type = type;
		tentacleCount = 1;
	}

	@Override
	public TentacleType getType() {
		return type;
	}

	@Override
	public String getDeterminer(GameCharacter gc) {
		return type.getDeterminer(gc);
	}

	@Override
	public String getName(GameCharacter gc) {
		return type.getName(gc);
	}

	@Override
	public String getNameSingular(GameCharacter gc) {
		return type.getNameSingular(gc);
	}

	@Override
	public String getNamePlural(GameCharacter gc) {
		return type.getNamePlural(gc);
	}

	@Override
	public String getDescriptor(GameCharacter gc) {
		return type.getDescriptor(gc);
	}

	public String setType(GameCharacter owner, TentacleType type) {
		if(!Main.game.isStarted() || owner==null) {
			this.type = type;
			if(owner!=null) {
				owner.postTransformationCalculation();
			}
			return "";
		}

		if (type == getType()) {
			if(type == TentacleType.NONE) {
				if(owner.isPlayer()) {
					return "
[style.colourDisabled(You already lack tentacles, so nothing happens...)]
";
				} else {
					return UtilText.parse(owner, "
[style.colourDisabled([npc.Name] already lacks tentacles, so nothing happens...)]
");
				}
			} else {
				if(owner.isPlayer()) {
					return "
[style.colourDisabled(You already have the [pc.tentacles] of [pc.a_tentacleRace], so nothing happens...)]
";
				} else {
					return UtilText.parse(owner, "
[style.colourDisabled([npc.Name] already has the [npc.tentacles] of [npc.a_tentacleRace], so nothing happens...)]
");
				}
			}
		}

		UtilText.transformationContentSB.setLength(0);

		if(this.type == TentacleType.NONE) {
			UtilText.transformationContentSB.append(
					"
"
						+ "[npc.Name] [npc.verb(rub)] at the middle of [npc.her] back as [npc.she] [npc.verb(feel)] [npc.her] [npc.skin] growing hot and sensitive, and as [npc.she] [npc.verb(do)] so,"
							+ " [npc.she] [npc.verb(feel)] something pushing out from under [npc.her] [npc.skin].");
		} else {
			UtilText.transformationContentSB.append(
					"
"
						+ (owner.getTentacleCount()==1
							?"[npc.Name] [npc.verb(feel)] [npc.her] [npc.tentacle] growing hot and itchy, and after just a moment it starts to transform."
							:"[npc.Name] [npc.verb(feel)] [npc.her] [npc.tentacles] growing hot and itchy, and after just a moment they start to transform."));
		}

		switch (type) {
			case NONE:
				UtilText.transformationContentSB.append(
						(owner.getTentacleCount()==1
							?" [npc.She] [npc.verb(gasp)] as [npc.she] [npc.verb(feel)] [npc.her] [npc.tentacle] shrinking down and disappearing into [npc.her] back."
							:" [npc.She] [npc.verb(gasp)] as [npc.she] [npc.verb(feel)] [npc.her] [npc.tentacles] shrinking down and disappearing into [npc.her] back.")
						+ "
"
						+ "[npc.Name] now [npc.has] [style.boldTfGeneric(no tentacles)]");
				break;
			case DEMON_COMMON:
				UtilText.transformationContentSB.append(
						(owner.getTentacleCount()==1
							?" A demonic, spaded tentacle sprouts from the middle of [npc.her] spine, rapidly growing in size until it's roughly as long as [npc.sheIsFull] tall."
								+ " [npc.She] quickly [npc.verb(discover)] that [npc.she] [npc.has] complete control over where it goes, allowing [npc.herHim] to use it like a third limb."
								+ "
"
								+ "[npc.Name] now [npc.has] a [style.boldDemon(demonic tentacle)]"
							:" [npc.TentacleCount] demonic, spaded tentacles sprout from the middle of [npc.her] spine, rapidly growing in size until they're roughly as long as [npc.sheIsFull] tall."
								+ " [npc.She] quickly [npc.verb(discover)] that [npc.she] [npc.has] complete control over where they go, allowing [npc.herHim] to use them like extra limbs."
								+ "
"
								+ "[npc.Name] now [npc.has] [npc.tentacleCount] [style.boldDemon(demonic tentacles)]")
						);
				break;
		}

		this.type = type;

		if(type == TentacleType.NONE) {
			UtilText.transformationContentSB.append(".
");
		} else {
			UtilText.transformationContentSB.append(", covered in [npc.tentacleFullDescription(true)].
");
		}

		return UtilText.parse(owner, UtilText.transformationContentSB.toString())
				+ "
"
					+ owner.postTransformationCalculation()
				+ "
";
	}

	public int getTentacleCount() {
		return tentacleCount;
	}

	public String setTentacleCount(GameCharacter owner, int tentacleCount) {
		tentacleCount = Math.max(1, Math.min(tentacleCount, 9));

		if(owner.getTentacleCount() == tentacleCount) {
			return "
[style.colourDisabled(Nothing happens...)]
";
		}

		boolean removingTentacles = owner.getTentacleCount() > tentacleCount;
		this.tentacleCount = tentacleCount;

		if (owner.getTentacleType() == TentacleType.NONE) {
			return "
[style.colourDisabled(Nothing happens...)]
";
		}

		if(removingTentacles) {
			return UtilText.parse(owner,
					"
"
						+ "A tingling feeling spreads over [npc.namePos] [npc.tentacles], before moving down into [npc.her] spine."
						+ " [npc.She] can't help but let out a little cry as [npc.she] [npc.verb(feel)] some of them [style.boldShrink(shrinking away)] and disappearing back down into [npc.her] [npc.skin].
"
						+ "After a few moments, [npc.sheIs] left with [style.boldTfGeneric("
								+(tentacleCount==1
									?"a single [npc.tentacle]"
									:Util.intToString(tentacleCount)+" [npc.tentacles]")
						+ ")]."
					+ "
");

		} else {
			return UtilText.parse(owner,
					"
"
						+ "A tingling feeling spreads over [npc.namePos] [npc.tentacles], before moving down into [npc.her] spine."
						+ " [npc.She] can't help but let out a little cry as [npc.she] [npc.verb(feel)] new [npc.tentacles] [style.boldGrow(pushing up)] and growing out of [npc.her] [npc.skin].
"
						+ "After a few moments, [npc.sheIs] left with [style.boldTfGeneric("
								+(tentacleCount==1
									?"a single [npc.tentacle]"
									:Util.intToString(tentacleCount)+" [npc.tentacles]")
						+ ")]."
					+ "
");
		}
	}

	@Override
	public boolean isBestial(GameCharacter owner) {
		if(owner==null) {
			return false;
		}
		return owner.getLegConfiguration().getBestialParts().contains(Tentacle.class) && getType().getRace().isBestialPartsAvailable();
	}
}

repo_name: klorpa/Pedo

license: unknown


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

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

import com.lilithsthrone.game.character.GameCharacter;
import com.lilithsthrone.game.character.body.types.TesticleType;
import com.lilithsthrone.game.character.body.valueEnums.CumProduction;
import com.lilithsthrone.game.character.body.valueEnums.FluidExpulsion;
import com.lilithsthrone.game.character.body.valueEnums.FluidRegeneration;
import com.lilithsthrone.game.character.body.valueEnums.TesticleSize;
import com.lilithsthrone.game.dialogue.utils.UtilText;
import com.lilithsthrone.main.Main;
import com.lilithsthrone.utils.Colour;
import com.lilithsthrone.utils.Units;
import com.lilithsthrone.utils.Util;

/**
 * @since 0.1.83
 * @version 0.3.1
 * @author Innoxia
 */
public class Testicle implements BodyPartInterface {

	public static final int MIN_TESTICLE_COUNT = 2;
	public static final int MAX_TESTICLE_COUNT = 8;

	public static final int MINIMUM_VALUE_FOR_ALL_CUM_TO_BE_EXPELLED = 5; //ml

	protected TesticleType type;
	protected int testicleSize;
	protected int cumStorage;
	protected float cumStored;
	protected int cumRegeneration;
	protected int testicleCount;
	protected int cumExpulsion;
	protected boolean internal;

	protected FluidCum cum;

	public Testicle(TesticleType type, int testicleSize, int cumStorage, int testicleCount) {
		this.type = type;
		this.testicleSize = Math.max(0, Math.min(testicleSize, TesticleSize.SEVEN_ABSURD.getValue()));
		this.cumStorage = cumStorage;
		cumStored = cumStorage;
		cumRegeneration = FluidRegeneration.CUM_REGEN_DEFAULT;
		cumExpulsion = FluidExpulsion.THREE_LARGE.getMinimumValue();

		this.testicleCount = Math.max(MIN_TESTICLE_COUNT, Math.min(testicleCount, MAX_TESTICLE_COUNT));

		internal = type.isInternal();

		cum = new FluidCum(type.getFluidType());
	}

	public FluidCum getCum() {
		return cum;
	}

	@Override
	public TesticleType getType() {
		return type;
	}

	@Override
	public String getDeterminer(GameCharacter gc) {
		if(gc.getTesticleCount()==2) {
			return "a pair of";
		} else if(gc.getTesticleCount()==3) {
			return "a trio of";
		} else {
			return Util.intToString(gc.getTesticleCount());
		}
	}

	@Override
	public String getName(GameCharacter gc) {
		return type.getName(gc);
	}

	@Override
	public String getNameSingular(GameCharacter gc) {
		return type.getNameSingular(gc);
	}

	@Override
	public String getNamePlural(GameCharacter gc) {
		return type.getNamePlural(gc);
	}

	@Override
	public String getDescriptor(GameCharacter owner) {
		List<String> list = new ArrayList<>();

		list.add(owner.getTesticleSize().getDescriptor());

		list.add(type.getDescriptor(owner));

		return Util.randomItemFrom(list);
	}

	public void setType(GameCharacter owner, TesticleType type) {
		this.type = type;
		cum.setType(type.getFluidType());
	}

	public TesticleSize getTesticleSize() {
		return TesticleSize.getTesticleSizeFromInt(testicleSize);
	}

	public String setTesticleSize(GameCharacter owner, int testicleSize) {
		if(owner!=null && !owner.hasPenisIgnoreDildo()) {
			return "
[style.colourDisabled(Nothing happens...)]
";
		}

		int oldSize = this.testicleSize;
		this.testicleSize = Math.max(0, Math.min(testicleSize, TesticleSize.SEVEN_ABSURD.getValue()));
		int sizeChange = this.testicleSize - oldSize;

		if(owner==null) {
			return "";
		}

		if (sizeChange == 0) {
			if(owner.isPlayer()) {
				return "
[style.colourDisabled(The size of your [pc.balls] doesn't change...)]
";
			} else {
				return UtilText.parse(owner, "
[style.colourDisabled(The size of [npc.namePos] [npc.balls] doesn't change...)]
");
			}

		} else if (sizeChange > 0) {
			return UtilText.parse(owner,
					"
"
						+ "[npc.Name] [npc.verb(let)] out a lewd moan as [npc.she] [npc.verb(feel)] [npc.her] [npc.balls] suddenly swell and [style.boldGrow(grow larger)].
"
						+ "[npc.She] now [npc.has] [style.boldSex(" + owner.getTesticleSize().getDescriptor() + " [pc.balls])]!"
					+ "
");

		} else {
			if (owner.isPlayer()) {
				return "
"
							+ "You let out a surprised gasp as you feel your [pc.balls] suddenly [style.boldShrink(shrink)].
"
							+ "You now have [style.boldSex(" +owner.getTesticleSize().getDescriptor()+ " [pc.balls])]!"
						+ "
";
			} else {
				return UtilText.parse(owner,
						"
"
							+ "[npc.Name] lets out a surprised gasp as [npc.she] feels [npc.her] [npc.balls] suddenly [style.boldShrink(shrink)].
"
							+ "[npc.She] now has [style.boldSex(" +owner.getTesticleSize().getDescriptor()+ " [npc.balls])]!"
						+ "
");
			}
		}
	}

	public int getTesticleCount() {
		return testicleCount;
	}

	public String setTesticleCount(GameCharacter owner, int testicleCount) {
		testicleCount = Math.max(MIN_TESTICLE_COUNT, Math.min(testicleCount, MAX_TESTICLE_COUNT));

		if(owner.getTesticleCount() == testicleCount || !owner.hasPenisIgnoreDildo()) {
			return "
[style.colourDisabled(Nothing happens...)]
";
		}

		boolean removingTesticles = this.testicleCount > testicleCount;
		this.testicleCount = testicleCount;

		if(removingTesticles) {
			if(owner.isPlayer()) {
				return UtilText.parse(owner, "
"
							+ "A tingling feeling spreads down into your [pc.balls], and you let out a little cry as you feel some of them shrinking away and [style.boldShrink(disappearing)].
"
							+ "After a few moments, you're left with [style.boldTfGeneric([pc.a_balls])]."
						+ "
");
			} else {
				return UtilText.parse(owner,
						"
"
							+ "A tingling feeling spreads down into [npc.namePos] [npc.balls], and [npc.she] lets out a little cry as [npc.she] feels some of them shrinking away and [style.boldShrink(disappearing)].
"
							+ "After a few moments, [npc.sheIs] left with [style.boldTfGeneric([npc.a_balls])]."
						+ "
");
			}

		} else {
			if(owner.isPlayer()) {
				return UtilText.parse(owner, "
"
							+ "A tingling feeling spreads down into your [pc.balls], and you let out a little cry as you feel them [style.boldGrow(multiplying)].
"
							+ "After a few moments, you're left with [style.boldTfGeneric([pc.a_balls])]."
						+ "
");
			} else {
				return UtilText.parse(owner,
						"
"
							+ "A tingling feeling spreads down into [npc.namePos] [npc.balls], and [npc.she] lets out a little cry as [npc.she] feels them [style.boldGrow(multiplying)].
"
							+ "After a few moments, [npc.sheIs] left with [style.boldTfGeneric([npc.a_balls])]."
						+ "
");
			}
		}
	}

	public boolean isInternal(GameCharacter owner) {
		if(!Main.game.isFutanariTesticlesEnabled() && owner!=null && owner.hasVagina()) {
			return true;
		}
		return internal;
	}

	public String setInternal(GameCharacter owner, boolean internal) {
		if(owner==null) {
			this.internal = internal;
			return "";
		}

		if(owner.isInternalTesticles() == internal || !owner.hasPenisIgnoreDildo()) {
			return "
[style.colourDisabled(Nothing happens...)]
";
		}

		this.internal = internal;

		if(internal) {
			if(owner.isPlayer()) {
				return "
"
							+ "You feel your [pc.balls] tightening and [style.boldShrink(withdrawing)] up into your groin, and you let out a little cry as you feel them shift up inside your body.
"
							+ "Your [pc.balls+] [style.boldTfGeneric(are now internal)]."
						+ "
";
			} else {
				return UtilText.parse(owner,
						"
"
							+ "[npc.Name] feels [npc.her] [npc.balls] tightening and [style.boldShrink(withdrawing)] up into [npc.her] groin, and [npc.she] lets out a little cry as [npc.she] feels them shift up inside [npc.her] body.
"
							+ "[npc.Her] [npc.balls+] [style.boldTfGeneric(are now internal)]."
						+ "
");
			}

		} else {
			if(owner.isPlayer()) {
				return "
"
							+ "You feel your internal [pc.balls] slackening and [style.boldGrow(dropping down)], and you let out a little cry as they settle down into an external sack.
"
							+ "Your [pc.balls+] [style.boldTfGeneric(are now external)]."
						+ "
";
			} else {
				return UtilText.parse(owner,
						"
"
							+ "[npc.Name] feels [npc.her] internal [npc.balls] slackening and [style.boldGrow(dropping down)], and [npc.she] lets out a little cry as they settle down into an external sack.
"
							+ "[npc.Her] [npc.balls+] [style.boldTfGeneric(are now external)]."
						+ "
");
			}
		}
	}

	// Cum storage and regeneration:

	// CumProduction:

	public CumProduction getCumStorage() {
		return CumProduction.getCumProductionFromInt(cumStorage);
	}

	public int getRawCumStorageValue() {
		return cumStorage;
	}

	/**
	 * Sets the cumStorage. Value is bound to >=0 && <=CumProduction.SEVEN_MONSTROUS_AMOUNT_POURING.getMaximumValue()
	 */
	public String setCumStorage(GameCharacter owner, int cumStorage) {
		int oldCumProduction = this.cumStorage;
		this.cumStorage = Math.max(0, Math.min(cumStorage, CumProduction.SEVEN_MONSTROUS.getMaximumValue()));
		int cumChange = this.cumStorage - oldCumProduction;

		if(owner==null) {
			return "";
		}

		if (cumChange == 0) {
			if(owner.isPlayer()) {
				return "
[style.colourDisabled(The amount of [pc.cum] that you're able to produce doesn't change...)]
";
			} else {
				return UtilText.parse(owner, "
[style.colourDisabled(The amount of [npc.cum] that [npc.name] is able to produce doesn't change...)]
");
			}
		}

		String cumDescriptor = getCumStorage().getDescriptor();
		if (cumChange > 0) {
			return UtilText.parse(owner,
					"
"
						+ "[npc.Name] [npc.verb(feel)] a strange bubbling and churning taking place deep within [npc.her] [npc.balls],"
							+ " and [npc.she] can't help but let out [npc.a_moan+] as a small squirt of precum suddenly drools out from [npc.her] [npc.cock];"
								+ " clear evidence that that [npc.her] [npc.cum] production has [style.boldGrow(increased)].
"
						+ "[npc.SheIsFull] now able to produce [style.boldSex(" + cumDescriptor + " [npc.cum])]!"
					+ "
");

		} else {
			return UtilText.parse(owner,
					"
"
						+ "[npc.Name] [npc.verb(feel)] a strange sucking sensation taking place deep within [npc.her] [npc.balls],"
							+ " and [npc.she] can't help but let out a shocked gasp as [npc.she] [npc.verb(realise)] that [npc.sheIs] feeling [npc.her] [npc.cum] production [style.boldShrink(drying up)].
"
						+ "[npc.SheIsFull] now able to produce [style.boldSex(" + cumDescriptor + " [npc.cum])]!"
					+ "
");
		}
	}

	// Stored cum:

	public CumProduction getStoredCum() {
		return CumProduction.getCumProductionFromInt((int)cumStored);
	}

	public float getRawStoredCumValue() {
		return cumStored;
	}

	/**
	 * Sets the cumStorage. Value is bound to >=0 && <=getRawCumStorageValue()
	 */
	public String setStoredCum(GameCharacter owner, float cumStored) {
		float oldStoredCum = this.cumStored;
		this.cumStored = Math.max(0, (Math.min(cumStored, getRawCumStorageValue())));
		float cumChange = oldStoredCum - this.cumStored;

		if(owner==null) {
			return "";
		}

		if (cumChange <= 0) {
			return "";
		} else {
			return UtilText.parse(owner, "
"
					+ UtilText.returnStringAtRandom(
							Units.fluid(cumChange, Units.UnitType.LONG)+" of [npc.cum+] squirts out of [npc.her] [npc.cock+].",
							Units.fluid(cumChange, Units.UnitType.LONG)+" of [npc.cum+] shoots out of [npc.her] [npc.cock+].",
							Units.fluid(cumChange, Units.UnitType.LONG)+" of [npc.cum+] spurts out of [npc.her] [npc.cock+].")
				+ ""
				+ (this.cumStored==0
					?"
[npc.Name] now [npc.has] no more [npc.cum] stored in [npc.her] [npc.balls]!"
					:"")
				+ "
");
		}
	}

	// Regeneration:

	public FluidRegeneration getCumProductionRegeneration() {
		return FluidRegeneration.getFluidRegenerationFromInt(cumRegeneration);
	}

	public int getRawCumProductionRegenerationValue() {
		return cumRegeneration;
	}

	/**
	 * Sets the cumRegeneration. Value is bound to >=0 && <=FluidRegeneration.FOUR_VERY_RAPID.getMaximumRegenerationValuePerDay()
	 */
	public String setCumProductionRegeneration(GameCharacter owner, int cumRegeneration) {
		int oldRegeneration = this.cumRegeneration;
		this.cumRegeneration = Math.max(0, Math.min(cumRegeneration, FluidRegeneration.FOUR_VERY_RAPID.getMaximumRegenerationValuePerDay()));
		int regenerationChange = this.cumRegeneration - oldRegeneration;

		if(owner==null) {
			return "";
		}

		if (regenerationChange == 0) {
			if(owner.isPlayer()) {
				return "
[style.colourDisabled(Your rate of [pc.cum] regeneration doesn't change...)]
";
			} else {
				return UtilText.parse(owner, "
[style.colourDisabled([npc.namePos] rate of [npc.cum] regeneration doesn't change...)]
");
			}
		}

		String regenerationDescriptor = getCumProductionRegeneration().getName();
		if (regenerationChange > 0) {
			return UtilText.parse(owner,
					"
"
						+ "[npc.Name] [npc.verb(feel)] an alarming bubbling and churning taking place deep within [npc.her] [npc.balls],"
							+ " and [npc.she] can't help but let out [npc.a_moan+] as a small squirt of precum suddenly drools out from [npc.her] [npc.cock];"
								+ " clear evidence that that [npc.her] [npc.cum] regeneration has [style.boldGrow(increased)].
"
						+ "[npc.Her] rate of [npc.cum] regeneration is now [style.boldSex(" + regenerationDescriptor + ")]!"
					+ "
");

		} else {
			return UtilText.parse(owner,
					"
"
						+ "[npc.Name] [npc.verb(feel)] strange sucking sensation taking place deep within [npc.her] [npc.balls],"
							+ " and [npc.she] can't help but let out a shocked gasp as [npc.she] [npc.verb(realise)] that [npc.sheIs] feeling [npc.her] [npc.cum] regeneration [style.boldShrink(decreasing)].
"
						+ "[npc.Her] rate of [npc.cum] regeneration is now [style.boldSex(" + regenerationDescriptor + ")]!"
					+ "
");
		}
	}

	// Expulsion:

	public FluidExpulsion getCumExpulsion() {
		return FluidExpulsion.getFluidExpulsionFromInt(cumExpulsion);
	}

	public int getRawCumExpulsionValue() {
		return cumExpulsion;
	}

	public String setCumExpulsion(GameCharacter owner, int cumExpulsion) {
		int oldExpulsion = this.cumExpulsion;
		this.cumExpulsion = Math.max(0, Math.min(cumExpulsion, FluidExpulsion.FOUR_HUGE.getMaximumValue()));
		int expulsionChange = this.cumExpulsion - oldExpulsion;

		if(owner==null) {
			return "";
		}

		if (expulsionChange == 0) {
			if(owner.isPlayer()) {
				return "
[style.colourDisabled(Your rate of [pc.cum] expulsion doesn't change...)]
";
			} else {
				return UtilText.parse(owner, "
[style.colourDisabled([npc.namePos] rate of [npc.cum] expulsion doesn't change...)]
");
			}
		}

		String expulsionDescriptor = getCumExpulsion().getDescriptor();
		if (expulsionChange > 0) {
			return UtilText.parse(owner,
					"
"
						+ "[npc.Name] suddenly [npc.verb(feel)] a strange tightening and building up of pressure deep within [npc.her] [npc.balls],"
								+ " and [npc.she] can't help but let out [npc.a_moan+] as a small amount of precum powerfully squirts out from [npc.her] [npc.cock];"
									+ " clear evidence that that [npc.her] [npc.cum] expulsion has [style.boldGrow(increased)].
"
						+ "[npc.She] will now expel [style.boldSex(" + UtilText.generateSingularDeterminer(expulsionDescriptor) + " "+expulsionDescriptor+")] amount of stored cum at each orgasm!"
					+ "
");

		} else {
			return UtilText.parse(owner,
					"
"
						+ "[npc.Name] suddenly [npc.verb(feel)] a strange loosening and reduction of pressure deep within [npc.her] [npc.balls],"
							+ " and [npc.she] can't help but let out [npc.a_moan+] as a small amount of precum weakly dribbles out from [npc.her] [npc.cock];"
								+ " clear evidence that that [npc.her] [npc.cum] expulsion has [style.boldShrink(decreased)].
"
						+ "[npc.She] will now expel [style.boldSex(" + UtilText.generateSingularDeterminer(expulsionDescriptor) + " "+expulsionDescriptor+")] amount of stored cum at each orgasm!"
					+ "
");
		}
	}

	@Override
	public boolean isBestial(GameCharacter owner) {
		if(owner==null) {
			return false;
		}
		return owner.getLegConfiguration().getBestialParts().contains(Testicle.class) && getType().getRace().isBestialPartsAvailable();
	}
}


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

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import com.lilithsthrone.game.character.GameCharacter;
import com.lilithsthrone.game.character.body.types.TongueType;
import com.lilithsthrone.game.character.body.valueEnums.TongueLength;
import com.lilithsthrone.game.character.body.valueEnums.TongueModifier;
import com.lilithsthrone.game.dialogue.utils.UtilText;
import com.lilithsthrone.game.inventory.InventorySlot;
import com.lilithsthrone.game.inventory.clothing.AbstractClothing;
import com.lilithsthrone.utils.Units;
import com.lilithsthrone.utils.Util;

/**
 * @since 0.1.0
 * @version 0.3.1
 * @author Innoxia
 */
public class Tongue implements BodyPartInterface {

	protected TongueType type;
	protected Set<TongueModifier> tongueModifiers;
	protected int tongueLength;
	protected boolean pierced;

	public Tongue(TongueType type) {
		this.type = type;
		pierced = false;

		tongueLength = type.getDefaultTongueLength();

		this.tongueModifiers = new HashSet<>(type.getDefaultRacialTongueModifiers());
	}

	@Override
	public TongueType getType() {
		return type;
	}

	@Override
	public String getDeterminer(GameCharacter gc) {
		return type.getDeterminer(gc);
	}

	@Override
	public String getName(GameCharacter gc) {
		return type.getName(gc);
	}

	@Override
	public String getNameSingular(GameCharacter gc) {
		return type.getNameSingular(gc);
	}

	@Override
	public String getNamePlural(GameCharacter gc) {
		return type.getNamePlural(gc);
	}

	public String getDescriptor(GameCharacter owner) {
		List<String> list = new ArrayList<>();

		for(TongueModifier tm : tongueModifiers) {
			list.add(tm.getName());
		}
		list.add(type.getDescriptor(owner));

		return Util.randomItemFrom(list);
	}

	/**
	 * Tongue type is set when FaceType changes.
	 */
	public void setType(TongueType type) {
		this.type = type;
	}

	public boolean isPierced() {
		return pierced;
	}

	public String setPierced(GameCharacter owner, boolean pierced) {
		if(this.pierced == pierced) {
			return "
[style.colourDisabled(Nothing happens...)]
";
		}

		this.pierced = pierced;

		if(pierced) {
			if(owner.isPlayer()) {
				return "
Your [pc.tongue] is now [style.boldGrow(pierced)]!
";
			} else {
				return UtilText.parse(owner,
						"
[npc.NamePos] [npc.tongue] is now [style.boldGrow(pierced)]!
");
			}

		} else {
			AbstractClothing c = owner.getClothingInSlot(InventorySlot.PIERCING_TONGUE);
			String piercingUnequip = "";
			if(c!=null) {
				owner.forceUnequipClothingIntoVoid(owner, c);
				piercingUnequip = owner.addClothing(c, false);
			}

			if(owner.isPlayer()) {
				return "
"
							+ "Your [pc.tongue] is [style.boldShrink(no longer pierced)]!"
						+ "
"
						+piercingUnequip;
			} else {
				return UtilText.parse(owner,
						"
"
								+ "[npc.NamePos] [npc.tongue] is [style.boldShrink(no longer pierced)]!"
						+ "
"
						+piercingUnequip);
			}
		}
	}

	public TongueLength getTongueLength() {
		return TongueLength.getTongueLengthFromInt(tongueLength);
	}

	public int getTongueLengthValue() {
		return tongueLength;
	}

	public String setTongueLength(GameCharacter owner, int tongueLength) {
		int oldTongueLength = this.tongueLength;
		this.tongueLength = Math.max(0, Math.min(tongueLength, TongueLength.FOUR_ABSURDLY_LONG.getMaximumValue()));
		int sizeChange = this.tongueLength - oldTongueLength;

		if(sizeChange == 0) {
			if(owner.isPlayer()) {
				return "
[style.colourDisabled(The length of your [pc.tongue] doesn't change...)]
";
			} else {
				return UtilText.parse(owner, "
[style.colourDisabled(The length of [npc.namePos] [npc.tongue] doesn't change...)]
");
			}
		}

		if(sizeChange < 0) {
			if(owner.isPlayer()) {
				return "
A soothing coolness rises up into your [pc.tongue], causing you to let out a surprised gasp as you feel it [style.boldShrink(getting shorter)].
"
						+ "You now have "+UtilText.generateSingularDeterminer(Util.intToString(this.tongueLength))+" [style.boldTfGeneric("
						+ Units.size(this.tongueLength, Units.UnitType.LONG_SINGULAR)+" [pc.tongue])]!
";
			} else {
				return UtilText.parse(owner, "
[npc.Name] lets out a little cry as [npc.she] feels a soothing coolness rise up into [npc.her] [npc.tongue], before it suddenly [style.boldShrink(gets shorter)].
"
						+ "[npc.Name] now has "+UtilText.generateSingularDeterminer(Util.intToString(this.tongueLength))+" [style.boldTfGeneric("
						+ Units.size(this.tongueLength, Units.UnitType.LONG_SINGULAR)+" [npc.tongue])]!
");
			}

		} else {
			if(owner.isPlayer()) {
				return "
A pulsating warmth rises up into your [pc.tongue], causing you to let out a surprised gasp as you feel it [style.boldGrow(growing longer)].
"
						+ "You now have "+UtilText.generateSingularDeterminer(Util.intToString(this.tongueLength))+" [style.boldTfGeneric("
						+ Units.size(this.tongueLength, Units.UnitType.LONG_SINGULAR)+" [pc.tongue])]!
";
			} else {
				return UtilText.parse(owner, "
[npc.Name] lets out a little cry as [npc.she] feels a pulsating warmth rise up into [npc.her] [npc.tongue], before it suddenly [style.boldGrow(grows longer)].
"
						+ "[npc.Name] now has "+UtilText.generateSingularDeterminer(Util.intToString(this.tongueLength))+" [style.boldTfGeneric("
						+ Units.size(this.tongueLength, Units.UnitType.LONG_SINGULAR)+" [npc.tongue])]!
");
			}
		}
	}

	public boolean hasTongueModifier(TongueModifier modifier) {
		return tongueModifiers.contains(modifier);
	}

	public String addTongueModifier(GameCharacter owner, TongueModifier modifier) {
		if(hasTongueModifier(modifier)) {
			return "
[style.colourDisabled(Nothing happens...)]
";
		}

		tongueModifiers.add(modifier);

		switch(modifier) {
			case RIBBED:
				if(owner.isPlayer()) {
					return "
"
								+ "You feel an intense pressure building up in your [pc.tongue], but before you have a chance to panic, it suddenly fades away, leaving you with a series of [style.boldGrow(hard, fleshy ribs)] lining your [pc.tongue].
"
								+ "[style.boldSex(Your [pc.tongue] is now ribbed!)]"
							+ "
";
				} else {
					return "
"
								+ "An intense pressure builds up in [npc.namePos] [npc.tongue], but before [npc.she] has a chance to panic, it suddenly fades away,"
									+ " leaving [npc.herHim] with a series of [style.boldGrow(hard, fleshy ribs)] lining [npc.her] [npc.tongue].
"
								+ "[style.boldSex([npc.NamePos] [npc.tongue] is now ribbed!)]"
							+ "
";
				}
			case TENTACLED:
				if(owner.isPlayer()) {
					return "
"
								+ "You feel an intense pressure building up in your [pc.tongue], and you let out a gasp as you feel [style.boldGrow(a series of little wriggling tentacles)] grow up all over your [pc.tongue].
"
								+ "[style.boldSex(Your [pc.tongue] is now covered with little tentacles, which wriggle with a mind of their own!)]"
							+ "
";
				} else {
					return "
"
								+ "An intense pressure builds up in [npc.namePos] [npc.tongue], and [npc.she] lets out a gasp as [npc.she] feels [style.boldGrow(a series of little wriggling tentacles)] grow up all over [npc.her] [npc.tongue].
"
								+ "[style.boldSex([npc.NamePos] [npc.tongue] is now covered with little tentacles, which wriggle with a mind of their own!)]"
							+ "
";
				}
			case BIFURCATED:
				if(owner.isPlayer()) {
					return "
"
								+ "You feel an intense pressure building up in your [pc.tongue], and you let out a gasp as you feel [style.boldGrow(it split in two)].
"
								+ "[style.boldSex(Your [pc.tongue] is now bifurcated, like a snake's!)]"
							+ "
";
				} else {
					return "
"
								+ "An intense pressure builds up in [npc.namePos] [npc.tongue], and [npc.she] lets out a gasp as [npc.she] feels [style.boldGrow(it split in two)].
"
								+ "[style.boldSex([npc.NamePos] [npc.tongue] is now bifurcated, like a snake's!)]"
							+ "
";
				}
		}

		// Catch:
		return "
[style.colourDisabled(Nothing happens...)]
";
	}

	public String removeTongueModifier(GameCharacter owner, TongueModifier modifier) {
		if(!hasTongueModifier(modifier)) {
			return "
[style.colourDisabled(Nothing happens...)]
";
		}

		tongueModifiers.remove(modifier);

		switch(modifier) {
			case RIBBED:
				if(owner.isPlayer()) {
					return "
"
								+ "You feel a soft coolness rising up into your [pc.tongue], but before you have a chance to react, it suddenly fades away, [style.boldShrink(removing)] your hard, fleshy ribs in the process.
"
								+ "[style.boldSex(Your [pc.tongue] is no longer ribbed!)]"
							+ "
";
				} else {
					return "
"
								+ "An soft coolness rises up into [npc.namePos] [npc.tongue], but before [npc.she] has a chance to react, it suddenly fades away, [style.boldShrink(removing)] [npc.her] hard, fleshy ribs in the process.
"
								+ "[style.boldSex([npc.NamePos] [npc.tongue] is no longer ribbed!)]"
							+ "
";
				}
			case TENTACLED:
				if(owner.isPlayer()) {
					return "
"
								+ "You feel a soft coolness rise up into your [pc.tongue], and you let out a gasp as you feel your [style.boldShrink(little wriggling tentacles disappear)].
"
								+ "[style.boldSex(Your [pc.tongue] is no longer covered with little tentacles!)]"
							+ "
";
				} else {
					return "
"
								+ "A soft coolness rises up into [npc.namePos] [npc.tongue], and [npc.she] lets out a gasp as [npc.she] feels [npc.her] [style.boldShrink(little wriggling tentacles disappear)].
"
								+ "[style.boldSex([npc.NamePos] [npc.tongue] is no longer covered with little tentacles!)]"
							+ "
";
				}
			case BIFURCATED:
				if(owner.isPlayer()) {
					return "
"
								+ "You feel a soft coolness rise up into your [pc.tongue], and you let out a gasp as you feel [style.boldShrink(it fuse back into a single point)].
"
								+ "[style.boldSex(Your [pc.tongue] is no longer bifurcated!)]"
							+ "
";
				} else {
					return "
"
								+ "A soft coolness rises up into [npc.namePos] [npc.tongue], and [npc.she] lets out a gasp as [npc.she] feels [style.boldShrink(it fuse back into a single point)].
"
								+ "[style.boldSex([npc.NamePos] [npc.tongue] is no longer bifurcated!)]"
							+ "
";
				}
		}

		// Catch:
		return "
[style.colourDisabled(Nothing happens...)]
";
	}

	@Override
	public boolean isBestial(GameCharacter owner) {
		if(owner==null) {
			return false;
		}
		return owner.getLegConfiguration().getBestialParts().contains(Tongue.class) && getType().getRace().isBestialPartsAvailable();
	}
}