code:
package com.lilithsthrone.game.inventory.enchanting;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;

import com.lilithsthrone.game.character.effects.Perk;
import com.lilithsthrone.game.character.fetishes.Fetish;
import com.lilithsthrone.game.character.markings.AbstractTattooType;
import com.lilithsthrone.game.character.markings.Tattoo;
import com.lilithsthrone.game.combat.SpellSchool;
import com.lilithsthrone.game.dialogue.utils.EnchantmentDialogue;
import com.lilithsthrone.game.inventory.AbstractCoreItem;
import com.lilithsthrone.game.inventory.clothing.AbstractClothing;
import com.lilithsthrone.game.inventory.clothing.AbstractClothingType;
import com.lilithsthrone.game.inventory.item.AbstractItem;
import com.lilithsthrone.game.inventory.item.AbstractItemType;
import com.lilithsthrone.game.inventory.item.ItemType;
import com.lilithsthrone.game.inventory.weapon.AbstractWeapon;
import com.lilithsthrone.game.inventory.weapon.AbstractWeaponType;
import com.lilithsthrone.main.Main;
import com.lilithsthrone.rendering.SVGImages;
import com.lilithsthrone.utils.Colour;
import com.lilithsthrone.utils.SvgUtil;
import com.lilithsthrone.utils.Util;

/**
 * @since 0.1.75
 * @version 0.2.6
 * @author Innoxia
 */
public class EnchantingUtils {

	public static final int FLAME_COST_MODIFER = 500;

	public static AbstractItem craftItem(AbstractCoreItem ingredient, List<ItemEffect> effects) {
		AbstractItem craftedItem = null;

		craftedItem = AbstractItemType.generateItem((AbstractItemType) ingredient.getEnchantmentItemType(effects));

		List<ItemEffect> effectsToBeAdded = new ArrayList<>();
		effectsToBeAdded.addAll(effects);

		craftedItem.setItemEffects(effectsToBeAdded);

		craftedItem.setName(EnchantmentDialogue.getOutputName());
		craftedItem.setColour(ingredient.getEnchantmentEffect().getColour());
		craftedItem.setSVGString(getSVGString(ingredient, effectsToBeAdded));

		return craftedItem;
	}

	public static AbstractClothing craftClothing(AbstractCoreItem ingredient, List<ItemEffect> effects) {
		AbstractClothing craftedClothing = null;

		List<ItemEffect> effectsToBeAdded = new ArrayList<>(effects);

		craftedClothing = AbstractClothingType.generateClothing(
				(AbstractClothingType) ingredient.getEnchantmentItemType(effects),
				((AbstractClothing)ingredient).getColour(),
				((AbstractClothing)ingredient).getSecondaryColour(),
				((AbstractClothing)ingredient).getTertiaryColour(),
				effectsToBeAdded);

		craftedClothing.setPattern(((AbstractClothing)ingredient).getPattern());
		craftedClothing.setPatternColour(((AbstractClothing)ingredient).getPatternColour());
		craftedClothing.setPatternSecondaryColour(((AbstractClothing)ingredient).getPatternSecondaryColour());
		craftedClothing.setPatternTertiaryColour(((AbstractClothing)ingredient).getPatternTertiaryColour());

		craftedClothing.setName(EnchantmentDialogue.getOutputName());

		craftedClothing.setEnchantmentKnown(null, true);

//		System.out.println("Has clothing: "+Main.game.getPlayer().hasClothing(craftedClothing));
//		for(char c : EnchantmentDialogue.getOutputName().toCharArray()) {
//			System.out.print("["+c+","+(int)c+"]");
//		}

		return craftedClothing;
	}

	public static Tattoo craftTattoo(AbstractCoreItem ingredient, List<ItemEffect> effects) {
		List<ItemEffect> effectsToBeAdded = new ArrayList<>(effects);
		((Tattoo)ingredient).setEffects(effectsToBeAdded);
		((Tattoo)ingredient).setName(EnchantmentDialogue.getOutputName());
		return (Tattoo) ingredient;
	}

