1
mirror of https://github.com/StarWishsama/Slimefun4.git synced 2024-09-19 19:25:48 +00:00

Cherry-picked Talisman of the Wise from #2645

This commit is contained in:
TheBusyBiscuit 2021-01-24 18:04:52 +01:00
parent f6e9d70baa
commit 0b4c2f2e08
9 changed files with 64 additions and 233 deletions

View File

@ -30,6 +30,7 @@
* Added a new language: Bulgarian
* Added a new language: Hebrew
* (API) Added AsyncProfileLoadEvent
* Added Talisman of the Wise
#### Changes
* Massive performance improvements to holograms/armorstands

View File

@ -562,8 +562,7 @@ public final class SlimefunItems {
public static final SlimefunItemStack TALISMAN_WHIRLWIND = new SlimefunItemStack("WHIRLWIND_TALISMAN", Material.EMERALD, "&aTalisman of the Whirlwind", "", "&fHaving this Talisman", "&fin your Inventory will reflect", "&f60% of any projectiles fired at you.", "&e&oOnly a thrown Trident can pierce", "&e&othrough this layer of protection");
public static final SlimefunItemStack TALISMAN_WIZARD = new SlimefunItemStack("WIZARD_TALISMAN", Material.EMERALD, "&aTalisman of the Wizard", "", "&fWhile you have this Talisman", "&fin your Inventory it allows you to", "&fobtain Fortune Level 4/5 however", "&fit also has a chance to lower the", "&fLevel of some Enchantments on your Item");
public static final SlimefunItemStack TALISMAN_CAVEMAN = new SlimefunItemStack("CAVEMAN_TALISMAN", Material.EMERALD, "&aTalisman of the Caveman", "", "&fWhile you have this Talisman", "&fin your inventory it gives", "&fyou a 50% chance for a decent", "&fHaste buff when you mine any ore");
public static final SlimefunItemStack TALISMAN_WISE = new SlimefunItemStack("WISE_TALISMAN", Material.EMERALD, "&aTalisman of the Wise", "", "&fWhile you have this Talisman", "&fin your inventory it gives", "&fyou a 20% chance of doubling", "&fall experience you obtain");
public static final SlimefunItemStack TALISMAN_RESURRECTED = new SlimefunItemStack("RESURRECTED_TALISMAN", Material.EMERALD, "&aTalisman of the Resurrected", "", "&fWhile you have this Talisman", "&fin your inventory it will", "&fteleport you back safely when", "&fyou fall into the void", "&e&oRight click while holding this", "&e&otalisman to set a custom", "&e&orespawn location!");
public static final SlimefunItemStack TALISMAN_WISE = new SlimefunItemStack("WISE_TALISMAN", Material.EMERALD, "&aTalisman of the Wise", "", "&fWhile you have this Talisman", "&fin your inventory it gives", "&fyou a 20% chance of doubling", "&fany experience you obtain");
/* Staves */
public static final SlimefunItemStack STAFF_ELEMENTAL = new SlimefunItemStack("STAFF_ELEMENTAL", Material.STICK, "&6Elemental Staff");

View File

@ -1,106 +0,0 @@
package io.github.thebusybiscuit.slimefun4.implementation.items.magical.talismans;
import java.util.UUID;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import org.bukkit.Bukkit;
import org.bukkit.Location;
import org.bukkit.NamespacedKey;
import org.bukkit.World;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta;
import org.bukkit.persistence.PersistentDataContainer;
import org.bukkit.potion.PotionEffect;
import org.bukkit.potion.PotionEffectType;
import com.google.gson.JsonObject;
import io.github.thebusybiscuit.cscorelib2.data.PersistentJsonDataType;
import io.github.thebusybiscuit.cscorelib2.protection.ProtectableAction;
import io.github.thebusybiscuit.slimefun4.core.handlers.ItemUseHandler;
import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin;
import me.mrCookieSlime.Slimefun.Objects.SlimefunItem.SlimefunItem;
import me.mrCookieSlime.Slimefun.api.SlimefunItemStack;
/**
* This {@link SlimefunItem} is a special variant of the {@Link Talisman}. This specific {@Link Talisman} saves you
* from a death caused by the void and teleports to a safe location.
* This location is determined as follows: Talisman NBT-saved location -> Bed spawn -> World spawn
*
* @author svr333
*
*/
public class ResurrectedTalisman extends Talisman {
private final NamespacedKey locationKey = new NamespacedKey(SlimefunPlugin.instance(), "resurrected_location");
public ResurrectedTalisman(SlimefunItemStack item, ItemStack[] recipe) {
super(item, recipe, true, true, "resurrected", new PotionEffect(PotionEffectType.GLOWING, 400, 0), new PotionEffect(PotionEffectType.ABSORPTION, 400, 4), new PotionEffect(PotionEffectType.DAMAGE_RESISTANCE, 200, 20));
addItemHandler(getItemHandler());
}
@Nonnull
public ItemUseHandler getItemHandler() {
return e -> {
Location currentLoc = e.getPlayer().getLocation();
JsonObject json = createJsonFromLocation(currentLoc);
ItemStack item = e.getItem();
if (SlimefunPlugin.getProtectionManager().hasPermission(e.getPlayer(), currentLoc, ProtectableAction.PLACE_BLOCK) && item.hasItemMeta()) {
ItemMeta itemMeta = item.getItemMeta();
itemMeta.getPersistentDataContainer().set(locationKey, PersistentJsonDataType.JSON_OBJECT, json);
item.setItemMeta(itemMeta);
SlimefunPlugin.getLocalization().sendMessage(e.getPlayer(), "messages.talisman.resurrected-location", true);
return;
}
SlimefunPlugin.getLocalization().sendMessage(e.getPlayer(), "messages.talisman.resurrected-location-failed", true);
};
}
@Nullable
public Location getSavedLocation(@Nonnull ItemStack item) {
PersistentDataContainer pdc = item.getItemMeta().getPersistentDataContainer();
JsonObject json = pdc.get(locationKey, PersistentJsonDataType.JSON_OBJECT);
if (json != null) {
return parseLocationFromJsonObject(json);
} else {
return null;
}
}
@Nonnull
private JsonObject createJsonFromLocation(@Nonnull Location loc) {
JsonObject json = new JsonObject();
json.addProperty("world", loc.getWorld().getUID().toString());
json.addProperty("x", loc.getX());
json.addProperty("y", loc.getY());
json.addProperty("z", loc.getZ());
return json;
}
@Nullable
private Location parseLocationFromJsonObject(@Nonnull JsonObject json) {
UUID uuid = UUID.fromString(json.get("world").getAsString());
World world = Bukkit.getWorld(uuid);
if (world == null) {
return null;
}
int x = json.get("x").getAsInt();
int y = json.get("y").getAsInt();
int z = json.get("z").getAsInt();
return new Location(world, x, y, z);
}
}

View File

@ -19,7 +19,6 @@ import org.bukkit.event.block.BlockDropItemEvent;
import org.bukkit.event.enchantment.EnchantItemEvent;
import org.bukkit.event.entity.EntityDeathEvent;
import org.bukkit.event.entity.EntityEvent;
import org.bukkit.event.entity.PlayerDeathEvent;
import org.bukkit.event.player.PlayerEvent;
import org.bukkit.inventory.Inventory;
import org.bukkit.inventory.ItemStack;
@ -152,68 +151,50 @@ public class Talisman extends SlimefunItem {
return talisman.getMessageSuffix() != null;
}
public static boolean tryActivate(@Nonnull Event e, @Nonnull SlimefunItemStack stack) {
return tryActivateAndGet(e, stack.getItem()) != null;
@ParametersAreNonnullByDefault
public static boolean checkFor(Event e, SlimefunItemStack stack) {
return checkFor(e, stack.getItem());
}
public static boolean tryActivate(@Nonnull Event e, @Nonnull SlimefunItem item) {
return tryActivateAndGet(e, item) != null;
}
public static ItemStack tryActivateAndGet(@Nonnull Event e, @Nonnull SlimefunItemStack stack) {
return tryActivateAndGet(e, stack.getItem());
}
@Nullable
public static ItemStack tryActivateAndGet(@Nonnull Event e, @Nonnull SlimefunItem item) {
@ParametersAreNonnullByDefault
public static boolean checkFor(Event e, SlimefunItem item) {
if (!(item instanceof Talisman)) {
return null;
return false;
}
Talisman talisman = (Talisman) item;
if (ThreadLocalRandom.current().nextInt(100) > talisman.getChance()) {
return null;
return false;
}
Player p = getPlayerByEventType(e);
if (p == null || !pass(p, talisman)) {
return null;
return false;
}
ItemStack possibleTalisman = retrieveTalismanFromInventory(p.getInventory(), talisman.getItem());
ItemStack talismanItem = talisman.getItem();
if (possibleTalisman != null) {
if (SlimefunUtils.containsSimilarItem(p.getInventory(), talismanItem, true)) {
if (Slimefun.hasUnlocked(p, talisman, true)) {
activateTalisman(e, p, p.getInventory(), talisman, possibleTalisman);
return possibleTalisman;
activateTalisman(e, p, p.getInventory(), talisman, talismanItem);
return true;
} else {
return null;
return false;
}
}
} else {
ItemStack enderTalisman = talisman.getEnderVariant();
possibleTalisman = retrieveTalismanFromInventory(p.getEnderChest(), talisman.getEnderVariant());
if (possibleTalisman != null) {
if (Slimefun.hasUnlocked(p, talisman, true)) {
activateTalisman(e, p, p.getEnderChest(), talisman, possibleTalisman);
return possibleTalisman;
if (SlimefunUtils.containsSimilarItem(p.getEnderChest(), enderTalisman, true)) {
if (Slimefun.hasUnlocked(p, talisman, true)) {
activateTalisman(e, p, p.getEnderChest(), talisman, enderTalisman);
return true;
} else {
return false;
}
} else {
return null;
return false;
}
}
return null;
}
@Nullable
private static ItemStack retrieveTalismanFromInventory(@Nonnull Inventory inv, @Nonnull ItemStack talismanItem) {
for (ItemStack item : inv) {
if (SlimefunUtils.isItemSimilar(item, talismanItem, false, false)) {
return item;
}
}
return null;
}
@ParametersAreNonnullByDefault
@ -248,15 +229,20 @@ public class Talisman extends SlimefunItem {
@ParametersAreNonnullByDefault
private static void consumeItem(Inventory inv, Talisman talisman, ItemStack talismanItem) {
if (talisman.isConsumable()) {
ItemUtils.consumeItem(talismanItem, false);
ItemStack[] contents = inv.getContents();
for (int i = 0; i < contents.length; i++) {
ItemStack item = contents[i];
if (SlimefunUtils.isItemSimilar(item, talismanItem, true, false)) {
ItemUtils.consumeItem(item, false);
return;
}
}
}
}
@Nullable
private static Player getPlayerByEventType(@Nonnull Event e) {
if (e instanceof PlayerDeathEvent) {
return ((PlayerDeathEvent) e).getEntity();
} else if (e instanceof EntityDeathEvent) {
private static Player getPlayerByEventType(Event e) {
if (e instanceof EntityDeathEvent) {
return ((EntityDeathEvent) e).getEntity().getKiller();
} else if (e instanceof BlockBreakEvent) {
return ((BlockBreakEvent) e).getPlayer();
@ -273,7 +259,7 @@ public class Talisman extends SlimefunItem {
return null;
}
private static boolean pass(@Nonnull Player p, @Nonnull SlimefunItem talisman) {
private static boolean pass(Player p, SlimefunItem talisman) {
for (PotionEffect effect : ((Talisman) talisman).getEffects()) {
if (effect != null && p.hasPotionEffect(effect.getType())) {
return false;
@ -282,4 +268,5 @@ public class Talisman extends SlimefunItem {
return true;
}
}
}

View File

@ -1,10 +1,8 @@
package io.github.thebusybiscuit.slimefun4.implementation.listeners;
import java.util.Arrays;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Optional;
import java.util.Map;
import java.util.Random;
import java.util.concurrent.ThreadLocalRandom;
@ -12,15 +10,8 @@ import java.util.concurrent.ThreadLocalRandom;
import javax.annotation.Nonnull;
import javax.annotation.ParametersAreNonnullByDefault;
import io.github.thebusybiscuit.slimefun4.implementation.items.magical.talismans.ResurrectedTalisman;
import io.github.thebusybiscuit.slimefun4.utils.SlimefunUtils;
import io.papermc.lib.PaperLib;
import me.mrCookieSlime.Slimefun.Objects.SlimefunItem.SlimefunItem;
import org.bukkit.Bukkit;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.NamespacedKey;
import org.bukkit.enchantments.Enchantment;
import org.bukkit.entity.AbstractArrow;
import org.bukkit.entity.ArmorStand;
@ -40,7 +31,6 @@ import org.bukkit.event.entity.EntityDamageByEntityEvent;
import org.bukkit.event.entity.EntityDamageEvent;
import org.bukkit.event.entity.EntityDamageEvent.DamageCause;
import org.bukkit.event.entity.EntityDeathEvent;
import org.bukkit.event.entity.PlayerDeathEvent;
import org.bukkit.event.player.PlayerExpChangeEvent;
import org.bukkit.event.player.PlayerItemBreakEvent;
import org.bukkit.event.player.PlayerToggleSprintEvent;
@ -71,24 +61,24 @@ public class TalismanListener implements Listener {
public void onDamageGet(EntityDamageEvent e) {
if (e.getEntity() instanceof Player) {
if (e.getCause() == DamageCause.LAVA) {
Talisman.tryActivate(e, SlimefunItems.TALISMAN_LAVA);
Talisman.checkFor(e, SlimefunItems.TALISMAN_LAVA);
}
if (e.getCause() == DamageCause.DROWNING) {
Talisman.tryActivate(e, SlimefunItems.TALISMAN_WATER);
Talisman.checkFor(e, SlimefunItems.TALISMAN_WATER);
}
if (e.getCause() == DamageCause.FALL) {
Talisman.tryActivate(e, SlimefunItems.TALISMAN_ANGEL);
Talisman.checkFor(e, SlimefunItems.TALISMAN_ANGEL);
}
if (e.getCause() == DamageCause.FIRE) {
Talisman.tryActivate(e, SlimefunItems.TALISMAN_FIRE);
Talisman.checkFor(e, SlimefunItems.TALISMAN_FIRE);
}
if (e.getCause() == DamageCause.ENTITY_ATTACK) {
Talisman.tryActivate(e, SlimefunItems.TALISMAN_KNIGHT);
Talisman.tryActivate(e, SlimefunItems.TALISMAN_WARRIOR);
Talisman.checkFor(e, SlimefunItems.TALISMAN_KNIGHT);
Talisman.checkFor(e, SlimefunItems.TALISMAN_WARRIOR);
}
if (e.getCause() == DamageCause.PROJECTILE && e instanceof EntityDamageByEntityEvent) {
@ -101,7 +91,7 @@ public class TalismanListener implements Listener {
if (e.getDamager() instanceof Projectile && !(e.getDamager() instanceof Trident)) {
Projectile projectile = (Projectile) e.getDamager();
if (Talisman.tryActivate(e, SlimefunItems.TALISMAN_WHIRLWIND)) {
if (Talisman.checkFor(e, SlimefunItems.TALISMAN_WHIRLWIND)) {
Player p = (Player) e.getEntity();
returnProjectile(p, projectile);
}
@ -153,7 +143,7 @@ public class TalismanListener implements Listener {
// We are also excluding entities which can pickup items, this is not perfect
// but it at least prevents dupes by tossing items to zombies
if (!entity.getCanPickupItems() && Talisman.tryActivate(e, SlimefunItems.TALISMAN_HUNTER)) {
if (!entity.getCanPickupItems() && Talisman.checkFor(e, SlimefunItems.TALISMAN_HUNTER)) {
Collection<ItemStack> extraDrops = getExtraDrops(e.getEntity(), e.getDrops());
for (ItemStack drop : extraDrops) {
@ -188,7 +178,6 @@ public class TalismanListener implements Listener {
// Prevents duplication of handheld items or armor
EntityEquipment equipment = entity.getEquipment();
if (equipment != null) {
for (ItemStack item : equipment.getArmorContents()) {
items.remove(item);
@ -203,7 +192,7 @@ public class TalismanListener implements Listener {
@EventHandler
public void onItemBreak(PlayerItemBreakEvent e) {
if (Talisman.tryActivate(e, SlimefunItems.TALISMAN_ANVIL)) {
if (Talisman.checkFor(e, SlimefunItems.TALISMAN_ANVIL)) {
PlayerInventory inv = e.getPlayer().getInventory();
int slot = inv.getHeldItemSlot();
@ -236,7 +225,7 @@ public class TalismanListener implements Listener {
@EventHandler
public void onSprint(PlayerToggleSprintEvent e) {
if (e.isSprinting()) {
Talisman.tryActivate(e, SlimefunItems.TALISMAN_TRAVELLER);
Talisman.checkFor(e, SlimefunItems.TALISMAN_TRAVELLER);
}
}
@ -246,7 +235,7 @@ public class TalismanListener implements Listener {
Map<Enchantment, Integer> enchantments = e.getEnchantsToAdd();
// Magician Talisman
if (Talisman.tryActivate(e, SlimefunItems.TALISMAN_MAGICIAN)) {
if (Talisman.checkFor(e, SlimefunItems.TALISMAN_MAGICIAN)) {
MagicianTalisman talisman = (MagicianTalisman) SlimefunItems.TALISMAN_MAGICIAN.getItem();
TalismanEnchantment enchantment = talisman.getRandomEnchantment(e.getItem(), enchantments.keySet());
@ -256,7 +245,8 @@ public class TalismanListener implements Listener {
}
// Wizard Talisman
if (!enchantments.containsKey(Enchantment.SILK_TOUCH) && Enchantment.LOOT_BONUS_BLOCKS.canEnchantItem(e.getItem()) && Talisman.tryActivate(e, SlimefunItems.TALISMAN_WIZARD)) {
if (!enchantments.containsKey(Enchantment.SILK_TOUCH) && Enchantment.LOOT_BONUS_BLOCKS.canEnchantItem(e.getItem()) && Talisman.checkFor(e, SlimefunItems.TALISMAN_WIZARD)) {
for (Enchantment enchantment : enchantments.keySet()) {
if (random.nextInt(100) < 40) {
e.getEnchantsToAdd().put(enchantment, random.nextInt(3) + 1);
@ -266,19 +256,26 @@ public class TalismanListener implements Listener {
enchantments.put(Enchantment.LOOT_BONUS_BLOCKS, random.nextInt(3) + 3);
}
}
@EventHandler(ignoreCancelled = true)
public void onExperienceReceive(PlayerExpChangeEvent e) {
if (e.getAmount() > 0 && Talisman.checkFor(e, SlimefunItems.TALISMAN_WISE)) {
// Double-XP
e.setAmount(e.getAmount() * 2);
}
}
@EventHandler(ignoreCancelled = true)
public void onBlockDropItems(BlockDropItemEvent e) {
// We only want to double ores
Material type = e.getBlockState().getType();
if (type.name().endsWith("_ORE")) {
ItemStack item = e.getPlayer().getInventory().getItemInMainHand();
if (item.getType() != Material.AIR && item.getAmount() > 0 && !item.containsEnchantment(Enchantment.SILK_TOUCH)) {
Collection<Item> drops = e.getItems();
if (Talisman.tryActivate(e, SlimefunItems.TALISMAN_MINER)) {
if (Talisman.checkFor(e, SlimefunItems.TALISMAN_MINER)) {
int dropAmount = getAmountWithFortune(type, item.getEnchantmentLevel(Enchantment.LOOT_BONUS_BLOCKS));
boolean doubledDrops = false;
@ -303,47 +300,10 @@ public class TalismanListener implements Listener {
@EventHandler
public void onBlockBreak(BlockBreakEvent e) {
if (SlimefunTag.CAVEMAN_TALISMAN_TRIGGERS.isTagged(e.getBlock().getType())) {
Talisman.tryActivate(e, SlimefunItems.TALISMAN_CAVEMAN);
Talisman.checkFor(e, SlimefunItems.TALISMAN_CAVEMAN);
}
}
@EventHandler
public void onExperienceReceive(PlayerExpChangeEvent e) {
if (e.getAmount() > 0 && Talisman.tryActivate(e, SlimefunItems.TALISMAN_WISE)) {
e.setAmount(e.getAmount() * 2);
}
}
@EventHandler
public void onPlayerDeath(PlayerDeathEvent e) {
Player player = e.getEntity();
DamageCause dmgCause = player.getLastDamageCause().getCause();
ItemStack talisman = Talisman.tryActivateAndGet(e, SlimefunItems.TALISMAN_RESURRECTED);
if (dmgCause == DamageCause.VOID && talisman != null) {
// This event is cancelled by the Talisman, so they don't actually die, we just teleport them after 2 ticks.
SlimefunPlugin.runSync(() -> PaperLib.teleportAsync(player, getSafeRespawnLocation(talisman, player)), 2);
}
}
@Nonnull
private Location getSafeRespawnLocation(@Nonnull ItemStack item, @Nonnull Player player) {
SlimefunItem sfItem = SlimefunItem.getByItem(item);
if (sfItem instanceof ResurrectedTalisman) {
ResurrectedTalisman talisman = (ResurrectedTalisman) sfItem;
Location savedLoc = talisman.getSavedLocation(item);
if (savedLoc != null) {
return savedLoc;
}
}
Location bedSpawn = player.getBedSpawnLocation();
return bedSpawn != null ? bedSpawn : player.getLocation().getWorld().getSpawnLocation();
}
private int getAmountWithFortune(@Nonnull Material type, int fortuneLevel) {
if (fortuneLevel > 0) {
Random random = ThreadLocalRandom.current();
@ -355,4 +315,4 @@ public class TalismanListener implements Listener {
return 1;
}
}
}
}

View File

@ -281,7 +281,6 @@ public final class ResearchSetup {
register("energy_connectors", 269, "Wired Connections", 12, SlimefunItems.ENERGY_CONNECTOR);
register("bee_armor", 270, "Bee Armor", 24, SlimefunItems.BEE_HELMET, SlimefunItems.BEE_WINGS, SlimefunItems.BEE_LEGGINGS, SlimefunItems.BEE_BOOTS);
register("wise_talisman", 271, "Talisman of the Wise", 20, SlimefunItems.TALISMAN_WISE);
register("resurrected_talisman", 272, "Talisman of the Resurrected", 20, SlimefunItems.TALISMAN_RESURRECTED);
}
@ParametersAreNonnullByDefault

View File

@ -5,7 +5,6 @@ import java.util.List;
import javax.annotation.Nonnull;
import io.github.thebusybiscuit.slimefun4.implementation.items.magical.talismans.ResurrectedTalisman;
import org.bukkit.Material;
import org.bukkit.NamespacedKey;
import org.bukkit.inventory.ItemStack;
@ -867,10 +866,6 @@ public final class SlimefunItemSetup {
false, false, "wise", 20)
.register(plugin);
new ResurrectedTalisman(SlimefunItems.TALISMAN_RESURRECTED,
new ItemStack[] { SlimefunItems.MAGIC_LUMP_3, SlimefunItems.ESSENCE_OF_AFTERLIFE, SlimefunItems.MAGIC_LUMP_3, SlimefunItems.ELYTRA_SCALE, SlimefunItems.TALISMAN_ANGEL, SlimefunItems.ELYTRA_SCALE, SlimefunItems.MAGIC_LUMP_3, null, SlimefunItems.MAGIC_LUMP_3 })
.register(plugin);
new SlimefunItem(categories.resources, SlimefunItems.GILDED_IRON, RecipeType.SMELTERY,
new ItemStack[] {SlimefunItems.GOLD_24K, SlimefunItems.IRON_DUST, null, null, null, null, null, null, null})
.register(plugin);

View File

@ -158,10 +158,7 @@ messages:
whirlwind: '&a&oYour Talisman reflected the Projectile'
wizard: '&a&oYour Talisman has given you a better Fortune Level but maybe also lowered some other Enchantment Levels'
caveman: '&a&oYour Talisman gave you haste'
wise: '&a&oYour Talisman doubled your experience drops'
resurrected: '&a&oYour Talisman a-voided your death, but sacrificed itself in the process'
resurrected-location: 'Successfully saved your current location. You will teleport here when you fall into the void.'
resurrected-location-failed: 'Failed to set location here, you dont have enough permissions.'
wise: '&a&oYour Talisman has doubled your experience drops'
soulbound-rune:
fail: '&cYou can only bind one item to your soul at a time.'

View File

@ -63,7 +63,6 @@ slimefun:
fire_talisman: Talisman of the Firefighter
caveman_talisman: Talisman of the Caveman
wise_talisman: Talisman of the Wise
resurrected_talisman: Talisman of the Resurrected
lava_crystal: Firey Situation
magician_talisman: Talisman of the Magician
traveller_talisman: Talisman of the Traveller