Compare commits

...

10 Commits

Author SHA1 Message Date
WinDanesz f9cf1b39db Fix telekineticDisarmament setting and Amulet of Anchoring 2024-03-29 18:07:19 +01:00
WinDanesz 3fb3c1c039 feat: made EntityWizard.trades public so that addon devs can manipulate trades 2024-03-28 01:00:26 +01:00
WinDanesz e8bc6ca725 version bump to 4.3.13 2024-03-28 01:00:26 +01:00
WinDanesz df531d3724 fix: Fixed all synchronized WizardData stored variables on dedicated servers. This issue was causing e.g. the Ancient Compass to not display its targets on servers. Fixes #857 2024-03-28 00:46:32 +01:00
ScoTWT 2728012f33 Update zh_tw.lang (#709) 2024-03-27 22:19:46 +01:00
red1854th 853df2eb42 Update ko_kr.lang (#714)
* Update Korean translations, courtesy of red1854th

* Update Korean translations, courtesy of red1854th
2024-03-27 22:18:20 +01:00
ipdnaeip 0cb2165ddf Added methods for retrieving entities within a cylinder, replaced radius-based methods, implemented DPS check for heal aura, adjusted targeting criteria for summoned creatures, tweaked heal method, fixed flamecatcher ammo loss, updated Enrage target and expanded spellcasting item compatibility for movement speed charm. - by ipdnaeip (#864)
Added getEntitiesWithinCylinder and getLivingWithinCylinder methods to return all entities within a cylinder.

Replaced getLivingWithinRadius for spells that should use a cylinder instead. The height of the cylinder is determined by the height of the entities.

Added a DPS checker on the heal aura damage just in case someone has damage immunity disabled.

Modified the AllyDesignationSystem and Wizard classes to no longer target summoned creatures automatically. They will still target hostile summoned creatures or creatures from players that have aggressed on them.

Modified the heal method in the Heal class to not reduce absorption amount. It should never really happen, but just in case.

Modified the flamecatcher to no longer lose ammo if it was used but no arrow was fired.

Enrage now targets EntityLiving instead of EntityCreature.

The movement speed charm now works with any spellcasting item as opposed to just wands.
2024-03-27 22:11:29 +01:00
WinDanesz ca7e9034ed feat: Added WandHelper.rechargeManaOnApplyButtonPressed static method for easier mana recharging across addons 2024-03-27 22:03:01 +01:00
WinDanesz 1322c920f5 fix: Spells are now sorted alphabetically by their names, instead of first being sorted by modid 2024-03-15 01:31:51 +01:00
WinDanesz e5c00e3882 feat: The Amulet of Anchoring also prevents the Telekinesis spell to knock items out of the wearer's hand. (Previously it only granted protection against being moved by Greater Telekinesis) 2024-03-14 00:05:40 +01:00
28 changed files with 4372 additions and 3805 deletions
+2 -2
View File
@@ -1,7 +1,7 @@
{ {
"homepage": "https://www.curseforge.com/minecraft/mc-mods/electroblobs-wizardry", "homepage": "https://www.curseforge.com/minecraft/mc-mods/electroblobs-wizardry",
"promos": { "promos": {
"1.12.2-latest": "4.3.12", "1.12.2-latest": "4.3.13",
"1.12.2-recommended": "4.3.12" "1.12.2-recommended": "4.3.13"
} }
} }
+1 -1
View File
@@ -38,7 +38,7 @@ apply plugin: org.ajoberstar.grgit.gradle.GrgitPlugin
apply plugin: 'wtf.gofancy.fancygradle' apply plugin: 'wtf.gofancy.fancygradle'
version = "4.3.12" version = "4.3.13"
group= "electroblob.wizardry"// http://maven.apache.org/guides/mini/guide-naming-conventions.html group= "electroblob.wizardry"// http://maven.apache.org/guides/mini/guide-naming-conventions.html
archivesBaseName = "ElectroblobsWizardry" archivesBaseName = "ElectroblobsWizardry"
@@ -82,7 +82,7 @@ public class Wizardry {
* 1.x.x represents Minecraft 1.7.x versions, 2.x.x represents Minecraft 1.10.x versions, 3.x.x represents Minecraft * 1.x.x represents Minecraft 1.7.x versions, 2.x.x represents Minecraft 1.10.x versions, 3.x.x represents Minecraft
* 1.11.x versions, and so on. * 1.11.x versions, and so on.
*/ */
public static final String VERSION = "4.3.12"; public static final String VERSION = "4.3.13";
/** /**
* Json file used by Forge's built-in <a href="https://mcforge.readthedocs.io/en/1.12.x/gettingstarted/autoupdate/">update checker</a>. * Json file used by Forge's built-in <a href="https://mcforge.readthedocs.io/en/1.12.x/gettingstarted/autoupdate/">update checker</a>.
@@ -3,10 +3,7 @@ package electroblob.wizardry.client;
import electroblob.wizardry.client.renderer.overlay.RenderBlinkEffect; import electroblob.wizardry.client.renderer.overlay.RenderBlinkEffect;
import electroblob.wizardry.data.DispenserCastingData; import electroblob.wizardry.data.DispenserCastingData;
import electroblob.wizardry.data.SpellEmitterData; import electroblob.wizardry.data.SpellEmitterData;
import electroblob.wizardry.item.ItemArtefact; import electroblob.wizardry.item.*;
import electroblob.wizardry.item.ItemFlamecatcher;
import electroblob.wizardry.item.ItemSpectralBow;
import electroblob.wizardry.item.ItemWand;
import electroblob.wizardry.potion.PotionSlowTime; import electroblob.wizardry.potion.PotionSlowTime;
import electroblob.wizardry.registry.WizardryItems; import electroblob.wizardry.registry.WizardryItems;
import electroblob.wizardry.registry.WizardryPotions; import electroblob.wizardry.registry.WizardryPotions;
@@ -120,6 +117,7 @@ public final class WizardryClientEventHandler {
Minecraft.getMinecraft().player.prevRotationPitch = 0; Minecraft.getMinecraft().player.prevRotationPitch = 0;
Minecraft.getMinecraft().player.rotationYaw = 0; Minecraft.getMinecraft().player.rotationYaw = 0;
Minecraft.getMinecraft().player.rotationPitch = 0; Minecraft.getMinecraft().player.rotationPitch = 0;
} }
} }
@@ -136,7 +134,7 @@ public final class WizardryClientEventHandler {
if(ItemArtefact.isArtefactActive(event.getEntityPlayer(), WizardryItems.charm_move_speed) if(ItemArtefact.isArtefactActive(event.getEntityPlayer(), WizardryItems.charm_move_speed)
&& event.getEntityPlayer().isHandActive() && event.getEntityPlayer().isHandActive()
&& event.getEntityPlayer().getActiveItemStack().getItem() instanceof ItemWand){ && event.getEntityPlayer().getActiveItemStack().getItem() instanceof ISpellCastingItem){
// Normally speed is set to 20% when using items, this makes it 80% // Normally speed is set to 20% when using items, this makes it 80%
event.getMovementInput().moveStrafe *= 4; event.getMovementInput().moveStrafe *= 4;
event.getMovementInput().moveForward *= 4; event.getMovementInput().moveForward *= 4;
@@ -64,6 +64,11 @@ public interface IStoredVariable<T> extends IVariable<T> {
this.ticker = (p, t) -> t; // Initialise this with a do-nothing function, can be overwritten later this.ticker = (p, t) -> t; // Initialise this with a do-nothing function, can be overwritten later
} }
@Override
public String getKey() {
return key;
}
/** /**
* Replaces this variable's update method with the given update function. <i>Beware of auto-unboxing of * Replaces this variable's update method with the given update function. <i>Beware of auto-unboxing of
* primitive types! For lambda expressions, check the second parameter isn't null before operating on it. * primitive types! For lambda expressions, check the second parameter isn't null before operating on it.
@@ -47,7 +47,10 @@ public interface IVariable<T> {
*/ */
void write(ByteBuf buf, T value); void write(ByteBuf buf, T value);
String getKey();
/** /**
*
* Reads this variable's value from the given {@link ByteBuf}. * Reads this variable's value from the given {@link ByteBuf}.
*/ */
T read(ByteBuf buf); T read(ByteBuf buf);
@@ -110,6 +113,11 @@ public interface IVariable<T> {
// NYI // NYI
} }
@Override
public String getKey() {
return "none"; // we don't mind as these are never synced (electroblob.wizardry.data.IVariable.Variable.isSynced)
}
@Override @Override
public T read(ByteBuf buf){ public T read(ByteBuf buf){
return null; // NYI return null; // NYI
@@ -199,9 +199,14 @@ public class WizardData implements INBTSerializable<NBTTagCompound> {
} }
/** Returns a set containing the registered {@link IStoredVariable} objects for which {@link IVariable#isSynced()} /** Returns a set containing the registered {@link IStoredVariable} objects for which {@link IVariable#isSynced()}
* returns true. Used internally for packet reading. */ * returns true, ordered by their keys obtained from {@link IVariable#getKey()}. Used internally for packets. */
public static Set<IVariable> getSyncedVariables(){ public static Set<IVariable> getSyncedVariablesOrderedByKey(){
return storedVariables.stream().filter(IVariable::isSynced).collect(Collectors.toSet()); Comparator<IVariable> keyComparator = Comparator.comparing(IVariable::getKey);
return storedVariables.stream()
.filter(IVariable::isSynced)
.sorted(keyComparator)
.collect(Collectors.toCollection(LinkedHashSet::new));
} }
/** /**
@@ -35,8 +35,8 @@ public class EntityDecay extends EntityMagicConstruct {
0.6F + rand.nextFloat() * 0.15F); 0.6F + rand.nextFloat() * 0.15F);
if(!this.world.isRemote){ if(!this.world.isRemote){
List<EntityLivingBase> targets = EntityUtils.getLivingWithinRadius(1.0d, this.posX, this.posY, List<EntityLivingBase> targets = EntityUtils.getLivingWithinCylinder(this.width/2f, this.posX, this.posY,
this.posZ, this.world); this.posZ, this.height, this.world);
for(EntityLivingBase target : targets){ for(EntityLivingBase target : targets){
if(target != this.getCaster()){ if(target != this.getCaster()){
// If this check wasn't here the potion would be reapplied every tick and hence the entity would be // If this check wasn't here the potion would be reapplied every tick and hence the entity would be
@@ -34,7 +34,7 @@ public class EntityFireRing extends EntityScaledConstruct {
if(this.ticksExisted % 5 == 0 && !this.world.isRemote){ if(this.ticksExisted % 5 == 0 && !this.world.isRemote){
List<EntityLivingBase> targets = EntityUtils.getLivingWithinRadius(width/2, this.posX, this.posY, this.posZ, this.world); List<EntityLivingBase> targets = EntityUtils.getLivingWithinCylinder(this.width/2, this.posX, this.posY, this.posZ, this.height, this.world);
for(EntityLivingBase target : targets){ for(EntityLivingBase target : targets){
@@ -34,7 +34,7 @@ public class EntityFireSigil extends EntityScaledConstruct {
if(!this.world.isRemote){ if(!this.world.isRemote){
List<EntityLivingBase> targets = EntityUtils.getLivingWithinRadius(width/2, posX, posY, posZ, world); List<EntityLivingBase> targets = EntityUtils.getLivingWithinCylinder(this.width/2, this.posX, this.posY, this.posZ, this.height, this.world);
for(EntityLivingBase target : targets){ for(EntityLivingBase target : targets){
@@ -36,8 +36,8 @@ public class EntityFrostSigil extends EntityScaledConstruct {
if(!this.world.isRemote){ if(!this.world.isRemote){
List<EntityLivingBase> targets = EntityUtils.getLivingWithinRadius(width/2, this.posX, this.posY, List<EntityLivingBase> targets = EntityUtils.getLivingWithinCylinder(width/2, this.posX, this.posY,
this.posZ, this.world); this.posZ, this.height, this.world);
for(EntityLivingBase target : targets){ for(EntityLivingBase target : targets){
@@ -33,23 +33,24 @@ public class EntityHealAura extends EntityScaledConstruct {
if(!this.world.isRemote){ if(!this.world.isRemote){
List<EntityLivingBase> targets = EntityUtils.getLivingWithinRadius(width/2, posX, posY, posZ, world); List<EntityLivingBase> targets = EntityUtils.getLivingWithinCylinder(width/2, posX, posY, posZ, this.height, world);
for(EntityLivingBase target : targets){ for(EntityLivingBase target : targets){
if(this.isValidTarget(target)){ if(this.isValidTarget(target)){
if(target.isEntityUndead()){ if(target.isEntityUndead()) {
double velX = target.motionX; double velX = target.motionX;
double velY = target.motionY; double velY = target.motionY;
double velZ = target.motionZ; double velZ = target.motionZ;
if(this.getCaster() != null){ if (this.ticksExisted % 10 == 1) {
if (this.getCaster() != null) {
target.attackEntityFrom( target.attackEntityFrom(
MagicDamage.causeIndirectMagicDamage(this, getCaster(), DamageType.RADIANT), MagicDamage.causeIndirectMagicDamage(this, getCaster(), DamageType.RADIANT),
Spells.healing_aura.getProperty(Spell.DAMAGE).floatValue() * damageMultiplier); Spells.healing_aura.getProperty(Spell.DAMAGE).floatValue() * damageMultiplier);
}else{ } else {
target.attackEntityFrom(DamageSource.MAGIC, Spells.healing_aura.getProperty(Spell.DAMAGE).floatValue() * damageMultiplier); target.attackEntityFrom(DamageSource.MAGIC, Spells.healing_aura.getProperty(Spell.DAMAGE).floatValue() * damageMultiplier);
} }
@@ -58,6 +59,7 @@ public class EntityHealAura extends EntityScaledConstruct {
target.motionY = velY; target.motionY = velY;
target.motionZ = velZ; target.motionZ = velZ;
} }
}
}else if(target.getHealth() < target.getMaxHealth() && target.ticksExisted % 5 == 0){ }else if(target.getHealth() < target.getMaxHealth() && target.ticksExisted % 5 == 0){
target.heal(Spells.healing_aura.getProperty(Spell.HEALTH).floatValue() * damageMultiplier); target.heal(Spells.healing_aura.getProperty(Spell.HEALTH).floatValue() * damageMultiplier);
@@ -39,8 +39,8 @@ public class EntityLightningSigil extends EntityScaledConstruct {
this.setDead(); this.setDead();
} }
List<EntityLivingBase> targets = EntityUtils.getLivingWithinRadius(width/2, this.posX, this.posY, List<EntityLivingBase> targets = EntityUtils.getLivingWithinCylinder(this.width/2, this.posX, this.posY,
this.posZ, this.world); this.posZ, this.height, this.world);
for(EntityLivingBase target : targets){ for(EntityLivingBase target : targets){
@@ -68,7 +68,7 @@ public class EntityWizard extends EntityCreature implements INpc, IMerchant, ISp
protected Predicate<Entity> targetSelector; protected Predicate<Entity> targetSelector;
/** The wizard's trades. */ /** The wizard's trades. */
private MerchantRecipeList trades; public MerchantRecipeList trades;
/** The wizard's current customer. */ /** The wizard's current customer. */
@Nullable @Nullable
private EntityPlayer customer; private EntityPlayer customer;
@@ -130,8 +130,12 @@ public class EntityWizard extends EntityCreature implements INpc, IMerchant, ISp
if(entity != null && !entity.isInvisible() if(entity != null && !entity.isInvisible()
&& AllyDesignationSystem.isValidTarget(EntityWizard.this, entity)){ && AllyDesignationSystem.isValidTarget(EntityWizard.this, entity)){
// ... and is a mob, a summoned creature ... // ... and is a non summoned creature mob ...
if((entity instanceof IMob || entity instanceof ISummonedCreature if((entity instanceof IMob && !(entity instanceof ISummonedCreature)
// or is a summoned creature with a mob owner or an owner who has attacked the wizard ...
|| entity instanceof ISummonedCreature && (((ISummonedCreature)entity).getOwner() instanceof IMob || ((ISummonedCreature)entity).getOwner() == this.getRevengeTarget() || ((ISummonedCreature) entity).getOwner() == this.getAttackTarget())
// ... or in the whitelist ... // ... or in the whitelist ...
|| Arrays.asList(Wizardry.settings.summonedCreatureTargetsWhitelist) || Arrays.asList(Wizardry.settings.summonedCreatureTargetsWhitelist)
.contains(EntityList.getKey(entity.getClass()))) .contains(EntityList.getKey(entity.getClass())))
@@ -193,6 +193,13 @@ public class ItemFlamecatcher extends ItemBow implements IConjuredItem {
charge = net.minecraftforge.event.ForgeEventFactory.onArrowLoose(stack, world, (EntityPlayer)entity, charge, true); charge = net.minecraftforge.event.ForgeEventFactory.onArrowLoose(stack, world, (EntityPlayer)entity, charge, true);
if(charge < 0) return; if(charge < 0) return;
float velocity = (float)charge / DRAW_TIME;
velocity = (velocity * velocity + velocity * 2) / 3;
if(velocity > 1) velocity = 1;
if((double)velocity >= 0.1D){
if(stack.getTagCompound() != null){ if(stack.getTagCompound() != null){
int shotsLeft = stack.getTagCompound().getInteger(Flamecatcher.SHOTS_REMAINING_NBT_KEY) - 1; int shotsLeft = stack.getTagCompound().getInteger(Flamecatcher.SHOTS_REMAINING_NBT_KEY) - 1;
stack.getTagCompound().setInteger(Flamecatcher.SHOTS_REMAINING_NBT_KEY, shotsLeft); stack.getTagCompound().setInteger(Flamecatcher.SHOTS_REMAINING_NBT_KEY, shotsLeft);
@@ -201,13 +208,6 @@ public class ItemFlamecatcher extends ItemBow implements IConjuredItem {
} }
} }
float velocity = (float)charge / DRAW_TIME;
velocity = (velocity * velocity + velocity * 2) / 3;
if(velocity > 1) velocity = 1;
if((double)velocity >= 0.1D){
if(!world.isRemote){ if(!world.isRemote){
EntityFlamecatcherArrow arrow = new EntityFlamecatcherArrow(world); EntityFlamecatcherArrow arrow = new EntityFlamecatcherArrow(world);
arrow.aim(player, EntityFlamecatcherArrow.SPEED * velocity); arrow.aim(player, EntityFlamecatcherArrow.SPEED * velocity);
@@ -864,30 +864,7 @@ public class ItemWand extends Item implements IWorkbenchItem, ISpellCastingItem,
WandHelper.setSpells(centre.getStack(), spells); WandHelper.setSpells(centre.getStack(), spells);
// Charges wand by appropriate amount // Charges wand by appropriate amount
if(crystals.getStack() != ItemStack.EMPTY && !this.isManaFull(centre.getStack())){ if (WandHelper.rechargeManaOnApplyButtonPressed(centre, crystals)) {
int chargeDepleted = this.getManaCapacity(centre.getStack()) - this.getMana(centre.getStack());
// Not too pretty but allows addons implementing the IManaStoringItem interface to provide their mana amount for custom crystals,
// previously this was defaulted to the regular crystal's amount, allowing players to exploit it if a crystal was worth less mana than that.
int manaPerItem = crystals.getStack().getItem() instanceof IManaStoringItem ?
((IManaStoringItem) crystals.getStack().getItem()).getMana(crystals.getStack()) :
crystals.getStack().getItem() instanceof ItemCrystal ? Constants.MANA_PER_CRYSTAL : Constants.MANA_PER_SHARD;
if(crystals.getStack().getItem() == WizardryItems.crystal_shard) manaPerItem = Constants.MANA_PER_SHARD;
if(crystals.getStack().getItem() == WizardryItems.grand_crystal) manaPerItem = Constants.GRAND_CRYSTAL_MANA;
if(crystals.getStack().getCount() * manaPerItem < chargeDepleted){
// If there aren't enough crystals to fully charge the wand
this.rechargeMana(centre.getStack(), crystals.getStack().getCount() * manaPerItem);
crystals.decrStackSize(crystals.getStack().getCount());
}else{
// If there are excess crystals (or just enough)
this.setMana(centre.getStack(), this.getManaCapacity(centre.getStack()));
crystals.decrStackSize((int)Math.ceil(((double)chargeDepleted) / manaPerItem));
}
changed = true; changed = true;
} }
@@ -10,7 +10,11 @@ import net.minecraftforge.fml.common.network.simpleimpl.IMessage;
import net.minecraftforge.fml.common.network.simpleimpl.IMessageHandler; import net.minecraftforge.fml.common.network.simpleimpl.IMessageHandler;
import net.minecraftforge.fml.common.network.simpleimpl.MessageContext; import net.minecraftforge.fml.common.network.simpleimpl.MessageContext;
import java.util.*; import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
/** /**
* <b>[Server -> Client]</b> This packet is sent to synchronise any fields that need synchronising in * <b>[Server -> Client]</b> This packet is sent to synchronise any fields that need synchronising in
@@ -54,9 +58,8 @@ public class PacketPlayerSync implements IMessageHandler<Message, IMessage> {
this.seed = buf.readLong(); this.seed = buf.readLong();
this.selectedMinionID = buf.readInt(); this.selectedMinionID = buf.readInt();
this.spellData = new HashMap<>(); this.spellData = new HashMap<>();
WizardData.getSyncedVariables().forEach(v -> spellData.put(v, v.read(buf))); WizardData.getSyncedVariablesOrderedByKey().forEach(v -> spellData.put(v, v.read(buf)));
// Have to send empty tags to guarantee correct ByteBuf size/order, but no point keeping the resulting nulls // Have to send empty tags to guarantee correct ByteBuf size/order, but no point keeping the resulting nulls
spellData.values().removeIf(Objects::isNull); spellData.values().removeIf(Objects::isNull);
@@ -73,7 +76,7 @@ public class PacketPlayerSync implements IMessageHandler<Message, IMessage> {
buf.writeLong(seed); buf.writeLong(seed);
buf.writeInt(selectedMinionID); buf.writeInt(selectedMinionID);
WizardData.getSyncedVariables().forEach(v -> v.write(buf, spellData.get(v))); WizardData.getSyncedVariablesOrderedByKey().forEach(v -> v.write(buf, spellData.get(v)));
if(this.spellsDiscovered == null) return; if(this.spellsDiscovered == null) return;
for(Spell spell : this.spellsDiscovered){ for(Spell spell : this.spellsDiscovered){
@@ -4,7 +4,7 @@ import electroblob.wizardry.item.SpellActions;
import electroblob.wizardry.util.ParticleBuilder; import electroblob.wizardry.util.ParticleBuilder;
import electroblob.wizardry.util.ParticleBuilder.Type; import electroblob.wizardry.util.ParticleBuilder.Type;
import electroblob.wizardry.util.SpellModifiers; import electroblob.wizardry.util.SpellModifiers;
import net.minecraft.entity.EntityCreature; import net.minecraft.entity.EntityLiving;
import net.minecraft.entity.EntityLivingBase; import net.minecraft.entity.EntityLivingBase;
import net.minecraft.tileentity.TileEntityDispenser; import net.minecraft.tileentity.TileEntityDispenser;
import net.minecraft.util.math.Vec3d; import net.minecraft.util.math.Vec3d;
@@ -29,7 +29,7 @@ public class Enrage extends SpellAreaEffect {
@Override @Override
protected boolean affectEntity(World world, Vec3d origin, @Nullable EntityLivingBase caster, EntityLivingBase target, int targetCount, int ticksInUse, SpellModifiers modifiers){ protected boolean affectEntity(World world, Vec3d origin, @Nullable EntityLivingBase caster, EntityLivingBase target, int targetCount, int ticksInUse, SpellModifiers modifiers){
if(caster != null && target instanceof EntityCreature){ if(caster != null && target instanceof EntityLiving){
target.setRevengeTarget(caster); // Yours truly, angry mobs target.setRevengeTarget(caster); // Yours truly, angry mobs
} }
@@ -38,7 +38,7 @@ public class Heal extends SpellBuff {
entity.heal(health); entity.heal(health);
// If the player is able to heal, they can't possibly have absorption hearts, so no need to check! // If the player is able to heal, they can't possibly have absorption hearts, so no need to check!
if(excessHealth > 0 && entity instanceof EntityPlayer if(excessHealth > entity.getAbsorptionAmount() && entity instanceof EntityPlayer
&& ItemArtefact.isArtefactActive((EntityPlayer)entity, WizardryItems.amulet_absorption)){ && ItemArtefact.isArtefactActive((EntityPlayer)entity, WizardryItems.amulet_absorption)){
entity.setAbsorptionAmount(excessHealth); entity.setAbsorptionAmount(excessHealth);
} }
@@ -1,7 +1,9 @@
package electroblob.wizardry.spell; package electroblob.wizardry.spell;
import electroblob.wizardry.Wizardry; import electroblob.wizardry.Wizardry;
import electroblob.wizardry.item.ItemArtefact;
import electroblob.wizardry.item.SpellActions; import electroblob.wizardry.item.SpellActions;
import electroblob.wizardry.registry.WizardryItems;
import electroblob.wizardry.util.SpellModifiers; import electroblob.wizardry.util.SpellModifiers;
import net.minecraft.block.state.IBlockState; import net.minecraft.block.state.IBlockState;
import net.minecraft.entity.Entity; import net.minecraft.entity.Entity;
@@ -34,7 +36,7 @@ public class Telekinesis extends SpellRay {
target.motionZ = (origin.z - target.posZ) / 6; target.motionZ = (origin.z - target.posZ) / 6;
return true; return true;
}else if(target instanceof EntityPlayer && (Wizardry.settings.telekineticDisarmament || !(caster instanceof EntityPlayer))){ } else if (target instanceof EntityPlayer && (Wizardry.settings.telekineticDisarmament && !ItemArtefact.isArtefactActive((EntityPlayer) target, WizardryItems.amulet_anchoring)) {
EntityPlayer player = (EntityPlayer)target; EntityPlayer player = (EntityPlayer)target;
@@ -141,6 +141,11 @@ public final class AllyDesignationSystem {
return false; return false;
} }
// Tests whether the target is a creature that was summoned/tamed (or is otherwise owned) by the attacker
if(target instanceof IEntityOwnable && attacker instanceof EntityLiving && !(((EntityLiving)attacker).getRevengeTarget() == ((IEntityOwnable)target).getOwner() || ((EntityLiving)attacker).getAttackTarget() == ((IEntityOwnable)target).getOwner())){
return false;
}
// Tests whether the target is a creature that was mind controlled by the attacker // Tests whether the target is a creature that was mind controlled by the attacker
if(target instanceof EntityLiving && ((EntityLivingBase)target).isPotionActive(WizardryPotions.mind_control)){ if(target instanceof EntityLiving && ((EntityLivingBase)target).isPotionActive(WizardryPotions.mind_control)){
@@ -117,6 +117,45 @@ public final class EntityUtils {
return entityList; return entityList;
} }
/**
* Returns all EntityLivingBase within the cylinder radius of the given coordinates. This should
* used by circle effects.
*
* @param radius The search radius
* @param x The x coordinate to search around
* @param y The y coordinate to search around
* @param z The z coordinate to search around
* @param height The height of the cylinder
* @param world The world to search in
*/
public static List<EntityLivingBase> getLivingWithinCylinder(double radius, double x, double y, double z, double height, World world) {
return getEntitiesWithinCylinder(radius, x, y, z, height, world, EntityLivingBase.class);
}
/**
* Returns all entities of the specified type within the cylinder radius of the given coordinates. This should
* used by circle effects.
*
* @param radius The search radius
* @param x The x coordinate to search around
* @param y The y coordinate to search around
* @param z The z coordinate to search around
* @param height The height of the cylinder
* @param world The world to search in
* @param entityType The class of entity to search for; pass in Entity.class for all entities
*/
public static <T extends Entity> List<T> getEntitiesWithinCylinder(double radius, double x, double y, double z, double height, World world, Class<T> entityType) {
AxisAlignedBB aabb = new AxisAlignedBB(x - radius, y, z - radius, x + radius, y + height, z + radius);
List<T> entityList = world.getEntitiesWithinAABB(entityType, aabb);
for(T entity : entityList) {
if (entity.getDistance(x, entity.posY, z) > radius) {
entityList.remove(entity);
break;
}
}
return entityList;
}
/** /**
* Gets an entity from its UUID. If the UUID is known to belong to an {@code EntityPlayer}, use the more efficient * Gets an entity from its UUID. If the UUID is known to belong to an {@code EntityPlayer}, use the more efficient
* {@link World#getPlayerEntityByUUID(UUID)} instead. * {@link World#getPlayerEntityByUUID(UUID)} instead.
@@ -20,8 +20,7 @@ public interface ISpellSortable {
TIER("tier", Comparator.naturalOrder()), TIER("tier", Comparator.naturalOrder()),
ELEMENT("element", Comparator.comparing(Spell::getElement).thenComparing(Spell::getTier)), ELEMENT("element", Comparator.comparing(Spell::getElement).thenComparing(Spell::getTier)),
ALPHABETICAL("alphabetical", Comparator.comparing(Spell::getUnlocalisedName)); ALPHABETICAL("alphabetical", Comparator.comparing(s -> s.getRegistryName().getPath().toString()));
public String name; public String name;
public Comparator<? super Spell> comparator; public Comparator<? super Spell> comparator;
@@ -1,9 +1,14 @@
package electroblob.wizardry.util; package electroblob.wizardry.util;
import electroblob.wizardry.constants.Constants;
import electroblob.wizardry.item.IManaStoringItem;
import electroblob.wizardry.item.IWorkbenchItem;
import electroblob.wizardry.item.ItemCrystal;
import electroblob.wizardry.item.ItemWand; import electroblob.wizardry.item.ItemWand;
import electroblob.wizardry.registry.Spells; import electroblob.wizardry.registry.Spells;
import electroblob.wizardry.registry.WizardryItems; import electroblob.wizardry.registry.WizardryItems;
import electroblob.wizardry.spell.Spell; import electroblob.wizardry.spell.Spell;
import net.minecraft.inventory.Slot;
import net.minecraft.item.Item; import net.minecraft.item.Item;
import net.minecraft.item.ItemStack; import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NBTTagCompound; import net.minecraft.nbt.NBTTagCompound;
@@ -494,4 +499,49 @@ public final class WandHelper {
setProgression(wand, getProgression(wand) + progression); setProgression(wand, getProgression(wand) + progression);
} }
/**
* Recharges the mana of an item when the apply button is pressed in the arcane workbench GUI.
* This method requires the central item to implement both the {@link IWorkbenchItem} and {@link IManaStoringItem} interfaces.
*
* @param centre The slot representing the central item to be recharged.
* @param crystals The slot containing mana crystals for recharging.
* @return {@code true} if the mana of the central item was successfully recharged, {@code false} otherwise.
*/
public static boolean rechargeManaOnApplyButtonPressed(Slot centre, Slot crystals) {
boolean changed = false;
if (!(centre.getStack().getItem() instanceof IWorkbenchItem) || !(centre.getStack().getItem() instanceof IManaStoringItem)) {
return false;
}
IManaStoringItem iManaStoringItem = (IManaStoringItem) centre.getStack().getItem();
// Charges the item by appropriate amount
if (crystals.getStack() != ItemStack.EMPTY && !iManaStoringItem.isManaFull(centre.getStack())) {
int chargeDepleted = iManaStoringItem.getManaCapacity(centre.getStack()) - iManaStoringItem.getMana(centre.getStack());
// Not too pretty but allows addons implementing the IManaStoringItem interface to provide their mana amount for custom crystals,
// previously this was defaulted to the regular crystal's amount, allowing players to exploit it if a crystal was worth less mana than that.
int manaPerItem = crystals.getStack().getItem() instanceof IManaStoringItem ?
((IManaStoringItem) crystals.getStack().getItem()).getMana(crystals.getStack()) :
crystals.getStack().getItem() instanceof ItemCrystal ? Constants.MANA_PER_CRYSTAL : Constants.MANA_PER_SHARD;
if (crystals.getStack().getItem() == WizardryItems.crystal_shard) {manaPerItem = Constants.MANA_PER_SHARD;}
if (crystals.getStack().getItem() == WizardryItems.grand_crystal) {manaPerItem = Constants.GRAND_CRYSTAL_MANA;}
if (crystals.getStack().getCount() * manaPerItem < chargeDepleted) {
// If there aren't enough crystals to fully charge the item
iManaStoringItem.rechargeMana(centre.getStack(), crystals.getStack().getCount() * manaPerItem);
crystals.decrStackSize(crystals.getStack().getCount());
} else {
// If there are excess crystals (or just enough)
iManaStoringItem.setMana(centre.getStack(), iManaStoringItem.getManaCapacity(centre.getStack()));
crystals.decrStackSize((int) Math.ceil(((double) chargeDepleted) / manaPerItem));
}
changed = true;
}
return changed;
}
} }
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
@@ -89,7 +89,7 @@
}, },
"shrine": { "shrine": {
"location": "ebwizardry:textures/gui/handbook/pictures/shrine.png", "location": "ebwizardry:textures/gui/handbook/pictures/shrine.png",
"caption": "\"자연\"의 사", "caption": "\"자연\"의 사",
"u": 0, "u": 0,
"v": 0, "v": 0,
"width": 110, "width": 110,
@@ -296,7 +296,7 @@
"마법사의 안내서", "마법사의 안내서",
"Electroblob" "by Electroblob"
] ]
}, },
@@ -308,7 +308,7 @@
"화살표 모양 버튼을 눌러 쪽을 넘기고, 이중 화살표 모양 버튼을 사용하여 목차 사이를 빠르게 전환할 수 있다네. 목차 목록으로 돌아가려면 중앙 메뉴 버튼을 누르면 된다네.", "화살표 모양 버튼을 눌러 쪽을 넘기고, 이중 화살표 모양 버튼을 사용하여 목차 사이를 빠르게 전환할 수 있다네. 목차 목록으로 돌아가려면 중앙 메뉴 버튼을 누르면 된다네.",
"보라색 글씨는 클릭하면 관련 페이지로 바로 이동할 수 있고, 책갈피에 마우스를 대고 마우스 오른쪽 버튼을 클릭하여 현재 페이지를 책갈피로 지정하고, 마우스 왼쪽 버튼을 클릭하여 책갈피가 있는 페이지로 돌아갈 수 있다네." "보라색 글씨는 클릭하면 관련 페이지로 바로 이동할 수 있고, 책갈피에 마우스를 대고 오른쪽 버튼을 클릭하여 현재 페이지를 책갈피로 지정하고, 왼쪽 버튼을 클릭하여 책갈피가 있는 페이지로 돌아갈 수 있다네."
] ]
}, },
@@ -353,7 +353,7 @@
], ],
"text": [ "text": [
" 마나는 마법사에게 힘을 주는 불가사의한 에너지. 마나는 그 자체로 물리적인 물질이 아니라, 세상의 모든 것에 스며드는 항상 존재하는 기운이라네.", " 마나는 마법사에게 힘을 주는 불가사의한 에너지러네. 마나는 그 자체로 물리적인 물질이 아니라, 세상의 모든 것에 스며드는 항상 존재하는 기운이라네.",
"특히 자연적으로 발생하는 결정에서 크게 발현되는데, 지하의 암석에 박혀 있는 것을 발견할 수 있다네.", "특히 자연적으로 발생하는 결정에서 크게 발현되는데, 지하의 암석에 박혀 있는 것을 발견할 수 있다네.",
"@wands 지팡이@는 그 안에 마나를 저장하고 사용할 수 있는 장치이고, 이 마나는 @spells 주문@을 사용할 때 마다 사용되며 주문마다 그 위력이나 지속력에 따라 사용하는 마나의 양이 다르다네.", "@wands 지팡이@는 그 안에 마나를 저장하고 사용할 수 있는 장치이고, 이 마나는 @spells 주문@을 사용할 때 마다 사용되며 주문마다 그 위력이나 지속력에 따라 사용하는 마나의 양이 다르다네.",
@@ -374,11 +374,11 @@
], ],
"text": [ "text": [
"지팡이는 마법사의 무기라네. 지팡이가 감당하는 한에서는 지팡이로는 어떤 @spells 주문@도 사용할 수 있다네 @tiers 등급@ 참조). 지팡이는 다양한 종류가 있지만, 처음 얻는 지팡이는 거의 기본적인 마법 지팡이일 걸세.", "지팡이는 마법사의 무기라네. 지팡이가 감당하는 한에서는 지팡이로는 어떤 @spells 주문@도 사용할 수 있다네 (@tiers 등급@ 참조). 지팡이는 다양한 종류가 있지만, 처음 얻는 지팡이는 거의 기본적인 마법 지팡이일 걸세.",
"#image magic_wand", "#image magic_wand",
"대부분의 지팡이는 나무 막대기에 마법수정을 연결햐여 만들어졌는고, 반대 쪽 끝에는 금 조각이 부착되어 있다. 물론 수정은 주문을 시전할 때의 필요한 마나를 가지고있기 때문에 지팡이의 힘의 원천이다 그러나 나머지 부분도 중요하다 지팡이를 잡을 수 있는 수단뿐만 아니라 마나가 순환되고 주문을 시전할 수 있는 길을 제공하기 때문이.", "대부분의 지팡이는 나무 막대기에 마법수정을 연결햐여 만들어졌는고, 반대 쪽 끝에는 금 조각이 부착되어 있다. 물론 수정은 주문을 시전할 때의 필요한 마나를 가지고있기 때문에 지팡이의 힘의 원천이다만, 나머지 부분도 중요하다 지팡이를 잡을 수 있는 수단뿐만 아니라 마나가 순환되고 주문을 시전할 수 있는 길을 제공하기 때문이라네.",
"지팡이로 주문을 많이 사용할 수록 주문시전에 더 효과적이게 되고, 더 높은 등급의 주문을 시전할 수 있다네. 지팡이 자체의 모양과 모양에서 일어나는 미묘한 변화로 구별할 수 있네. " "지팡이로 주문을 많이 사용할 수록 주문시전에 더 효과적이게 되고, 더 높은 등급의 주문을 시전할 수 있다네. 지팡이 자체의 모양과 모양에서 일어나는 미묘한 변화로 구별할 수 있네. "
, ,
@@ -386,7 +386,7 @@
"지팡이를 잡으면 화면 구석에 작은 HUD가 나타난다네. 현재 선택한 마법을 그림으로 표현한 것과 함께 주문이 표시되며, 마법을 시전한 후 그 주문을 다시 사용할 수 있는 시간을 나타내는 재사용 대기 막대가 표시될 걸세. 또한 지팡이에 추가된 다음 주문과 이전의 주문들의 이름을 보여준다네. 주문을 전환하려면 #next_spell_key키 및 #previous_spell_key키(설정-> 조작에서 변경할 수 있음)를 사용하면 된다네. 웅크리고 마우스를 움직이면서 마법을 바꿀 수도 있다는 것을 알아두게.", "지팡이를 잡으면 화면 구석에 작은 HUD가 나타난다네. 현재 선택한 마법을 그림으로 표현한 것과 함께 주문이 표시되며, 마법을 시전한 후 그 주문을 다시 사용할 수 있는 시간을 나타내는 재사용 대기 막대가 표시될 걸세. 또한 지팡이에 추가된 다음 주문과 이전의 주문들의 이름을 보여준다네. 주문을 전환하려면 #next_spell_key키 및 #previous_spell_key키(설정-> 조작에서 변경할 수 있음)를 사용하면 된다네. 웅크리고 마우스를 움직이면서 마법을 바꿀 수도 있다는 것을 알아두게.",
"인벤토리로 지팡이를 볼 때, 지팡이에 마우스를 올리면 마나가 얼마나 저장되어 있는지 그리고 현재 선택된 주문과 지팡이가 가지고 있는 특별한 능력들을 볼 수 있다네. 지팡이에 대한 더 세세한 정보는 @arcane_workbench 신비로운 작업대@에 올려 보면 알 수 있다." "인벤토리로 지팡이를 볼 때, 지팡이에 마우스를 올리면 마나가 얼마나 저장되어 있는지 그리고 현재 선택된 주문과 지팡이가 가지고 있는 특별한 능력들을 볼 수 있다네. 지팡이에 대한 더 세세한 정보는 @arcane_workbench 신비로운 작업대@에 올려 보면 알 수 있다."
] ]
}, },
@@ -398,15 +398,15 @@
], ],
"text": [ "text": [
"@wands 지팡이@는 마법이 없으면 쓸모가 없다. 마법은 영구적인 주문서와 일시적인 두루마리의 형태로 기록된다네.", "@wands 지팡이@는 마법이 없으면 쓸모가 없다. 마법은 영구적인 주문서와 일시적인 두루마리의 형태로 기록된다네.",
"주문서는 그 자체로는 별로 쓸모가 없다;주문서는 주문서가 가지고 있는 주문을 지팡이에 추가하는데 사용한다네. 주문서는 전세계 어디에서나 발견될 수 있고 주문서를 발견하는 데 오래 걸리지 않을 걸세. 주문서를 찾으면, 주문서에 마우스를 올려서 주문에 대한 기본적인 정보를 한눈에 볼 수 있고, 주문서를 들고 마우스 오른쪽 버튼을 클릭하여 자세한 내용을 읽을 수도 있다네.", "주문서는 그 자체로는 별로 쓸모가 없다;주문서는 주문서가 가지고 있는 주문을 지팡이에 추가하는데 사용한다네. 주문서는 전세계 어디에서나 발견될 수 있고 주문서를 발견하는 데 오래 걸리지 않을 걸세. 주문서를 찾으면, 주문서에 마우스를 올려서 주문에 대한 기본적인 정보를 한눈에 볼 수 있고, 주문서를 들고 오른쪽 버튼을 클릭하여 자세한 내용을 읽을 수도 있다네.",
"반면 두루마리는 다른 용도로 사용된다네. 마우스 오른쪽 버튼을 누르면 해당 두루마리에 걸려 있는 마법이 시전되고 두루마리가 파괴될걸세. 주문서처럼 두루마리도 전세계 어디에서나 찾아볼 수 있지만 직접 만들 수도 있다네. (@enchanting_scrolls 마법이 부여된 두루마리@ 참조)", "반면 두루마리는 다른 용도로 사용된다네. 오른쪽 버튼을 누르면 해당 두루마리에 걸려 있는 마법이 시전되고 두루마리가 파괴될걸세. 주문서처럼 두루마리도 전세계 어디에서나 찾아볼 수 있지만 직접 만들 수도 있다네. (@enchanting_scrolls 마법이 부여된 두루마리@ 참조)",
"두루마리는 특정 상황에서 한 두 번 마법을 사용해야 할 때 꽤 유용하지만, @wands 지팡이@의 공간이 부족할때 쓸만한 수단이네. 또한 충전 시간이 필요한 주문을 즉시 시전할 수 있다는 이점이 있다네. 단, 지팡이를 사용하는 것에 비해 비효율적인 방법이라는 점을 유의하게.", "두루마리는 특정 상황에서 한 두 번 마법을 사용해야 할 때 꽤 유용하지만, @wands 지팡이@의 공간이 부족할때 쓸만한 수단이네. 또한 충전 시간이 필요한 주문을 즉시 시전할 수 있다는 이점이 있다네. 단, 지팡이를 사용하는 것에 비해 비효율적인 방법이라는 점을 유의하게.",
"식별하지 않은 사람의 눈으로는 주문에 쓰여진 마법의 룬문자를 읽을 수 없다네. 주문을 식별하기 위해서는, 주문을 시전하면 된다네.시전하면 가끔 원치 않는 부작용이 일어날걸세. 많은 주문들은 시전하기 위해 특정한 조건이 필요하다네. 더 나아가, 알 수 없는 주문을 시전할 때 잘못 읽을 가능성도 있으며, 그 주문이 얼마나 강력한지에 따라 잠재적으로 위험한 부작용를 초래할 수 있다네. 안전한 방법은 상자에서 발견하거나 마법사에게 구입할 수 있는 지식의 두루마리를 사용하는 것이. 손에 들고 마우스 오른쪽 버튼을 클릭하면 단축바에 가장 앞에 있는 주문서나 두루마리를 식별하며, 이 과정에서 지식의 두루마리를 소비할걸세." "식별하지 않은 사람의 눈으로는 주문에 쓰여진 마법의 룬문자를 읽을 수 없다네. 주문을 식별하기 위해서는, 주문을 시전하면 된다네.시전하면 가끔 원치 않는 부작용이 일어날걸세. 많은 주문들은 시전하기 위해 특정한 조건이 필요하다네. 더 나아가, 알 수 없는 주문을 시전할 때 잘못 읽을 가능성도 있으며, 그 주문이 얼마나 강력한지에 따라 잠재적으로 위험한 부작용를 초래할 수 있다네. 안전한 방법은 상자에서 발견하거나 마법사에게 구입할 수 있는 지식의 두루마리를 사용하는 것이. 손에 들고 오른쪽 버튼을 클릭하면 단축바에 가장 앞에 있는 주문서나 두루마리를 식별하며, 이 과정에서 지식의 두루마리를 소비할걸세."
] ]
}, },
@@ -452,7 +452,7 @@
], ],
"text": [ "text": [
"신비로운 작업대의 중앙 슬롯에 지팡이를 놓고 왼쪽 아래 슬롯에 마법 수정을 놓고 적용 버튼을 누르면 지팡이가 충전될걸세. 각 마법수정은 #mana_per_crystal마나의 값어치가 있고, 지팡이는 필요할 때까지 수정을 사용하기 때문에, 마나를 충전할 때 생각하고 충전해야 한다네. 지팡이는 수정을 #mana_per_crystal마나 만큼씩 회복할 수 있음으로, 예를 들어 30마나가 더 필요할 경우 충전할 때 #example_charging_loss마나가 손실된다네." "신비로운 작업대의 중앙 슬롯에 지팡이를 놓고 왼쪽 아래 슬롯에 마법 수정을 놓고 적용 버튼을 누르면 지팡이가 충전될걸세. 각 마법수정은 #mana_per_crystal마나의 값어치가 있고, 지팡이는 필요할 때까지 수정을 사용하기 때문에, 마나를 충전할 때 생각하고 충전해야 한다네. 지팡이는 수정을 #mana_per_crystal마나 만큼씩 회복할 수 있음으로, 예를 들어 30만큼의 마나가 더 필요할 경우 충전할 때 #example_charging_loss만큼의 마나가 손실된다네."
] ]
}, },
"upgrading_wands": { "upgrading_wands": {
@@ -511,13 +511,13 @@
"아주 특별한 마법사들은 특정 원소에 영향을 주는 특별한 옷을 입는다네. 그 특별한 마법사의 갑옷은 찾기가 쉽지 않다네.", "아주 특별한 마법사들은 특정 원소에 영향을 주는 특별한 옷을 입는다네. 그 특별한 마법사의 갑옷은 찾기가 쉽지 않다네.",
"마법의 기본을 터득한 후에는 많은 마법사들이 훈련을 하기 위해 특별한 경로를 따라가거나 분야를 선택하게 된다네. 가장 주된 분야로는 학자와 전투법사 , 주술사 총 3가지가 있다네. 각 분야의 로브는 특이한 외형과 특성을 가지고 있는데 각 분야의 마법사들을 쉽게 구별하고 각 분야의 목적에 맞추기 위해 희귀하고 특이한 재료로 로브를 변형하였기 때문이라네. ", "마법의 기본을 터득한 후에는 많은 마법사들이 훈련을 하기 위해 특별한 경로를 따라가거나 분야를 선택하게 된다네. 가장 주된 분야로는 학자와 전투법사, 주술사 총 3가지가 있다네. 각 분야의 로브는 특이한 외형과 특성을 가지고 있는데 각 분야의 마법사들을 쉽게 구별하고 각 분야의 목적에 맞추기 위해 희귀하고 특이한 재료로 로브를 변형하였기 때문이라네. ",
"#image classes", "#image classes",
"학자", "학자",
"지식을 추구하기 위해 삶을 바치면서, 학자는 완벽하게 효율적인 시전 방법을 연구하여 , 가능한 한 적은 양의 마나를 사용하여 마법을 시전할 수 있게 됐다네. 학자의 비단 로브의 화려함에는 상당한 보호 기능이 있다네. 학자는 뛰어난 마법 부여로 실력으로 로브에 마법을 부여하기 때문이네. 그러나 이 비단 로브는 고체 금속을 도금한 갑옷과는 비교가 되지도 않는다네. 그리고 안전한 도서관에서 긴 시간을 보내는 학자의 특성상 전투에 더욱더 더디게 만드는 데 한몫했을걸세", "지식을 추구하기 위해 삶을 바치면서, 학자는 완벽하게 효율적인 시전 방법을 연구하여, 가능한 한 적은 양의 마나를 사용하여 마법을 시전할 수 있게 됐다네. 학자의 비단 로브의 화려함에는 상당한 보호 기능이 있다네. 학자는 뛰어난 마법 부여로 실력으로 로브에 마법을 부여하기 때문이네. 그러나 이 비단 로브는 고체 금속을 도금한 갑옷과는 비교가 되지도 않는다네. 그리고 안전한 도서관에서 긴 시간을 보내는 학자의 특성상 전투에 더욱더 더디게 만드는 데 한몫했을걸세",
"전투법사", "전투법사",
@@ -545,7 +545,7 @@
"집에서 연구만 한다고 해서 불가사의한 마법을 정복할 수는 없다네. 마법이 가득한 세상은 바로밖에 있다네! 고대 유적과 유물, 그리고 선악 무도한 존재들이 기다리고 있다네. 위대한 마법사들도 호기심이 많고 주변 환경 탐사와 그들이 발견한 것을 실험함으로써 지식과 힘을 많이 얻는다네.", "집에서 연구만 한다고 해서 불가사의한 마법을 정복할 수는 없다네. 마법이 가득한 세상은 바로밖에 있다네! 고대 유적과 유물, 그리고 선악 무도한 존재들이 기다리고 있다네. 위대한 마법사들도 호기심이 많고 주변 환경 탐사와 그들이 발견한 것을 실험함으로써 지식과 힘을 많이 얻는다네.",
"마법사는 시간의 많은 부분을 불가피하게 혼자 보내지만, 지식의 공유는 마법을 배우는 데 거의 필수적이라네. 마법의 대가들을 찾고, 가능한 한 많이 배우라네: 의사소통은 틀림없이 가장 큰 힘이 될 것이네." "마법사는 시간의 많은 부분을 불가피하게 혼자 보내지만, 지식의 공유는 마법을 배우는 데 거의 필수적이라네. 마법의 대가들을 찾고, 가능한 한 많이 배우라네. 의사소통은 틀림없이 가장 큰 힘이 될 것이네."
], ],
"sections": { "sections": {
"crystal_flowers": { "crystal_flowers": {
@@ -556,7 +556,7 @@
], ],
"text": [ "text": [
"여행하는 동안, 가끔 야생에서 자라는 기이한 빛나는 꽃을 보게 될걸세. 이 독특한 꽃은 마법수정 꽃으로 알려져 있고, 마력을 집중시키는 특이한 성질을 지니고 있다네, 오늘날까지, 아무도 왜 그런지 모른다네. 그 꽃을 수확하여 마법수정으로 추출할 수 있다네. 그러나, 지상의 마나의 원천이 될 정도로 많은 양의 마나를 얻기 힘들다네.", "여행하는 동안, 가끔 야생에서 자라는 기이한 빛나는 꽃을 보게 될걸세. 이 독특한 꽃은 마법수정 꽃으로 알려져 있고, 마나를 집중시키는 특이한 성질을 지니고 있다네, 오늘날까지, 아무도 왜 그런지 모른다네. 그 꽃을 수확하여 마법수정으로 추출할 수 있다네. 그러나, 지상의 마나의 원천이 될 정도로 많은 양의 마나를 얻기 힘들다네.",
"#image crystal_flower", "#image crystal_flower",
"#recipe crystal_flower_to_crystals" "#recipe crystal_flower_to_crystals"
@@ -599,18 +599,18 @@
] ]
}, },
"shrines": { "shrines": {
"title": "사", "title": "사",
"include_in_contents": "magical_world_subsections", "include_in_contents": "magical_world_subsections",
"triggers": [ "triggers": [
"ebwizardry:visit_shrine" "ebwizardry:visit_shrine"
], ],
"text": [ "text": [
"두 번째로, 방첨탑 보다 희귀한 구조물인 신사가 있다네. 이 구조물은 중앙 받침대를 원형으로 기둥이 둘러싸고 있는 모습이고, 그 위에 고대 @artefacts 유물@이 있는 상자가 놓여 있다네. 이 상자는 일반적으로 마법 잠금 마법에 의해 보호되어 있어서 주인 이외에는 아무도 그것을 열지 못한다네. 또한 사 전체가 봉쇄 마법으로 보호되어 있어 가까이 있는 모든 것을 빠져나지 못하게 한다네.", "두 번째로, 방첨탑 보다 희귀한 구조물인 사당이 있다네. 이 구조물은 중앙 받침대를 원형으로 기둥이 둘러싸고 있는 모습이고, 그 위에 고대 @artefacts 유물@이 있는 상자가 놓여 있다네. 이 상자는 일반적으로 마법 잠금 마법에 의해 보호되어 있어서 주인 이외에는 아무도 그것을 열지 못한다네. 또한 사 전체가 봉쇄 마법으로 보호되어 있어 가까이 있는 모든 것을 빠져나지 못하게 한다네.",
"#image shrine", "#image shrine",
"신사는 불가사의한 힘과 의미 때문에, 돈으로서의 가치는 말할 것도 없고, 특히 출세를 노리는 마법사에게 매력적이지만, 마법사들이 봉쇄된 사 안에 갇혀 서서히 미쳐가고 있다는 수많은 보고가 있다네. 점점 더 많은 사람이 그러한 불가사의한 사당의 봉쇄 마법에 잡힌 것은 의도적인 사의 구조이고, 그 안에 갇힌 마법사들은 사실 그 구조를 보호하기 위해 통제되고 있다고 추론된다네." "사당은 불가사의한 힘과 의미 때문에, 돈으로서의 가치는 말할 것도 없고, 특히 출세를 노리는 마법사에게 매력적이지만, 마법사들이 봉쇄된 사 안에 갇혀 서서히 미쳐가고 있다는 수많은 보고가 있다네. 점점 더 많은 사람이 그러한 불가사의한 사당의 봉쇄 마법에 잡힌 것은 의도적인 사의 구조이고, 그 안에 갇힌 마법사들은 사실 그 구조를 보호하기 위해 통제되고 있다고 추론된다네."
] ]
}, },
"library_ruins": { "library_ruins": {
@@ -625,9 +625,9 @@
"#image library_ruins", "#image library_ruins",
"도서관은 단순히 책을 저장하는 데만 사용되는 것은 아니라네. 과거의 마법사들은 마법물질에 대한 원소적 고취의 의식을 행하는 데 사용되는 고취의 제단의 힘을 사용했다네. 제단의 위치는 특정한 천체의 움직임과 작은 마나 변동에 따라 정렬되어야 하기 때문에 정확하고 어려운 기술이라네. 제단을 만드는 관습은 최근 희귀해졌는데, 주로 한번 지어지면 제단이 수세기 동안 지속되기 때문에 새로운 제단은 필요하지 않기 때문이라네. 대신, 대부분의 마법사들은 고취의 의식을 행할 필요가 있을 때 기존의 제단을 찾아서 수리한다네.", "도서관은 단순히 책을 저장하는 데만 사용되는 것은 아니라네. 과거의 마법사들은 마법물질에 대한 원소적 주입 의식을 행하는 데 사용되는 주입의 제단의 힘을 사용했다네. 제단의 위치는 특정한 천체의 움직임과 작은 마나 변동에 따라 정렬되어야 하기 때문에 정확하고 어려운 기술이라네. 제단을 만드는 관습은 최근 희귀해졌는데, 주로 한번 지어지면 제단이 수세기 동안 지속되기 때문에 새로운 제단은 필요하지 않기 때문이라네. 대신, 대부분의 마법사들은 주입 의식을 행할 필요가 있을 때 기존의 제단을 찾아서 수리한다네.",
"나중에, 언젠가 나만의 도서관을 지어 주문서를 보관할 때가 생길 것이. 도서관에 필요한 것들을 만드는 방법:", "나중에, 언젠가 나만의 도서관을 지어 주문서를 보관할 때가 생길 것이. 도서관에 필요한 것들을 만드는 방법:",
"#recipe bookshelves", "#recipe bookshelves",
@@ -669,7 +669,7 @@
], ],
"text": [ "text": [
"@shrines 신사@를 탐험할 때, 운이 좋다면 독특하고 강력한 효과와 특별한 힘이 있는 고대 마법의 유물을 발견할 수 있을걸세. 추가 효과를 부여하는 반지, 수비능력을 향상하는 목걸이, 특별한 효과를 부여하는 부적 등 3가지만이 발견된 것으로 알려져 있다네. 이 유물은 특정한 상황에서 효과를 발휘하므로; 단순히 몸에 지닌 것은 효과를 기대하기 힘들다네." "@shrines 사당@을 탐험할 때, 운이 좋다면 독특하고 강력한 효과와 특별한 힘이 있는 고대 마법의 유물을 발견할 수 있을걸세. 추가 효과를 부여하는 반지, 수비능력을 향상하는 목걸이, 특별한 효과를 부여하는 부적 등 3가지만이 발견된 것으로 알려져 있다네. 이 유물은 특정한 상황에서 효과를 발휘하므로; 단순히 몸에 지닌 것은 효과를 기대하기 힘들다네."
] ]
} }
} }
@@ -683,7 +683,7 @@
], ],
"text":[ "text":[
"지팡이와 주문은 4개의 등급으로 이루어져있다네: #colour_novice초보#colour_reset와 #colour_apprentice견습#colour_reset, #colour_advanced숙련#colour_reset과 #colour_master대가#colour_reset. 각 등급은 마지막 등급으로 갈 수록 더 강력하다네.", "지팡이와 주문은 4개의 등급으로 이루어져있다네: #colour_novice초보#colour_reset와 #colour_apprentice견습#colour_reset, #colour_advanced숙련#colour_reset과 #colour_master대가#colour_reset. 각 등급은 마지막 등급으로 갈수록 더 강력하다네.",
"#image tiers", "#image tiers",
" ", " ",
@@ -755,7 +755,7 @@
"아르켄더의 신비로운 충전 회사 - 모든 필요를 충족시키는 마법 물품!", "아르켄더의 신비로운 충전 회사 - 모든 필요를 충족시키는 마법 물품!",
"이동 중에 지팡이를 재충전해야 하는 상황이 와도? 문제는 없습니다! 마나을 병으로 만들어, 단순한 유리병과 여덟 개의 마법수정으로 마나병을 만들 수 있습니다! 마나병을 사용해야 할 때, 간단히 조합으로 지팡이와 합쳐내면 쉽게 충전이 가능합니다. *", "이동 중에 지팡이를 재충전해야 하는 상황이 와도? 문제는 없습니다! 마나을 병으로 만들어, 단순한 유리병과 여덟 개의 마법수정으로 마나병을 만들 수 있습니다! 마나병을 사용해야 할 때, 간단히 제작으로 지팡이와 합쳐내면 쉽게 충전이 가능합니다. *",
"#recipe medium_mana_flask", "#recipe medium_mana_flask",
@@ -798,7 +798,7 @@
}, },
"crafting_recipes": { "crafting_recipes": {
"title": "조합법", "title": "제작법",
"include_in_contents": "main_contents", "include_in_contents": "main_contents",
"text": [ "text": [
@@ -854,7 +854,7 @@
"현지화를 담당해주신 분들:", "현지화를 담당해주신 분들:",
"- 스페인어: MadWrist, Alsentar \n- 멕시코 스페인어: MadWrist \n- 러시아어: VilagVil, kellixon, bigenergy \n- 프랑스어: Hahdrim \n- 브라질 포르투갈어: lorrampi \n- 중국어(간체): ZHENGLOC, dragon-evol, Hokorizero, TUsama, Determancer \n- 한: shejery, rewi_wire \n- 폴란드어: Trozuu \n- 독일어: BirdyDragon \n- 중국어(번체): chesterccj305 \n- 헝가리어: Bombadil", "- 스페인어: MadWrist, Alsentar \n- 멕시코 스페인어: MadWrist \n- 러시아어: VilagVil, kellixon, bigenergy \n- 프랑스어: Hahdrim \n- 브라질 포르투갈어: lorrampi \n- 중국어(간체): ZHENGLOC, dragon-evol, Hokorizero, TUsama, Determancer \n- 한국어: shejery, rewi_wire \n- 폴란드어: Trozuu \n- 독일어: BirdyDragon \n- 중국어(번체): chesterccj305 \n- 헝가리어: Bombadil",
"소리 효과를 담당해주신 분들:", "소리 효과를 담당해주신 분들:",
@@ -867,4 +867,3 @@
} }
} }
}
+1 -1
View File
@@ -2,7 +2,7 @@
{ {
"modid" : "ebwizardry", "modid" : "ebwizardry",
"name" : "Electroblob's Wizardry", "name" : "Electroblob's Wizardry",
"version" : "4.3.12", "version" : "4.3.13",
"mcversion" : "1.12.2", "mcversion" : "1.12.2",
"url" : "https://minecraft.curseforge.com/projects/electroblobs-wizardry", "url" : "https://minecraft.curseforge.com/projects/electroblobs-wizardry",
"credits" : "\nDesigned, coded and textured by Electroblob.\nDiscord Moderators: FavouriteDragon, WinDanesz\nCode contributed by: Corail31, 12foo, Shadows-of-Fire, Tora-B, Avatair, Aeronica, UltraHex, Azim-Palmer, raoulvdberge, rafasoares, xinyuan-liu, SettingDust, Aralu115, WinDanesz, ZettaSword.\nTranslators: Alsentar (Spanish), MadWrist (Mexican Spanish), VilagVil, kellixon, bigenergy, MugGod2 & DrHesperus (Russian), Hahdrim & Crowller (French), lorrampi (Brazilian Portuguese), ZHENGLOC, dragon-evol, Hokorizero, TUsama & Determancer (Chinese - Simplified), shejery, rewi_wire, 방통 & red1854th (Korean), Trozuu & Olej (Polish), BirdyDragon & Lemopav (German), chesterccj305 (Chinese - Traditional), Bombadil (Hungarian).\nSound Effects: OhhWowProductions, fredzed, deleted_user_3277771, DiscoveryME, OGSoundFX, leosalom, juskiddink", "credits" : "\nDesigned, coded and textured by Electroblob.\nDiscord Moderators: FavouriteDragon, WinDanesz\nCode contributed by: Corail31, 12foo, Shadows-of-Fire, Tora-B, Avatair, Aeronica, UltraHex, Azim-Palmer, raoulvdberge, rafasoares, xinyuan-liu, SettingDust, Aralu115, WinDanesz, ZettaSword.\nTranslators: Alsentar (Spanish), MadWrist (Mexican Spanish), VilagVil, kellixon, bigenergy, MugGod2 & DrHesperus (Russian), Hahdrim & Crowller (French), lorrampi (Brazilian Portuguese), ZHENGLOC, dragon-evol, Hokorizero, TUsama & Determancer (Chinese - Simplified), shejery, rewi_wire, 방통 & red1854th (Korean), Trozuu & Olej (Polish), BirdyDragon & Lemopav (German), chesterccj305 (Chinese - Traditional), Bombadil (Hungarian).\nSound Effects: OhhWowProductions, fredzed, deleted_user_3277771, DiscoveryME, OGSoundFX, leosalom, juskiddink",