	public static AbstractWeapon craftWeapon(AbstractCoreItem ingredient, List<ItemEffect> effects) {
		AbstractWeapon craftedWeapon = null;

		List<ItemEffect> effectsToBeAdded = new ArrayList<>();
		effectsToBeAdded.addAll(effects);

		craftedWeapon = AbstractWeaponType.generateWeapon(
				(AbstractWeaponType) ingredient.getEnchantmentItemType(effects),
				((AbstractWeapon) ingredient).getDamageType(),
				((AbstractWeapon)ingredient).getPrimaryColour(),
				((AbstractWeapon)ingredient).getSecondaryColour());

		craftedWeapon.setEffects(effectsToBeAdded);

		craftedWeapon.setName(EnchantmentDialogue.getOutputName());

		return craftedWeapon;
	}

	public static String getPotionName(AbstractCoreItem ingredient, List<ItemEffect> effects) {

		if(ingredient.getEnchantmentItemType(effects) instanceof AbstractClothingType
				|| ingredient.getEnchantmentItemType(effects) instanceof AbstractTattooType
				|| ingredient.getEnchantmentItemType(effects) instanceof AbstractWeaponType) {
			return ingredient.getName();
		}

		if(((AbstractItem)ingredient).getItemType().getId().equals(ItemType.ORIENTATION_HYPNO_WATCH.getId())) {
			if(effects.isEmpty() || effects.get(0).getPrimaryModifier()==TFModifier.REMOVAL) {
				return "Hypno-Watch";
			}
			if(effects.get(0).getPrimaryModifier()==TFModifier.ORIENTATION_GYNEPHILIC) {
				return "Gynephilic Hypno-Watch";
			} else if(effects.get(0).getPrimaryModifier()==TFModifier.ORIENTATION_AMBIPHILIC) {
				return "Ambiphilic Hypno-Watch";
			} else {
				return "Androphilic Hypno-Watch";
			}
		}

		String potionName = ((AbstractItemType) ingredient.getEnchantmentItemType(effects)).getName(false);
		String potionDescriptor = "";
		String potionSuffix = "";
		String potionPreSuffix = "";

		if(ingredient!=null) {
			try {
				potionDescriptor = ingredient.getEffects().get(0).getItemEffectType().getPotionDescriptor();
			} catch(Exception ex) {
				System.err.println("EnchantingUtils: getPotionName() error 1.");
			}
		}

		String finalPotionName = ((potionDescriptor==null || potionDescriptor.isEmpty())?"":Util.capitaliseSentence(potionDescriptor)+" ") + potionName;

		for(ItemEffect ie : effects) {
			if(ie.getPrimaryModifier() != null && ie.getPrimaryModifier() != TFModifier.NONE) {
				potionSuffix = ie.getPrimaryModifier().getDescriptor();

				if(ie.getSecondaryModifier() != TFModifier.NONE) {
					if(ie.getSecondaryModifier()==TFModifier.ARCANE_BOOST && ie.getPotency().isNegative()) {
						potionPreSuffix = "drained";
					} else {
						potionPreSuffix = ie.getSecondaryModifier().getDescriptor();
					}
				}

				if(potionSuffix!="") {
					if(potionPreSuffix!="") {
						if(ie.getSecondaryModifier().isSoloDescriptor())
							finalPotionName += " of "+potionPreSuffix;
						else
							finalPotionName += " of "+potionPreSuffix+" "+potionSuffix;
					} else {
						finalPotionName += " of "+potionSuffix;
					}
				}

				break;
			}
		}

		return Util.capitaliseSentence(finalPotionName);
	}

	private static Set<TFModifier> freePrimaryModifiers = Util.newHashSetOfValues(TFModifier.TF_MOD_WETNESS, TFModifier.TF_MILK, TFModifier.TF_MILK_CROTCH, TFModifier.TF_CUM, TFModifier.TF_GIRLCUM);
	private static Set<TFModifier> freeSecondaryModifiers = Util.newHashSetOfValues(TFModifier.TF_MOD_WETNESS, TFModifier.TF_MOD_REGENERATION, TFModifier.TF_MOD_CUM_EXPULSION);

	private static boolean isEffectFreeForWaterSchool(ItemEffect effect) {
		return freePrimaryModifiers.contains(effect.getPrimaryModifier())
				|| freeSecondaryModifiers.contains(effect.getSecondaryModifier());
	}

	private static boolean isEffectFreeForRemovingPositiveAttribute(ItemEffect effect) {
		if(effect.getPrimaryModifier()==TFModifier.CLOTHING_ATTRIBUTE || effect.getPrimaryModifier()==TFModifier.CLOTHING_MAJOR_ATTRIBUTE) {
			return !effect.getPotency().isNegative();
		}
		return false;
	}

	private static int applyDiscountsForPerksAndFetishes(AbstractCoreItem ingredient, int cost) {
		if(Main.game.getPlayer().hasFetish(Fetish.FETISH_TRANSFORMATION_GIVING) && ingredient instanceof AbstractItem) {
			cost/=2;
		}
		if(Main.game.getPlayer().hasPerkAnywhereInTree(Perk.CLOTHING_ENCHANTER) && ingredient instanceof AbstractClothing) {
			cost/=2;
		}
		if(Main.game.getPlayer().hasPerkAnywhereInTree(Perk.WEAPON_ENCHANTER) && ingredient instanceof AbstractWeapon) {
			cost/=2;
		}
		return cost;
	}

	public static int getModifierEffectCost(boolean addingEffect, AbstractCoreItem ingredient, ItemEffect effect) {
		if(!(ingredient instanceof Tattoo)
				&& Main.game.getPlayer().isSpellSchoolSpecialAbilityUnlocked(SpellSchool.WATER)
				&& isEffectFreeForWaterSchool(effect)) {
			return 0;
		}

		if(!addingEffect && isEffectFreeForRemovingPositiveAttribute(effect)) {
			return 0;
		}

		return applyDiscountsForPerksAndFetishes(ingredient, effect.getCost());
	}

	public static int getCost(AbstractCoreItem ingredient, List<ItemEffect> effects) {
		Map<ItemEffect, Integer> effectCount = new HashMap<>();
		for(ItemEffect ie : effects) {
			effectCount.merge(ie, 1, Integer::sum);
		}
		for(ItemEffect ie : ingredient.getEffects()) {
			if(effects.contains(ie)) {
				if(effectCount.get(ie)>0 || !isEffectFreeForRemovingPositiveAttribute(ie)) {
					effectCount.merge(ie, -1, Integer::sum);
				}
			} else {
				if(!isEffectFreeForRemovingPositiveAttribute(ie)) {
					effectCount.merge(ie, 1, Integer::sum);
				}
			}
		}

		if (!(ingredient instanceof Tattoo) && Main.game.getPlayer().isSpellSchoolSpecialAbilityUnlocked(SpellSchool.WATER)) {
			effectCount.keySet().removeIf(EnchantingUtils::isEffectFreeForWaterSchool);
		}

		int cost = 0;
		for(Entry<ItemEffect, Integer> entry : effectCount.entrySet()) {
			int costIncrement = entry.getKey().getCost() * Math.abs(entry.getValue());

			if(entry.getKey().getSecondaryModifier()==TFModifier.CLOTHING_SEALING) {
				switch(entry.getKey().getPotency()) {
					case MAJOR_BOOST:
						costIncrement*=4;
						break;
					case BOOST:
						costIncrement*=2;
						break;
					default:
						break;
				}
			}

			cost += costIncrement;
		}

		return applyDiscountsForPerksAndFetishes(ingredient, cost);
	}

	public static String getSVGString(AbstractCoreItem ingredient, List<ItemEffect> effects) {

		if(ingredient.getEnchantmentItemType(effects) instanceof AbstractClothingType
				|| ingredient.getEnchantmentItemType(effects) instanceof AbstractTattooType
				|| ingredient.getEnchantmentItemType(effects) instanceof AbstractWeaponType) {
			return ingredient.getSVGString();
		}

		if(((AbstractItem)ingredient).getItemType().getId().equals(ItemType.ORIENTATION_HYPNO_WATCH.getId())) {
			if(effects.isEmpty() || effects.get(0).getPrimaryModifier()==TFModifier.REMOVAL) {
				return SVGImages.SVG_IMAGE_PROVIDER.getHypnoWatchBase();
			}

			if(effects.get(0).getPrimaryModifier()==TFModifier.ORIENTATION_GYNEPHILIC) {
				return SVGImages.SVG_IMAGE_PROVIDER.getHypnoWatchGynephilic();

			} else if(effects.get(0).getPrimaryModifier()==TFModifier.ORIENTATION_AMBIPHILIC) {
				return SVGImages.SVG_IMAGE_PROVIDER.getHypnoWatchAmbiphilic();

			} else {
				return SVGImages.SVG_IMAGE_PROVIDER.getHypnoWatchAndrophilic();
			}
		}

		StringBuilder SVGImageSB = new StringBuilder();

		SVGImageSB.append("
"+SVGImages.SVG_IMAGE_PROVIDER.getRefinedBackgroundMap().get(ingredient.getEnchantmentEffect().getColour())+"
");

		String s = ((AbstractItemType) ingredient.getEnchantmentItemType(effects)).getSVGString();

		Colour colour = Colour.CLOTHING_BLUE_LIGHT;

		for(ItemEffect ie : effects) {
			if(ie.getPrimaryModifier() != null && ie.getPrimaryModifier() != TFModifier.NONE) {
				colour = ie.getPrimaryModifier().getColour();

				break;
			}
		}

		s = SvgUtil.colourReplacement(((AbstractItem)ingredient).getItemType().getId(), colour, null, null, s);

		SVGImageSB.append("
"+s+"
");

		for(ItemEffect ie : effects) {
			if(ie.getSecondaryModifier() != null && ie.getSecondaryModifier() != TFModifier.NONE) {
				SVGImageSB.append("
"+SVGImages.SVG_IMAGE_PROVIDER.getRefinedSwirlsMap().get(ie.getSecondaryModifier().getColour())+"
");

				break;
			}
		}

		return SVGImageSB.toString();
	}

	public static String getImportedSVGString(AbstractCoreItem item, Colour importedColour, List<ItemEffect> effects) {

		if(((AbstractItem)item).getItemType().getId().equals(ItemType.ORIENTATION_HYPNO_WATCH.getId())) {
			if(effects.isEmpty() || effects.get(0).getPrimaryModifier()==TFModifier.REMOVAL) {
				return SVGImages.SVG_IMAGE_PROVIDER.getHypnoWatchBase();
			}

			if(effects.get(0).getPrimaryModifier()==TFModifier.ORIENTATION_GYNEPHILIC) {
				return SVGImages.SVG_IMAGE_PROVIDER.getHypnoWatchGynephilic();

			} else if(effects.get(0).getPrimaryModifier()==TFModifier.ORIENTATION_AMBIPHILIC) {
				return SVGImages.SVG_IMAGE_PROVIDER.getHypnoWatchAmbiphilic();

			} else {
				return SVGImages.SVG_IMAGE_PROVIDER.getHypnoWatchAndrophilic();
			}
		}

		StringBuilder SVGImageSB = new StringBuilder();

		String importedColourString = SVGImages.SVG_IMAGE_PROVIDER.getRefinedBackgroundMap().get(importedColour);
		if(importedColourString==null || importedColourString.isEmpty() || importedColourString.equals("null")) {
			importedColourString = SVGImages.SVG_IMAGE_PROVIDER.getRefinedBackgroundMap().get(effects.get(0).getItemEffectType().getColour());
		}

		SVGImageSB.append("
"+importedColourString+"
");

		String s = item.getSVGString();

		Colour colour = Colour.CLOTHING_BLUE_LIGHT;

		for(ItemEffect ie : effects) {
			if(ie.getPrimaryModifier() != null && ie.getPrimaryModifier() != TFModifier.NONE) {
				colour = ie.getPrimaryModifier().getColour();

				break;
			}
		}

		s = s.replaceAll("#ff2a2a", colour.getShades()[0]);
		s = s.replaceAll("#ff5555|#f55", colour.getShades()[1]);
		s = s.replaceAll("#ff8080", colour.getShades()[2]);
		s = s.replaceAll("#ffaaaa|#faa", colour.getShades()[3]);
		s = s.replaceAll("#ffd5d5", colour.getShades()[4]);
		SVGImageSB.append("
"+s+"
");

		for(ItemEffect ie : effects) {
			if(ie.getSecondaryModifier() != null && ie.getSecondaryModifier() != TFModifier.NONE) {
				SVGImageSB.append("
"+SVGImages.SVG_IMAGE_PROVIDER.getRefinedSwirlsMap().get(ie.getSecondaryModifier().getColour())+"
");

				break;
			}
		}

		return SVGImageSB.toString();
	}
}

repo_name: klorpa/Pedo

license: unknown


code:
package com.lilithsthrone.game.inventory.enchanting;

import java.util.List;

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

import com.lilithsthrone.game.Game;
import com.lilithsthrone.game.character.CharacterUtils;
import com.lilithsthrone.game.character.GameCharacter;
import com.lilithsthrone.game.character.race.Race;
import com.lilithsthrone.game.dialogue.utils.UtilText;
import com.lilithsthrone.main.Main;
import com.lilithsthrone.utils.XMLSaving;

/**
 * @since 0.1.8
 * @version 0.3.3.10
 * @author Innoxia
 */
public class ItemEffect implements XMLSaving {

	public static final int SEALED_COST_MINOR_BOOST = 5;
	public static final int SEALED_COST_MINOR_DRAIN = 25;
	public static final int SEALED_COST_DRAIN = 100;
	public static final int SEALED_COST_MAJOR_DRAIN = 500;

	private AbstractItemEffectType itemEffectType;
	private TFModifier primaryModifier;
	private TFModifier secondaryModifier;
	private TFPotency potency;
	private int limit;
	private ItemEffectTimer timer;

	public ItemEffect(AbstractItemEffectType itemEffectType) {
		this.itemEffectType = itemEffectType;
		this.primaryModifier = null;
		this.secondaryModifier = null;
		this.potency = null;
		this.limit = 0;
		this.timer = new ItemEffectTimer();
	}

	public ItemEffect(AbstractItemEffectType itemEffectType, TFModifier primaryModifier, TFModifier secondaryModifier, TFPotency potency, int limit) {
		this.itemEffectType = itemEffectType;
		this.primaryModifier = primaryModifier;
		this.secondaryModifier = secondaryModifier;
		this.potency = potency;
		this.limit = limit;
		this.timer = new ItemEffectTimer();
	}

	public String getId() {
		return (itemEffectType==null?"n":itemEffectType.toString())
				+ (primaryModifier==null?"n":primaryModifier.toString())
				+ (secondaryModifier==null?"n":secondaryModifier.toString())
				+ (potency==null?"n":potency.toString())
				+ limit;
	}

	@Override
	public boolean equals(Object o) {
		if(o instanceof ItemEffect){
			if((((ItemEffect)o).getItemEffectType()==null && itemEffectType==null
					||((ItemEffect)o).getItemEffectType()!=null && ((ItemEffect)o).getItemEffectType().equals(itemEffectType))
				&& ((ItemEffect)o).getPrimaryModifier() == primaryModifier
				&& ((ItemEffect)o).getSecondaryModifier() == secondaryModifier
				&& ((ItemEffect)o).getPotency() == potency
				&& ((ItemEffect)o).getLimit() == limit){
					return true;
			}
		}
		return false;
	}

	@Override
	public int hashCode() {
		int result = 17;
		if(itemEffectType!=null) {
			result = 31 * result + itemEffectType.hashCode();
		}
		if(primaryModifier!=null) {
			result = 31 * result + primaryModifier.hashCode();
		}
		if(secondaryModifier!=null) {
			result = 31 * result + secondaryModifier.hashCode();
		}
		if(potency!=null) {
			result = 31 * result + potency.hashCode();
		}
		result = 31 * result + limit;
		return result;
	}

	public Element saveAsXML(Element parentElement, Document doc) {
		Element effect = doc.createElement("effect");
		parentElement.appendChild(effect);

		CharacterUtils.addAttribute(doc, effect, "type", ItemEffectType.getIdFromItemEffectType(getItemEffectType()));
		CharacterUtils.addAttribute(doc, effect, "mod1", (getPrimaryModifier()==null?"null":getPrimaryModifier().toString()));
		CharacterUtils.addAttribute(doc, effect, "mod2", (getSecondaryModifier()==null?"null":getSecondaryModifier().toString()));
		CharacterUtils.addAttribute(doc, effect, "potency", (getPotency()==null?"null":getPotency().toString()));
		CharacterUtils.addAttribute(doc, effect, "limit", String.valueOf(getLimit()));
		CharacterUtils.addAttribute(doc, effect, "timer", String.valueOf(getTimer().getSecondsPassed()));

		return effect;
	}

	public static ItemEffect loadFromXML(Element parentElement, Document doc) {
		String itemEffectType = parentElement.getAttribute("type");
		if(itemEffectType.isEmpty()) {
			itemEffectType = parentElement.getAttribute("itemEffectType"); // Support for effects prior to 0.3.1.5
		}

		String primaryMod = parentElement.getAttribute("mod1");
		if(primaryMod.isEmpty()) {
			primaryMod = parentElement.getAttribute("primaryModifier"); // Support for effects prior to 0.3.1.5
		}

		String secondaryMod = parentElement.getAttribute("mod2");
		if(secondaryMod.isEmpty()) {
			secondaryMod = parentElement.getAttribute("secondaryModifier"); // Support for effects prior to 0.3.1.5
		}

		if(itemEffectType.equals("RACE_DEMON")) {
			throw new NullPointerException();
		}

		switch(itemEffectType) {
			case "ATTRIBUTE_STRENGTH":
			case "ATTRIBUTE_FITNESS":
				itemEffectType = "ATTRIBUTE_PHYSIQUE";
				break;
			case "ATTRIBUTE_INTELLIGENCE":
				itemEffectType = "ATTRIBUTE_ARCANE";
				break;
		}
		switch(primaryMod) {
			case "DAMAGE_ATTACK":
			case "RESISTANCE_ATTACK":
				return null;
			case "CLOTHING_SEALING":
				primaryMod = "CLOTHING_SPECIAL";
				secondaryMod = "CLOTHING_SEALING";
				break;
			case "CLOTHING_ENSLAVEMENT":
				primaryMod = "CLOTHING_SPECIAL";
				secondaryMod = "CLOTHING_ENSLAVEMENT";
				break;
			case "TF_PENIS":
				if(Main.isVersionOlderThan(Game.loadingVersion, "0.3.5.1")) {
					if(secondaryMod=="TF_MOD_SIZE_SECONDARY") {
						secondaryMod = "TF_MOD_SIZE_TERTIARY";
					}
				}
				break;
		}
		switch(secondaryMod) {
			case "TF_MOD_FETISH_SEEDER":
				secondaryMod = "TF_MOD_FETISH_IMPREGNATION";
				break;
			case "TF_MOD_FETISH_BROODMOTHER":
				secondaryMod = "TF_MOD_FETISH_PREGNANCY";
				break;
			case "CRITICAL_CHANCE":
				secondaryMod = "CRITICAL_DAMAGE";
				break;
		}

		ItemEffect ie;
		try { // Wrap this in a try, as the TFModifier.valueOf might fail, due to removing Broodmother/Seeder fetish modifiers in 0.2.7.5, and then critical chance in 0.3.3.5.
			TFModifier primary = (primaryMod.equals("null") || primaryMod.isEmpty()?null:TFModifier.valueOf(primaryMod));
			TFModifier secondary = (secondaryMod.equals("null") || secondaryMod.isEmpty()?null:TFModifier.valueOf(secondaryMod));

			if(secondary!=null && TFModifier.getWeaponMajorAttributeList().contains(secondary)) {
				primary = TFModifier.CLOTHING_MAJOR_ATTRIBUTE;
			}

			ie = new ItemEffect(
					ItemEffectType.getItemEffectTypeFromId(itemEffectType),
					primary,
					secondary,
					(parentElement.getAttribute("potency").equals("null")?null:TFPotency.valueOf(parentElement.getAttribute("potency"))),
					Integer.valueOf(parentElement.getAttribute("limit")));

		} catch(Exception ex) {
			System.err.println("(Minor error, can ignore.) Unable to import ItemEffect (" + primaryMod + ", " + secondaryMod + ") from" + doc.getDocumentURI());
			System.err.println(ex);
			return null;
		}

		try {
			int time = Integer.valueOf(parentElement.getAttribute("timer"));

			if(Main.isVersionOlderThan(Game.loadingVersion, "0.2.6.5")) {// I think this was to align effects to all be on the hour:
				int timer = time/60;
				ie.getTimer().setSecondsPassed(((timer*60) + (int)(Main.game.getMinutesPassed()%60)));

			} else if(Main.isVersionOlderThan(Game.loadingVersion, "0.3.0.6")) {
				ie.getTimer().setSecondsPassed(time*60);

			} else {
				ie.getTimer().setSecondsPassed(time);
			}
		} catch(Exception ex) {
			ex.printStackTrace();
		}

		return ie;
	}

	//TODO
//	public static List<ItemEffect> groupEffects(List<ItemEffect> effects) {
//		List<ItemEffect> groupedEffects = new ArrayList<>();
//
//		for(ItemEffect ie : effects) {
//
//		}
//
//		return groupedEffects;
//	}

	public String applyEffect(GameCharacter user, GameCharacter target, int secondsPassed) {
		this.timer.incrementSecondsPassed(secondsPassed);
		if(target!=null) {
			if(target.getRace()==Race.DEMON
					&& (getSecondaryModifier()==TFModifier.TF_TYPE_1
							|| getSecondaryModifier()==TFModifier.TF_TYPE_2
							|| getSecondaryModifier()==TFModifier.TF_TYPE_3
							|| getSecondaryModifier()==TFModifier.TF_TYPE_4
							|| getSecondaryModifier()==TFModifier.TF_TYPE_5
							|| getSecondaryModifier()==TFModifier.TF_MOD_LEG_CONFIG_ARACHNID
							|| getSecondaryModifier()==TFModifier.TF_MOD_LEG_CONFIG_BIPEDAL
							|| getSecondaryModifier()==TFModifier.TF_MOD_LEG_CONFIG_CEPHALOPOD
							|| getSecondaryModifier()==TFModifier.TF_MOD_LEG_CONFIG_TAIL
							|| getSecondaryModifier()==TFModifier.TF_MOD_LEG_CONFIG_TAIL_LONG
							|| getSecondaryModifier()==TFModifier.TF_MOD_LEG_CONFIG_TAUR
							|| getSecondaryModifier()==TFModifier.REMOVAL)) {
				return UtilText.parse(target,
						"
"
							+ "As [npc.nameIsFull] [style.boldDemon([npc.a_race])], the transformation has [style.boldBad(no effect)]!"
						+ "
");
			}
		}
		return getItemEffectType().applyEffect(getPrimaryModifier(), getSecondaryModifier(), getPotency(), getLimit(), user, target, this.timer);
	}

	public List<String> getEffectsDescription(GameCharacter user, GameCharacter target) {
		return getItemEffectType().getEffectsDescription(getPrimaryModifier(), getSecondaryModifier(), getPotency(), getLimit(), user, target);
	}

	public int getCost() {
		int cost = 1;
		if(getPrimaryModifier()!=null) {
			if(getPrimaryModifier()!=TFModifier.NONE) {
				cost+=getPrimaryModifier().getValue();
			}
		}
		if(getSecondaryModifier()!=null) {
			if(getSecondaryModifier()!=TFModifier.NONE) {
				cost+=getSecondaryModifier().getValue();
			}
		}
		if(potency!=null) {
			cost += potency.getValue();
		}
		if(getLimit() != -1) {
			cost+=1;
		}

		return cost;
	}

	public AbstractItemEffectType getItemEffectType() {
		return itemEffectType;
	}

	public void setItemEffectType(AbstractItemEffectType itemEffectType) {
		this.itemEffectType = itemEffectType;
	}

	public TFModifier getPrimaryModifier() {
		return primaryModifier;
	}

	public void setPrimaryModifier(TFModifier primaryModifier) {
		this.primaryModifier = primaryModifier;
	}

	public TFModifier getSecondaryModifier() {
		return secondaryModifier;
	}

	public void setSecondaryModifier(TFModifier secondaryModifier) {
		this.secondaryModifier = secondaryModifier;
	}

	public TFPotency getPotency() {
		return potency;
	}

	public int getLimit() {
		return limit;
	}

	public void setLimit(int limit) {
		this.limit = limit;
	}

	public ItemEffectTimer getTimer() {
		return timer;
	}

	public void setTimer(ItemEffectTimer timer) {
		this.timer = timer;
	}

}


code:
package com.lilithsthrone.game.inventory.enchanting;

import com.lilithsthrone.main.Main;

/**
 * @since 0.2.0
 * @version 0.3.1
 * @author Innoxia
 */
public class ItemEffectTimer {
	private int secondsPassed;

	public ItemEffectTimer() {
		if(Main.game!=null) {
			secondsPassed = (int) (Main.game.getSecondsPassed()%(60*60)); // To synchronise all TFs on the hour.
		} else {
			secondsPassed = 0;
		}
	}

	public int getSecondsPassed() {
		return secondsPassed;
	}

	public void setSecondsPassed(int secondsPassed) {
		this.secondsPassed = secondsPassed;
	}

	public void incrementSecondsPassed(int increment) {
		setSecondsPassed(getSecondsPassed() + increment);
	}

}