From f37812be3ec4ddc1f6d89bede6e478b2c7c53bad Mon Sep 17 00:00:00 2001 From: Electroblob77 <35599699+Electroblob77@users.noreply.github.com> Date: Sun, 18 Aug 2019 00:04:18 +0100 Subject: [PATCH] That's one heck of a commit you've got there... I may have got a bit behind with version control. A lot behind, in fact. Maybe I'll go back and split this sometime - then again, I probably won't. But hey, at least it's here! --- .gitignore | 7 +- build.gradle | 39 +- gradle.properties | 2 + gradlew | 4 +- gradlew.bat | 4 +- .../electroblob/wizardry/CommonProxy.java | 164 +- .../java/electroblob/wizardry/Settings.java | 705 +++++-- .../java/electroblob/wizardry/Wizardry.java | 176 +- .../wizardry/WizardryEventHandler.java | 479 ++--- .../wizardry/WizardryGuiFactory.java | 6 +- .../wizardry/WizardryGuiHandler.java | 7 +- .../wizardry/WizardryWorldGenerator.java | 949 --------- .../advancement/ArcaneWorkbenchTrigger.java | 135 ++ .../CustomAdvancementTrigger.java | 5 +- .../advancement/SpellCastTrigger.java | 139 ++ .../advancement/SpellDiscoveryTrigger.java | 143 ++ .../wizardry/advancement/SpellPredicate.java | 117 ++ .../advancement/StructureTrigger.java | 136 ++ .../wizardry/api/WizardryEnumHelper.java | 96 + .../wizardry/block/BlockArcaneWorkbench.java | 11 + .../wizardry/block/BlockCrystal.java | 76 + .../wizardry/block/BlockCrystalFlower.java | 4 +- .../wizardry/block/BlockCrystalOre.java | 4 +- .../wizardry/block/BlockDryFrostedIce.java | 28 + .../wizardry/block/BlockMagicLight.java | 49 +- .../wizardry/block/BlockObsidianCrust.java | 116 ++ .../wizardry/block/BlockPedestal.java | 123 ++ .../wizardry/block/BlockRunestone.java | 85 + .../wizardry/block/BlockSnare.java | 25 +- .../wizardry/block/BlockSpectral.java | 15 +- .../wizardry/block/BlockStatue.java | 31 +- .../wizardry/block/BlockThorns.java | 181 ++ .../block/BlockTransportationStone.java | 109 +- .../wizardry/block/BlockVanishingCobweb.java | 18 +- .../wizardry/client/ClientProxy.java | 473 +++-- .../wizardry/client/DrawingUtils.java | 39 +- .../wizardry/client/MixedFontRenderer.java | 4 +- .../wizardry/client/MovingSoundEntity.java | 52 - .../client/WizardryClientEventHandler.java | 550 ++--- .../client/WizardryControlHandler.java | 95 +- .../client/audio/MovingSoundEntity.java | 35 + .../wizardry/client/audio/SoundLoop.java | 94 + .../wizardry/client/audio/SoundLoopSpell.java | 117 ++ .../client/gui/GuiArcaneWorkbench.java | 452 ++-- .../client/gui/GuiButtonInvisible.java | 4 +- .../client/gui/GuiButtonResurrect.java | 90 + .../wizardry/client/gui/GuiSpellBook.java | 53 +- .../wizardry/client/gui/GuiSpellDisplay.java | 113 +- .../{ => gui/config}/EntityNameEntry.java | 16 +- .../gui/{ => config}/GuiConfigWizardry.java | 75 +- .../gui/{ => config}/GuiSelectHUDSkin.java | 13 +- .../client/gui/config/NamedBooleanEntry.java | 93 + .../config}/SpellHUDSkinChooserEntry.java | 17 +- .../client/gui/handbook/Contents.java | 49 +- .../client/gui/handbook/CraftingRecipe.java | 73 +- .../gui/handbook/GuiButtonHyperlink.java | 70 +- .../gui/handbook/GuiButtonTurnPage.java | 4 +- .../gui/handbook/GuiWizardHandbook.java | 106 +- .../client/gui/handbook/HandbookToast.java | 54 + .../wizardry/client/gui/handbook/Image.java | 31 +- .../wizardry/client/gui/handbook/Section.java | 132 +- .../model/BakedModelGlowingOverlay.java | 234 +++ .../wizardry/client/model/ModelIceGiant.java | 10 +- .../wizardry/client/model/ModelWizard.java | 8 +- .../client/model/ModelWizardArmour.java | 153 +- .../client/model/WizardryItemModels.java | 197 -- .../wizardry/client/model/WizardryModels.java | 343 ++++ .../client/particle/ParticleBeam.java | 14 +- .../client/particle/ParticleBuff.java | 65 +- .../client/particle/ParticleDarkMagic.java | 4 +- .../client/particle/ParticleDust.java | 6 +- .../client/particle/ParticleFlash.java | 13 +- .../wizardry/client/particle/ParticleIce.java | 3 +- .../client/particle/ParticleLeaf.java | 5 +- .../client/particle/ParticleLightning.java | 18 +- .../particle/ParticleLightningPulse.java | 10 +- .../client/particle/ParticleMagicBubble.java | 4 +- .../client/particle/ParticleMagicFlame.java | 50 +- .../client/particle/ParticlePath.java | 8 +- .../client/particle/ParticleScorch.java | 12 +- .../client/particle/ParticleSnow.java | 5 +- .../client/particle/ParticleSpark.java | 11 +- .../client/particle/ParticleSparkle.java | 3 +- .../client/particle/ParticleSphere.java | 131 ++ .../client/particle/ParticleSummon.java | 132 ++ .../client/particle/ParticleTargeted.java | 97 +- .../client/particle/ParticleTornado.java | 17 +- .../client/particle/ParticleVine.java | 154 ++ .../client/particle/ParticleWizardry.java | 280 ++- .../wizardry/client/renderer/LayerFrost.java | 153 ++ .../wizardry/client/renderer/LayerStone.java | 19 +- .../renderer/LayerStrayMinionClothing.java | 33 + .../client/renderer/RenderArcaneLock.java | 89 + .../renderer/RenderArcaneWorkbench.java | 21 +- .../client/renderer/RenderBlackHole.java | 40 +- .../client/renderer/RenderBubble.java | 3 +- .../renderer/RenderContainmentField.java | 268 +++ .../wizardry/client/renderer/RenderDecay.java | 3 +- .../wizardry/client/renderer/RenderDecoy.java | 10 +- .../client/renderer/RenderEvilWizard.java | 4 +- .../client/renderer/RenderFireRing.java | 3 +- .../client/renderer/RenderForceArrow.java | 7 +- .../client/renderer/RenderForcefield.java | 124 ++ .../client/renderer/RenderHammer.java | 4 +- .../client/renderer/RenderIceGiant.java | 4 +- .../client/renderer/RenderIceSpike.java | 10 +- .../client/renderer/RenderLightningDisc.java | 3 +- .../client/renderer/RenderMagicArrow.java | 7 +- .../client/renderer/RenderMagicLight.java | 29 +- .../client/renderer/RenderPhoenix.java | 7 +- .../renderer/RenderPossessingPlayer.java | 41 + .../client/renderer/RenderProjectile.java | 7 +- .../client/renderer/RenderShadowWard.java | 148 ++ .../client/renderer/RenderShield.java | 168 ++ .../wizardry/client/renderer/RenderSigil.java | 9 +- .../client/renderer/RenderSpiritHorse.java | 41 +- .../client/renderer/RenderSpiritWolf.java | 37 +- .../client/renderer/RenderStrayMinion.java | 24 + .../renderer/RenderTransportationUI.java | 177 ++ .../wizardry/client/renderer/RenderWings.java | 113 + .../client/renderer/RenderWizard.java | 4 +- .../client/renderer/RenderWraithMinion.java | 4 +- .../wizardry/command/CommandCastSpell.java | 204 +- .../command/CommandDiscoverSpell.java | 39 +- .../wizardry/command/CommandSetAlly.java | 43 +- .../wizardry/command/CommandViewAllies.java | 20 +- .../wizardry/command/SpellEmitter.java | 177 ++ .../wizardry/constants/Constants.java | 26 +- .../wizardry/constants/Element.java | 51 +- .../wizardry/constants/SpellType.java | 18 +- .../electroblob/wizardry/constants/Tier.java | 51 +- .../wizardry/data/BlockCastingData.java | 183 ++ .../wizardry/data/DispenserCastingData.java | 219 ++ .../wizardry/data/IStoredVariable.java | 256 +++ .../electroblob/wizardry/data/IVariable.java | 118 ++ .../wizardry/data/Persistence.java | 25 + .../wizardry/data/SpellEmitterData.java | 128 ++ .../wizardry/{ => data}/SpellGlyphData.java | 39 +- .../wizardry/{ => data}/WizardData.java | 530 +++-- .../EnchantmentMagicProtection.java | 111 + .../wizardry/enchantment/Imbuement.java | 16 +- .../entity/EntityLevitatingBlock.java | 296 +++ .../wizardry/entity/EntityMeteor.java | 37 +- .../wizardry/entity/EntityShield.java | 28 +- .../wizardry/entity/ICustomHitbox.java | 31 + .../entity/construct/EntityArrowRain.java | 5 +- .../entity/construct/EntityBlackHole.java | 72 +- .../entity/construct/EntityBlizzard.java | 16 +- .../entity/construct/EntityBubble.java | 23 +- .../construct/EntityCombustionRune.java | 58 + .../entity/construct/EntityDecay.java | 18 +- .../entity/construct/EntityEarthquake.java | 91 +- .../entity/construct/EntityFireRing.java | 23 +- .../entity/construct/EntityFireSigil.java | 23 +- .../entity/construct/EntityForcefield.java | 357 +++- .../entity/construct/EntityFrostSigil.java | 20 +- .../entity/construct/EntityHailstorm.java | 5 +- .../entity/construct/EntityHammer.java | 174 +- .../entity/construct/EntityHealAura.java | 21 +- .../entity/construct/EntityIceSpike.java | 47 +- .../construct/EntityLightningSigil.java | 28 +- .../construct/EntityMagicConstruct.java | 73 +- .../entity/construct/EntityTornado.java | 122 +- .../entity/living/EntityAIAttackSpell.java | 26 +- .../entity/living/EntityBlazeMinion.java | 39 +- .../wizardry/entity/living/EntityDecoy.java | 30 +- .../entity/living/EntityEvilWizard.java | 144 +- .../entity/living/EntityHuskMinion.java | 42 + .../entity/living/EntityIceGiant.java | 39 +- .../entity/living/EntityIceWraith.java | 27 +- .../entity/living/EntityLightningWraith.java | 25 +- .../entity/living/EntityMagicSlime.java | 30 +- .../wizardry/entity/living/EntityPhoenix.java | 22 +- .../entity/living/EntityShadowWraith.java | 24 +- .../entity/living/EntitySilverfishMinion.java | 38 +- .../entity/living/EntitySkeletonMinion.java | 55 +- .../entity/living/EntitySpiderMinion.java | 31 +- .../entity/living/EntitySpiritHorse.java | 57 +- .../entity/living/EntitySpiritWolf.java | 61 +- .../entity/living/EntityStormElemental.java | 25 +- .../entity/living/EntityStrayMinion.java | 35 + .../entity/living/EntitySummonedCreature.java | 35 +- .../entity/living/EntityVexMinion.java | 151 ++ .../living/EntityWitherSkeletonMinion.java | 37 +- .../wizardry/entity/living/EntityWizard.java | 272 +-- .../entity/living/EntityZombieMinion.java | 33 +- .../living/IIntelligentSpellCaster.java | 4 +- .../wizardry/entity/living/ISpellCaster.java | 11 +- .../entity/living/ISummonedCreature.java | 224 +- .../entity/projectile/EntityDarknessOrb.java | 22 +- .../entity/projectile/EntityDart.java | 20 +- .../entity/projectile/EntityEmber.java | 87 + .../entity/projectile/EntityFirebolt.java | 32 +- .../entity/projectile/EntityFirebomb.java | 30 +- .../entity/projectile/EntityForceArrow.java | 69 +- .../entity/projectile/EntityForceOrb.java | 23 +- .../entity/projectile/EntityIceCharge.java | 74 +- .../entity/projectile/EntityIceLance.java | 21 +- .../entity/projectile/EntityIceShard.java | 21 +- .../entity/projectile/EntityIceball.java | 117 ++ .../projectile/EntityLargeMagicFireball.java | 106 + .../projectile/EntityLightningArrow.java | 28 +- .../projectile/EntityLightningDisc.java | 55 +- .../entity/projectile/EntityMagicArrow.java | 103 +- .../projectile/EntityMagicFireball.java | 198 ++ .../entity/projectile/EntityMagicMissile.java | 19 +- .../projectile/EntityMagicProjectile.java | 94 +- .../entity/projectile/EntityPoisonBomb.java | 35 +- .../entity/projectile/EntitySmokeBomb.java | 26 +- .../entity/projectile/EntitySpark.java | 56 +- .../entity/projectile/EntitySparkBomb.java | 30 +- .../entity/projectile/EntityThunderbolt.java | 25 +- .../wizardry/event/DiscoverSpellEvent.java | 27 +- .../wizardry/event/SpellCastEvent.java | 160 +- .../integration/DamageSafetyChecker.java | 14 +- .../WizardryAntiqueAtlasIntegration.java | 71 + .../baubles/WizardryBaublesIntegration.java | 110 + .../wizardry/item/IConjuredItem.java | 83 +- .../wizardry/item/IManaStoringItem.java | 72 + .../wizardry/item/IMultiTexturedItem.java | 23 + .../wizardry/item/ISpellCastingItem.java | 129 ++ .../wizardry/item/IWorkbenchItem.java | 10 +- .../wizardry/item/ItemArcaneTome.java | 12 +- .../wizardry/item/ItemArmourUpgrade.java | 10 +- .../wizardry/item/ItemArtefact.java | 875 ++++++++ .../wizardry/item/ItemBlankScroll.java | 18 +- .../item/ItemBlockMultiTexturedElemental.java | 42 + .../wizardry/item/ItemCrystal.java | 44 + .../wizardry/item/ItemFirebomb.java | 8 +- .../wizardry/item/ItemFlamingAxe.java | 57 +- .../wizardry/item/ItemFrostAxe.java | 47 +- .../item/ItemIdentificationScroll.java | 41 +- .../wizardry/item/ItemLightningHammer.java | 220 ++ .../wizardry/item/ItemManaFlask.java | 37 + .../wizardry/item/ItemPoisonBomb.java | 8 +- .../wizardry/item/ItemPurifyingElixir.java | 99 + .../electroblob/wizardry/item/ItemScroll.java | 138 +- .../wizardry/item/ItemSmokeBomb.java | 8 +- .../wizardry/item/ItemSparkBomb.java | 41 + .../wizardry/item/ItemSpectralArmour.java | 38 +- .../wizardry/item/ItemSpectralBow.java | 76 +- .../wizardry/item/ItemSpectralPickaxe.java | 45 +- .../wizardry/item/ItemSpectralSword.java | 47 +- .../wizardry/item/ItemSpellBook.java | 35 +- .../electroblob/wizardry/item/ItemWand.java | 694 ++++--- .../wizardry/item/ItemWandUpgrade.java | 32 + .../wizardry/item/ItemWizardArmour.java | 247 ++- .../wizardry/item/ItemWizardHandbook.java | 10 +- .../wizardry/loot/RandomSpell.java | 130 +- .../wizardry/loot/WizardSpell.java | 9 +- .../wizardry/misc/BehaviourSpellDispense.java | 105 + .../electroblob/wizardry/misc/Forfeit.java | 487 +++++ .../{util => misc}/WildcardTradeList.java | 2 +- .../{util => misc}/WizardryPathFinder.java | 10 +- .../packet/PacketCastContinuousSpell.java | 29 +- .../wizardry/packet/PacketCastSpell.java | 12 +- .../wizardry/packet/PacketCastSpellAtPos.java | 85 + .../wizardry/packet/PacketClairvoyance.java | 6 +- .../wizardry/packet/PacketConquerShrine.java | 58 + .../wizardry/packet/PacketControlInput.java | 133 +- .../packet/PacketDispenserCastSpell.java | 94 + .../wizardry/packet/PacketEmitterData.java | 55 + .../wizardry/packet/PacketEndSlowTime.java | 47 + .../wizardry/packet/PacketGlyphData.java | 17 +- .../wizardry/packet/PacketNPCCastSpell.java | 5 +- .../wizardry/packet/PacketPlayerSync.java | 43 +- .../wizardry/packet/PacketPossession.java | 58 + .../packet/PacketRequestAdvancementSync.java | 50 + .../wizardry/packet/PacketResurrection.java | 47 + .../packet/PacketSpellProperties.java | 64 + .../packet/PacketSyncAdvancements.java | 61 + .../wizardry/packet/PacketSyncSettings.java | 34 +- .../wizardry/packet/PacketTransportation.java | 7 +- .../packet/WizardryPacketHandler.java | 10 + .../electroblob/wizardry/potion/Curse.java | 70 + .../wizardry/potion/CurseEnfeeblement.java | 49 + .../wizardry/potion/CurseUndeath.java | 58 + .../potion/ICustomPotionParticles.java | 19 +- .../wizardry/potion/ISyncedPotion.java | 81 + .../wizardry/potion/PotionContainment.java | 121 ++ .../wizardry/potion/PotionDecay.java | 13 +- .../wizardry/potion/PotionFrost.java | 5 - .../wizardry/potion/PotionFrostStep.java | 116 ++ .../wizardry/potion/PotionMagicEffect.java | 3 +- .../wizardry/potion/PotionSlowTime.java | 172 ++ .../electroblob/wizardry/registry/Spells.java | 525 ++--- .../registry/WizardryAdvancementTriggers.java | 59 +- .../wizardry/registry/WizardryBlocks.java | 84 +- .../registry/WizardryEnchantments.java | 28 +- .../wizardry/registry/WizardryEntities.java | 190 ++ .../wizardry/registry/WizardryItems.java | 726 ++++--- .../wizardry/registry/WizardryLoot.java | 156 ++ .../wizardry/registry/WizardryPotions.java | 98 +- .../wizardry/registry/WizardryRecipes.java | 137 ++ .../wizardry/registry/WizardryRegistry.java | 225 -- .../wizardry/registry/WizardrySounds.java | 273 ++- .../wizardry/registry/WizardryTabs.java | 156 +- .../java/electroblob/wizardry/spell/Arc.java | 28 +- .../wizardry/spell/ArcaneJammer.java | 36 +- .../wizardry/spell/ArcaneLock.java | 133 ++ .../electroblob/wizardry/spell/ArrowRain.java | 13 +- .../electroblob/wizardry/spell/Banish.java | 110 +- .../electroblob/wizardry/spell/Blink.java | 38 +- .../electroblob/wizardry/spell/Bubble.java | 40 +- .../wizardry/spell/ChainLightning.java | 80 +- .../electroblob/wizardry/spell/Charge.java | 125 ++ .../wizardry/spell/Clairvoyance.java | 73 +- .../electroblob/wizardry/spell/Cobwebs.java | 45 +- .../wizardry/spell/ConjureArmour.java | 20 +- .../wizardry/spell/ConjureBlock.java | 79 + .../wizardry/spell/Containment.java | 54 + .../wizardry/spell/CureEffects.java | 27 +- .../wizardry/spell/CurseOfEnfeeblement.java | 60 + .../wizardry/spell/CurseOfSoulbinding.java | 96 +- .../wizardry/spell/CurseOfUndeath.java | 55 + .../electroblob/wizardry/spell/Decay.java | 26 +- .../electroblob/wizardry/spell/Decoy.java | 25 +- .../electroblob/wizardry/spell/Detonate.java | 34 +- .../wizardry/spell/Disintegration.java | 97 + .../wizardry/spell/Divination.java | 149 ++ .../{Fireball.java => DragonFireball.java} | 48 +- .../wizardry/spell/Earthquake.java | 54 +- .../wizardry/spell/EmpoweringPresence.java | 81 + .../wizardry/spell/Entrapment.java | 19 +- .../electroblob/wizardry/spell/Evade.java | 48 + .../wizardry/spell/FireBreath.java | 95 + .../electroblob/wizardry/spell/Firestorm.java | 110 - .../electroblob/wizardry/spell/FlameRay.java | 76 +- .../wizardry/spell/FlamingAxe.java | 7 +- .../wizardry/spell/FlamingWeapon.java | 19 +- .../electroblob/wizardry/spell/Flight.java | 39 +- .../wizardry/spell/FontOfMana.java | 63 +- .../wizardry/spell/ForceArrow.java | 21 + .../wizardry/spell/Forcefield.java | 21 + .../wizardry/spell/ForestOfThorns.java | 99 + .../wizardry/spell/ForestsCurse.java | 26 +- .../electroblob/wizardry/spell/Freeze.java | 55 +- .../wizardry/spell/FreezingWeapon.java | 19 +- .../electroblob/wizardry/spell/FrostAxe.java | 6 +- .../electroblob/wizardry/spell/FrostRay.java | 79 +- .../electroblob/wizardry/spell/Glide.java | 51 +- .../electroblob/wizardry/spell/Grapple.java | 419 ++++ .../wizardry/spell/GreaterFireball.java | 85 - .../wizardry/spell/GreaterHeal.java | 9 +- .../wizardry/spell/GreaterTelekinesis.java | 159 ++ .../electroblob/wizardry/spell/GroupHeal.java | 76 +- .../wizardry/spell/GrowthAura.java | 60 +- .../electroblob/wizardry/spell/Hailstorm.java | 15 +- .../java/electroblob/wizardry/spell/Heal.java | 9 +- .../electroblob/wizardry/spell/HealAlly.java | 34 +- .../electroblob/wizardry/spell/IceAge.java | 148 +- .../electroblob/wizardry/spell/IceSpikes.java | 62 +- .../electroblob/wizardry/spell/IceStatue.java | 38 +- .../electroblob/wizardry/spell/Ignite.java | 26 +- .../wizardry/spell/ImbueWeapon.java | 41 +- .../wizardry/spell/Intimidate.java | 52 +- .../wizardry/spell/InvigoratingPresence.java | 38 +- .../wizardry/spell/InvokeWeather.java | 28 +- .../java/electroblob/wizardry/spell/Leap.java | 25 +- .../wizardry/spell/Levitation.java | 39 +- .../electroblob/wizardry/spell/LifeDrain.java | 74 +- .../electroblob/wizardry/spell/Light.java | 36 +- .../wizardry/spell/LightningBolt.java | 67 +- .../wizardry/spell/LightningHammer.java | 18 +- .../wizardry/spell/LightningPulse.java | 47 +- .../wizardry/spell/LightningRay.java | 98 +- .../wizardry/spell/LightningWeb.java | 160 +- .../wizardry/spell/Metamorphosis.java | 60 +- .../electroblob/wizardry/spell/Meteor.java | 25 +- .../wizardry/spell/MindControl.java | 91 +- .../electroblob/wizardry/spell/MindTrick.java | 21 +- .../java/electroblob/wizardry/spell/Mine.java | 157 ++ .../java/electroblob/wizardry/spell/None.java | 7 +- .../electroblob/wizardry/spell/Paralysis.java | 123 ++ .../electroblob/wizardry/spell/Petrify.java | 30 +- .../electroblob/wizardry/spell/PhaseStep.java | 140 +- .../wizardry/spell/PlagueOfDarkness.java | 42 +- .../wizardry/spell/PocketFurnace.java | 27 +- .../wizardry/spell/PocketWorkbench.java | 11 +- .../electroblob/wizardry/spell/Poison.java | 33 +- .../wizardry/spell/Possession.java | 714 +++++++ .../wizardry/spell/RayOfPurification.java | 103 + .../wizardry/spell/RemoveCurse.java | 53 + .../wizardry/spell/ReplenishHunger.java | 14 +- .../wizardry/spell/Resurrection.java | 111 + .../electroblob/wizardry/spell/Reversal.java | 83 + .../electroblob/wizardry/spell/Satiety.java | 40 + .../wizardry/spell/ShadowWard.java | 49 +- .../electroblob/wizardry/spell/Shield.java | 48 +- .../electroblob/wizardry/spell/Shockwave.java | 84 +- .../wizardry/spell/ShulkerBullet.java | 101 + .../wizardry/spell/SixthSense.java | 45 +- .../electroblob/wizardry/spell/Slime.java | 52 +- .../electroblob/wizardry/spell/SlowTime.java | 46 + .../electroblob/wizardry/spell/Snare.java | 17 +- .../electroblob/wizardry/spell/Snowball.java | 24 +- .../wizardry/spell/SpectralPathway.java | 26 +- .../electroblob/wizardry/spell/SpeedTime.java | 133 ++ .../electroblob/wizardry/spell/Spell.java | 658 ++++-- .../wizardry/spell/SpellAreaEffect.java | 75 +- .../wizardry/spell/SpellArrow.java | 144 +- .../electroblob/wizardry/spell/SpellBuff.java | 169 +- .../wizardry/spell/SpellConjuration.java | 55 +- .../wizardry/spell/SpellConstruct.java | 127 +- .../wizardry/spell/SpellConstructRanged.java | 126 +- .../wizardry/spell/SpellMinion.java | 225 +- .../wizardry/spell/SpellProjectile.java | 148 +- .../electroblob/wizardry/spell/SpellRay.java | 301 +-- .../wizardry/spell/SummonIronGolem.java | 15 +- .../wizardry/spell/SummonShadowWraith.java | 5 +- .../wizardry/spell/SummonSkeleton.java | 24 +- .../wizardry/spell/SummonSkeletonLegion.java | 26 +- .../wizardry/spell/SummonSnowGolem.java | 10 +- .../wizardry/spell/SummonSpiritHorse.java | 76 +- .../wizardry/spell/SummonSpiritWolf.java | 68 +- .../wizardry/spell/SummonWitherSkeleton.java | 24 + .../wizardry/spell/SummonZombie.java | 28 + .../wizardry/spell/Telekinesis.java | 26 +- .../wizardry/spell/Thunderstorm.java | 139 +- .../electroblob/wizardry/spell/Tornado.java | 16 +- .../wizardry/spell/Transience.java | 59 +- .../wizardry/spell/Transportation.java | 190 +- .../wizardry/spell/VanishingBox.java | 11 +- .../wizardry/spell/WallOfFrost.java | 92 +- .../electroblob/wizardry/spell/Whirlwind.java | 57 +- .../electroblob/wizardry/spell/Wither.java | 34 +- .../wizardry/spell/WitherSkull.java | 57 +- .../tileentity/ContainerArcaneWorkbench.java | 45 +- .../tileentity/SlotItemClassList.java | 40 + .../wizardry/tileentity/SlotItemList.java | 14 +- .../tileentity/SlotWorkbenchItem.java | 2 +- .../tileentity/TileEntityArcaneWorkbench.java | 61 +- .../tileentity/TileEntityMagicLight.java | 5 + .../tileentity/TileEntityPlayerSave.java | 54 +- .../tileentity/TileEntityPlayerSaveTimed.java | 69 + .../tileentity/TileEntityShrineCore.java | 218 ++ .../wizardry/tileentity/TileEntityStatue.java | 9 +- .../wizardry/tileentity/TileEntityTimer.java | 7 +- .../wizardry/util/AllyDesignationSystem.java | 234 +++ .../wizardry/util/CustomSoundCategory.java | 86 + .../wizardry/util/IElementalDamage.java | 6 - .../electroblob/wizardry/util/Location.java | 47 + .../wizardry/util/MagicDamage.java | 77 +- .../electroblob/wizardry/util/NBTExtras.java | 231 +++ .../wizardry/util/ParticleBuilder.java | 387 +++- .../electroblob/wizardry/util/RayTracer.java | 207 ++ .../wizardry/util/RelativeFacing.java | 42 + .../wizardry/util/SpellModifiers.java | 98 +- .../wizardry/util/SpellProperties.java | 361 ++++ .../electroblob/wizardry/util/WandHelper.java | 116 +- .../wizardry/util/WizardryUtilities.java | 1061 +++++----- .../worldgen/MossifierTemplateProcessor.java | 51 + .../worldgen/MultiTemplateProcessor.java | 39 + .../worldgen/WoodTypeTemplateProcessor.java | 90 + .../worldgen/WorldGenCrystalFlower.java | 61 + .../wizardry/worldgen/WorldGenCrystalOre.java | 61 + .../wizardry/worldgen/WorldGenObelisk.java | 101 + .../wizardry/worldgen/WorldGenShrine.java | 95 + .../worldgen/WorldGenSurfaceStructure.java | 450 ++++ .../worldgen/WorldGenWizardTower.java | 165 ++ .../ebwizardry/advancements/advanced.json | 108 + .../advancements/all_artefacts.json | 647 ++++++ .../ebwizardry/advancements/all_spells.json | 1385 ++++++++++++- .../ebwizardry/advancements/anger_wizard.json | 4 +- .../ebwizardry/advancements/apprentice.json | 99 +- .../advancements/arcane_initiate.json | 4 +- .../ebwizardry/advancements/armour_set.json | 24 +- .../ebwizardry/advancements/artefact.json | 713 +++++++ .../advancements/buy_master_spell.json | 6 +- .../advancements/charge_creeper.json | 19 - .../ebwizardry/advancements/craft_flask.json | 26 - .../ebwizardry/advancements/crystal.json | 10 +- .../advancements/defeat_evil_wizard.json | 6 +- .../advancements/discover_master_spell.json | 28 + .../advancements/discover_spell.json | 22 + .../advancements/element_master.json | 20 - .../ebwizardry/advancements/elemental.json | 19 - .../advancements/enchant_scroll.json | 24 + .../ebwizardry/advancements/frankenstein.json | 20 - .../ebwizardry/advancements/freeze_blaze.json | 19 - .../handbook/arcane_workbench.json | 14 + .../handbook/crystal_flowers.json | 14 + .../advancements/handbook/elements.json | 92 + .../handbook/magical_creatures.json | 242 +++ .../advancements/handbook/mana_flasks.json | 10 + .../advancements/handbook/obelisks.json | 10 + .../handbook/on_subsection_unlock.json | 7 + .../advancements/handbook/scrolls.json | 14 + .../advancements/handbook/spells.json | 14 + .../advancements/handbook/throwables.json | 14 + .../advancements/handbook/tome_of_arcana.json | 14 + .../advancements/identify_spell.json | 11 +- .../ebwizardry/advancements/jam_wizard.json | 19 - .../ebwizardry/advancements/legendary.json | 4 +- .../ebwizardry/advancements/master.json | 101 +- .../ebwizardry/advancements/max_out_wand.json | 6 +- .../ebwizardry/advancements/pig_tornado.json | 20 - .../assets/ebwizardry/advancements/root.json | 4 +- .../advancements/self_destruct.json | 20 - .../advancements/slime_skeleton.json | 19 - .../advancements/special_upgrade.json | 6 +- .../advancements/spell_failure.json | 19 + .../ebwizardry/advancements/visit_shrine.json | 23 + .../ebwizardry/advancements/wizard_tower.json | 22 + .../ebwizardry/advancements/wizard_trade.json | 6 +- .../ebwizardry/blockstates/crystal_block.json | 6 - .../blockstates/dry_frosted_ice.json | 8 + .../blockstates/earth_crystal_block.json | 6 + .../blockstates/earth_runestone.json | 31 + .../blockstates/earth_runestone_pedestal.json | 6 + .../blockstates/fire_crystal_block.json | 6 + .../blockstates/fire_runestone.json | 31 + .../blockstates/fire_runestone_pedestal.json | 6 + .../blockstates/healing_crystal_block.json | 6 + .../blockstates/healing_runestone.json | 31 + .../healing_runestone_pedestal.json | 6 + .../blockstates/ice_crystal_block.json | 6 + .../ebwizardry/blockstates/ice_runestone.json | 31 + .../blockstates/ice_runestone_pedestal.json | 6 + .../blockstates/lightning_crystal_block.json | 6 + .../blockstates/lightning_runestone.json | 31 + .../lightning_runestone_pedestal.json | 6 + .../blockstates/magic_crystal_block.json | 6 + .../blockstates/necromancy_crystal_block.json | 6 + .../blockstates/necromancy_runestone.json | 31 + .../necromancy_runestone_pedestal.json | 6 + .../blockstates/obsidian_crust.json | 8 + .../blockstates/sorcery_crystal_block.json | 6 + .../blockstates/sorcery_runestone.json | 31 + .../sorcery_runestone_pedestal.json | 6 + .../assets/ebwizardry/blockstates/thorns.json | 20 + .../assets/ebwizardry/lang/en_gb.lang | 1812 +++++++++++------ .../assets/ebwizardry/lang/en_us.lang | 1808 ++++++++++------ .../assets/ebwizardry/lang/es_es.lang | 118 +- .../assets/ebwizardry/lang/es_mx.lang | 118 +- .../assets/ebwizardry/lang/fr_fr.lang | 760 +++++++ .../assets/ebwizardry/lang/ko_kr.lang | 760 +++++++ .../assets/ebwizardry/lang/ru_ru.lang | 116 +- .../assets/ebwizardry/lang/zh_cn.lang | 116 +- .../loot_tables/chests/dungeon_additions.json | 75 +- .../chests/jungle_dispenser_additions.json | 65 + .../loot_tables/chests/obelisk.json | 195 ++ .../ebwizardry/loot_tables/chests/shrine.json | 210 ++ .../loot_tables/chests/wizard_tower.json | 19 +- .../loot_tables/entities/mob_additions.json | 8 +- .../subsets/elemental_crystals.json | 24 + .../loot_tables/subsets/epic_artefacts.json | 75 + .../loot_tables/subsets/novice_wands.json | 50 - .../loot_tables/subsets/rare_artefacts.json | 145 ++ .../subsets/uncommon_artefacts.json | 115 ++ .../loot_tables/subsets/wand_upgrades.json | 7 +- .../models/block/earth_crystal_block.json | 6 + .../models/block/earth_runestone_1.json | 8 + .../models/block/earth_runestone_2.json | 8 + .../models/block/earth_runestone_3.json | 8 + .../models/block/earth_runestone_4.json | 8 + .../block/earth_runestone_pedestal.json | 9 + .../models/block/fire_crystal_block.json | 6 + .../models/block/fire_runestone_1.json | 8 + .../models/block/fire_runestone_2.json | 8 + .../models/block/fire_runestone_3.json | 8 + .../models/block/fire_runestone_4.json | 8 + .../models/block/fire_runestone_pedestal.json | 9 + .../models/block/healing_crystal_block.json | 6 + .../models/block/healing_runestone_1.json | 8 + .../models/block/healing_runestone_2.json | 8 + .../models/block/healing_runestone_3.json | 8 + .../models/block/healing_runestone_4.json | 8 + .../block/healing_runestone_pedestal.json | 9 + .../models/block/ice_crystal_block.json | 6 + .../models/block/ice_runestone_1.json | 8 + .../models/block/ice_runestone_2.json | 8 + .../models/block/ice_runestone_3.json | 8 + .../models/block/ice_runestone_4.json | 8 + .../models/block/ice_runestone_pedestal.json | 9 + .../models/block/lightning_crystal_block.json | 6 + .../models/block/lightning_runestone_1.json | 8 + .../models/block/lightning_runestone_2.json | 8 + .../models/block/lightning_runestone_3.json | 8 + .../models/block/lightning_runestone_4.json | 8 + .../block/lightning_runestone_pedestal.json | 9 + ...al_block.json => magic_crystal_block.json} | 0 .../block/necromancy_crystal_block.json | 6 + .../models/block/necromancy_runestone_1.json | 8 + .../models/block/necromancy_runestone_2.json | 8 + .../models/block/necromancy_runestone_3.json | 8 + .../models/block/necromancy_runestone_4.json | 8 + .../block/necromancy_runestone_pedestal.json | 9 + .../models/block/obsidian_crust_0.json | 6 + .../models/block/obsidian_crust_1.json | 6 + .../models/block/obsidian_crust_2.json | 6 + .../models/block/obsidian_crust_3.json | 6 + .../ebwizardry/models/block/runestone.json | 27 + .../models/block/runestone_pedestal.json | 30 + .../models/block/sorcery_crystal_block.json | 6 + .../models/block/sorcery_runestone_1.json | 8 + .../models/block/sorcery_runestone_2.json | 8 + .../models/block/sorcery_runestone_3.json | 8 + .../models/block/sorcery_runestone_4.json | 8 + .../block/sorcery_runestone_pedestal.json | 9 + .../models/block/thorns_lower_0.json | 6 + .../models/block/thorns_lower_1.json | 6 + .../models/block/thorns_lower_2.json | 6 + .../models/block/thorns_lower_3.json | 6 + .../models/block/thorns_lower_4.json | 6 + .../models/block/thorns_lower_5.json | 6 + .../models/block/thorns_lower_6.json | 6 + .../models/block/thorns_lower_7.json | 6 + .../models/block/thorns_upper_0.json | 6 + .../models/block/thorns_upper_1.json | 6 + .../models/block/thorns_upper_2.json | 6 + .../models/block/thorns_upper_3.json | 6 + .../models/block/thorns_upper_4.json | 6 + .../models/block/thorns_upper_5.json | 6 + .../models/block/thorns_upper_6.json | 6 + .../models/block/thorns_upper_7.json | 6 + .../models/item/amulet_anchoring.json | 6 + .../models/item/amulet_arcane_defence.json | 6 + .../models/item/amulet_auto_shield.json | 6 + .../models/item/amulet_banishing.json | 6 + .../models/item/amulet_channeling.json | 6 + .../models/item/amulet_fire_cloaking.json | 6 + .../models/item/amulet_fire_protection.json | 6 + .../ebwizardry/models/item/amulet_glide.json | 6 + .../models/item/amulet_ice_immunity.json | 6 + .../models/item/amulet_ice_protection.json | 6 + .../ebwizardry/models/item/amulet_lich.json | 6 + .../models/item/amulet_potential.json | 6 + .../models/item/amulet_recovery.json | 6 + .../models/item/amulet_resurrection.json | 6 + .../models/item/amulet_transience.json | 6 + .../models/item/amulet_warding.json | 6 + .../ebwizardry/models/item/amulet_wisdom.json | 6 + .../models/item/amulet_wither_immunity.json | 6 + .../models/item/astral_diamond.json | 6 + .../models/item/basic_lightning_wand.json | 6 - .../models/item/basic_necromancy_wand.json | 6 - .../models/item/basic_sorcery_wand.json | 6 - .../models/item/charm_abseiling.json | 6 + .../models/item/charm_auto_smelt.json | 6 + .../models/item/charm_experience_tome.json | 6 + .../ebwizardry/models/item/charm_feeding.json | 6 + .../ebwizardry/models/item/charm_flight.json | 6 + .../ebwizardry/models/item/charm_growth.json | 6 + .../ebwizardry/models/item/charm_haggler.json | 6 + .../models/item/charm_lava_walking.json | 6 + .../ebwizardry/models/item/charm_light.json | 6 + .../models/item/charm_minion_health.json | 6 + .../models/item/charm_minion_variants.json | 6 + .../models/item/charm_silk_touch.json | 6 + .../models/item/charm_stop_time.json | 6 + .../ebwizardry/models/item/charm_storm.json | 6 + .../models/item/charm_transportation.json | 6 + .../ebwizardry/models/item/crystal_block.json | 3 - ...{magic_crystal.json => crystal_earth.json} | 2 +- .../ebwizardry/models/item/crystal_fire.json | 6 + .../models/item/crystal_healing.json | 6 + .../ebwizardry/models/item/crystal_ice.json | 6 + .../models/item/crystal_lightning.json | 6 + .../ebwizardry/models/item/crystal_magic.json | 6 + .../models/item/crystal_necromancy.json | 6 + .../ebwizardry/models/item/crystal_shard.json | 6 + .../models/item/crystal_sorcery.json | 6 + .../models/item/earth_crystal_block.json | 3 + .../models/item/earth_runestone.json | 8 + .../models/item/earth_runestone_pedestal.json | 9 + .../models/item/fire_crystal_block.json | 3 + .../models/item/fire_runestone.json | 8 + .../models/item/fire_runestone_pedestal.json | 9 + .../ebwizardry/models/item/flaming_axe.json | 59 +- .../models/item/flaming_axe_conjuring_0.json | 6 + .../models/item/flaming_axe_conjuring_1.json | 6 + .../models/item/flaming_axe_conjuring_2.json | 6 + .../models/item/flaming_axe_conjuring_3.json | 6 + .../models/item/flaming_axe_conjuring_4.json | 6 + .../models/item/flaming_axe_conjuring_5.json | 6 + .../models/item/flaming_axe_conjuring_6.json | 6 + .../models/item/flaming_axe_conjuring_7.json | 6 + .../ebwizardry/models/item/frost_axe.json | 59 +- .../models/item/frost_axe_conjuring_0.json | 6 + .../models/item/frost_axe_conjuring_1.json | 6 + .../models/item/frost_axe_conjuring_2.json | 6 + .../models/item/frost_axe_conjuring_3.json | 6 + .../models/item/frost_axe_conjuring_4.json | 6 + .../models/item/frost_axe_conjuring_5.json | 6 + .../models/item/frost_axe_conjuring_6.json | 6 + .../models/item/frost_axe_conjuring_7.json | 6 + .../ebwizardry/models/item/grand_crystal.json | 6 + .../models/item/healing_crystal_block.json | 3 + .../models/item/healing_runestone.json | 8 + .../item/healing_runestone_pedestal.json | 9 + .../models/item/ice_crystal_block.json | 3 + .../ebwizardry/models/item/ice_runestone.json | 8 + .../models/item/ice_runestone_pedestal.json | 9 + .../models/item/large_mana_flask.json | 6 + .../models/item/lightning_crystal_block.json | 3 + .../models/item/lightning_hammer.json | 122 ++ .../models/item/lightning_runestone.json | 8 + .../item/lightning_runestone_pedestal.json | 9 + .../models/item/magic_crystal_block.json | 3 + .../ebwizardry/models/item/magic_wand.json | 2 +- .../models/item/medium_mana_flask.json | 6 + .../ebwizardry/models/item/melee_upgrade.json | 6 + .../models/item/necromancy_crystal_block.json | 3 + .../models/item/necromancy_runestone.json | 8 + .../item/necromancy_runestone_pedestal.json | 9 + ..._fire_wand.json => novice_earth_wand.json} | 2 +- ..._earth_wand.json => novice_fire_wand.json} | 2 +- ...ing_wand.json => novice_healing_wand.json} | 2 +- ...sic_ice_wand.json => novice_ice_wand.json} | 2 +- .../models/item/novice_lightning_wand.json | 6 + .../models/item/novice_necromancy_wand.json | 6 + .../models/item/novice_sorcery_wand.json | 6 + .../models/item/purifying_elixir.json | 6 + .../models/item/ring_arcane_frost.json | 6 + .../models/item/ring_battlemage.json | 6 + .../models/item/ring_blockwrangler.json | 6 + .../models/item/ring_combustion.json | 6 + .../models/item/ring_condensing.json | 6 + .../ebwizardry/models/item/ring_conjurer.json | 6 + .../ebwizardry/models/item/ring_defender.json | 6 + .../models/item/ring_disintegration.json | 6 + .../models/item/ring_earth_biome.json | 6 + .../models/item/ring_earth_melee.json | 6 + .../models/item/ring_extraction.json | 6 + .../models/item/ring_fire_biome.json | 6 + .../models/item/ring_fire_melee.json | 6 + .../models/item/ring_full_moon.json | 6 + .../ebwizardry/models/item/ring_hammer.json | 6 + .../models/item/ring_ice_biome.json | 6 + .../models/item/ring_ice_melee.json | 6 + .../models/item/ring_interdiction.json | 6 + .../ebwizardry/models/item/ring_leeching.json | 6 + .../models/item/ring_lightning_melee.json | 6 + .../models/item/ring_mana_return.json | 6 + .../models/item/ring_mind_control.json | 6 + .../models/item/ring_necromancy_melee.json | 6 + .../ebwizardry/models/item/ring_paladin.json | 6 + .../ebwizardry/models/item/ring_poison.json | 6 + .../ebwizardry/models/item/ring_seeking.json | 6 + .../models/item/ring_shattering.json | 6 + .../models/item/ring_siphoning.json | 6 + .../models/item/ring_soulbinding.json | 6 + .../models/item/ring_spirit_animal.json | 6 + .../ebwizardry/models/item/ring_storm.json | 6 + .../models/item/runestone_item.json | 28 + .../models/item/runestone_pedestal_item.json | 31 + .../models/item/small_mana_flask.json | 6 + .../models/item/sorcery_crystal_block.json | 3 + .../models/item/sorcery_runestone.json | 8 + .../item/sorcery_runestone_pedestal.json | 9 + .../item/{mana_flask.json => spark_bomb.json} | 2 +- .../ebwizardry/models/item/spectral_bow.json | 55 + .../models/item/spectral_bow_conjuring_0.json | 6 + .../models/item/spectral_bow_conjuring_1.json | 6 + .../models/item/spectral_bow_conjuring_2.json | 6 + .../models/item/spectral_bow_conjuring_3.json | 6 + .../models/item/spectral_bow_conjuring_4.json | 6 + .../models/item/spectral_bow_conjuring_5.json | 6 + .../models/item/spectral_bow_conjuring_6.json | 6 + .../models/item/spectral_bow_conjuring_7.json | 6 + .../models/item/spectral_pickaxe.json | 59 +- .../item/spectral_pickaxe_conjuring_0.json | 6 + .../item/spectral_pickaxe_conjuring_1.json | 6 + .../item/spectral_pickaxe_conjuring_2.json | 6 + .../item/spectral_pickaxe_conjuring_3.json | 6 + .../item/spectral_pickaxe_conjuring_4.json | 6 + .../item/spectral_pickaxe_conjuring_5.json | 6 + .../item/spectral_pickaxe_conjuring_6.json | 6 + .../item/spectral_pickaxe_conjuring_7.json | 6 + .../models/item/spectral_sword.json | 59 +- .../item/spectral_sword_conjuring_0.json | 6 + .../item/spectral_sword_conjuring_1.json | 6 + .../item/spectral_sword_conjuring_2.json | 6 + .../item/spectral_sword_conjuring_3.json | 6 + .../item/spectral_sword_conjuring_4.json | 6 + .../item/spectral_sword_conjuring_5.json | 6 + .../item/spectral_sword_conjuring_6.json | 6 + .../item/spectral_sword_conjuring_7.json | 6 + .../assets/ebwizardry/models/item/thorns.json | 6 + .../ebwizardry/recipes/arcane_workbench.json | 37 +- .../ebwizardry/recipes/crystal_block.json | 6 +- .../recipes/crystal_block_earth.json | 18 + .../recipes/crystal_block_fire.json | 18 + .../recipes/crystal_block_healing.json | 18 + .../ebwizardry/recipes/crystal_block_ice.json | 18 + .../recipes/crystal_block_lightning.json | 18 + .../recipes/crystal_block_necromancy.json | 18 + .../recipes/crystal_block_sorcery.json | 18 + .../recipes/crystal_block_to_crystals.json | 4 +- .../crystal_block_to_crystals_earth.json | 15 + .../crystal_block_to_crystals_fire.json | 15 + .../crystal_block_to_crystals_healing.json | 15 + .../crystal_block_to_crystals_ice.json | 15 + .../crystal_block_to_crystals_lightning.json | 15 + .../crystal_block_to_crystals_necromancy.json | 15 + .../crystal_block_to_crystals_sorcery.json | 15 + .../recipes/crystal_flower_to_crystals.json | 1 + .../ebwizardry/recipes/crystal_shard.json | 13 + .../ebwizardry/recipes/large_mana_flask.json | 19 + .../recipes/magic_missile_spell_book.json | 3 +- .../assets/ebwizardry/recipes/magic_silk.json | 37 +- .../assets/ebwizardry/recipes/magic_wand.json | 3 +- .../ebwizardry/recipes/medium_mana_flask.json | 50 + .../ebwizardry/recipes/runestone_earth.json | 23 + .../ebwizardry/recipes/runestone_fire.json | 23 + .../ebwizardry/recipes/runestone_healing.json | 23 + .../ebwizardry/recipes/runestone_ice.json | 23 + .../recipes/runestone_lightning.json | 23 + .../recipes/runestone_necromancy.json | 23 + .../recipes/runestone_pedestal_earth.json | 23 + .../recipes/runestone_pedestal_fire.json | 23 + .../recipes/runestone_pedestal_healing.json | 23 + .../recipes/runestone_pedestal_ice.json | 23 + .../recipes/runestone_pedestal_lightning.json | 23 + .../runestone_pedestal_necromancy.json | 23 + .../recipes/runestone_pedestal_sorcery.json | 23 + .../ebwizardry/recipes/runestone_sorcery.json | 23 + ...{mana_flask.json => small_mana_flask.json} | 6 +- .../assets/ebwizardry/recipes/spark_bomb.json | 23 + .../recipes/transportation_stone.json | 37 +- .../assets/ebwizardry/recipes/wand_earth.json | 25 + .../assets/ebwizardry/recipes/wand_fire.json | 25 + .../ebwizardry/recipes/wand_healing.json | 25 + .../assets/ebwizardry/recipes/wand_ice.json | 25 + .../ebwizardry/recipes/wand_lightning.json | 25 + .../ebwizardry/recipes/wand_necromancy.json | 25 + .../ebwizardry/recipes/wand_sorcery.json | 25 + .../ebwizardry/recipes/wizard_handbook.json | 37 +- .../ebwizardry/shaders/post/possession.json | 73 + .../ebwizardry/shaders/post/sixth_sense.json | 67 + .../ebwizardry/shaders/post/slow_time.json | 37 + .../ebwizardry/shaders/post/transience.json | 67 + .../resources/assets/ebwizardry/sounds.json | 390 +++- .../assets/ebwizardry/sounds/aura_end.ogg | Bin 0 -> 51608 bytes .../assets/ebwizardry/sounds/aura_loop.ogg | Bin 0 -> 216380 bytes .../assets/ebwizardry/sounds/aura_start.ogg | Bin 0 -> 18824 bytes .../assets/ebwizardry/sounds/book.ogg | Bin 0 -> 21349 bytes .../assets/ebwizardry/sounds/boom.ogg | Bin 38721 -> 0 bytes .../assets/ebwizardry/sounds/buff.ogg | Bin 0 -> 28647 bytes .../sounds/{aura.ogg => conjure.ogg} | Bin .../{largeaura.ogg => conjure_large.ogg} | Bin .../ebwizardry/sounds/dark_aura_end.ogg | Bin 0 -> 63140 bytes .../ebwizardry/sounds/dark_aura_loop.ogg | Bin 0 -> 59784 bytes .../ebwizardry/sounds/dark_aura_start.ogg | Bin 0 -> 30358 bytes .../assets/ebwizardry/sounds/firebolt.ogg | Bin 0 -> 70607 bytes .../assets/ebwizardry/sounds/flameray1.ogg | Bin 23817 -> 0 bytes .../assets/ebwizardry/sounds/flameray2.ogg | Bin 31282 -> 0 bytes .../assets/ebwizardry/sounds/flames_end.ogg | Bin 0 -> 37073 bytes .../assets/ebwizardry/sounds/flames_loop.ogg | Bin 0 -> 285773 bytes .../assets/ebwizardry/sounds/flames_start.ogg | Bin 0 -> 30379 bytes .../assets/ebwizardry/sounds/grow.ogg | Bin 0 -> 47592 bytes ...electricityb.ogg => lightning_ray_end.ogg} | Bin .../ebwizardry/sounds/lightning_ray_loop.ogg | Bin 0 -> 43032 bytes ...ectricitya.ogg => lightning_ray_start.ogg} | Bin .../assets/ebwizardry/sounds/page1.ogg | Bin 0 -> 11164 bytes .../assets/ebwizardry/sounds/page2.ogg | Bin 0 -> 14045 bytes .../assets/ebwizardry/sounds/page3.ogg | Bin 0 -> 17081 bytes .../assets/ebwizardry/sounds/pull1.ogg | Bin 0 -> 29901 bytes .../assets/ebwizardry/sounds/pull2.ogg | Bin 0 -> 31418 bytes .../assets/ebwizardry/sounds/shockwave.ogg | Bin 0 -> 44395 bytes .../ebwizardry/sounds/small_aura_end.ogg | Bin 0 -> 59448 bytes .../ebwizardry/sounds/small_aura_loop.ogg | Bin 0 -> 209049 bytes .../ebwizardry/sounds/small_aura_start.ogg | Bin 0 -> 87860 bytes .../assets/ebwizardry/sounds/spellbind.ogg | Bin 0 -> 78949 bytes .../sounds/{darkaura1.ogg => summon1.ogg} | Bin .../sounds/{darkaura2.ogg => summon2.ogg} | Bin .../assets/ebwizardry/spells/agility.json | 25 + .../assets/ebwizardry/spells/arc.json | 23 + .../ebwizardry/spells/arcane_jammer.json | 23 + .../assets/ebwizardry/spells/arcane_lock.json | 22 + .../assets/ebwizardry/spells/arrow_rain.json | 23 + .../assets/ebwizardry/spells/banish.json | 24 + .../assets/ebwizardry/spells/black_hole.json | 23 + .../assets/ebwizardry/spells/blink.json | 22 + .../assets/ebwizardry/spells/blizzard.json | 24 + .../assets/ebwizardry/spells/bubble.json | 23 + .../ebwizardry/spells/chain_lightning.json | 29 + .../assets/ebwizardry/spells/charge.json | 25 + .../ebwizardry/spells/clairvoyance.json | 23 + .../assets/ebwizardry/spells/cobwebs.json | 24 + .../ebwizardry/spells/combustion_rune.json | 23 + .../ebwizardry/spells/conjure_armour.json | 22 + .../ebwizardry/spells/conjure_block.json | 23 + .../assets/ebwizardry/spells/conjure_bow.json | 22 + .../ebwizardry/spells/conjure_pickaxe.json | 22 + .../ebwizardry/spells/conjure_sword.json | 22 + .../assets/ebwizardry/spells/containment.json | 24 + .../ebwizardry/spells/cure_effects.json | 20 + .../spells/curse_of_enfeeblement.json | 23 + .../spells/curse_of_soulbinding.json | 22 + .../ebwizardry/spells/curse_of_undeath.json | 23 + .../ebwizardry/spells/darkness_orb.json | 25 + .../assets/ebwizardry/spells/darkvision.json | 23 + .../assets/ebwizardry/spells/dart.json | 25 + .../assets/ebwizardry/spells/decay.json | 25 + .../assets/ebwizardry/spells/decoy.json | 23 + .../assets/ebwizardry/spells/detonate.json | 24 + .../ebwizardry/spells/diamondflesh.json | 23 + .../ebwizardry/spells/disintegration.json | 26 + .../assets/ebwizardry/spells/divination.json | 22 + .../ebwizardry/spells/dragon_fireball.json | 22 + .../assets/ebwizardry/spells/earthquake.json | 23 + .../spells/empowering_presence.json | 24 + .../assets/ebwizardry/spells/entrapment.json | 24 + .../assets/ebwizardry/spells/evade.json | 22 + .../assets/ebwizardry/spells/fire_breath.json | 24 + .../ebwizardry/spells/fire_resistance.json | 23 + .../assets/ebwizardry/spells/fire_sigil.json | 24 + .../assets/ebwizardry/spells/fireball.json | 24 + .../assets/ebwizardry/spells/firebolt.json | 24 + .../assets/ebwizardry/spells/firebomb.json | 26 + .../assets/ebwizardry/spells/fireskin.json | 24 + .../assets/ebwizardry/spells/flame_ray.json | 24 + .../assets/ebwizardry/spells/flaming_axe.json | 24 + .../ebwizardry/spells/flaming_weapon.json | 22 + .../assets/ebwizardry/spells/flight.json | 23 + .../ebwizardry/spells/font_of_mana.json | 24 + .../ebwizardry/spells/font_of_vitality.json | 25 + .../assets/ebwizardry/spells/force_arrow.json | 23 + .../assets/ebwizardry/spells/force_orb.json | 24 + .../assets/ebwizardry/spells/forcefield.json | 23 + .../ebwizardry/spells/forest_of_thorns.json | 24 + .../ebwizardry/spells/forests_curse.json | 25 + .../assets/ebwizardry/spells/freeze.json | 25 + .../ebwizardry/spells/freezing_weapon.json | 22 + .../assets/ebwizardry/spells/frost_axe.json | 22 + .../assets/ebwizardry/spells/frost_ray.json | 25 + .../assets/ebwizardry/spells/frost_sigil.json | 25 + .../assets/ebwizardry/spells/frost_step.json | 23 + .../assets/ebwizardry/spells/glide.json | 24 + .../assets/ebwizardry/spells/grapple.json | 24 + .../ebwizardry/spells/greater_fireball.json | 24 + .../ebwizardry/spells/greater_heal.json | 22 + .../spells/greater_telekinesis.json | 25 + .../ebwizardry/spells/greater_ward.json | 23 + .../assets/ebwizardry/spells/group_heal.json | 23 + .../assets/ebwizardry/spells/growth_aura.json | 22 + .../assets/ebwizardry/spells/hailstorm.json | 23 + .../assets/ebwizardry/spells/heal.json | 22 + .../assets/ebwizardry/spells/heal_ally.json | 23 + .../ebwizardry/spells/healing_aura.json | 24 + .../ebwizardry/spells/homing_spark.json | 24 + .../assets/ebwizardry/spells/ice_age.json | 23 + .../assets/ebwizardry/spells/ice_charge.json | 29 + .../assets/ebwizardry/spells/ice_lance.json | 25 + .../assets/ebwizardry/spells/ice_shard.json | 25 + .../assets/ebwizardry/spells/ice_shroud.json | 25 + .../assets/ebwizardry/spells/ice_spikes.json | 27 + .../assets/ebwizardry/spells/ice_statue.json | 23 + .../assets/ebwizardry/spells/iceball.json | 25 + .../assets/ebwizardry/spells/ignite.json | 23 + .../ebwizardry/spells/imbue_weapon.json | 22 + .../assets/ebwizardry/spells/intimidate.json | 24 + .../spells/invigorating_presence.json | 24 + .../ebwizardry/spells/invisibility.json | 23 + .../ebwizardry/spells/invoke_weather.json | 22 + .../assets/ebwizardry/spells/ironflesh.json | 23 + .../assets/ebwizardry/spells/leap.json | 23 + .../assets/ebwizardry/spells/levitation.json | 23 + .../assets/ebwizardry/spells/life_drain.json | 24 + .../assets/ebwizardry/spells/light.json | 23 + .../ebwizardry/spells/lightning_arrow.json | 23 + .../ebwizardry/spells/lightning_bolt.json | 22 + .../ebwizardry/spells/lightning_disc.json | 24 + .../ebwizardry/spells/lightning_hammer.json | 28 + .../ebwizardry/spells/lightning_pulse.json | 24 + .../ebwizardry/spells/lightning_ray.json | 23 + .../ebwizardry/spells/lightning_sigil.json | 26 + .../ebwizardry/spells/lightning_web.json | 29 + .../ebwizardry/spells/magic_missile.json | 23 + .../ebwizardry/spells/metamorphosis.json | 22 + .../assets/ebwizardry/spells/meteor.json | 23 + .../ebwizardry/spells/mind_control.json | 23 + .../assets/ebwizardry/spells/mind_trick.json | 23 + .../assets/ebwizardry/spells/mine.json | 22 + .../assets/ebwizardry/spells/muffle.json | 23 + .../assets/ebwizardry/spells/none.json | 20 + .../assets/ebwizardry/spells/oakflesh.json | 23 + .../assets/ebwizardry/spells/paralysis.json | 25 + .../assets/ebwizardry/spells/petrify.json | 23 + .../assets/ebwizardry/spells/phase_step.json | 23 + .../ebwizardry/spells/plague_of_darkness.json | 25 + .../ebwizardry/spells/pocket_furnace.json | 22 + .../ebwizardry/spells/pocket_workbench.json | 20 + .../assets/ebwizardry/spells/poison.json | 25 + .../assets/ebwizardry/spells/poison_bomb.json | 29 + .../assets/ebwizardry/spells/possession.json | 24 + .../spells/ray_of_purification.json | 26 + .../ebwizardry/spells/remove_curse.json | 20 + .../ebwizardry/spells/replenish_hunger.json | 23 + .../ebwizardry/spells/resurrection.json | 23 + .../assets/ebwizardry/spells/reversal.json | 23 + .../ebwizardry/spells/ring_of_fire.json | 24 + .../assets/ebwizardry/spells/satiety.json | 23 + .../assets/ebwizardry/spells/shadow_ward.json | 22 + .../assets/ebwizardry/spells/shield.json | 22 + .../assets/ebwizardry/spells/shockwave.json | 24 + .../ebwizardry/spells/shulker_bullet.json | 22 + .../ebwizardry/spells/silverfish_swarm.json | 24 + .../assets/ebwizardry/spells/sixth_sense.json | 23 + .../assets/ebwizardry/spells/slime.json | 23 + .../assets/ebwizardry/spells/slow_time.json | 24 + .../assets/ebwizardry/spells/smoke_bomb.json | 24 + .../assets/ebwizardry/spells/snare.json | 25 + .../assets/ebwizardry/spells/snowball.json | 22 + .../assets/ebwizardry/spells/spark_bomb.json | 26 + .../ebwizardry/spells/spectral_pathway.json | 23 + .../assets/ebwizardry/spells/speed_time.json | 24 + .../ebwizardry/spells/spider_swarm.json | 24 + .../assets/ebwizardry/spells/static_aura.json | 24 + .../ebwizardry/spells/summon_blaze.json | 24 + .../ebwizardry/spells/summon_ice_giant.json | 24 + .../ebwizardry/spells/summon_ice_wraith.json | 24 + .../ebwizardry/spells/summon_iron_golem.json | 22 + .../spells/summon_lightning_wraith.json | 24 + .../ebwizardry/spells/summon_phoenix.json | 24 + .../spells/summon_shadow_wraith.json | 24 + .../ebwizardry/spells/summon_skeleton.json | 24 + .../spells/summon_skeleton_legion.json | 24 + .../ebwizardry/spells/summon_snow_golem.json | 22 + .../spells/summon_spirit_horse.json | 22 + .../ebwizardry/spells/summon_spirit_wolf.json | 22 + .../spells/summon_storm_elemental.json | 24 + .../spells/summon_wither_skeleton.json | 24 + .../ebwizardry/spells/summon_zombie.json | 24 + .../assets/ebwizardry/spells/telekinesis.json | 22 + .../assets/ebwizardry/spells/thunderbolt.json | 24 + .../ebwizardry/spells/thunderstorm.json | 29 + .../assets/ebwizardry/spells/tornado.json | 26 + .../assets/ebwizardry/spells/transience.json | 22 + .../ebwizardry/spells/transportation.json | 22 + .../ebwizardry/spells/vanishing_box.json | 20 + .../assets/ebwizardry/spells/vex_swarm.json | 24 + .../ebwizardry/spells/wall_of_frost.json | 23 + .../assets/ebwizardry/spells/ward.json | 23 + .../ebwizardry/spells/water_breathing.json | 23 + .../assets/ebwizardry/spells/whirlwind.json | 23 + .../assets/ebwizardry/spells/wither.json | 25 + .../ebwizardry/spells/wither_skull.json | 22 + .../ebwizardry/structures/obelisk_0.nbt | Bin 0 -> 578 bytes .../ebwizardry/structures/obelisk_1.nbt | Bin 0 -> 615 bytes .../ebwizardry/structures/obelisk_2.nbt | Bin 0 -> 601 bytes .../ebwizardry/structures/obelisk_3.nbt | Bin 0 -> 609 bytes .../ebwizardry/structures/obelisk_4.nbt | Bin 0 -> 660 bytes .../assets/ebwizardry/structures/shrine_0.nbt | Bin 0 -> 742 bytes .../assets/ebwizardry/structures/shrine_1.nbt | Bin 0 -> 743 bytes .../assets/ebwizardry/structures/shrine_2.nbt | Bin 0 -> 744 bytes .../assets/ebwizardry/structures/shrine_3.nbt | Bin 0 -> 748 bytes .../assets/ebwizardry/structures/shrine_4.nbt | Bin 0 -> 741 bytes .../assets/ebwizardry/structures/shrine_5.nbt | Bin 0 -> 743 bytes .../assets/ebwizardry/structures/shrine_6.nbt | Bin 0 -> 745 bytes .../assets/ebwizardry/structures/shrine_7.nbt | Bin 0 -> 754 bytes .../ebwizardry/structures/wizard_tower_0.nbt | Bin 0 -> 2188 bytes .../ebwizardry/structures/wizard_tower_1.nbt | Bin 0 -> 2341 bytes .../ebwizardry/structures/wizard_tower_2.nbt | Bin 0 -> 2422 bytes .../ebwizardry/structures/wizard_tower_3.nbt | Bin 0 -> 1927 bytes .../structures/wizard_tower_chest_0.nbt | Bin 0 -> 2249 bytes .../structures/wizard_tower_chest_1.nbt | Bin 0 -> 2396 bytes .../structures/wizard_tower_chest_2.nbt | Bin 0 -> 2480 bytes .../structures/wizard_tower_chest_3.nbt | Bin 0 -> 1986 bytes .../ebwizardry/texts/handbook_en_gb.json | 396 +++- .../ebwizardry/texts/handbook_en_gb.txt | 225 -- .../ebwizardry/texts/handbook_en_us.json | 394 +++- .../ebwizardry/texts/handbook_en_us.txt | 225 -- .../ebwizardry/texts/handbook_es_es.txt | 2 +- .../ebwizardry/texts/handbook_es_mx.txt | 2 +- .../ebwizardry/texts/handbook_ko_kr.txt | 239 +++ .../textures/armour/invisible_armour.png | Bin 2411 -> 0 bytes .../armour/legendary_wizard_armour.png | Bin 0 -> 12450 bytes .../armour/legendary_wizard_armour_earth.png | Bin 0 -> 13287 bytes .../legendary_wizard_armour_earth_legs.png | Bin 0 -> 1726 bytes .../armour/legendary_wizard_armour_fire.png | Bin 0 -> 13116 bytes .../legendary_wizard_armour_fire_legs.png | Bin 0 -> 1703 bytes .../legendary_wizard_armour_healing.png | Bin 0 -> 14008 bytes .../legendary_wizard_armour_healing_legs.png | Bin 0 -> 2067 bytes .../armour/legendary_wizard_armour_ice.png | Bin 0 -> 14111 bytes .../legendary_wizard_armour_ice_legs.png | Bin 0 -> 1999 bytes .../armour/legendary_wizard_armour_legs.png | Bin 0 -> 1693 bytes .../legendary_wizard_armour_lightning.png | Bin 0 -> 12621 bytes ...legendary_wizard_armour_lightning_legs.png | Bin 0 -> 1749 bytes .../legendary_wizard_armour_necromancy.png | Bin 0 -> 12490 bytes ...egendary_wizard_armour_necromancy_legs.png | Bin 0 -> 1926 bytes .../legendary_wizard_armour_sorcery.png | Bin 0 -> 13352 bytes .../legendary_wizard_armour_sorcery_legs.png | Bin 0 -> 1874 bytes .../textures/armour/wizard_armour.png | Bin 2566 -> 11798 bytes .../textures/armour/wizard_armour_earth.png | Bin 2803 -> 11486 bytes .../armour/wizard_armour_earth_legs.png | Bin 425 -> 1851 bytes .../textures/armour/wizard_armour_fire.png | Bin 2807 -> 12095 bytes .../textures/armour/wizard_armour_healing.png | Bin 2797 -> 12777 bytes .../textures/armour/wizard_armour_ice.png | Bin 2781 -> 12968 bytes .../armour/wizard_armour_ice_legs.png | Bin 417 -> 1941 bytes .../armour/wizard_armour_lightning.png | Bin 2787 -> 11578 bytes .../armour/wizard_armour_necromancy.png | Bin 2800 -> 11032 bytes .../textures/armour/wizard_armour_sorcery.png | Bin 2792 -> 11818 bytes .../blocks/arcane_workbench_bottom.png | Bin 741 -> 1391 bytes .../textures/blocks/arcane_workbench_side.png | Bin 695 -> 2183 bytes .../textures/blocks/arcane_workbench_top.png | Bin 658 -> 2338 bytes .../textures/blocks/crystal_block_earth.png | Bin 0 -> 2864 bytes .../textures/blocks/crystal_block_fire.png | Bin 0 -> 704 bytes .../textures/blocks/crystal_block_healing.png | Bin 0 -> 740 bytes .../textures/blocks/crystal_block_ice.png | Bin 0 -> 876 bytes .../blocks/crystal_block_lightning.png | Bin 0 -> 858 bytes .../blocks/crystal_block_necromancy.png | Bin 0 -> 858 bytes .../textures/blocks/crystal_block_sorcery.png | Bin 0 -> 806 bytes .../textures/blocks/obsidian_crust_0.png | Bin 0 -> 884 bytes .../textures/blocks/obsidian_crust_1.png | Bin 0 -> 918 bytes .../textures/blocks/obsidian_crust_2.png | Bin 0 -> 949 bytes .../textures/blocks/obsidian_crust_3.png | Bin 0 -> 973 bytes .../textures/blocks/runestone_earth_0.png | Bin 0 -> 627 bytes .../textures/blocks/runestone_earth_1.png | Bin 0 -> 742 bytes .../blocks/runestone_earth_1_overlay.png | Bin 0 -> 749 bytes .../textures/blocks/runestone_earth_2.png | Bin 0 -> 732 bytes .../blocks/runestone_earth_2_overlay.png | Bin 0 -> 734 bytes .../textures/blocks/runestone_earth_3.png | Bin 0 -> 727 bytes .../blocks/runestone_earth_3_overlay.png | Bin 0 -> 730 bytes .../textures/blocks/runestone_earth_4.png | Bin 0 -> 733 bytes .../blocks/runestone_earth_4_overlay.png | Bin 0 -> 739 bytes .../textures/blocks/runestone_fire_0.png | Bin 0 -> 626 bytes .../textures/blocks/runestone_fire_1.png | Bin 0 -> 712 bytes .../blocks/runestone_fire_1_overlay.png | Bin 0 -> 713 bytes .../textures/blocks/runestone_fire_2.png | Bin 0 -> 738 bytes .../blocks/runestone_fire_2_overlay.png | Bin 0 -> 743 bytes .../textures/blocks/runestone_fire_3.png | Bin 0 -> 712 bytes .../blocks/runestone_fire_3_overlay.png | Bin 0 -> 714 bytes .../textures/blocks/runestone_fire_4.png | Bin 0 -> 717 bytes .../blocks/runestone_fire_4_overlay.png | Bin 0 -> 715 bytes .../textures/blocks/runestone_healing_0.png | Bin 0 -> 661 bytes .../textures/blocks/runestone_healing_1.png | Bin 0 -> 838 bytes .../blocks/runestone_healing_1_overlay.png | Bin 0 -> 841 bytes .../textures/blocks/runestone_healing_2.png | Bin 0 -> 813 bytes .../blocks/runestone_healing_2_overlay.png | Bin 0 -> 815 bytes .../textures/blocks/runestone_healing_3.png | Bin 0 -> 724 bytes .../blocks/runestone_healing_3_overlay.png | Bin 0 -> 724 bytes .../textures/blocks/runestone_healing_4.png | Bin 0 -> 813 bytes .../blocks/runestone_healing_4_overlay.png | Bin 0 -> 821 bytes .../textures/blocks/runestone_ice_0.png | Bin 0 -> 746 bytes .../textures/blocks/runestone_ice_1.png | Bin 0 -> 860 bytes .../blocks/runestone_ice_1_overlay.png | Bin 0 -> 869 bytes .../textures/blocks/runestone_ice_2.png | Bin 0 -> 829 bytes .../blocks/runestone_ice_2_overlay.png | Bin 0 -> 833 bytes .../textures/blocks/runestone_ice_3.png | Bin 0 -> 839 bytes .../blocks/runestone_ice_3_overlay.png | Bin 0 -> 843 bytes .../textures/blocks/runestone_ice_4.png | Bin 0 -> 862 bytes .../blocks/runestone_ice_4_overlay.png | Bin 0 -> 871 bytes .../textures/blocks/runestone_lightning_0.png | Bin 0 -> 629 bytes .../textures/blocks/runestone_lightning_1.png | Bin 0 -> 747 bytes .../blocks/runestone_lightning_1_overlay.png | Bin 0 -> 751 bytes .../textures/blocks/runestone_lightning_2.png | Bin 0 -> 735 bytes .../blocks/runestone_lightning_2_overlay.png | Bin 0 -> 742 bytes .../textures/blocks/runestone_lightning_3.png | Bin 0 -> 738 bytes .../blocks/runestone_lightning_3_overlay.png | Bin 0 -> 745 bytes .../textures/blocks/runestone_lightning_4.png | Bin 0 -> 773 bytes .../blocks/runestone_lightning_4_overlay.png | Bin 0 -> 783 bytes .../blocks/runestone_necromancy_0.png | Bin 0 -> 571 bytes .../blocks/runestone_necromancy_1.png | Bin 0 -> 703 bytes .../blocks/runestone_necromancy_1_overlay.png | Bin 0 -> 705 bytes .../blocks/runestone_necromancy_2.png | Bin 0 -> 714 bytes .../blocks/runestone_necromancy_2_overlay.png | Bin 0 -> 717 bytes .../blocks/runestone_necromancy_3.png | Bin 0 -> 685 bytes .../blocks/runestone_necromancy_3_overlay.png | Bin 0 -> 685 bytes .../blocks/runestone_necromancy_4.png | Bin 0 -> 723 bytes .../blocks/runestone_necromancy_4_overlay.png | Bin 0 -> 727 bytes .../blocks/runestone_pedestal_earth.png | Bin 0 -> 737 bytes .../runestone_pedestal_earth_overlay.png | Bin 0 -> 6570 bytes .../blocks/runestone_pedestal_fire.png | Bin 0 -> 702 bytes .../runestone_pedestal_fire_overlay.png | Bin 0 -> 6467 bytes .../blocks/runestone_pedestal_healing.png | Bin 0 -> 769 bytes .../runestone_pedestal_healing_overlay.png | Bin 0 -> 6610 bytes .../blocks/runestone_pedestal_ice.png | Bin 0 -> 785 bytes .../blocks/runestone_pedestal_ice_overlay.png | Bin 0 -> 6510 bytes .../blocks/runestone_pedestal_lightning.png | Bin 0 -> 712 bytes .../runestone_pedestal_lightning_overlay.png | Bin 0 -> 6497 bytes .../blocks/runestone_pedestal_necromancy.png | Bin 0 -> 713 bytes .../runestone_pedestal_necromancy_overlay.png | Bin 0 -> 6436 bytes .../blocks/runestone_pedestal_sorcery.png | Bin 0 -> 709 bytes .../runestone_pedestal_sorcery_overlay.png | Bin 0 -> 6273 bytes .../textures/blocks/runestone_sorcery_0.png | Bin 0 -> 521 bytes .../textures/blocks/runestone_sorcery_1.png | Bin 0 -> 636 bytes .../blocks/runestone_sorcery_1_overlay.png | Bin 0 -> 644 bytes .../textures/blocks/runestone_sorcery_2.png | Bin 0 -> 679 bytes .../blocks/runestone_sorcery_2_overlay.png | Bin 0 -> 678 bytes .../textures/blocks/runestone_sorcery_3.png | Bin 0 -> 619 bytes .../blocks/runestone_sorcery_3_overlay.png | Bin 0 -> 621 bytes .../textures/blocks/runestone_sorcery_4.png | Bin 0 -> 649 bytes .../blocks/runestone_sorcery_4_overlay.png | Bin 0 -> 653 bytes .../textures/blocks/thorns_lower_0.png | Bin 0 -> 368 bytes .../textures/blocks/thorns_lower_1.png | Bin 0 -> 506 bytes .../textures/blocks/thorns_lower_2.png | Bin 0 -> 718 bytes .../textures/blocks/thorns_lower_3.png | Bin 0 -> 903 bytes .../textures/blocks/thorns_lower_4.png | Bin 0 -> 947 bytes .../textures/blocks/thorns_lower_5.png | Bin 0 -> 968 bytes .../textures/blocks/thorns_lower_6.png | Bin 0 -> 987 bytes .../textures/blocks/thorns_lower_7.png | Bin 0 -> 995 bytes .../textures/blocks/thorns_upper_0.png | Bin 0 -> 170 bytes .../textures/blocks/thorns_upper_1.png | Bin 0 -> 170 bytes .../textures/blocks/thorns_upper_2.png | Bin 0 -> 170 bytes .../textures/blocks/thorns_upper_3.png | Bin 0 -> 210 bytes .../textures/blocks/thorns_upper_4.png | Bin 0 -> 343 bytes .../textures/blocks/thorns_upper_5.png | Bin 0 -> 580 bytes .../textures/blocks/thorns_upper_6.png | Bin 0 -> 699 bytes .../textures/blocks/thorns_upper_7.png | Bin 0 -> 804 bytes .../textures/entity/arcane_lock_0.png | Bin 0 -> 1860 bytes .../textures/entity/arcane_lock_1.png | Bin 0 -> 1876 bytes .../textures/entity/arcane_lock_2.png | Bin 0 -> 1890 bytes .../textures/entity/arcane_lock_3.png | Bin 0 -> 1879 bytes .../textures/entity/arcane_lock_4.png | Bin 0 -> 1844 bytes .../textures/entity/arcane_lock_5.png | Bin 0 -> 1878 bytes .../textures/entity/arcane_lock_6.png | Bin 0 -> 1889 bytes .../textures/entity/arcane_lock_7.png | Bin 0 -> 1836 bytes .../textures/entity/combustion_rune.png | Bin 0 -> 1512 bytes .../textures/entity/containment_field_0.png | Bin 0 -> 571 bytes .../textures/entity/containment_field_1.png | Bin 0 -> 576 bytes .../textures/entity/containment_field_2.png | Bin 0 -> 587 bytes .../textures/entity/containment_field_3.png | Bin 0 -> 583 bytes .../textures/entity/containment_field_4.png | Bin 0 -> 573 bytes .../textures/entity/containment_field_5.png | Bin 0 -> 587 bytes .../textures/entity/containment_field_6.png | Bin 0 -> 600 bytes .../textures/entity/containment_field_7.png | Bin 0 -> 585 bytes .../ebwizardry/textures/entity/ember.png | Bin 0 -> 1244 bytes .../ebwizardry/textures/entity/fireball.png | Bin 0 -> 1764 bytes .../ebwizardry/textures/entity/firebolt.png | Bin 255 -> 1348 bytes .../textures/entity/frost_overlay.png | Bin 0 -> 242 bytes .../ebwizardry/textures/entity/iceball.png | Bin 0 -> 1803 bytes .../ebwizardry/textures/entity/wizard_7.png | Bin 0 -> 1599 bytes .../ebwizardry/textures/entity/wizard_8.png | Bin 0 -> 1598 bytes .../textures/entity/wizard_female_0.png | Bin 0 -> 1544 bytes .../textures/entity/wizard_female_1.png | Bin 0 -> 1543 bytes .../textures/entity/wizard_female_2.png | Bin 0 -> 1544 bytes .../textures/gui/advancement_background.png | Bin 703 -> 2337 bytes .../textures/gui/arcane_workbench.png | Bin 28839 -> 30590 bytes .../textures/gui/armour_picture.png | Bin 0 -> 75075 bytes .../textures/gui/curse_background.png | Bin 0 -> 621 bytes ...icon_simple.png => element_icon_magic.png} | Bin .../textures/gui/elements_picture.png | Bin 0 -> 7821 bytes .../ebwizardry/textures/gui/handbook.png | Bin 12848 -> 23928 bytes .../textures/gui/obelisk_picture.png | Bin 0 -> 123931 bytes .../gui/potion_icon_arcane_jammer.png | Bin 0 -> 15501 bytes .../textures/gui/potion_icon_containment.png | Bin 0 -> 12674 bytes .../gui/potion_icon_curse_of_enfeeblement.png | Bin 0 -> 8068 bytes .../gui/potion_icon_curse_of_soulbinding.png | Bin 0 -> 13480 bytes .../gui/potion_icon_curse_of_undeath.png | Bin 0 -> 6870 bytes .../{decay_icon.png => potion_icon_decay.png} | Bin .../textures/gui/potion_icon_empowerment.png | Bin 0 -> 11629 bytes .../textures/gui/potion_icon_fear.png | Bin 0 -> 12325 bytes .../textures/gui/potion_icon_fireskin.png | Bin 0 -> 9284 bytes .../textures/gui/potion_icon_font_of_mana.png | Bin 0 -> 14340 bytes .../{frost_icon.png => potion_icon_frost.png} | Bin .../textures/gui/potion_icon_frost_step.png | Bin 0 -> 14405 bytes .../textures/gui/potion_icon_ice_shroud.png | Bin 0 -> 11596 bytes .../textures/gui/potion_icon_mind_control.png | Bin 0 -> 8152 bytes .../textures/gui/potion_icon_mind_trick.png | Bin 0 -> 9578 bytes .../textures/gui/potion_icon_muffle.png | Bin 0 -> 9869 bytes .../textures/gui/potion_icon_paralysis.png | Bin 0 -> 11924 bytes .../textures/gui/potion_icon_sixth_sense.png | Bin 0 -> 14563 bytes .../textures/gui/potion_icon_slow_time.png | Bin 0 -> 10784 bytes .../textures/gui/potion_icon_static_aura.png | Bin 0 -> 11658 bytes .../textures/gui/potion_icon_transience.png | Bin 0 -> 12311 bytes .../textures/gui/potion_icon_ward.png | Bin 0 -> 8631 bytes .../ebwizardry/textures/gui/potion_icons.png | Bin 3317 -> 0 bytes .../textures/gui/shrine_picture.png | Bin 0 -> 196524 bytes .../textures/gui/spell_book_advanced.png | Bin 5292 -> 12024 bytes .../textures/gui/spell_book_apprentice.png | Bin 5272 -> 11927 bytes .../textures/gui/spell_book_basic.png | Bin 5267 -> 0 bytes .../textures/gui/spell_book_master.png | Bin 5666 -> 12366 bytes .../textures/gui/spell_book_novice.png | Bin 0 -> 11511 bytes .../textures/gui/spell_hud/_index.json | 12 + .../textures/gui/spell_hud/mahogany.json | 33 + .../textures/gui/spell_hud/mahogany.png | Bin 0 -> 20766 bytes .../textures/gui/spell_hud/oceanic.json | 33 + .../textures/gui/spell_hud/oceanic.png | Bin 0 -> 21417 bytes .../textures/gui/spell_hud/planks.json | 33 + .../textures/gui/spell_hud/planks.png | Bin 0 -> 22007 bytes .../ebwizardry/textures/gui/spellbook.png | Bin 20096 -> 0 bytes .../ebwizardry/textures/gui/tiers_picture.png | Bin 0 -> 927 bytes .../ebwizardry/textures/gui/tower_picture.png | Bin 0 -> 206602 bytes .../textures/gui/transportation_marker.png | Bin 0 -> 5708 bytes .../integration/antiqueatlas/obelisk.png | Bin 0 -> 3297 bytes .../integration/antiqueatlas/shrine.png | Bin 0 -> 3333 bytes .../integration/antiqueatlas/wizard_tower.png | Bin 0 -> 3328 bytes .../textures/items/amulet_anchoring.png | Bin 0 -> 5710 bytes .../textures/items/amulet_arcane_defence.png | Bin 0 -> 2150 bytes .../textures/items/amulet_auto_shield.png | Bin 0 -> 422 bytes .../textures/items/amulet_banishing.png | Bin 0 -> 5865 bytes .../textures/items/amulet_channeling.png | Bin 0 -> 500 bytes .../textures/items/amulet_fire_cloaking.png | Bin 0 -> 1803 bytes .../textures/items/amulet_fire_protection.png | Bin 0 -> 405 bytes .../textures/items/amulet_glide.png | Bin 0 -> 440 bytes .../textures/items/amulet_ice_immunity.png | Bin 0 -> 6552 bytes .../textures/items/amulet_ice_protection.png | Bin 0 -> 1873 bytes .../ebwizardry/textures/items/amulet_lich.png | Bin 0 -> 558 bytes .../textures/items/amulet_potential.png | Bin 0 -> 478 bytes .../textures/items/amulet_recovery.png | Bin 0 -> 6026 bytes .../textures/items/amulet_resurrection.png | Bin 0 -> 5914 bytes .../textures/items/amulet_transience.png | Bin 0 -> 496 bytes .../textures/items/amulet_warding.png | Bin 0 -> 430 bytes .../textures/items/amulet_wisdom.png | Bin 0 -> 1793 bytes .../textures/items/amulet_wither_immunity.png | Bin 0 -> 1831 bytes .../textures/items/astral_diamond.png | Bin 0 -> 2141 bytes .../textures/items/charm_abseiling.png | Bin 0 -> 6509 bytes .../textures/items/charm_auto_smelt.png | Bin 0 -> 419 bytes .../textures/items/charm_experience_tome.png | Bin 0 -> 2170 bytes .../textures/items/charm_feeding.png | Bin 0 -> 2114 bytes .../textures/items/charm_flight.png | Bin 0 -> 5949 bytes .../textures/items/charm_growth.png | Bin 0 -> 5722 bytes .../textures/items/charm_haggler.png | Bin 0 -> 1788 bytes .../textures/items/charm_lava_walking.png | Bin 0 -> 507 bytes .../ebwizardry/textures/items/charm_light.png | Bin 0 -> 456 bytes .../textures/items/charm_minion_health.png | Bin 0 -> 430 bytes .../textures/items/charm_minion_variants.png | Bin 0 -> 2098 bytes .../textures/items/charm_silk_touch.png | Bin 0 -> 387 bytes .../textures/items/charm_stop_time.png | Bin 0 -> 569 bytes .../ebwizardry/textures/items/charm_storm.png | Bin 0 -> 1945 bytes .../textures/items/charm_transportation.png | Bin 0 -> 556 bytes .../textures/items/crystal_earth.png | Bin 0 -> 656 bytes .../textures/items/crystal_fire.png | Bin 0 -> 623 bytes .../textures/items/crystal_grand.png | Bin 0 -> 667 bytes .../textures/items/crystal_healing.png | Bin 0 -> 618 bytes .../ebwizardry/textures/items/crystal_ice.png | Bin 0 -> 562 bytes .../textures/items/crystal_lightning.png | Bin 0 -> 688 bytes .../textures/items/crystal_magic.png | Bin 0 -> 519 bytes .../textures/items/crystal_necromancy.png | Bin 0 -> 588 bytes .../textures/items/crystal_shard.png | Bin 0 -> 361 bytes .../textures/items/crystal_sorcery.png | Bin 0 -> 620 bytes .../items/flaming_axe_conjuring_0.png | Bin 0 -> 1979 bytes .../items/flaming_axe_conjuring_1.png | Bin 0 -> 5979 bytes .../items/flaming_axe_conjuring_1.png.mcmeta | 12 + .../items/flaming_axe_conjuring_2.png | Bin 0 -> 5994 bytes .../items/flaming_axe_conjuring_2.png.mcmeta | 12 + .../items/flaming_axe_conjuring_3.png | Bin 0 -> 5955 bytes .../items/flaming_axe_conjuring_3.png.mcmeta | 12 + .../items/flaming_axe_conjuring_4.png | Bin 0 -> 5845 bytes .../items/flaming_axe_conjuring_4.png.mcmeta | 12 + .../items/flaming_axe_conjuring_5.png | Bin 0 -> 5875 bytes .../items/flaming_axe_conjuring_5.png.mcmeta | 12 + .../items/flaming_axe_conjuring_6.png | Bin 0 -> 5743 bytes .../items/flaming_axe_conjuring_6.png.mcmeta | 12 + .../items/flaming_axe_conjuring_7.png | Bin 0 -> 5908 bytes .../items/flaming_axe_conjuring_7.png.mcmeta | 12 + .../textures/items/frost_axe_conjuring_0.png | Bin 0 -> 1979 bytes .../textures/items/frost_axe_conjuring_1.png | Bin 0 -> 1977 bytes .../textures/items/frost_axe_conjuring_2.png | Bin 0 -> 2009 bytes .../textures/items/frost_axe_conjuring_3.png | Bin 0 -> 2012 bytes .../textures/items/frost_axe_conjuring_4.png | Bin 0 -> 1996 bytes .../textures/items/frost_axe_conjuring_5.png | Bin 0 -> 1977 bytes .../textures/items/frost_axe_conjuring_6.png | Bin 0 -> 1977 bytes .../textures/items/frost_axe_conjuring_7.png | Bin 0 -> 1915 bytes .../textures/items/magic_crystal.png | Bin 510 -> 0 bytes .../ebwizardry/textures/items/mana_flask.png | Bin 409 -> 0 bytes .../textures/items/mana_flask_large.png | Bin 0 -> 473 bytes .../textures/items/mana_flask_medium.png | Bin 0 -> 470 bytes .../textures/items/mana_flask_small.png | Bin 0 -> 432 bytes .../textures/items/purifying_elixir.png | Bin 0 -> 1946 bytes .../textures/items/ring_arcane_frost.png | Bin 0 -> 429 bytes .../textures/items/ring_battlemage.png | Bin 0 -> 1725 bytes .../textures/items/ring_blockwrangler.png | Bin 0 -> 5961 bytes .../textures/items/ring_bronze_generic.png | Bin 0 -> 5855 bytes .../textures/items/ring_combustion.png | Bin 0 -> 9840 bytes .../textures/items/ring_combustion.png.mcmeta | 12 + .../textures/items/ring_condensing.png | Bin 0 -> 579 bytes .../textures/items/ring_conjurer.png | Bin 0 -> 335 bytes .../textures/items/ring_defender.png | Bin 0 -> 6228 bytes .../textures/items/ring_defender.png.mcmeta | 12 + .../textures/items/ring_disintegration.png | Bin 0 -> 424 bytes .../textures/items/ring_earth_biome.png | Bin 0 -> 5746 bytes .../textures/items/ring_earth_melee.png | Bin 0 -> 1859 bytes .../textures/items/ring_extraction.png | Bin 0 -> 1882 bytes .../textures/items/ring_fire_biome.png | Bin 0 -> 1819 bytes .../textures/items/ring_fire_melee.png | Bin 0 -> 2023 bytes .../textures/items/ring_full_moon.png | Bin 0 -> 5455 bytes .../textures/items/ring_gold_generic.png | Bin 0 -> 5866 bytes .../ebwizardry/textures/items/ring_hammer.png | Bin 0 -> 367 bytes .../textures/items/ring_ice_biome.png | Bin 0 -> 458 bytes .../textures/items/ring_ice_melee.png | Bin 0 -> 1889 bytes .../textures/items/ring_interdiction.png | Bin 0 -> 541 bytes .../textures/items/ring_leeching.png | Bin 0 -> 392 bytes .../textures/items/ring_lightning_melee.png | Bin 0 -> 589 bytes .../textures/items/ring_mana_return.png | Bin 0 -> 444 bytes .../textures/items/ring_mind_control.png | Bin 0 -> 357 bytes .../textures/items/ring_necromancy_melee.png | Bin 0 -> 1997 bytes .../textures/items/ring_paladin.png | Bin 0 -> 577 bytes .../ebwizardry/textures/items/ring_poison.png | Bin 0 -> 5591 bytes .../textures/items/ring_seeking.png | Bin 0 -> 387 bytes .../textures/items/ring_shattering.png | Bin 0 -> 311 bytes .../textures/items/ring_silver_generic.png | Bin 0 -> 5910 bytes .../textures/items/ring_siphoning.png | Bin 0 -> 384 bytes .../textures/items/ring_soulbinding.png | Bin 0 -> 456 bytes .../ebwizardry/textures/items/ring_storm.png | Bin 0 -> 1206 bytes .../textures/items/ring_storm.png.mcmeta | 42 + .../textures/{entity => items}/spark_bomb.png | Bin .../items/spectral_bow_conjuring_0.png | Bin 0 -> 1651 bytes .../items/spectral_bow_conjuring_1.png | Bin 0 -> 1693 bytes .../items/spectral_bow_conjuring_2.png | Bin 0 -> 1786 bytes .../items/spectral_bow_conjuring_3.png | Bin 0 -> 1815 bytes .../items/spectral_bow_conjuring_4.png | Bin 0 -> 1833 bytes .../items/spectral_bow_conjuring_5.png | Bin 0 -> 1809 bytes .../items/spectral_bow_conjuring_6.png | Bin 0 -> 1797 bytes .../items/spectral_bow_conjuring_7.png | Bin 0 -> 1786 bytes .../items/spectral_pickaxe_conjuring_0.png | Bin 0 -> 1588 bytes .../items/spectral_pickaxe_conjuring_1.png | Bin 0 -> 1593 bytes .../items/spectral_pickaxe_conjuring_2.png | Bin 0 -> 1616 bytes .../items/spectral_pickaxe_conjuring_3.png | Bin 0 -> 1673 bytes .../items/spectral_pickaxe_conjuring_4.png | Bin 0 -> 1686 bytes .../items/spectral_pickaxe_conjuring_5.png | Bin 0 -> 1723 bytes .../items/spectral_pickaxe_conjuring_6.png | Bin 0 -> 1707 bytes .../items/spectral_pickaxe_conjuring_7.png | Bin 0 -> 1694 bytes .../items/spectral_sword_conjuring_0.png | Bin 0 -> 1668 bytes .../items/spectral_sword_conjuring_1.png | Bin 0 -> 1729 bytes .../items/spectral_sword_conjuring_2.png | Bin 0 -> 1777 bytes .../items/spectral_sword_conjuring_3.png | Bin 0 -> 1791 bytes .../items/spectral_sword_conjuring_4.png | Bin 0 -> 1791 bytes .../items/spectral_sword_conjuring_5.png | Bin 0 -> 1797 bytes .../items/spectral_sword_conjuring_6.png | Bin 0 -> 1817 bytes .../items/spectral_sword_conjuring_7.png | Bin 0 -> 1803 bytes .../textures/items/upgrade_attunement.png | Bin 556 -> 5741 bytes .../textures/items/upgrade_blast.png | Bin 371 -> 5553 bytes .../textures/items/upgrade_condenser.png | Bin 411 -> 5610 bytes .../textures/items/upgrade_cooldown.png | Bin 452 -> 5698 bytes .../textures/items/upgrade_duration.png | Bin 412 -> 5594 bytes .../textures/items/upgrade_melee.png | Bin 0 -> 5965 bytes .../textures/items/upgrade_range.png | Bin 535 -> 5613 bytes .../textures/items/upgrade_siphon.png | Bin 447 -> 5851 bytes .../textures/items/upgrade_storage.png | Bin 392 -> 5865 bytes .../textures/items/wand_basic_lightning.png | Bin 363 -> 0 bytes .../textures/items/wand_basic_necromancy.png | Bin 361 -> 0 bytes .../items/{wand_basic.png => wand_novice.png} | Bin ..._basic_earth.png => wand_novice_earth.png} | Bin ...nd_basic_fire.png => wand_novice_fire.png} | Bin ...ic_healing.png => wand_novice_healing.png} | Bin ...wand_basic_ice.png => wand_novice_ice.png} | Bin .../textures/items/wand_novice_lightning.png | Bin 0 -> 502 bytes .../textures/items/wand_novice_necromancy.png | Bin 0 -> 496 bytes ...ic_sorcery.png => wand_novice_sorcery.png} | Bin .../textures/particle/flame_0_0.png | Bin 0 -> 1695 bytes .../textures/particle/flame_0_1.png | Bin 0 -> 1719 bytes .../textures/particle/flame_0_2.png | Bin 0 -> 1741 bytes .../textures/particle/flame_0_3.png | Bin 0 -> 1769 bytes .../textures/particle/flame_0_4.png | Bin 0 -> 1748 bytes .../textures/particle/flame_0_5.png | Bin 0 -> 1680 bytes .../textures/particle/flame_0_6.png | Bin 0 -> 1685 bytes .../textures/particle/flame_0_7.png | Bin 0 -> 1679 bytes .../textures/particle/flame_1_0.png | Bin 0 -> 1716 bytes .../textures/particle/flame_1_1.png | Bin 0 -> 1737 bytes .../textures/particle/flame_1_2.png | Bin 0 -> 1729 bytes .../textures/particle/flame_1_3.png | Bin 0 -> 1763 bytes .../textures/particle/flame_1_4.png | Bin 0 -> 1762 bytes .../textures/particle/flame_1_5.png | Bin 0 -> 1671 bytes .../textures/particle/flame_1_6.png | Bin 0 -> 1671 bytes .../textures/particle/flame_1_7.png | Bin 0 -> 1667 bytes .../textures/particle/flame_2_0.png | Bin 0 -> 1683 bytes .../textures/particle/flame_2_1.png | Bin 0 -> 1730 bytes .../textures/particle/flame_2_2.png | Bin 0 -> 1694 bytes .../textures/particle/flame_2_3.png | Bin 0 -> 1564 bytes .../textures/particle/flame_2_4.png | Bin 0 -> 1633 bytes .../textures/particle/flame_2_5.png | Bin 0 -> 1605 bytes .../textures/particle/flame_2_6.png | Bin 0 -> 1581 bytes .../textures/particle/flame_2_7.png | Bin 0 -> 1579 bytes .../textures/particle/flame_3_0.png | Bin 0 -> 1683 bytes .../textures/particle/flame_3_1.png | Bin 0 -> 1730 bytes .../textures/particle/flame_3_2.png | Bin 0 -> 1719 bytes .../textures/particle/flame_3_3.png | Bin 0 -> 1593 bytes .../textures/particle/flame_3_4.png | Bin 0 -> 1618 bytes .../textures/particle/flame_3_5.png | Bin 0 -> 1606 bytes .../textures/particle/flame_3_6.png | Bin 0 -> 1562 bytes .../textures/particle/flame_3_7.png | Bin 0 -> 1559 bytes .../ebwizardry/textures/particle/ice_0.png | Bin 307 -> 1649 bytes .../ebwizardry/textures/particle/ice_1.png | Bin 238 -> 1333 bytes .../ebwizardry/textures/particle/ice_2.png | Bin 217 -> 1363 bytes .../ebwizardry/textures/particle/ice_3.png | Bin 191 -> 1213 bytes .../ebwizardry/textures/particle/ice_4.png | Bin 289 -> 1591 bytes .../ebwizardry/textures/particle/ice_5.png | Bin 259 -> 1498 bytes .../ebwizardry/textures/particle/ice_6.png | Bin 187 -> 1177 bytes .../ebwizardry/textures/particle/ice_7.png | Bin 183 -> 1162 bytes .../ebwizardry/textures/particle/leaf_0.png | Bin 196 -> 1274 bytes .../ebwizardry/textures/particle/leaf_1.png | Bin 187 -> 1155 bytes .../ebwizardry/textures/particle/leaf_10.png | Bin 184 -> 1170 bytes .../ebwizardry/textures/particle/leaf_11.png | Bin 184 -> 1091 bytes .../ebwizardry/textures/particle/leaf_12.png | Bin 191 -> 1120 bytes .../ebwizardry/textures/particle/leaf_13.png | Bin 180 -> 1074 bytes .../ebwizardry/textures/particle/leaf_14.png | Bin 181 -> 1084 bytes .../ebwizardry/textures/particle/leaf_15.png | Bin 243 -> 1373 bytes .../ebwizardry/textures/particle/leaf_2.png | Bin 194 -> 1165 bytes .../ebwizardry/textures/particle/leaf_3.png | Bin 167 -> 1091 bytes .../ebwizardry/textures/particle/leaf_4.png | Bin 197 -> 1186 bytes .../ebwizardry/textures/particle/leaf_5.png | Bin 229 -> 1285 bytes .../ebwizardry/textures/particle/leaf_6.png | Bin 223 -> 1227 bytes .../ebwizardry/textures/particle/leaf_7.png | Bin 232 -> 1269 bytes .../ebwizardry/textures/particle/leaf_8.png | Bin 251 -> 1324 bytes .../ebwizardry/textures/particle/leaf_9.png | Bin 243 -> 1309 bytes .../ebwizardry/textures/particle/path.png | Bin 219 -> 1046 bytes .../ebwizardry/textures/particle/snow_0.png | Bin 140 -> 991 bytes .../ebwizardry/textures/particle/snow_1.png | Bin 140 -> 990 bytes .../ebwizardry/textures/particle/snow_2.png | Bin 145 -> 995 bytes .../ebwizardry/textures/particle/snow_3.png | Bin 137 -> 961 bytes .../textures/particle/sparkle_0.png | Bin 307 -> 1521 bytes .../textures/particle/sparkle_1.png | Bin 239 -> 1252 bytes .../textures/particle/sparkle_10.png | Bin 134 -> 904 bytes .../textures/particle/sparkle_2.png | Bin 240 -> 1225 bytes .../textures/particle/sparkle_3.png | Bin 215 -> 1154 bytes .../textures/particle/sparkle_4.png | Bin 298 -> 1564 bytes .../textures/particle/sparkle_5.png | Bin 243 -> 1359 bytes .../textures/particle/sparkle_6.png | Bin 182 -> 1183 bytes .../textures/particle/sparkle_7.png | Bin 191 -> 1146 bytes .../textures/particle/sparkle_8.png | Bin 257 -> 1491 bytes .../textures/particle/sparkle_9.png | Bin 181 -> 1214 bytes .../ebwizardry/textures/particle/summon.png | Bin 0 -> 1310 bytes .../ebwizardry/textures/particle/vine.png | Bin 0 -> 865 bytes .../textures/particle/vine_leaf_0.png | Bin 0 -> 1272 bytes .../textures/particle/vine_leaf_1.png | Bin 0 -> 1246 bytes .../textures/particle/vine_leaf_2.png | Bin 0 -> 1351 bytes .../textures/particle/vine_leaf_3.png | Bin 0 -> 1195 bytes .../textures/particle/vine_leaf_4.png | Bin 0 -> 1087 bytes .../ebwizardry/textures/spells/agility.png | Bin 2200 -> 5547 bytes .../textures/spells/arcane_lock.png | Bin 0 -> 5300 bytes .../ebwizardry/textures/spells/arrow_rain.png | Bin 2421 -> 6382 bytes .../ebwizardry/textures/spells/charge.png | Bin 0 -> 2260 bytes .../textures/spells/combustion_rune.png | Bin 0 -> 6199 bytes .../textures/spells/conjure_axe.png | Bin 0 -> 4557 bytes .../textures/spells/conjure_block.png | Bin 0 -> 1744 bytes .../textures/spells/conjure_shovel.png | Bin 0 -> 4317 bytes .../textures/spells/containment.png | Bin 0 -> 4994 bytes .../textures/spells/curse_of_enfeeblement.png | Bin 0 -> 1726 bytes .../textures/spells/curse_of_undeath.png | Bin 0 -> 1990 bytes .../textures/spells/disintegration.png | Bin 0 -> 2076 bytes .../ebwizardry/textures/spells/divination.png | Bin 0 -> 5844 bytes .../textures/spells/dragon_fireball.png | Bin 0 -> 5692 bytes .../textures/spells/empowering_presence.png | Bin 0 -> 2527 bytes .../ebwizardry/textures/spells/evade.png | Bin 0 -> 5322 bytes .../textures/spells/fire_breath.png | Bin 0 -> 1938 bytes .../textures/spells/fire_resistance.png | Bin 2381 -> 6180 bytes .../textures/spells/forest_of_thorns.png | Bin 0 -> 2579 bytes .../ebwizardry/textures/spells/frost_step.png | Bin 0 -> 5334 bytes .../ebwizardry/textures/spells/grapple.png | Bin 0 -> 6134 bytes .../textures/spells/greater_telekinesis.png | Bin 0 -> 2461 bytes .../textures/spells/greater_ward.png | Bin 0 -> 2424 bytes .../textures/spells/guardian_angel.png | Bin 0 -> 6455 bytes .../textures/spells/guardian_beam.png | Bin 0 -> 5882 bytes .../textures/spells/healing_totem.png | Bin 0 -> 5218 bytes .../ebwizardry/textures/spells/iceball.png | Bin 0 -> 1848 bytes .../ebwizardry/textures/spells/levitation.png | Bin 2188 -> 6044 bytes .../textures/spells/lightning_hammer.png | Bin 2426 -> 6121 bytes .../ebwizardry/textures/spells/mine.png | Bin 0 -> 1575 bytes .../ebwizardry/textures/spells/muffle.png | Bin 0 -> 1979 bytes .../ebwizardry/textures/spells/paralysis.png | Bin 0 -> 2420 bytes .../ebwizardry/textures/spells/permafrost.png | Bin 0 -> 5249 bytes .../ebwizardry/textures/spells/phase_step.png | Bin 2023 -> 5141 bytes .../ebwizardry/textures/spells/possession.png | Bin 0 -> 2290 bytes .../textures/spells/ray_of_purification.png | Bin 0 -> 2278 bytes .../textures/spells/remove_curse.png | Bin 0 -> 2459 bytes .../textures/spells/resurrection.png | Bin 0 -> 2254 bytes .../ebwizardry/textures/spells/reversal.png | Bin 0 -> 5726 bytes .../ebwizardry/textures/spells/rupture.png | Bin 0 -> 1846 bytes .../ebwizardry/textures/spells/satiety.png | Bin 0 -> 2450 bytes .../ebwizardry/textures/spells/shapeshift.png | Bin 0 -> 5336 bytes .../textures/spells/shocking_weapon.png | Bin 0 -> 5691 bytes .../textures/spells/shulker_bullet.png | Bin 0 -> 4963 bytes .../ebwizardry/textures/spells/slow_time.png | Bin 0 -> 2411 bytes .../ebwizardry/textures/spells/speed_time.png | Bin 0 -> 2530 bytes .../textures/spells/summon_creeper.png | Bin 0 -> 5393 bytes .../textures/spells/summon_spirit_horse.png | Bin 2211 -> 5855 bytes .../textures/spells/summon_spirit_wolf.png | Bin 2241 -> 5638 bytes .../ebwizardry/textures/spells/vex_swarm.png | Bin 0 -> 5544 bytes .../ebwizardry/textures/spells/ward.png | Bin 0 -> 2304 bytes src/main/resources/mcmod.info | 11 +- 1564 files changed, 47652 insertions(+), 12984 deletions(-) delete mode 100644 src/main/java/electroblob/wizardry/WizardryWorldGenerator.java create mode 100644 src/main/java/electroblob/wizardry/advancement/ArcaneWorkbenchTrigger.java rename src/main/java/electroblob/wizardry/{util => advancement}/CustomAdvancementTrigger.java (96%) create mode 100644 src/main/java/electroblob/wizardry/advancement/SpellCastTrigger.java create mode 100644 src/main/java/electroblob/wizardry/advancement/SpellDiscoveryTrigger.java create mode 100644 src/main/java/electroblob/wizardry/advancement/SpellPredicate.java create mode 100644 src/main/java/electroblob/wizardry/advancement/StructureTrigger.java create mode 100644 src/main/java/electroblob/wizardry/api/WizardryEnumHelper.java create mode 100644 src/main/java/electroblob/wizardry/block/BlockCrystal.java create mode 100644 src/main/java/electroblob/wizardry/block/BlockDryFrostedIce.java create mode 100644 src/main/java/electroblob/wizardry/block/BlockObsidianCrust.java create mode 100644 src/main/java/electroblob/wizardry/block/BlockPedestal.java create mode 100644 src/main/java/electroblob/wizardry/block/BlockRunestone.java create mode 100644 src/main/java/electroblob/wizardry/block/BlockThorns.java delete mode 100644 src/main/java/electroblob/wizardry/client/MovingSoundEntity.java create mode 100644 src/main/java/electroblob/wizardry/client/audio/MovingSoundEntity.java create mode 100644 src/main/java/electroblob/wizardry/client/audio/SoundLoop.java create mode 100644 src/main/java/electroblob/wizardry/client/audio/SoundLoopSpell.java create mode 100644 src/main/java/electroblob/wizardry/client/gui/GuiButtonResurrect.java rename src/main/java/electroblob/wizardry/client/{ => gui/config}/EntityNameEntry.java (90%) rename src/main/java/electroblob/wizardry/client/gui/{ => config}/GuiConfigWizardry.java (90%) rename src/main/java/electroblob/wizardry/client/gui/{ => config}/GuiSelectHUDSkin.java (95%) create mode 100644 src/main/java/electroblob/wizardry/client/gui/config/NamedBooleanEntry.java rename src/main/java/electroblob/wizardry/client/{ => gui/config}/SpellHUDSkinChooserEntry.java (85%) create mode 100644 src/main/java/electroblob/wizardry/client/gui/handbook/HandbookToast.java create mode 100644 src/main/java/electroblob/wizardry/client/model/BakedModelGlowingOverlay.java delete mode 100644 src/main/java/electroblob/wizardry/client/model/WizardryItemModels.java create mode 100644 src/main/java/electroblob/wizardry/client/model/WizardryModels.java create mode 100644 src/main/java/electroblob/wizardry/client/particle/ParticleSphere.java create mode 100644 src/main/java/electroblob/wizardry/client/particle/ParticleSummon.java create mode 100644 src/main/java/electroblob/wizardry/client/particle/ParticleVine.java create mode 100644 src/main/java/electroblob/wizardry/client/renderer/LayerFrost.java create mode 100644 src/main/java/electroblob/wizardry/client/renderer/LayerStrayMinionClothing.java create mode 100644 src/main/java/electroblob/wizardry/client/renderer/RenderArcaneLock.java create mode 100644 src/main/java/electroblob/wizardry/client/renderer/RenderContainmentField.java create mode 100644 src/main/java/electroblob/wizardry/client/renderer/RenderForcefield.java create mode 100644 src/main/java/electroblob/wizardry/client/renderer/RenderPossessingPlayer.java create mode 100644 src/main/java/electroblob/wizardry/client/renderer/RenderShadowWard.java create mode 100644 src/main/java/electroblob/wizardry/client/renderer/RenderShield.java create mode 100644 src/main/java/electroblob/wizardry/client/renderer/RenderStrayMinion.java create mode 100644 src/main/java/electroblob/wizardry/client/renderer/RenderTransportationUI.java create mode 100644 src/main/java/electroblob/wizardry/client/renderer/RenderWings.java create mode 100644 src/main/java/electroblob/wizardry/command/SpellEmitter.java create mode 100644 src/main/java/electroblob/wizardry/data/BlockCastingData.java create mode 100644 src/main/java/electroblob/wizardry/data/DispenserCastingData.java create mode 100644 src/main/java/electroblob/wizardry/data/IStoredVariable.java create mode 100644 src/main/java/electroblob/wizardry/data/IVariable.java create mode 100644 src/main/java/electroblob/wizardry/data/Persistence.java create mode 100644 src/main/java/electroblob/wizardry/data/SpellEmitterData.java rename src/main/java/electroblob/wizardry/{ => data}/SpellGlyphData.java (85%) rename src/main/java/electroblob/wizardry/{ => data}/WizardData.java (51%) create mode 100644 src/main/java/electroblob/wizardry/enchantment/EnchantmentMagicProtection.java create mode 100644 src/main/java/electroblob/wizardry/entity/EntityLevitatingBlock.java create mode 100644 src/main/java/electroblob/wizardry/entity/ICustomHitbox.java create mode 100644 src/main/java/electroblob/wizardry/entity/construct/EntityCombustionRune.java create mode 100644 src/main/java/electroblob/wizardry/entity/living/EntityHuskMinion.java create mode 100644 src/main/java/electroblob/wizardry/entity/living/EntityStrayMinion.java create mode 100644 src/main/java/electroblob/wizardry/entity/living/EntityVexMinion.java create mode 100644 src/main/java/electroblob/wizardry/entity/projectile/EntityEmber.java create mode 100644 src/main/java/electroblob/wizardry/entity/projectile/EntityIceball.java create mode 100644 src/main/java/electroblob/wizardry/entity/projectile/EntityLargeMagicFireball.java create mode 100644 src/main/java/electroblob/wizardry/entity/projectile/EntityMagicFireball.java create mode 100644 src/main/java/electroblob/wizardry/integration/antiqueatlas/WizardryAntiqueAtlasIntegration.java create mode 100644 src/main/java/electroblob/wizardry/integration/baubles/WizardryBaublesIntegration.java create mode 100644 src/main/java/electroblob/wizardry/item/IManaStoringItem.java create mode 100644 src/main/java/electroblob/wizardry/item/IMultiTexturedItem.java create mode 100644 src/main/java/electroblob/wizardry/item/ISpellCastingItem.java create mode 100644 src/main/java/electroblob/wizardry/item/ItemArtefact.java create mode 100644 src/main/java/electroblob/wizardry/item/ItemBlockMultiTexturedElemental.java create mode 100644 src/main/java/electroblob/wizardry/item/ItemCrystal.java create mode 100644 src/main/java/electroblob/wizardry/item/ItemLightningHammer.java create mode 100644 src/main/java/electroblob/wizardry/item/ItemManaFlask.java create mode 100644 src/main/java/electroblob/wizardry/item/ItemPurifyingElixir.java create mode 100644 src/main/java/electroblob/wizardry/item/ItemSparkBomb.java create mode 100644 src/main/java/electroblob/wizardry/item/ItemWandUpgrade.java create mode 100644 src/main/java/electroblob/wizardry/misc/BehaviourSpellDispense.java create mode 100644 src/main/java/electroblob/wizardry/misc/Forfeit.java rename src/main/java/electroblob/wizardry/{util => misc}/WildcardTradeList.java (98%) rename src/main/java/electroblob/wizardry/{util => misc}/WizardryPathFinder.java (99%) create mode 100644 src/main/java/electroblob/wizardry/packet/PacketCastSpellAtPos.java create mode 100644 src/main/java/electroblob/wizardry/packet/PacketConquerShrine.java create mode 100644 src/main/java/electroblob/wizardry/packet/PacketDispenserCastSpell.java create mode 100644 src/main/java/electroblob/wizardry/packet/PacketEmitterData.java create mode 100644 src/main/java/electroblob/wizardry/packet/PacketEndSlowTime.java create mode 100644 src/main/java/electroblob/wizardry/packet/PacketPossession.java create mode 100644 src/main/java/electroblob/wizardry/packet/PacketRequestAdvancementSync.java create mode 100644 src/main/java/electroblob/wizardry/packet/PacketResurrection.java create mode 100644 src/main/java/electroblob/wizardry/packet/PacketSpellProperties.java create mode 100644 src/main/java/electroblob/wizardry/packet/PacketSyncAdvancements.java create mode 100644 src/main/java/electroblob/wizardry/potion/Curse.java create mode 100644 src/main/java/electroblob/wizardry/potion/CurseEnfeeblement.java create mode 100644 src/main/java/electroblob/wizardry/potion/CurseUndeath.java create mode 100644 src/main/java/electroblob/wizardry/potion/ISyncedPotion.java create mode 100644 src/main/java/electroblob/wizardry/potion/PotionContainment.java create mode 100644 src/main/java/electroblob/wizardry/potion/PotionFrostStep.java create mode 100644 src/main/java/electroblob/wizardry/potion/PotionSlowTime.java create mode 100644 src/main/java/electroblob/wizardry/registry/WizardryEntities.java create mode 100644 src/main/java/electroblob/wizardry/registry/WizardryLoot.java create mode 100644 src/main/java/electroblob/wizardry/registry/WizardryRecipes.java delete mode 100644 src/main/java/electroblob/wizardry/registry/WizardryRegistry.java create mode 100644 src/main/java/electroblob/wizardry/spell/ArcaneLock.java create mode 100644 src/main/java/electroblob/wizardry/spell/Charge.java create mode 100644 src/main/java/electroblob/wizardry/spell/ConjureBlock.java create mode 100644 src/main/java/electroblob/wizardry/spell/Containment.java create mode 100644 src/main/java/electroblob/wizardry/spell/CurseOfEnfeeblement.java create mode 100644 src/main/java/electroblob/wizardry/spell/CurseOfUndeath.java create mode 100644 src/main/java/electroblob/wizardry/spell/Disintegration.java create mode 100644 src/main/java/electroblob/wizardry/spell/Divination.java rename src/main/java/electroblob/wizardry/spell/{Fireball.java => DragonFireball.java} (54%) create mode 100644 src/main/java/electroblob/wizardry/spell/EmpoweringPresence.java create mode 100644 src/main/java/electroblob/wizardry/spell/Evade.java create mode 100644 src/main/java/electroblob/wizardry/spell/FireBreath.java delete mode 100644 src/main/java/electroblob/wizardry/spell/Firestorm.java create mode 100644 src/main/java/electroblob/wizardry/spell/ForceArrow.java create mode 100644 src/main/java/electroblob/wizardry/spell/Forcefield.java create mode 100644 src/main/java/electroblob/wizardry/spell/ForestOfThorns.java create mode 100644 src/main/java/electroblob/wizardry/spell/Grapple.java delete mode 100644 src/main/java/electroblob/wizardry/spell/GreaterFireball.java create mode 100644 src/main/java/electroblob/wizardry/spell/GreaterTelekinesis.java create mode 100644 src/main/java/electroblob/wizardry/spell/Mine.java create mode 100644 src/main/java/electroblob/wizardry/spell/Paralysis.java create mode 100644 src/main/java/electroblob/wizardry/spell/Possession.java create mode 100644 src/main/java/electroblob/wizardry/spell/RayOfPurification.java create mode 100644 src/main/java/electroblob/wizardry/spell/RemoveCurse.java create mode 100644 src/main/java/electroblob/wizardry/spell/Resurrection.java create mode 100644 src/main/java/electroblob/wizardry/spell/Reversal.java create mode 100644 src/main/java/electroblob/wizardry/spell/Satiety.java create mode 100644 src/main/java/electroblob/wizardry/spell/ShulkerBullet.java create mode 100644 src/main/java/electroblob/wizardry/spell/SlowTime.java create mode 100644 src/main/java/electroblob/wizardry/spell/SpeedTime.java create mode 100644 src/main/java/electroblob/wizardry/spell/SummonWitherSkeleton.java create mode 100644 src/main/java/electroblob/wizardry/spell/SummonZombie.java create mode 100644 src/main/java/electroblob/wizardry/tileentity/SlotItemClassList.java create mode 100644 src/main/java/electroblob/wizardry/tileentity/TileEntityPlayerSaveTimed.java create mode 100644 src/main/java/electroblob/wizardry/tileentity/TileEntityShrineCore.java create mode 100644 src/main/java/electroblob/wizardry/util/AllyDesignationSystem.java create mode 100644 src/main/java/electroblob/wizardry/util/CustomSoundCategory.java create mode 100644 src/main/java/electroblob/wizardry/util/Location.java create mode 100644 src/main/java/electroblob/wizardry/util/NBTExtras.java create mode 100644 src/main/java/electroblob/wizardry/util/RayTracer.java create mode 100644 src/main/java/electroblob/wizardry/util/RelativeFacing.java create mode 100644 src/main/java/electroblob/wizardry/util/SpellProperties.java create mode 100644 src/main/java/electroblob/wizardry/worldgen/MossifierTemplateProcessor.java create mode 100644 src/main/java/electroblob/wizardry/worldgen/MultiTemplateProcessor.java create mode 100644 src/main/java/electroblob/wizardry/worldgen/WoodTypeTemplateProcessor.java create mode 100644 src/main/java/electroblob/wizardry/worldgen/WorldGenCrystalFlower.java create mode 100644 src/main/java/electroblob/wizardry/worldgen/WorldGenCrystalOre.java create mode 100644 src/main/java/electroblob/wizardry/worldgen/WorldGenObelisk.java create mode 100644 src/main/java/electroblob/wizardry/worldgen/WorldGenShrine.java create mode 100644 src/main/java/electroblob/wizardry/worldgen/WorldGenSurfaceStructure.java create mode 100644 src/main/java/electroblob/wizardry/worldgen/WorldGenWizardTower.java create mode 100644 src/main/resources/assets/ebwizardry/advancements/advanced.json create mode 100644 src/main/resources/assets/ebwizardry/advancements/all_artefacts.json create mode 100644 src/main/resources/assets/ebwizardry/advancements/artefact.json delete mode 100644 src/main/resources/assets/ebwizardry/advancements/charge_creeper.json delete mode 100644 src/main/resources/assets/ebwizardry/advancements/craft_flask.json create mode 100644 src/main/resources/assets/ebwizardry/advancements/discover_master_spell.json create mode 100644 src/main/resources/assets/ebwizardry/advancements/discover_spell.json delete mode 100644 src/main/resources/assets/ebwizardry/advancements/element_master.json delete mode 100644 src/main/resources/assets/ebwizardry/advancements/elemental.json create mode 100644 src/main/resources/assets/ebwizardry/advancements/enchant_scroll.json delete mode 100644 src/main/resources/assets/ebwizardry/advancements/frankenstein.json delete mode 100644 src/main/resources/assets/ebwizardry/advancements/freeze_blaze.json create mode 100644 src/main/resources/assets/ebwizardry/advancements/handbook/arcane_workbench.json create mode 100644 src/main/resources/assets/ebwizardry/advancements/handbook/crystal_flowers.json create mode 100644 src/main/resources/assets/ebwizardry/advancements/handbook/elements.json create mode 100644 src/main/resources/assets/ebwizardry/advancements/handbook/magical_creatures.json create mode 100644 src/main/resources/assets/ebwizardry/advancements/handbook/mana_flasks.json create mode 100644 src/main/resources/assets/ebwizardry/advancements/handbook/obelisks.json create mode 100644 src/main/resources/assets/ebwizardry/advancements/handbook/on_subsection_unlock.json create mode 100644 src/main/resources/assets/ebwizardry/advancements/handbook/scrolls.json create mode 100644 src/main/resources/assets/ebwizardry/advancements/handbook/spells.json create mode 100644 src/main/resources/assets/ebwizardry/advancements/handbook/throwables.json create mode 100644 src/main/resources/assets/ebwizardry/advancements/handbook/tome_of_arcana.json delete mode 100644 src/main/resources/assets/ebwizardry/advancements/jam_wizard.json delete mode 100644 src/main/resources/assets/ebwizardry/advancements/pig_tornado.json delete mode 100644 src/main/resources/assets/ebwizardry/advancements/self_destruct.json delete mode 100644 src/main/resources/assets/ebwizardry/advancements/slime_skeleton.json create mode 100644 src/main/resources/assets/ebwizardry/advancements/spell_failure.json create mode 100644 src/main/resources/assets/ebwizardry/advancements/visit_shrine.json create mode 100644 src/main/resources/assets/ebwizardry/advancements/wizard_tower.json delete mode 100644 src/main/resources/assets/ebwizardry/blockstates/crystal_block.json create mode 100644 src/main/resources/assets/ebwizardry/blockstates/dry_frosted_ice.json create mode 100644 src/main/resources/assets/ebwizardry/blockstates/earth_crystal_block.json create mode 100644 src/main/resources/assets/ebwizardry/blockstates/earth_runestone.json create mode 100644 src/main/resources/assets/ebwizardry/blockstates/earth_runestone_pedestal.json create mode 100644 src/main/resources/assets/ebwizardry/blockstates/fire_crystal_block.json create mode 100644 src/main/resources/assets/ebwizardry/blockstates/fire_runestone.json create mode 100644 src/main/resources/assets/ebwizardry/blockstates/fire_runestone_pedestal.json create mode 100644 src/main/resources/assets/ebwizardry/blockstates/healing_crystal_block.json create mode 100644 src/main/resources/assets/ebwizardry/blockstates/healing_runestone.json create mode 100644 src/main/resources/assets/ebwizardry/blockstates/healing_runestone_pedestal.json create mode 100644 src/main/resources/assets/ebwizardry/blockstates/ice_crystal_block.json create mode 100644 src/main/resources/assets/ebwizardry/blockstates/ice_runestone.json create mode 100644 src/main/resources/assets/ebwizardry/blockstates/ice_runestone_pedestal.json create mode 100644 src/main/resources/assets/ebwizardry/blockstates/lightning_crystal_block.json create mode 100644 src/main/resources/assets/ebwizardry/blockstates/lightning_runestone.json create mode 100644 src/main/resources/assets/ebwizardry/blockstates/lightning_runestone_pedestal.json create mode 100644 src/main/resources/assets/ebwizardry/blockstates/magic_crystal_block.json create mode 100644 src/main/resources/assets/ebwizardry/blockstates/necromancy_crystal_block.json create mode 100644 src/main/resources/assets/ebwizardry/blockstates/necromancy_runestone.json create mode 100644 src/main/resources/assets/ebwizardry/blockstates/necromancy_runestone_pedestal.json create mode 100644 src/main/resources/assets/ebwizardry/blockstates/obsidian_crust.json create mode 100644 src/main/resources/assets/ebwizardry/blockstates/sorcery_crystal_block.json create mode 100644 src/main/resources/assets/ebwizardry/blockstates/sorcery_runestone.json create mode 100644 src/main/resources/assets/ebwizardry/blockstates/sorcery_runestone_pedestal.json create mode 100644 src/main/resources/assets/ebwizardry/blockstates/thorns.json create mode 100644 src/main/resources/assets/ebwizardry/lang/fr_fr.lang create mode 100644 src/main/resources/assets/ebwizardry/lang/ko_kr.lang create mode 100644 src/main/resources/assets/ebwizardry/loot_tables/chests/jungle_dispenser_additions.json create mode 100644 src/main/resources/assets/ebwizardry/loot_tables/chests/obelisk.json create mode 100644 src/main/resources/assets/ebwizardry/loot_tables/chests/shrine.json create mode 100644 src/main/resources/assets/ebwizardry/loot_tables/subsets/elemental_crystals.json create mode 100644 src/main/resources/assets/ebwizardry/loot_tables/subsets/epic_artefacts.json delete mode 100644 src/main/resources/assets/ebwizardry/loot_tables/subsets/novice_wands.json create mode 100644 src/main/resources/assets/ebwizardry/loot_tables/subsets/rare_artefacts.json create mode 100644 src/main/resources/assets/ebwizardry/loot_tables/subsets/uncommon_artefacts.json create mode 100644 src/main/resources/assets/ebwizardry/models/block/earth_crystal_block.json create mode 100644 src/main/resources/assets/ebwizardry/models/block/earth_runestone_1.json create mode 100644 src/main/resources/assets/ebwizardry/models/block/earth_runestone_2.json create mode 100644 src/main/resources/assets/ebwizardry/models/block/earth_runestone_3.json create mode 100644 src/main/resources/assets/ebwizardry/models/block/earth_runestone_4.json create mode 100644 src/main/resources/assets/ebwizardry/models/block/earth_runestone_pedestal.json create mode 100644 src/main/resources/assets/ebwizardry/models/block/fire_crystal_block.json create mode 100644 src/main/resources/assets/ebwizardry/models/block/fire_runestone_1.json create mode 100644 src/main/resources/assets/ebwizardry/models/block/fire_runestone_2.json create mode 100644 src/main/resources/assets/ebwizardry/models/block/fire_runestone_3.json create mode 100644 src/main/resources/assets/ebwizardry/models/block/fire_runestone_4.json create mode 100644 src/main/resources/assets/ebwizardry/models/block/fire_runestone_pedestal.json create mode 100644 src/main/resources/assets/ebwizardry/models/block/healing_crystal_block.json create mode 100644 src/main/resources/assets/ebwizardry/models/block/healing_runestone_1.json create mode 100644 src/main/resources/assets/ebwizardry/models/block/healing_runestone_2.json create mode 100644 src/main/resources/assets/ebwizardry/models/block/healing_runestone_3.json create mode 100644 src/main/resources/assets/ebwizardry/models/block/healing_runestone_4.json create mode 100644 src/main/resources/assets/ebwizardry/models/block/healing_runestone_pedestal.json create mode 100644 src/main/resources/assets/ebwizardry/models/block/ice_crystal_block.json create mode 100644 src/main/resources/assets/ebwizardry/models/block/ice_runestone_1.json create mode 100644 src/main/resources/assets/ebwizardry/models/block/ice_runestone_2.json create mode 100644 src/main/resources/assets/ebwizardry/models/block/ice_runestone_3.json create mode 100644 src/main/resources/assets/ebwizardry/models/block/ice_runestone_4.json create mode 100644 src/main/resources/assets/ebwizardry/models/block/ice_runestone_pedestal.json create mode 100644 src/main/resources/assets/ebwizardry/models/block/lightning_crystal_block.json create mode 100644 src/main/resources/assets/ebwizardry/models/block/lightning_runestone_1.json create mode 100644 src/main/resources/assets/ebwizardry/models/block/lightning_runestone_2.json create mode 100644 src/main/resources/assets/ebwizardry/models/block/lightning_runestone_3.json create mode 100644 src/main/resources/assets/ebwizardry/models/block/lightning_runestone_4.json create mode 100644 src/main/resources/assets/ebwizardry/models/block/lightning_runestone_pedestal.json rename src/main/resources/assets/ebwizardry/models/block/{crystal_block.json => magic_crystal_block.json} (100%) create mode 100644 src/main/resources/assets/ebwizardry/models/block/necromancy_crystal_block.json create mode 100644 src/main/resources/assets/ebwizardry/models/block/necromancy_runestone_1.json create mode 100644 src/main/resources/assets/ebwizardry/models/block/necromancy_runestone_2.json create mode 100644 src/main/resources/assets/ebwizardry/models/block/necromancy_runestone_3.json create mode 100644 src/main/resources/assets/ebwizardry/models/block/necromancy_runestone_4.json create mode 100644 src/main/resources/assets/ebwizardry/models/block/necromancy_runestone_pedestal.json create mode 100644 src/main/resources/assets/ebwizardry/models/block/obsidian_crust_0.json create mode 100644 src/main/resources/assets/ebwizardry/models/block/obsidian_crust_1.json create mode 100644 src/main/resources/assets/ebwizardry/models/block/obsidian_crust_2.json create mode 100644 src/main/resources/assets/ebwizardry/models/block/obsidian_crust_3.json create mode 100644 src/main/resources/assets/ebwizardry/models/block/runestone.json create mode 100644 src/main/resources/assets/ebwizardry/models/block/runestone_pedestal.json create mode 100644 src/main/resources/assets/ebwizardry/models/block/sorcery_crystal_block.json create mode 100644 src/main/resources/assets/ebwizardry/models/block/sorcery_runestone_1.json create mode 100644 src/main/resources/assets/ebwizardry/models/block/sorcery_runestone_2.json create mode 100644 src/main/resources/assets/ebwizardry/models/block/sorcery_runestone_3.json create mode 100644 src/main/resources/assets/ebwizardry/models/block/sorcery_runestone_4.json create mode 100644 src/main/resources/assets/ebwizardry/models/block/sorcery_runestone_pedestal.json create mode 100644 src/main/resources/assets/ebwizardry/models/block/thorns_lower_0.json create mode 100644 src/main/resources/assets/ebwizardry/models/block/thorns_lower_1.json create mode 100644 src/main/resources/assets/ebwizardry/models/block/thorns_lower_2.json create mode 100644 src/main/resources/assets/ebwizardry/models/block/thorns_lower_3.json create mode 100644 src/main/resources/assets/ebwizardry/models/block/thorns_lower_4.json create mode 100644 src/main/resources/assets/ebwizardry/models/block/thorns_lower_5.json create mode 100644 src/main/resources/assets/ebwizardry/models/block/thorns_lower_6.json create mode 100644 src/main/resources/assets/ebwizardry/models/block/thorns_lower_7.json create mode 100644 src/main/resources/assets/ebwizardry/models/block/thorns_upper_0.json create mode 100644 src/main/resources/assets/ebwizardry/models/block/thorns_upper_1.json create mode 100644 src/main/resources/assets/ebwizardry/models/block/thorns_upper_2.json create mode 100644 src/main/resources/assets/ebwizardry/models/block/thorns_upper_3.json create mode 100644 src/main/resources/assets/ebwizardry/models/block/thorns_upper_4.json create mode 100644 src/main/resources/assets/ebwizardry/models/block/thorns_upper_5.json create mode 100644 src/main/resources/assets/ebwizardry/models/block/thorns_upper_6.json create mode 100644 src/main/resources/assets/ebwizardry/models/block/thorns_upper_7.json create mode 100644 src/main/resources/assets/ebwizardry/models/item/amulet_anchoring.json create mode 100644 src/main/resources/assets/ebwizardry/models/item/amulet_arcane_defence.json create mode 100644 src/main/resources/assets/ebwizardry/models/item/amulet_auto_shield.json create mode 100644 src/main/resources/assets/ebwizardry/models/item/amulet_banishing.json create mode 100644 src/main/resources/assets/ebwizardry/models/item/amulet_channeling.json create mode 100644 src/main/resources/assets/ebwizardry/models/item/amulet_fire_cloaking.json create mode 100644 src/main/resources/assets/ebwizardry/models/item/amulet_fire_protection.json create mode 100644 src/main/resources/assets/ebwizardry/models/item/amulet_glide.json create mode 100644 src/main/resources/assets/ebwizardry/models/item/amulet_ice_immunity.json create mode 100644 src/main/resources/assets/ebwizardry/models/item/amulet_ice_protection.json create mode 100644 src/main/resources/assets/ebwizardry/models/item/amulet_lich.json create mode 100644 src/main/resources/assets/ebwizardry/models/item/amulet_potential.json create mode 100644 src/main/resources/assets/ebwizardry/models/item/amulet_recovery.json create mode 100644 src/main/resources/assets/ebwizardry/models/item/amulet_resurrection.json create mode 100644 src/main/resources/assets/ebwizardry/models/item/amulet_transience.json create mode 100644 src/main/resources/assets/ebwizardry/models/item/amulet_warding.json create mode 100644 src/main/resources/assets/ebwizardry/models/item/amulet_wisdom.json create mode 100644 src/main/resources/assets/ebwizardry/models/item/amulet_wither_immunity.json create mode 100644 src/main/resources/assets/ebwizardry/models/item/astral_diamond.json delete mode 100644 src/main/resources/assets/ebwizardry/models/item/basic_lightning_wand.json delete mode 100644 src/main/resources/assets/ebwizardry/models/item/basic_necromancy_wand.json delete mode 100644 src/main/resources/assets/ebwizardry/models/item/basic_sorcery_wand.json create mode 100644 src/main/resources/assets/ebwizardry/models/item/charm_abseiling.json create mode 100644 src/main/resources/assets/ebwizardry/models/item/charm_auto_smelt.json create mode 100644 src/main/resources/assets/ebwizardry/models/item/charm_experience_tome.json create mode 100644 src/main/resources/assets/ebwizardry/models/item/charm_feeding.json create mode 100644 src/main/resources/assets/ebwizardry/models/item/charm_flight.json create mode 100644 src/main/resources/assets/ebwizardry/models/item/charm_growth.json create mode 100644 src/main/resources/assets/ebwizardry/models/item/charm_haggler.json create mode 100644 src/main/resources/assets/ebwizardry/models/item/charm_lava_walking.json create mode 100644 src/main/resources/assets/ebwizardry/models/item/charm_light.json create mode 100644 src/main/resources/assets/ebwizardry/models/item/charm_minion_health.json create mode 100644 src/main/resources/assets/ebwizardry/models/item/charm_minion_variants.json create mode 100644 src/main/resources/assets/ebwizardry/models/item/charm_silk_touch.json create mode 100644 src/main/resources/assets/ebwizardry/models/item/charm_stop_time.json create mode 100644 src/main/resources/assets/ebwizardry/models/item/charm_storm.json create mode 100644 src/main/resources/assets/ebwizardry/models/item/charm_transportation.json delete mode 100644 src/main/resources/assets/ebwizardry/models/item/crystal_block.json rename src/main/resources/assets/ebwizardry/models/item/{magic_crystal.json => crystal_earth.json} (53%) create mode 100644 src/main/resources/assets/ebwizardry/models/item/crystal_fire.json create mode 100644 src/main/resources/assets/ebwizardry/models/item/crystal_healing.json create mode 100644 src/main/resources/assets/ebwizardry/models/item/crystal_ice.json create mode 100644 src/main/resources/assets/ebwizardry/models/item/crystal_lightning.json create mode 100644 src/main/resources/assets/ebwizardry/models/item/crystal_magic.json create mode 100644 src/main/resources/assets/ebwizardry/models/item/crystal_necromancy.json create mode 100644 src/main/resources/assets/ebwizardry/models/item/crystal_shard.json create mode 100644 src/main/resources/assets/ebwizardry/models/item/crystal_sorcery.json create mode 100644 src/main/resources/assets/ebwizardry/models/item/earth_crystal_block.json create mode 100644 src/main/resources/assets/ebwizardry/models/item/earth_runestone.json create mode 100644 src/main/resources/assets/ebwizardry/models/item/earth_runestone_pedestal.json create mode 100644 src/main/resources/assets/ebwizardry/models/item/fire_crystal_block.json create mode 100644 src/main/resources/assets/ebwizardry/models/item/fire_runestone.json create mode 100644 src/main/resources/assets/ebwizardry/models/item/fire_runestone_pedestal.json create mode 100644 src/main/resources/assets/ebwizardry/models/item/flaming_axe_conjuring_0.json create mode 100644 src/main/resources/assets/ebwizardry/models/item/flaming_axe_conjuring_1.json create mode 100644 src/main/resources/assets/ebwizardry/models/item/flaming_axe_conjuring_2.json create mode 100644 src/main/resources/assets/ebwizardry/models/item/flaming_axe_conjuring_3.json create mode 100644 src/main/resources/assets/ebwizardry/models/item/flaming_axe_conjuring_4.json create mode 100644 src/main/resources/assets/ebwizardry/models/item/flaming_axe_conjuring_5.json create mode 100644 src/main/resources/assets/ebwizardry/models/item/flaming_axe_conjuring_6.json create mode 100644 src/main/resources/assets/ebwizardry/models/item/flaming_axe_conjuring_7.json create mode 100644 src/main/resources/assets/ebwizardry/models/item/frost_axe_conjuring_0.json create mode 100644 src/main/resources/assets/ebwizardry/models/item/frost_axe_conjuring_1.json create mode 100644 src/main/resources/assets/ebwizardry/models/item/frost_axe_conjuring_2.json create mode 100644 src/main/resources/assets/ebwizardry/models/item/frost_axe_conjuring_3.json create mode 100644 src/main/resources/assets/ebwizardry/models/item/frost_axe_conjuring_4.json create mode 100644 src/main/resources/assets/ebwizardry/models/item/frost_axe_conjuring_5.json create mode 100644 src/main/resources/assets/ebwizardry/models/item/frost_axe_conjuring_6.json create mode 100644 src/main/resources/assets/ebwizardry/models/item/frost_axe_conjuring_7.json create mode 100644 src/main/resources/assets/ebwizardry/models/item/grand_crystal.json create mode 100644 src/main/resources/assets/ebwizardry/models/item/healing_crystal_block.json create mode 100644 src/main/resources/assets/ebwizardry/models/item/healing_runestone.json create mode 100644 src/main/resources/assets/ebwizardry/models/item/healing_runestone_pedestal.json create mode 100644 src/main/resources/assets/ebwizardry/models/item/ice_crystal_block.json create mode 100644 src/main/resources/assets/ebwizardry/models/item/ice_runestone.json create mode 100644 src/main/resources/assets/ebwizardry/models/item/ice_runestone_pedestal.json create mode 100644 src/main/resources/assets/ebwizardry/models/item/large_mana_flask.json create mode 100644 src/main/resources/assets/ebwizardry/models/item/lightning_crystal_block.json create mode 100644 src/main/resources/assets/ebwizardry/models/item/lightning_hammer.json create mode 100644 src/main/resources/assets/ebwizardry/models/item/lightning_runestone.json create mode 100644 src/main/resources/assets/ebwizardry/models/item/lightning_runestone_pedestal.json create mode 100644 src/main/resources/assets/ebwizardry/models/item/magic_crystal_block.json create mode 100644 src/main/resources/assets/ebwizardry/models/item/medium_mana_flask.json create mode 100644 src/main/resources/assets/ebwizardry/models/item/melee_upgrade.json create mode 100644 src/main/resources/assets/ebwizardry/models/item/necromancy_crystal_block.json create mode 100644 src/main/resources/assets/ebwizardry/models/item/necromancy_runestone.json create mode 100644 src/main/resources/assets/ebwizardry/models/item/necromancy_runestone_pedestal.json rename src/main/resources/assets/ebwizardry/models/item/{basic_fire_wand.json => novice_earth_wand.json} (51%) rename src/main/resources/assets/ebwizardry/models/item/{basic_earth_wand.json => novice_fire_wand.json} (52%) rename src/main/resources/assets/ebwizardry/models/item/{basic_healing_wand.json => novice_healing_wand.json} (50%) rename src/main/resources/assets/ebwizardry/models/item/{basic_ice_wand.json => novice_ice_wand.json} (52%) create mode 100644 src/main/resources/assets/ebwizardry/models/item/novice_lightning_wand.json create mode 100644 src/main/resources/assets/ebwizardry/models/item/novice_necromancy_wand.json create mode 100644 src/main/resources/assets/ebwizardry/models/item/novice_sorcery_wand.json create mode 100644 src/main/resources/assets/ebwizardry/models/item/purifying_elixir.json create mode 100644 src/main/resources/assets/ebwizardry/models/item/ring_arcane_frost.json create mode 100644 src/main/resources/assets/ebwizardry/models/item/ring_battlemage.json create mode 100644 src/main/resources/assets/ebwizardry/models/item/ring_blockwrangler.json create mode 100644 src/main/resources/assets/ebwizardry/models/item/ring_combustion.json create mode 100644 src/main/resources/assets/ebwizardry/models/item/ring_condensing.json create mode 100644 src/main/resources/assets/ebwizardry/models/item/ring_conjurer.json create mode 100644 src/main/resources/assets/ebwizardry/models/item/ring_defender.json create mode 100644 src/main/resources/assets/ebwizardry/models/item/ring_disintegration.json create mode 100644 src/main/resources/assets/ebwizardry/models/item/ring_earth_biome.json create mode 100644 src/main/resources/assets/ebwizardry/models/item/ring_earth_melee.json create mode 100644 src/main/resources/assets/ebwizardry/models/item/ring_extraction.json create mode 100644 src/main/resources/assets/ebwizardry/models/item/ring_fire_biome.json create mode 100644 src/main/resources/assets/ebwizardry/models/item/ring_fire_melee.json create mode 100644 src/main/resources/assets/ebwizardry/models/item/ring_full_moon.json create mode 100644 src/main/resources/assets/ebwizardry/models/item/ring_hammer.json create mode 100644 src/main/resources/assets/ebwizardry/models/item/ring_ice_biome.json create mode 100644 src/main/resources/assets/ebwizardry/models/item/ring_ice_melee.json create mode 100644 src/main/resources/assets/ebwizardry/models/item/ring_interdiction.json create mode 100644 src/main/resources/assets/ebwizardry/models/item/ring_leeching.json create mode 100644 src/main/resources/assets/ebwizardry/models/item/ring_lightning_melee.json create mode 100644 src/main/resources/assets/ebwizardry/models/item/ring_mana_return.json create mode 100644 src/main/resources/assets/ebwizardry/models/item/ring_mind_control.json create mode 100644 src/main/resources/assets/ebwizardry/models/item/ring_necromancy_melee.json create mode 100644 src/main/resources/assets/ebwizardry/models/item/ring_paladin.json create mode 100644 src/main/resources/assets/ebwizardry/models/item/ring_poison.json create mode 100644 src/main/resources/assets/ebwizardry/models/item/ring_seeking.json create mode 100644 src/main/resources/assets/ebwizardry/models/item/ring_shattering.json create mode 100644 src/main/resources/assets/ebwizardry/models/item/ring_siphoning.json create mode 100644 src/main/resources/assets/ebwizardry/models/item/ring_soulbinding.json create mode 100644 src/main/resources/assets/ebwizardry/models/item/ring_spirit_animal.json create mode 100644 src/main/resources/assets/ebwizardry/models/item/ring_storm.json create mode 100644 src/main/resources/assets/ebwizardry/models/item/runestone_item.json create mode 100644 src/main/resources/assets/ebwizardry/models/item/runestone_pedestal_item.json create mode 100644 src/main/resources/assets/ebwizardry/models/item/small_mana_flask.json create mode 100644 src/main/resources/assets/ebwizardry/models/item/sorcery_crystal_block.json create mode 100644 src/main/resources/assets/ebwizardry/models/item/sorcery_runestone.json create mode 100644 src/main/resources/assets/ebwizardry/models/item/sorcery_runestone_pedestal.json rename src/main/resources/assets/ebwizardry/models/item/{mana_flask.json => spark_bomb.json} (55%) create mode 100644 src/main/resources/assets/ebwizardry/models/item/spectral_bow_conjuring_0.json create mode 100644 src/main/resources/assets/ebwizardry/models/item/spectral_bow_conjuring_1.json create mode 100644 src/main/resources/assets/ebwizardry/models/item/spectral_bow_conjuring_2.json create mode 100644 src/main/resources/assets/ebwizardry/models/item/spectral_bow_conjuring_3.json create mode 100644 src/main/resources/assets/ebwizardry/models/item/spectral_bow_conjuring_4.json create mode 100644 src/main/resources/assets/ebwizardry/models/item/spectral_bow_conjuring_5.json create mode 100644 src/main/resources/assets/ebwizardry/models/item/spectral_bow_conjuring_6.json create mode 100644 src/main/resources/assets/ebwizardry/models/item/spectral_bow_conjuring_7.json create mode 100644 src/main/resources/assets/ebwizardry/models/item/spectral_pickaxe_conjuring_0.json create mode 100644 src/main/resources/assets/ebwizardry/models/item/spectral_pickaxe_conjuring_1.json create mode 100644 src/main/resources/assets/ebwizardry/models/item/spectral_pickaxe_conjuring_2.json create mode 100644 src/main/resources/assets/ebwizardry/models/item/spectral_pickaxe_conjuring_3.json create mode 100644 src/main/resources/assets/ebwizardry/models/item/spectral_pickaxe_conjuring_4.json create mode 100644 src/main/resources/assets/ebwizardry/models/item/spectral_pickaxe_conjuring_5.json create mode 100644 src/main/resources/assets/ebwizardry/models/item/spectral_pickaxe_conjuring_6.json create mode 100644 src/main/resources/assets/ebwizardry/models/item/spectral_pickaxe_conjuring_7.json create mode 100644 src/main/resources/assets/ebwizardry/models/item/spectral_sword_conjuring_0.json create mode 100644 src/main/resources/assets/ebwizardry/models/item/spectral_sword_conjuring_1.json create mode 100644 src/main/resources/assets/ebwizardry/models/item/spectral_sword_conjuring_2.json create mode 100644 src/main/resources/assets/ebwizardry/models/item/spectral_sword_conjuring_3.json create mode 100644 src/main/resources/assets/ebwizardry/models/item/spectral_sword_conjuring_4.json create mode 100644 src/main/resources/assets/ebwizardry/models/item/spectral_sword_conjuring_5.json create mode 100644 src/main/resources/assets/ebwizardry/models/item/spectral_sword_conjuring_6.json create mode 100644 src/main/resources/assets/ebwizardry/models/item/spectral_sword_conjuring_7.json create mode 100644 src/main/resources/assets/ebwizardry/models/item/thorns.json create mode 100644 src/main/resources/assets/ebwizardry/recipes/crystal_block_earth.json create mode 100644 src/main/resources/assets/ebwizardry/recipes/crystal_block_fire.json create mode 100644 src/main/resources/assets/ebwizardry/recipes/crystal_block_healing.json create mode 100644 src/main/resources/assets/ebwizardry/recipes/crystal_block_ice.json create mode 100644 src/main/resources/assets/ebwizardry/recipes/crystal_block_lightning.json create mode 100644 src/main/resources/assets/ebwizardry/recipes/crystal_block_necromancy.json create mode 100644 src/main/resources/assets/ebwizardry/recipes/crystal_block_sorcery.json create mode 100644 src/main/resources/assets/ebwizardry/recipes/crystal_block_to_crystals_earth.json create mode 100644 src/main/resources/assets/ebwizardry/recipes/crystal_block_to_crystals_fire.json create mode 100644 src/main/resources/assets/ebwizardry/recipes/crystal_block_to_crystals_healing.json create mode 100644 src/main/resources/assets/ebwizardry/recipes/crystal_block_to_crystals_ice.json create mode 100644 src/main/resources/assets/ebwizardry/recipes/crystal_block_to_crystals_lightning.json create mode 100644 src/main/resources/assets/ebwizardry/recipes/crystal_block_to_crystals_necromancy.json create mode 100644 src/main/resources/assets/ebwizardry/recipes/crystal_block_to_crystals_sorcery.json create mode 100644 src/main/resources/assets/ebwizardry/recipes/crystal_shard.json create mode 100644 src/main/resources/assets/ebwizardry/recipes/large_mana_flask.json create mode 100644 src/main/resources/assets/ebwizardry/recipes/medium_mana_flask.json create mode 100644 src/main/resources/assets/ebwizardry/recipes/runestone_earth.json create mode 100644 src/main/resources/assets/ebwizardry/recipes/runestone_fire.json create mode 100644 src/main/resources/assets/ebwizardry/recipes/runestone_healing.json create mode 100644 src/main/resources/assets/ebwizardry/recipes/runestone_ice.json create mode 100644 src/main/resources/assets/ebwizardry/recipes/runestone_lightning.json create mode 100644 src/main/resources/assets/ebwizardry/recipes/runestone_necromancy.json create mode 100644 src/main/resources/assets/ebwizardry/recipes/runestone_pedestal_earth.json create mode 100644 src/main/resources/assets/ebwizardry/recipes/runestone_pedestal_fire.json create mode 100644 src/main/resources/assets/ebwizardry/recipes/runestone_pedestal_healing.json create mode 100644 src/main/resources/assets/ebwizardry/recipes/runestone_pedestal_ice.json create mode 100644 src/main/resources/assets/ebwizardry/recipes/runestone_pedestal_lightning.json create mode 100644 src/main/resources/assets/ebwizardry/recipes/runestone_pedestal_necromancy.json create mode 100644 src/main/resources/assets/ebwizardry/recipes/runestone_pedestal_sorcery.json create mode 100644 src/main/resources/assets/ebwizardry/recipes/runestone_sorcery.json rename src/main/resources/assets/ebwizardry/recipes/{mana_flask.json => small_mana_flask.json} (71%) create mode 100644 src/main/resources/assets/ebwizardry/recipes/spark_bomb.json create mode 100644 src/main/resources/assets/ebwizardry/recipes/wand_earth.json create mode 100644 src/main/resources/assets/ebwizardry/recipes/wand_fire.json create mode 100644 src/main/resources/assets/ebwizardry/recipes/wand_healing.json create mode 100644 src/main/resources/assets/ebwizardry/recipes/wand_ice.json create mode 100644 src/main/resources/assets/ebwizardry/recipes/wand_lightning.json create mode 100644 src/main/resources/assets/ebwizardry/recipes/wand_necromancy.json create mode 100644 src/main/resources/assets/ebwizardry/recipes/wand_sorcery.json create mode 100644 src/main/resources/assets/ebwizardry/shaders/post/possession.json create mode 100644 src/main/resources/assets/ebwizardry/shaders/post/sixth_sense.json create mode 100644 src/main/resources/assets/ebwizardry/shaders/post/slow_time.json create mode 100644 src/main/resources/assets/ebwizardry/shaders/post/transience.json create mode 100644 src/main/resources/assets/ebwizardry/sounds/aura_end.ogg create mode 100644 src/main/resources/assets/ebwizardry/sounds/aura_loop.ogg create mode 100644 src/main/resources/assets/ebwizardry/sounds/aura_start.ogg create mode 100644 src/main/resources/assets/ebwizardry/sounds/book.ogg delete mode 100644 src/main/resources/assets/ebwizardry/sounds/boom.ogg create mode 100644 src/main/resources/assets/ebwizardry/sounds/buff.ogg rename src/main/resources/assets/ebwizardry/sounds/{aura.ogg => conjure.ogg} (100%) rename src/main/resources/assets/ebwizardry/sounds/{largeaura.ogg => conjure_large.ogg} (100%) create mode 100644 src/main/resources/assets/ebwizardry/sounds/dark_aura_end.ogg create mode 100644 src/main/resources/assets/ebwizardry/sounds/dark_aura_loop.ogg create mode 100644 src/main/resources/assets/ebwizardry/sounds/dark_aura_start.ogg create mode 100644 src/main/resources/assets/ebwizardry/sounds/firebolt.ogg delete mode 100644 src/main/resources/assets/ebwizardry/sounds/flameray1.ogg delete mode 100644 src/main/resources/assets/ebwizardry/sounds/flameray2.ogg create mode 100644 src/main/resources/assets/ebwizardry/sounds/flames_end.ogg create mode 100644 src/main/resources/assets/ebwizardry/sounds/flames_loop.ogg create mode 100644 src/main/resources/assets/ebwizardry/sounds/flames_start.ogg create mode 100644 src/main/resources/assets/ebwizardry/sounds/grow.ogg rename src/main/resources/assets/ebwizardry/sounds/{electricityb.ogg => lightning_ray_end.ogg} (100%) create mode 100644 src/main/resources/assets/ebwizardry/sounds/lightning_ray_loop.ogg rename src/main/resources/assets/ebwizardry/sounds/{electricitya.ogg => lightning_ray_start.ogg} (100%) create mode 100644 src/main/resources/assets/ebwizardry/sounds/page1.ogg create mode 100644 src/main/resources/assets/ebwizardry/sounds/page2.ogg create mode 100644 src/main/resources/assets/ebwizardry/sounds/page3.ogg create mode 100644 src/main/resources/assets/ebwizardry/sounds/pull1.ogg create mode 100644 src/main/resources/assets/ebwizardry/sounds/pull2.ogg create mode 100644 src/main/resources/assets/ebwizardry/sounds/shockwave.ogg create mode 100644 src/main/resources/assets/ebwizardry/sounds/small_aura_end.ogg create mode 100644 src/main/resources/assets/ebwizardry/sounds/small_aura_loop.ogg create mode 100644 src/main/resources/assets/ebwizardry/sounds/small_aura_start.ogg create mode 100644 src/main/resources/assets/ebwizardry/sounds/spellbind.ogg rename src/main/resources/assets/ebwizardry/sounds/{darkaura1.ogg => summon1.ogg} (100%) rename src/main/resources/assets/ebwizardry/sounds/{darkaura2.ogg => summon2.ogg} (100%) create mode 100644 src/main/resources/assets/ebwizardry/spells/agility.json create mode 100644 src/main/resources/assets/ebwizardry/spells/arc.json create mode 100644 src/main/resources/assets/ebwizardry/spells/arcane_jammer.json create mode 100644 src/main/resources/assets/ebwizardry/spells/arcane_lock.json create mode 100644 src/main/resources/assets/ebwizardry/spells/arrow_rain.json create mode 100644 src/main/resources/assets/ebwizardry/spells/banish.json create mode 100644 src/main/resources/assets/ebwizardry/spells/black_hole.json create mode 100644 src/main/resources/assets/ebwizardry/spells/blink.json create mode 100644 src/main/resources/assets/ebwizardry/spells/blizzard.json create mode 100644 src/main/resources/assets/ebwizardry/spells/bubble.json create mode 100644 src/main/resources/assets/ebwizardry/spells/chain_lightning.json create mode 100644 src/main/resources/assets/ebwizardry/spells/charge.json create mode 100644 src/main/resources/assets/ebwizardry/spells/clairvoyance.json create mode 100644 src/main/resources/assets/ebwizardry/spells/cobwebs.json create mode 100644 src/main/resources/assets/ebwizardry/spells/combustion_rune.json create mode 100644 src/main/resources/assets/ebwizardry/spells/conjure_armour.json create mode 100644 src/main/resources/assets/ebwizardry/spells/conjure_block.json create mode 100644 src/main/resources/assets/ebwizardry/spells/conjure_bow.json create mode 100644 src/main/resources/assets/ebwizardry/spells/conjure_pickaxe.json create mode 100644 src/main/resources/assets/ebwizardry/spells/conjure_sword.json create mode 100644 src/main/resources/assets/ebwizardry/spells/containment.json create mode 100644 src/main/resources/assets/ebwizardry/spells/cure_effects.json create mode 100644 src/main/resources/assets/ebwizardry/spells/curse_of_enfeeblement.json create mode 100644 src/main/resources/assets/ebwizardry/spells/curse_of_soulbinding.json create mode 100644 src/main/resources/assets/ebwizardry/spells/curse_of_undeath.json create mode 100644 src/main/resources/assets/ebwizardry/spells/darkness_orb.json create mode 100644 src/main/resources/assets/ebwizardry/spells/darkvision.json create mode 100644 src/main/resources/assets/ebwizardry/spells/dart.json create mode 100644 src/main/resources/assets/ebwizardry/spells/decay.json create mode 100644 src/main/resources/assets/ebwizardry/spells/decoy.json create mode 100644 src/main/resources/assets/ebwizardry/spells/detonate.json create mode 100644 src/main/resources/assets/ebwizardry/spells/diamondflesh.json create mode 100644 src/main/resources/assets/ebwizardry/spells/disintegration.json create mode 100644 src/main/resources/assets/ebwizardry/spells/divination.json create mode 100644 src/main/resources/assets/ebwizardry/spells/dragon_fireball.json create mode 100644 src/main/resources/assets/ebwizardry/spells/earthquake.json create mode 100644 src/main/resources/assets/ebwizardry/spells/empowering_presence.json create mode 100644 src/main/resources/assets/ebwizardry/spells/entrapment.json create mode 100644 src/main/resources/assets/ebwizardry/spells/evade.json create mode 100644 src/main/resources/assets/ebwizardry/spells/fire_breath.json create mode 100644 src/main/resources/assets/ebwizardry/spells/fire_resistance.json create mode 100644 src/main/resources/assets/ebwizardry/spells/fire_sigil.json create mode 100644 src/main/resources/assets/ebwizardry/spells/fireball.json create mode 100644 src/main/resources/assets/ebwizardry/spells/firebolt.json create mode 100644 src/main/resources/assets/ebwizardry/spells/firebomb.json create mode 100644 src/main/resources/assets/ebwizardry/spells/fireskin.json create mode 100644 src/main/resources/assets/ebwizardry/spells/flame_ray.json create mode 100644 src/main/resources/assets/ebwizardry/spells/flaming_axe.json create mode 100644 src/main/resources/assets/ebwizardry/spells/flaming_weapon.json create mode 100644 src/main/resources/assets/ebwizardry/spells/flight.json create mode 100644 src/main/resources/assets/ebwizardry/spells/font_of_mana.json create mode 100644 src/main/resources/assets/ebwizardry/spells/font_of_vitality.json create mode 100644 src/main/resources/assets/ebwizardry/spells/force_arrow.json create mode 100644 src/main/resources/assets/ebwizardry/spells/force_orb.json create mode 100644 src/main/resources/assets/ebwizardry/spells/forcefield.json create mode 100644 src/main/resources/assets/ebwizardry/spells/forest_of_thorns.json create mode 100644 src/main/resources/assets/ebwizardry/spells/forests_curse.json create mode 100644 src/main/resources/assets/ebwizardry/spells/freeze.json create mode 100644 src/main/resources/assets/ebwizardry/spells/freezing_weapon.json create mode 100644 src/main/resources/assets/ebwizardry/spells/frost_axe.json create mode 100644 src/main/resources/assets/ebwizardry/spells/frost_ray.json create mode 100644 src/main/resources/assets/ebwizardry/spells/frost_sigil.json create mode 100644 src/main/resources/assets/ebwizardry/spells/frost_step.json create mode 100644 src/main/resources/assets/ebwizardry/spells/glide.json create mode 100644 src/main/resources/assets/ebwizardry/spells/grapple.json create mode 100644 src/main/resources/assets/ebwizardry/spells/greater_fireball.json create mode 100644 src/main/resources/assets/ebwizardry/spells/greater_heal.json create mode 100644 src/main/resources/assets/ebwizardry/spells/greater_telekinesis.json create mode 100644 src/main/resources/assets/ebwizardry/spells/greater_ward.json create mode 100644 src/main/resources/assets/ebwizardry/spells/group_heal.json create mode 100644 src/main/resources/assets/ebwizardry/spells/growth_aura.json create mode 100644 src/main/resources/assets/ebwizardry/spells/hailstorm.json create mode 100644 src/main/resources/assets/ebwizardry/spells/heal.json create mode 100644 src/main/resources/assets/ebwizardry/spells/heal_ally.json create mode 100644 src/main/resources/assets/ebwizardry/spells/healing_aura.json create mode 100644 src/main/resources/assets/ebwizardry/spells/homing_spark.json create mode 100644 src/main/resources/assets/ebwizardry/spells/ice_age.json create mode 100644 src/main/resources/assets/ebwizardry/spells/ice_charge.json create mode 100644 src/main/resources/assets/ebwizardry/spells/ice_lance.json create mode 100644 src/main/resources/assets/ebwizardry/spells/ice_shard.json create mode 100644 src/main/resources/assets/ebwizardry/spells/ice_shroud.json create mode 100644 src/main/resources/assets/ebwizardry/spells/ice_spikes.json create mode 100644 src/main/resources/assets/ebwizardry/spells/ice_statue.json create mode 100644 src/main/resources/assets/ebwizardry/spells/iceball.json create mode 100644 src/main/resources/assets/ebwizardry/spells/ignite.json create mode 100644 src/main/resources/assets/ebwizardry/spells/imbue_weapon.json create mode 100644 src/main/resources/assets/ebwizardry/spells/intimidate.json create mode 100644 src/main/resources/assets/ebwizardry/spells/invigorating_presence.json create mode 100644 src/main/resources/assets/ebwizardry/spells/invisibility.json create mode 100644 src/main/resources/assets/ebwizardry/spells/invoke_weather.json create mode 100644 src/main/resources/assets/ebwizardry/spells/ironflesh.json create mode 100644 src/main/resources/assets/ebwizardry/spells/leap.json create mode 100644 src/main/resources/assets/ebwizardry/spells/levitation.json create mode 100644 src/main/resources/assets/ebwizardry/spells/life_drain.json create mode 100644 src/main/resources/assets/ebwizardry/spells/light.json create mode 100644 src/main/resources/assets/ebwizardry/spells/lightning_arrow.json create mode 100644 src/main/resources/assets/ebwizardry/spells/lightning_bolt.json create mode 100644 src/main/resources/assets/ebwizardry/spells/lightning_disc.json create mode 100644 src/main/resources/assets/ebwizardry/spells/lightning_hammer.json create mode 100644 src/main/resources/assets/ebwizardry/spells/lightning_pulse.json create mode 100644 src/main/resources/assets/ebwizardry/spells/lightning_ray.json create mode 100644 src/main/resources/assets/ebwizardry/spells/lightning_sigil.json create mode 100644 src/main/resources/assets/ebwizardry/spells/lightning_web.json create mode 100644 src/main/resources/assets/ebwizardry/spells/magic_missile.json create mode 100644 src/main/resources/assets/ebwizardry/spells/metamorphosis.json create mode 100644 src/main/resources/assets/ebwizardry/spells/meteor.json create mode 100644 src/main/resources/assets/ebwizardry/spells/mind_control.json create mode 100644 src/main/resources/assets/ebwizardry/spells/mind_trick.json create mode 100644 src/main/resources/assets/ebwizardry/spells/mine.json create mode 100644 src/main/resources/assets/ebwizardry/spells/muffle.json create mode 100644 src/main/resources/assets/ebwizardry/spells/none.json create mode 100644 src/main/resources/assets/ebwizardry/spells/oakflesh.json create mode 100644 src/main/resources/assets/ebwizardry/spells/paralysis.json create mode 100644 src/main/resources/assets/ebwizardry/spells/petrify.json create mode 100644 src/main/resources/assets/ebwizardry/spells/phase_step.json create mode 100644 src/main/resources/assets/ebwizardry/spells/plague_of_darkness.json create mode 100644 src/main/resources/assets/ebwizardry/spells/pocket_furnace.json create mode 100644 src/main/resources/assets/ebwizardry/spells/pocket_workbench.json create mode 100644 src/main/resources/assets/ebwizardry/spells/poison.json create mode 100644 src/main/resources/assets/ebwizardry/spells/poison_bomb.json create mode 100644 src/main/resources/assets/ebwizardry/spells/possession.json create mode 100644 src/main/resources/assets/ebwizardry/spells/ray_of_purification.json create mode 100644 src/main/resources/assets/ebwizardry/spells/remove_curse.json create mode 100644 src/main/resources/assets/ebwizardry/spells/replenish_hunger.json create mode 100644 src/main/resources/assets/ebwizardry/spells/resurrection.json create mode 100644 src/main/resources/assets/ebwizardry/spells/reversal.json create mode 100644 src/main/resources/assets/ebwizardry/spells/ring_of_fire.json create mode 100644 src/main/resources/assets/ebwizardry/spells/satiety.json create mode 100644 src/main/resources/assets/ebwizardry/spells/shadow_ward.json create mode 100644 src/main/resources/assets/ebwizardry/spells/shield.json create mode 100644 src/main/resources/assets/ebwizardry/spells/shockwave.json create mode 100644 src/main/resources/assets/ebwizardry/spells/shulker_bullet.json create mode 100644 src/main/resources/assets/ebwizardry/spells/silverfish_swarm.json create mode 100644 src/main/resources/assets/ebwizardry/spells/sixth_sense.json create mode 100644 src/main/resources/assets/ebwizardry/spells/slime.json create mode 100644 src/main/resources/assets/ebwizardry/spells/slow_time.json create mode 100644 src/main/resources/assets/ebwizardry/spells/smoke_bomb.json create mode 100644 src/main/resources/assets/ebwizardry/spells/snare.json create mode 100644 src/main/resources/assets/ebwizardry/spells/snowball.json create mode 100644 src/main/resources/assets/ebwizardry/spells/spark_bomb.json create mode 100644 src/main/resources/assets/ebwizardry/spells/spectral_pathway.json create mode 100644 src/main/resources/assets/ebwizardry/spells/speed_time.json create mode 100644 src/main/resources/assets/ebwizardry/spells/spider_swarm.json create mode 100644 src/main/resources/assets/ebwizardry/spells/static_aura.json create mode 100644 src/main/resources/assets/ebwizardry/spells/summon_blaze.json create mode 100644 src/main/resources/assets/ebwizardry/spells/summon_ice_giant.json create mode 100644 src/main/resources/assets/ebwizardry/spells/summon_ice_wraith.json create mode 100644 src/main/resources/assets/ebwizardry/spells/summon_iron_golem.json create mode 100644 src/main/resources/assets/ebwizardry/spells/summon_lightning_wraith.json create mode 100644 src/main/resources/assets/ebwizardry/spells/summon_phoenix.json create mode 100644 src/main/resources/assets/ebwizardry/spells/summon_shadow_wraith.json create mode 100644 src/main/resources/assets/ebwizardry/spells/summon_skeleton.json create mode 100644 src/main/resources/assets/ebwizardry/spells/summon_skeleton_legion.json create mode 100644 src/main/resources/assets/ebwizardry/spells/summon_snow_golem.json create mode 100644 src/main/resources/assets/ebwizardry/spells/summon_spirit_horse.json create mode 100644 src/main/resources/assets/ebwizardry/spells/summon_spirit_wolf.json create mode 100644 src/main/resources/assets/ebwizardry/spells/summon_storm_elemental.json create mode 100644 src/main/resources/assets/ebwizardry/spells/summon_wither_skeleton.json create mode 100644 src/main/resources/assets/ebwizardry/spells/summon_zombie.json create mode 100644 src/main/resources/assets/ebwizardry/spells/telekinesis.json create mode 100644 src/main/resources/assets/ebwizardry/spells/thunderbolt.json create mode 100644 src/main/resources/assets/ebwizardry/spells/thunderstorm.json create mode 100644 src/main/resources/assets/ebwizardry/spells/tornado.json create mode 100644 src/main/resources/assets/ebwizardry/spells/transience.json create mode 100644 src/main/resources/assets/ebwizardry/spells/transportation.json create mode 100644 src/main/resources/assets/ebwizardry/spells/vanishing_box.json create mode 100644 src/main/resources/assets/ebwizardry/spells/vex_swarm.json create mode 100644 src/main/resources/assets/ebwizardry/spells/wall_of_frost.json create mode 100644 src/main/resources/assets/ebwizardry/spells/ward.json create mode 100644 src/main/resources/assets/ebwizardry/spells/water_breathing.json create mode 100644 src/main/resources/assets/ebwizardry/spells/whirlwind.json create mode 100644 src/main/resources/assets/ebwizardry/spells/wither.json create mode 100644 src/main/resources/assets/ebwizardry/spells/wither_skull.json create mode 100644 src/main/resources/assets/ebwizardry/structures/obelisk_0.nbt create mode 100644 src/main/resources/assets/ebwizardry/structures/obelisk_1.nbt create mode 100644 src/main/resources/assets/ebwizardry/structures/obelisk_2.nbt create mode 100644 src/main/resources/assets/ebwizardry/structures/obelisk_3.nbt create mode 100644 src/main/resources/assets/ebwizardry/structures/obelisk_4.nbt create mode 100644 src/main/resources/assets/ebwizardry/structures/shrine_0.nbt create mode 100644 src/main/resources/assets/ebwizardry/structures/shrine_1.nbt create mode 100644 src/main/resources/assets/ebwizardry/structures/shrine_2.nbt create mode 100644 src/main/resources/assets/ebwizardry/structures/shrine_3.nbt create mode 100644 src/main/resources/assets/ebwizardry/structures/shrine_4.nbt create mode 100644 src/main/resources/assets/ebwizardry/structures/shrine_5.nbt create mode 100644 src/main/resources/assets/ebwizardry/structures/shrine_6.nbt create mode 100644 src/main/resources/assets/ebwizardry/structures/shrine_7.nbt create mode 100644 src/main/resources/assets/ebwizardry/structures/wizard_tower_0.nbt create mode 100644 src/main/resources/assets/ebwizardry/structures/wizard_tower_1.nbt create mode 100644 src/main/resources/assets/ebwizardry/structures/wizard_tower_2.nbt create mode 100644 src/main/resources/assets/ebwizardry/structures/wizard_tower_3.nbt create mode 100644 src/main/resources/assets/ebwizardry/structures/wizard_tower_chest_0.nbt create mode 100644 src/main/resources/assets/ebwizardry/structures/wizard_tower_chest_1.nbt create mode 100644 src/main/resources/assets/ebwizardry/structures/wizard_tower_chest_2.nbt create mode 100644 src/main/resources/assets/ebwizardry/structures/wizard_tower_chest_3.nbt delete mode 100644 src/main/resources/assets/ebwizardry/texts/handbook_en_gb.txt delete mode 100644 src/main/resources/assets/ebwizardry/texts/handbook_en_us.txt create mode 100644 src/main/resources/assets/ebwizardry/texts/handbook_ko_kr.txt delete mode 100644 src/main/resources/assets/ebwizardry/textures/armour/invisible_armour.png create mode 100644 src/main/resources/assets/ebwizardry/textures/armour/legendary_wizard_armour.png create mode 100644 src/main/resources/assets/ebwizardry/textures/armour/legendary_wizard_armour_earth.png create mode 100644 src/main/resources/assets/ebwizardry/textures/armour/legendary_wizard_armour_earth_legs.png create mode 100644 src/main/resources/assets/ebwizardry/textures/armour/legendary_wizard_armour_fire.png create mode 100644 src/main/resources/assets/ebwizardry/textures/armour/legendary_wizard_armour_fire_legs.png create mode 100644 src/main/resources/assets/ebwizardry/textures/armour/legendary_wizard_armour_healing.png create mode 100644 src/main/resources/assets/ebwizardry/textures/armour/legendary_wizard_armour_healing_legs.png create mode 100644 src/main/resources/assets/ebwizardry/textures/armour/legendary_wizard_armour_ice.png create mode 100644 src/main/resources/assets/ebwizardry/textures/armour/legendary_wizard_armour_ice_legs.png create mode 100644 src/main/resources/assets/ebwizardry/textures/armour/legendary_wizard_armour_legs.png create mode 100644 src/main/resources/assets/ebwizardry/textures/armour/legendary_wizard_armour_lightning.png create mode 100644 src/main/resources/assets/ebwizardry/textures/armour/legendary_wizard_armour_lightning_legs.png create mode 100644 src/main/resources/assets/ebwizardry/textures/armour/legendary_wizard_armour_necromancy.png create mode 100644 src/main/resources/assets/ebwizardry/textures/armour/legendary_wizard_armour_necromancy_legs.png create mode 100644 src/main/resources/assets/ebwizardry/textures/armour/legendary_wizard_armour_sorcery.png create mode 100644 src/main/resources/assets/ebwizardry/textures/armour/legendary_wizard_armour_sorcery_legs.png create mode 100644 src/main/resources/assets/ebwizardry/textures/blocks/crystal_block_earth.png create mode 100644 src/main/resources/assets/ebwizardry/textures/blocks/crystal_block_fire.png create mode 100644 src/main/resources/assets/ebwizardry/textures/blocks/crystal_block_healing.png create mode 100644 src/main/resources/assets/ebwizardry/textures/blocks/crystal_block_ice.png create mode 100644 src/main/resources/assets/ebwizardry/textures/blocks/crystal_block_lightning.png create mode 100644 src/main/resources/assets/ebwizardry/textures/blocks/crystal_block_necromancy.png create mode 100644 src/main/resources/assets/ebwizardry/textures/blocks/crystal_block_sorcery.png create mode 100644 src/main/resources/assets/ebwizardry/textures/blocks/obsidian_crust_0.png create mode 100644 src/main/resources/assets/ebwizardry/textures/blocks/obsidian_crust_1.png create mode 100644 src/main/resources/assets/ebwizardry/textures/blocks/obsidian_crust_2.png create mode 100644 src/main/resources/assets/ebwizardry/textures/blocks/obsidian_crust_3.png create mode 100644 src/main/resources/assets/ebwizardry/textures/blocks/runestone_earth_0.png create mode 100644 src/main/resources/assets/ebwizardry/textures/blocks/runestone_earth_1.png create mode 100644 src/main/resources/assets/ebwizardry/textures/blocks/runestone_earth_1_overlay.png create mode 100644 src/main/resources/assets/ebwizardry/textures/blocks/runestone_earth_2.png create mode 100644 src/main/resources/assets/ebwizardry/textures/blocks/runestone_earth_2_overlay.png create mode 100644 src/main/resources/assets/ebwizardry/textures/blocks/runestone_earth_3.png create mode 100644 src/main/resources/assets/ebwizardry/textures/blocks/runestone_earth_3_overlay.png create mode 100644 src/main/resources/assets/ebwizardry/textures/blocks/runestone_earth_4.png create mode 100644 src/main/resources/assets/ebwizardry/textures/blocks/runestone_earth_4_overlay.png create mode 100644 src/main/resources/assets/ebwizardry/textures/blocks/runestone_fire_0.png create mode 100644 src/main/resources/assets/ebwizardry/textures/blocks/runestone_fire_1.png create mode 100644 src/main/resources/assets/ebwizardry/textures/blocks/runestone_fire_1_overlay.png create mode 100644 src/main/resources/assets/ebwizardry/textures/blocks/runestone_fire_2.png create mode 100644 src/main/resources/assets/ebwizardry/textures/blocks/runestone_fire_2_overlay.png create mode 100644 src/main/resources/assets/ebwizardry/textures/blocks/runestone_fire_3.png create mode 100644 src/main/resources/assets/ebwizardry/textures/blocks/runestone_fire_3_overlay.png create mode 100644 src/main/resources/assets/ebwizardry/textures/blocks/runestone_fire_4.png create mode 100644 src/main/resources/assets/ebwizardry/textures/blocks/runestone_fire_4_overlay.png create mode 100644 src/main/resources/assets/ebwizardry/textures/blocks/runestone_healing_0.png create mode 100644 src/main/resources/assets/ebwizardry/textures/blocks/runestone_healing_1.png create mode 100644 src/main/resources/assets/ebwizardry/textures/blocks/runestone_healing_1_overlay.png create mode 100644 src/main/resources/assets/ebwizardry/textures/blocks/runestone_healing_2.png create mode 100644 src/main/resources/assets/ebwizardry/textures/blocks/runestone_healing_2_overlay.png create mode 100644 src/main/resources/assets/ebwizardry/textures/blocks/runestone_healing_3.png create mode 100644 src/main/resources/assets/ebwizardry/textures/blocks/runestone_healing_3_overlay.png create mode 100644 src/main/resources/assets/ebwizardry/textures/blocks/runestone_healing_4.png create mode 100644 src/main/resources/assets/ebwizardry/textures/blocks/runestone_healing_4_overlay.png create mode 100644 src/main/resources/assets/ebwizardry/textures/blocks/runestone_ice_0.png create mode 100644 src/main/resources/assets/ebwizardry/textures/blocks/runestone_ice_1.png create mode 100644 src/main/resources/assets/ebwizardry/textures/blocks/runestone_ice_1_overlay.png create mode 100644 src/main/resources/assets/ebwizardry/textures/blocks/runestone_ice_2.png create mode 100644 src/main/resources/assets/ebwizardry/textures/blocks/runestone_ice_2_overlay.png create mode 100644 src/main/resources/assets/ebwizardry/textures/blocks/runestone_ice_3.png create mode 100644 src/main/resources/assets/ebwizardry/textures/blocks/runestone_ice_3_overlay.png create mode 100644 src/main/resources/assets/ebwizardry/textures/blocks/runestone_ice_4.png create mode 100644 src/main/resources/assets/ebwizardry/textures/blocks/runestone_ice_4_overlay.png create mode 100644 src/main/resources/assets/ebwizardry/textures/blocks/runestone_lightning_0.png create mode 100644 src/main/resources/assets/ebwizardry/textures/blocks/runestone_lightning_1.png create mode 100644 src/main/resources/assets/ebwizardry/textures/blocks/runestone_lightning_1_overlay.png create mode 100644 src/main/resources/assets/ebwizardry/textures/blocks/runestone_lightning_2.png create mode 100644 src/main/resources/assets/ebwizardry/textures/blocks/runestone_lightning_2_overlay.png create mode 100644 src/main/resources/assets/ebwizardry/textures/blocks/runestone_lightning_3.png create mode 100644 src/main/resources/assets/ebwizardry/textures/blocks/runestone_lightning_3_overlay.png create mode 100644 src/main/resources/assets/ebwizardry/textures/blocks/runestone_lightning_4.png create mode 100644 src/main/resources/assets/ebwizardry/textures/blocks/runestone_lightning_4_overlay.png create mode 100644 src/main/resources/assets/ebwizardry/textures/blocks/runestone_necromancy_0.png create mode 100644 src/main/resources/assets/ebwizardry/textures/blocks/runestone_necromancy_1.png create mode 100644 src/main/resources/assets/ebwizardry/textures/blocks/runestone_necromancy_1_overlay.png create mode 100644 src/main/resources/assets/ebwizardry/textures/blocks/runestone_necromancy_2.png create mode 100644 src/main/resources/assets/ebwizardry/textures/blocks/runestone_necromancy_2_overlay.png create mode 100644 src/main/resources/assets/ebwizardry/textures/blocks/runestone_necromancy_3.png create mode 100644 src/main/resources/assets/ebwizardry/textures/blocks/runestone_necromancy_3_overlay.png create mode 100644 src/main/resources/assets/ebwizardry/textures/blocks/runestone_necromancy_4.png create mode 100644 src/main/resources/assets/ebwizardry/textures/blocks/runestone_necromancy_4_overlay.png create mode 100644 src/main/resources/assets/ebwizardry/textures/blocks/runestone_pedestal_earth.png create mode 100644 src/main/resources/assets/ebwizardry/textures/blocks/runestone_pedestal_earth_overlay.png create mode 100644 src/main/resources/assets/ebwizardry/textures/blocks/runestone_pedestal_fire.png create mode 100644 src/main/resources/assets/ebwizardry/textures/blocks/runestone_pedestal_fire_overlay.png create mode 100644 src/main/resources/assets/ebwizardry/textures/blocks/runestone_pedestal_healing.png create mode 100644 src/main/resources/assets/ebwizardry/textures/blocks/runestone_pedestal_healing_overlay.png create mode 100644 src/main/resources/assets/ebwizardry/textures/blocks/runestone_pedestal_ice.png create mode 100644 src/main/resources/assets/ebwizardry/textures/blocks/runestone_pedestal_ice_overlay.png create mode 100644 src/main/resources/assets/ebwizardry/textures/blocks/runestone_pedestal_lightning.png create mode 100644 src/main/resources/assets/ebwizardry/textures/blocks/runestone_pedestal_lightning_overlay.png create mode 100644 src/main/resources/assets/ebwizardry/textures/blocks/runestone_pedestal_necromancy.png create mode 100644 src/main/resources/assets/ebwizardry/textures/blocks/runestone_pedestal_necromancy_overlay.png create mode 100644 src/main/resources/assets/ebwizardry/textures/blocks/runestone_pedestal_sorcery.png create mode 100644 src/main/resources/assets/ebwizardry/textures/blocks/runestone_pedestal_sorcery_overlay.png create mode 100644 src/main/resources/assets/ebwizardry/textures/blocks/runestone_sorcery_0.png create mode 100644 src/main/resources/assets/ebwizardry/textures/blocks/runestone_sorcery_1.png create mode 100644 src/main/resources/assets/ebwizardry/textures/blocks/runestone_sorcery_1_overlay.png create mode 100644 src/main/resources/assets/ebwizardry/textures/blocks/runestone_sorcery_2.png create mode 100644 src/main/resources/assets/ebwizardry/textures/blocks/runestone_sorcery_2_overlay.png create mode 100644 src/main/resources/assets/ebwizardry/textures/blocks/runestone_sorcery_3.png create mode 100644 src/main/resources/assets/ebwizardry/textures/blocks/runestone_sorcery_3_overlay.png create mode 100644 src/main/resources/assets/ebwizardry/textures/blocks/runestone_sorcery_4.png create mode 100644 src/main/resources/assets/ebwizardry/textures/blocks/runestone_sorcery_4_overlay.png create mode 100644 src/main/resources/assets/ebwizardry/textures/blocks/thorns_lower_0.png create mode 100644 src/main/resources/assets/ebwizardry/textures/blocks/thorns_lower_1.png create mode 100644 src/main/resources/assets/ebwizardry/textures/blocks/thorns_lower_2.png create mode 100644 src/main/resources/assets/ebwizardry/textures/blocks/thorns_lower_3.png create mode 100644 src/main/resources/assets/ebwizardry/textures/blocks/thorns_lower_4.png create mode 100644 src/main/resources/assets/ebwizardry/textures/blocks/thorns_lower_5.png create mode 100644 src/main/resources/assets/ebwizardry/textures/blocks/thorns_lower_6.png create mode 100644 src/main/resources/assets/ebwizardry/textures/blocks/thorns_lower_7.png create mode 100644 src/main/resources/assets/ebwizardry/textures/blocks/thorns_upper_0.png create mode 100644 src/main/resources/assets/ebwizardry/textures/blocks/thorns_upper_1.png create mode 100644 src/main/resources/assets/ebwizardry/textures/blocks/thorns_upper_2.png create mode 100644 src/main/resources/assets/ebwizardry/textures/blocks/thorns_upper_3.png create mode 100644 src/main/resources/assets/ebwizardry/textures/blocks/thorns_upper_4.png create mode 100644 src/main/resources/assets/ebwizardry/textures/blocks/thorns_upper_5.png create mode 100644 src/main/resources/assets/ebwizardry/textures/blocks/thorns_upper_6.png create mode 100644 src/main/resources/assets/ebwizardry/textures/blocks/thorns_upper_7.png create mode 100644 src/main/resources/assets/ebwizardry/textures/entity/arcane_lock_0.png create mode 100644 src/main/resources/assets/ebwizardry/textures/entity/arcane_lock_1.png create mode 100644 src/main/resources/assets/ebwizardry/textures/entity/arcane_lock_2.png create mode 100644 src/main/resources/assets/ebwizardry/textures/entity/arcane_lock_3.png create mode 100644 src/main/resources/assets/ebwizardry/textures/entity/arcane_lock_4.png create mode 100644 src/main/resources/assets/ebwizardry/textures/entity/arcane_lock_5.png create mode 100644 src/main/resources/assets/ebwizardry/textures/entity/arcane_lock_6.png create mode 100644 src/main/resources/assets/ebwizardry/textures/entity/arcane_lock_7.png create mode 100644 src/main/resources/assets/ebwizardry/textures/entity/combustion_rune.png create mode 100644 src/main/resources/assets/ebwizardry/textures/entity/containment_field_0.png create mode 100644 src/main/resources/assets/ebwizardry/textures/entity/containment_field_1.png create mode 100644 src/main/resources/assets/ebwizardry/textures/entity/containment_field_2.png create mode 100644 src/main/resources/assets/ebwizardry/textures/entity/containment_field_3.png create mode 100644 src/main/resources/assets/ebwizardry/textures/entity/containment_field_4.png create mode 100644 src/main/resources/assets/ebwizardry/textures/entity/containment_field_5.png create mode 100644 src/main/resources/assets/ebwizardry/textures/entity/containment_field_6.png create mode 100644 src/main/resources/assets/ebwizardry/textures/entity/containment_field_7.png create mode 100644 src/main/resources/assets/ebwizardry/textures/entity/ember.png create mode 100644 src/main/resources/assets/ebwizardry/textures/entity/fireball.png create mode 100644 src/main/resources/assets/ebwizardry/textures/entity/frost_overlay.png create mode 100644 src/main/resources/assets/ebwizardry/textures/entity/iceball.png create mode 100644 src/main/resources/assets/ebwizardry/textures/entity/wizard_7.png create mode 100644 src/main/resources/assets/ebwizardry/textures/entity/wizard_8.png create mode 100644 src/main/resources/assets/ebwizardry/textures/entity/wizard_female_0.png create mode 100644 src/main/resources/assets/ebwizardry/textures/entity/wizard_female_1.png create mode 100644 src/main/resources/assets/ebwizardry/textures/entity/wizard_female_2.png create mode 100644 src/main/resources/assets/ebwizardry/textures/gui/armour_picture.png create mode 100644 src/main/resources/assets/ebwizardry/textures/gui/curse_background.png rename src/main/resources/assets/ebwizardry/textures/gui/{element_icon_simple.png => element_icon_magic.png} (100%) create mode 100644 src/main/resources/assets/ebwizardry/textures/gui/elements_picture.png create mode 100644 src/main/resources/assets/ebwizardry/textures/gui/obelisk_picture.png create mode 100644 src/main/resources/assets/ebwizardry/textures/gui/potion_icon_arcane_jammer.png create mode 100644 src/main/resources/assets/ebwizardry/textures/gui/potion_icon_containment.png create mode 100644 src/main/resources/assets/ebwizardry/textures/gui/potion_icon_curse_of_enfeeblement.png create mode 100644 src/main/resources/assets/ebwizardry/textures/gui/potion_icon_curse_of_soulbinding.png create mode 100644 src/main/resources/assets/ebwizardry/textures/gui/potion_icon_curse_of_undeath.png rename src/main/resources/assets/ebwizardry/textures/gui/{decay_icon.png => potion_icon_decay.png} (100%) create mode 100644 src/main/resources/assets/ebwizardry/textures/gui/potion_icon_empowerment.png create mode 100644 src/main/resources/assets/ebwizardry/textures/gui/potion_icon_fear.png create mode 100644 src/main/resources/assets/ebwizardry/textures/gui/potion_icon_fireskin.png create mode 100644 src/main/resources/assets/ebwizardry/textures/gui/potion_icon_font_of_mana.png rename src/main/resources/assets/ebwizardry/textures/gui/{frost_icon.png => potion_icon_frost.png} (100%) create mode 100644 src/main/resources/assets/ebwizardry/textures/gui/potion_icon_frost_step.png create mode 100644 src/main/resources/assets/ebwizardry/textures/gui/potion_icon_ice_shroud.png create mode 100644 src/main/resources/assets/ebwizardry/textures/gui/potion_icon_mind_control.png create mode 100644 src/main/resources/assets/ebwizardry/textures/gui/potion_icon_mind_trick.png create mode 100644 src/main/resources/assets/ebwizardry/textures/gui/potion_icon_muffle.png create mode 100644 src/main/resources/assets/ebwizardry/textures/gui/potion_icon_paralysis.png create mode 100644 src/main/resources/assets/ebwizardry/textures/gui/potion_icon_sixth_sense.png create mode 100644 src/main/resources/assets/ebwizardry/textures/gui/potion_icon_slow_time.png create mode 100644 src/main/resources/assets/ebwizardry/textures/gui/potion_icon_static_aura.png create mode 100644 src/main/resources/assets/ebwizardry/textures/gui/potion_icon_transience.png create mode 100644 src/main/resources/assets/ebwizardry/textures/gui/potion_icon_ward.png delete mode 100644 src/main/resources/assets/ebwizardry/textures/gui/potion_icons.png create mode 100644 src/main/resources/assets/ebwizardry/textures/gui/shrine_picture.png delete mode 100644 src/main/resources/assets/ebwizardry/textures/gui/spell_book_basic.png create mode 100644 src/main/resources/assets/ebwizardry/textures/gui/spell_book_novice.png create mode 100644 src/main/resources/assets/ebwizardry/textures/gui/spell_hud/mahogany.json create mode 100644 src/main/resources/assets/ebwizardry/textures/gui/spell_hud/mahogany.png create mode 100644 src/main/resources/assets/ebwizardry/textures/gui/spell_hud/oceanic.json create mode 100644 src/main/resources/assets/ebwizardry/textures/gui/spell_hud/oceanic.png create mode 100644 src/main/resources/assets/ebwizardry/textures/gui/spell_hud/planks.json create mode 100644 src/main/resources/assets/ebwizardry/textures/gui/spell_hud/planks.png delete mode 100644 src/main/resources/assets/ebwizardry/textures/gui/spellbook.png create mode 100644 src/main/resources/assets/ebwizardry/textures/gui/tiers_picture.png create mode 100644 src/main/resources/assets/ebwizardry/textures/gui/tower_picture.png create mode 100644 src/main/resources/assets/ebwizardry/textures/gui/transportation_marker.png create mode 100644 src/main/resources/assets/ebwizardry/textures/integration/antiqueatlas/obelisk.png create mode 100644 src/main/resources/assets/ebwizardry/textures/integration/antiqueatlas/shrine.png create mode 100644 src/main/resources/assets/ebwizardry/textures/integration/antiqueatlas/wizard_tower.png create mode 100644 src/main/resources/assets/ebwizardry/textures/items/amulet_anchoring.png create mode 100644 src/main/resources/assets/ebwizardry/textures/items/amulet_arcane_defence.png create mode 100644 src/main/resources/assets/ebwizardry/textures/items/amulet_auto_shield.png create mode 100644 src/main/resources/assets/ebwizardry/textures/items/amulet_banishing.png create mode 100644 src/main/resources/assets/ebwizardry/textures/items/amulet_channeling.png create mode 100644 src/main/resources/assets/ebwizardry/textures/items/amulet_fire_cloaking.png create mode 100644 src/main/resources/assets/ebwizardry/textures/items/amulet_fire_protection.png create mode 100644 src/main/resources/assets/ebwizardry/textures/items/amulet_glide.png create mode 100644 src/main/resources/assets/ebwizardry/textures/items/amulet_ice_immunity.png create mode 100644 src/main/resources/assets/ebwizardry/textures/items/amulet_ice_protection.png create mode 100644 src/main/resources/assets/ebwizardry/textures/items/amulet_lich.png create mode 100644 src/main/resources/assets/ebwizardry/textures/items/amulet_potential.png create mode 100644 src/main/resources/assets/ebwizardry/textures/items/amulet_recovery.png create mode 100644 src/main/resources/assets/ebwizardry/textures/items/amulet_resurrection.png create mode 100644 src/main/resources/assets/ebwizardry/textures/items/amulet_transience.png create mode 100644 src/main/resources/assets/ebwizardry/textures/items/amulet_warding.png create mode 100644 src/main/resources/assets/ebwizardry/textures/items/amulet_wisdom.png create mode 100644 src/main/resources/assets/ebwizardry/textures/items/amulet_wither_immunity.png create mode 100644 src/main/resources/assets/ebwizardry/textures/items/astral_diamond.png create mode 100644 src/main/resources/assets/ebwizardry/textures/items/charm_abseiling.png create mode 100644 src/main/resources/assets/ebwizardry/textures/items/charm_auto_smelt.png create mode 100644 src/main/resources/assets/ebwizardry/textures/items/charm_experience_tome.png create mode 100644 src/main/resources/assets/ebwizardry/textures/items/charm_feeding.png create mode 100644 src/main/resources/assets/ebwizardry/textures/items/charm_flight.png create mode 100644 src/main/resources/assets/ebwizardry/textures/items/charm_growth.png create mode 100644 src/main/resources/assets/ebwizardry/textures/items/charm_haggler.png create mode 100644 src/main/resources/assets/ebwizardry/textures/items/charm_lava_walking.png create mode 100644 src/main/resources/assets/ebwizardry/textures/items/charm_light.png create mode 100644 src/main/resources/assets/ebwizardry/textures/items/charm_minion_health.png create mode 100644 src/main/resources/assets/ebwizardry/textures/items/charm_minion_variants.png create mode 100644 src/main/resources/assets/ebwizardry/textures/items/charm_silk_touch.png create mode 100644 src/main/resources/assets/ebwizardry/textures/items/charm_stop_time.png create mode 100644 src/main/resources/assets/ebwizardry/textures/items/charm_storm.png create mode 100644 src/main/resources/assets/ebwizardry/textures/items/charm_transportation.png create mode 100644 src/main/resources/assets/ebwizardry/textures/items/crystal_earth.png create mode 100644 src/main/resources/assets/ebwizardry/textures/items/crystal_fire.png create mode 100644 src/main/resources/assets/ebwizardry/textures/items/crystal_grand.png create mode 100644 src/main/resources/assets/ebwizardry/textures/items/crystal_healing.png create mode 100644 src/main/resources/assets/ebwizardry/textures/items/crystal_ice.png create mode 100644 src/main/resources/assets/ebwizardry/textures/items/crystal_lightning.png create mode 100644 src/main/resources/assets/ebwizardry/textures/items/crystal_magic.png create mode 100644 src/main/resources/assets/ebwizardry/textures/items/crystal_necromancy.png create mode 100644 src/main/resources/assets/ebwizardry/textures/items/crystal_shard.png create mode 100644 src/main/resources/assets/ebwizardry/textures/items/crystal_sorcery.png create mode 100644 src/main/resources/assets/ebwizardry/textures/items/flaming_axe_conjuring_0.png create mode 100644 src/main/resources/assets/ebwizardry/textures/items/flaming_axe_conjuring_1.png create mode 100644 src/main/resources/assets/ebwizardry/textures/items/flaming_axe_conjuring_1.png.mcmeta create mode 100644 src/main/resources/assets/ebwizardry/textures/items/flaming_axe_conjuring_2.png create mode 100644 src/main/resources/assets/ebwizardry/textures/items/flaming_axe_conjuring_2.png.mcmeta create mode 100644 src/main/resources/assets/ebwizardry/textures/items/flaming_axe_conjuring_3.png create mode 100644 src/main/resources/assets/ebwizardry/textures/items/flaming_axe_conjuring_3.png.mcmeta create mode 100644 src/main/resources/assets/ebwizardry/textures/items/flaming_axe_conjuring_4.png create mode 100644 src/main/resources/assets/ebwizardry/textures/items/flaming_axe_conjuring_4.png.mcmeta create mode 100644 src/main/resources/assets/ebwizardry/textures/items/flaming_axe_conjuring_5.png create mode 100644 src/main/resources/assets/ebwizardry/textures/items/flaming_axe_conjuring_5.png.mcmeta create mode 100644 src/main/resources/assets/ebwizardry/textures/items/flaming_axe_conjuring_6.png create mode 100644 src/main/resources/assets/ebwizardry/textures/items/flaming_axe_conjuring_6.png.mcmeta create mode 100644 src/main/resources/assets/ebwizardry/textures/items/flaming_axe_conjuring_7.png create mode 100644 src/main/resources/assets/ebwizardry/textures/items/flaming_axe_conjuring_7.png.mcmeta create mode 100644 src/main/resources/assets/ebwizardry/textures/items/frost_axe_conjuring_0.png create mode 100644 src/main/resources/assets/ebwizardry/textures/items/frost_axe_conjuring_1.png create mode 100644 src/main/resources/assets/ebwizardry/textures/items/frost_axe_conjuring_2.png create mode 100644 src/main/resources/assets/ebwizardry/textures/items/frost_axe_conjuring_3.png create mode 100644 src/main/resources/assets/ebwizardry/textures/items/frost_axe_conjuring_4.png create mode 100644 src/main/resources/assets/ebwizardry/textures/items/frost_axe_conjuring_5.png create mode 100644 src/main/resources/assets/ebwizardry/textures/items/frost_axe_conjuring_6.png create mode 100644 src/main/resources/assets/ebwizardry/textures/items/frost_axe_conjuring_7.png delete mode 100644 src/main/resources/assets/ebwizardry/textures/items/magic_crystal.png delete mode 100644 src/main/resources/assets/ebwizardry/textures/items/mana_flask.png create mode 100644 src/main/resources/assets/ebwizardry/textures/items/mana_flask_large.png create mode 100644 src/main/resources/assets/ebwizardry/textures/items/mana_flask_medium.png create mode 100644 src/main/resources/assets/ebwizardry/textures/items/mana_flask_small.png create mode 100644 src/main/resources/assets/ebwizardry/textures/items/purifying_elixir.png create mode 100644 src/main/resources/assets/ebwizardry/textures/items/ring_arcane_frost.png create mode 100644 src/main/resources/assets/ebwizardry/textures/items/ring_battlemage.png create mode 100644 src/main/resources/assets/ebwizardry/textures/items/ring_blockwrangler.png create mode 100644 src/main/resources/assets/ebwizardry/textures/items/ring_bronze_generic.png create mode 100644 src/main/resources/assets/ebwizardry/textures/items/ring_combustion.png create mode 100644 src/main/resources/assets/ebwizardry/textures/items/ring_combustion.png.mcmeta create mode 100644 src/main/resources/assets/ebwizardry/textures/items/ring_condensing.png create mode 100644 src/main/resources/assets/ebwizardry/textures/items/ring_conjurer.png create mode 100644 src/main/resources/assets/ebwizardry/textures/items/ring_defender.png create mode 100644 src/main/resources/assets/ebwizardry/textures/items/ring_defender.png.mcmeta create mode 100644 src/main/resources/assets/ebwizardry/textures/items/ring_disintegration.png create mode 100644 src/main/resources/assets/ebwizardry/textures/items/ring_earth_biome.png create mode 100644 src/main/resources/assets/ebwizardry/textures/items/ring_earth_melee.png create mode 100644 src/main/resources/assets/ebwizardry/textures/items/ring_extraction.png create mode 100644 src/main/resources/assets/ebwizardry/textures/items/ring_fire_biome.png create mode 100644 src/main/resources/assets/ebwizardry/textures/items/ring_fire_melee.png create mode 100644 src/main/resources/assets/ebwizardry/textures/items/ring_full_moon.png create mode 100644 src/main/resources/assets/ebwizardry/textures/items/ring_gold_generic.png create mode 100644 src/main/resources/assets/ebwizardry/textures/items/ring_hammer.png create mode 100644 src/main/resources/assets/ebwizardry/textures/items/ring_ice_biome.png create mode 100644 src/main/resources/assets/ebwizardry/textures/items/ring_ice_melee.png create mode 100644 src/main/resources/assets/ebwizardry/textures/items/ring_interdiction.png create mode 100644 src/main/resources/assets/ebwizardry/textures/items/ring_leeching.png create mode 100644 src/main/resources/assets/ebwizardry/textures/items/ring_lightning_melee.png create mode 100644 src/main/resources/assets/ebwizardry/textures/items/ring_mana_return.png create mode 100644 src/main/resources/assets/ebwizardry/textures/items/ring_mind_control.png create mode 100644 src/main/resources/assets/ebwizardry/textures/items/ring_necromancy_melee.png create mode 100644 src/main/resources/assets/ebwizardry/textures/items/ring_paladin.png create mode 100644 src/main/resources/assets/ebwizardry/textures/items/ring_poison.png create mode 100644 src/main/resources/assets/ebwizardry/textures/items/ring_seeking.png create mode 100644 src/main/resources/assets/ebwizardry/textures/items/ring_shattering.png create mode 100644 src/main/resources/assets/ebwizardry/textures/items/ring_silver_generic.png create mode 100644 src/main/resources/assets/ebwizardry/textures/items/ring_siphoning.png create mode 100644 src/main/resources/assets/ebwizardry/textures/items/ring_soulbinding.png create mode 100644 src/main/resources/assets/ebwizardry/textures/items/ring_storm.png create mode 100644 src/main/resources/assets/ebwizardry/textures/items/ring_storm.png.mcmeta rename src/main/resources/assets/ebwizardry/textures/{entity => items}/spark_bomb.png (100%) create mode 100644 src/main/resources/assets/ebwizardry/textures/items/spectral_bow_conjuring_0.png create mode 100644 src/main/resources/assets/ebwizardry/textures/items/spectral_bow_conjuring_1.png create mode 100644 src/main/resources/assets/ebwizardry/textures/items/spectral_bow_conjuring_2.png create mode 100644 src/main/resources/assets/ebwizardry/textures/items/spectral_bow_conjuring_3.png create mode 100644 src/main/resources/assets/ebwizardry/textures/items/spectral_bow_conjuring_4.png create mode 100644 src/main/resources/assets/ebwizardry/textures/items/spectral_bow_conjuring_5.png create mode 100644 src/main/resources/assets/ebwizardry/textures/items/spectral_bow_conjuring_6.png create mode 100644 src/main/resources/assets/ebwizardry/textures/items/spectral_bow_conjuring_7.png create mode 100644 src/main/resources/assets/ebwizardry/textures/items/spectral_pickaxe_conjuring_0.png create mode 100644 src/main/resources/assets/ebwizardry/textures/items/spectral_pickaxe_conjuring_1.png create mode 100644 src/main/resources/assets/ebwizardry/textures/items/spectral_pickaxe_conjuring_2.png create mode 100644 src/main/resources/assets/ebwizardry/textures/items/spectral_pickaxe_conjuring_3.png create mode 100644 src/main/resources/assets/ebwizardry/textures/items/spectral_pickaxe_conjuring_4.png create mode 100644 src/main/resources/assets/ebwizardry/textures/items/spectral_pickaxe_conjuring_5.png create mode 100644 src/main/resources/assets/ebwizardry/textures/items/spectral_pickaxe_conjuring_6.png create mode 100644 src/main/resources/assets/ebwizardry/textures/items/spectral_pickaxe_conjuring_7.png create mode 100644 src/main/resources/assets/ebwizardry/textures/items/spectral_sword_conjuring_0.png create mode 100644 src/main/resources/assets/ebwizardry/textures/items/spectral_sword_conjuring_1.png create mode 100644 src/main/resources/assets/ebwizardry/textures/items/spectral_sword_conjuring_2.png create mode 100644 src/main/resources/assets/ebwizardry/textures/items/spectral_sword_conjuring_3.png create mode 100644 src/main/resources/assets/ebwizardry/textures/items/spectral_sword_conjuring_4.png create mode 100644 src/main/resources/assets/ebwizardry/textures/items/spectral_sword_conjuring_5.png create mode 100644 src/main/resources/assets/ebwizardry/textures/items/spectral_sword_conjuring_6.png create mode 100644 src/main/resources/assets/ebwizardry/textures/items/spectral_sword_conjuring_7.png create mode 100644 src/main/resources/assets/ebwizardry/textures/items/upgrade_melee.png delete mode 100644 src/main/resources/assets/ebwizardry/textures/items/wand_basic_lightning.png delete mode 100644 src/main/resources/assets/ebwizardry/textures/items/wand_basic_necromancy.png rename src/main/resources/assets/ebwizardry/textures/items/{wand_basic.png => wand_novice.png} (100%) rename src/main/resources/assets/ebwizardry/textures/items/{wand_basic_earth.png => wand_novice_earth.png} (100%) rename src/main/resources/assets/ebwizardry/textures/items/{wand_basic_fire.png => wand_novice_fire.png} (100%) rename src/main/resources/assets/ebwizardry/textures/items/{wand_basic_healing.png => wand_novice_healing.png} (100%) rename src/main/resources/assets/ebwizardry/textures/items/{wand_basic_ice.png => wand_novice_ice.png} (100%) create mode 100644 src/main/resources/assets/ebwizardry/textures/items/wand_novice_lightning.png create mode 100644 src/main/resources/assets/ebwizardry/textures/items/wand_novice_necromancy.png rename src/main/resources/assets/ebwizardry/textures/items/{wand_basic_sorcery.png => wand_novice_sorcery.png} (100%) create mode 100644 src/main/resources/assets/ebwizardry/textures/particle/flame_0_0.png create mode 100644 src/main/resources/assets/ebwizardry/textures/particle/flame_0_1.png create mode 100644 src/main/resources/assets/ebwizardry/textures/particle/flame_0_2.png create mode 100644 src/main/resources/assets/ebwizardry/textures/particle/flame_0_3.png create mode 100644 src/main/resources/assets/ebwizardry/textures/particle/flame_0_4.png create mode 100644 src/main/resources/assets/ebwizardry/textures/particle/flame_0_5.png create mode 100644 src/main/resources/assets/ebwizardry/textures/particle/flame_0_6.png create mode 100644 src/main/resources/assets/ebwizardry/textures/particle/flame_0_7.png create mode 100644 src/main/resources/assets/ebwizardry/textures/particle/flame_1_0.png create mode 100644 src/main/resources/assets/ebwizardry/textures/particle/flame_1_1.png create mode 100644 src/main/resources/assets/ebwizardry/textures/particle/flame_1_2.png create mode 100644 src/main/resources/assets/ebwizardry/textures/particle/flame_1_3.png create mode 100644 src/main/resources/assets/ebwizardry/textures/particle/flame_1_4.png create mode 100644 src/main/resources/assets/ebwizardry/textures/particle/flame_1_5.png create mode 100644 src/main/resources/assets/ebwizardry/textures/particle/flame_1_6.png create mode 100644 src/main/resources/assets/ebwizardry/textures/particle/flame_1_7.png create mode 100644 src/main/resources/assets/ebwizardry/textures/particle/flame_2_0.png create mode 100644 src/main/resources/assets/ebwizardry/textures/particle/flame_2_1.png create mode 100644 src/main/resources/assets/ebwizardry/textures/particle/flame_2_2.png create mode 100644 src/main/resources/assets/ebwizardry/textures/particle/flame_2_3.png create mode 100644 src/main/resources/assets/ebwizardry/textures/particle/flame_2_4.png create mode 100644 src/main/resources/assets/ebwizardry/textures/particle/flame_2_5.png create mode 100644 src/main/resources/assets/ebwizardry/textures/particle/flame_2_6.png create mode 100644 src/main/resources/assets/ebwizardry/textures/particle/flame_2_7.png create mode 100644 src/main/resources/assets/ebwizardry/textures/particle/flame_3_0.png create mode 100644 src/main/resources/assets/ebwizardry/textures/particle/flame_3_1.png create mode 100644 src/main/resources/assets/ebwizardry/textures/particle/flame_3_2.png create mode 100644 src/main/resources/assets/ebwizardry/textures/particle/flame_3_3.png create mode 100644 src/main/resources/assets/ebwizardry/textures/particle/flame_3_4.png create mode 100644 src/main/resources/assets/ebwizardry/textures/particle/flame_3_5.png create mode 100644 src/main/resources/assets/ebwizardry/textures/particle/flame_3_6.png create mode 100644 src/main/resources/assets/ebwizardry/textures/particle/flame_3_7.png create mode 100644 src/main/resources/assets/ebwizardry/textures/particle/summon.png create mode 100644 src/main/resources/assets/ebwizardry/textures/particle/vine.png create mode 100644 src/main/resources/assets/ebwizardry/textures/particle/vine_leaf_0.png create mode 100644 src/main/resources/assets/ebwizardry/textures/particle/vine_leaf_1.png create mode 100644 src/main/resources/assets/ebwizardry/textures/particle/vine_leaf_2.png create mode 100644 src/main/resources/assets/ebwizardry/textures/particle/vine_leaf_3.png create mode 100644 src/main/resources/assets/ebwizardry/textures/particle/vine_leaf_4.png create mode 100644 src/main/resources/assets/ebwizardry/textures/spells/arcane_lock.png create mode 100644 src/main/resources/assets/ebwizardry/textures/spells/charge.png create mode 100644 src/main/resources/assets/ebwizardry/textures/spells/combustion_rune.png create mode 100644 src/main/resources/assets/ebwizardry/textures/spells/conjure_axe.png create mode 100644 src/main/resources/assets/ebwizardry/textures/spells/conjure_block.png create mode 100644 src/main/resources/assets/ebwizardry/textures/spells/conjure_shovel.png create mode 100644 src/main/resources/assets/ebwizardry/textures/spells/containment.png create mode 100644 src/main/resources/assets/ebwizardry/textures/spells/curse_of_enfeeblement.png create mode 100644 src/main/resources/assets/ebwizardry/textures/spells/curse_of_undeath.png create mode 100644 src/main/resources/assets/ebwizardry/textures/spells/disintegration.png create mode 100644 src/main/resources/assets/ebwizardry/textures/spells/divination.png create mode 100644 src/main/resources/assets/ebwizardry/textures/spells/dragon_fireball.png create mode 100644 src/main/resources/assets/ebwizardry/textures/spells/empowering_presence.png create mode 100644 src/main/resources/assets/ebwizardry/textures/spells/evade.png create mode 100644 src/main/resources/assets/ebwizardry/textures/spells/fire_breath.png create mode 100644 src/main/resources/assets/ebwizardry/textures/spells/forest_of_thorns.png create mode 100644 src/main/resources/assets/ebwizardry/textures/spells/frost_step.png create mode 100644 src/main/resources/assets/ebwizardry/textures/spells/grapple.png create mode 100644 src/main/resources/assets/ebwizardry/textures/spells/greater_telekinesis.png create mode 100644 src/main/resources/assets/ebwizardry/textures/spells/greater_ward.png create mode 100644 src/main/resources/assets/ebwizardry/textures/spells/guardian_angel.png create mode 100644 src/main/resources/assets/ebwizardry/textures/spells/guardian_beam.png create mode 100644 src/main/resources/assets/ebwizardry/textures/spells/healing_totem.png create mode 100644 src/main/resources/assets/ebwizardry/textures/spells/iceball.png create mode 100644 src/main/resources/assets/ebwizardry/textures/spells/mine.png create mode 100644 src/main/resources/assets/ebwizardry/textures/spells/muffle.png create mode 100644 src/main/resources/assets/ebwizardry/textures/spells/paralysis.png create mode 100644 src/main/resources/assets/ebwizardry/textures/spells/permafrost.png create mode 100644 src/main/resources/assets/ebwizardry/textures/spells/possession.png create mode 100644 src/main/resources/assets/ebwizardry/textures/spells/ray_of_purification.png create mode 100644 src/main/resources/assets/ebwizardry/textures/spells/remove_curse.png create mode 100644 src/main/resources/assets/ebwizardry/textures/spells/resurrection.png create mode 100644 src/main/resources/assets/ebwizardry/textures/spells/reversal.png create mode 100644 src/main/resources/assets/ebwizardry/textures/spells/rupture.png create mode 100644 src/main/resources/assets/ebwizardry/textures/spells/satiety.png create mode 100644 src/main/resources/assets/ebwizardry/textures/spells/shapeshift.png create mode 100644 src/main/resources/assets/ebwizardry/textures/spells/shocking_weapon.png create mode 100644 src/main/resources/assets/ebwizardry/textures/spells/shulker_bullet.png create mode 100644 src/main/resources/assets/ebwizardry/textures/spells/slow_time.png create mode 100644 src/main/resources/assets/ebwizardry/textures/spells/speed_time.png create mode 100644 src/main/resources/assets/ebwizardry/textures/spells/summon_creeper.png create mode 100644 src/main/resources/assets/ebwizardry/textures/spells/vex_swarm.png create mode 100644 src/main/resources/assets/ebwizardry/textures/spells/ward.png diff --git a/.gitignore b/.gitignore index 939f55fc..d45b2340 100644 --- a/.gitignore +++ b/.gitignore @@ -20,6 +20,9 @@ build # other eclipse run -misc -libs +logs +/misc +/libs +libsfordeobf +generated Thumbs.db \ No newline at end of file diff --git a/build.gradle b/build.gradle index 775fd0d4..6bd1915b 100644 --- a/build.gradle +++ b/build.gradle @@ -11,17 +11,39 @@ apply plugin: 'net.minecraftforge.gradle.forge' //Only edit below this line, the above code adds and enables the necessary things for Forge to be setup. -version = " 4.1.4 - MC 1.12.2" +version = "4.2.0" // There, it matches semver, happy now? (I am just gonna rename the file afterwards, you know that right?) group= "electroblob.wizardry"// http://maven.apache.org/guides/mini/guide-naming-conventions.html -archivesBaseName = "Electroblob's Wizardry " +archivesBaseName = "ElectroblobsWizardry" sourceCompatibility = targetCompatibility = "1.8" // Need this here so eclipse task generates correctly. compileJava { sourceCompatibility = targetCompatibility = "1.8" } +repositories { + maven { + // location of the maven that hosts JEI files + name = "Progwml6 maven" + url = "http://dvs1.progwml6.com/files/maven" + } + maven { + // location of a maven mirror for JEI files, as a fallback + name = "ModMaven" + url = "modmaven.k-4u.nl" + } + flatDir { + // evErYthINg hAS tO Be a mAVeN rEPoSiTOrY... (to use deobfProvided, for some reason) + // The lack of documentation is actually quite impressive, see the following threads: + // http://www.minecraftforge.net/forum/topic/44262-solved-how-to-build-mod-with-dependencies/ + // https://www.minecraftforum.net/forums/mapping-and-modding-java-edition/mapping-and-modding-tutorials/2866817-setting-up-dependencies-in-minecraft-forge-with + // http://www.minecraftforge.net/forum/topic/44534-adding-dependencies-to-a-forge-project/ + dirs "libsfordeobf" // Don't use libs or forge will think you have duplicate mods + } + +} + minecraft { - version = "1.12.2-14.23.2.2611" + version = "1.12.2-14.23.5.2814" runDir = "run" // the mappings can be changed at any time, and must be in the following format. @@ -38,6 +60,17 @@ dependencies { // or you may define them like so.. //compile "some.group:artifact:version:classifier" //compile "some.group:artifact:version" + + // compile against the JEI API but do not include it at runtime + deobfProvided "mezz.jei:jei_${mc_version}:${jei_version}:api" + // at runtime, use the full JEI jar + runtime "mezz.jei:jei_${mc_version}:${jei_version}" + + //deobfProvided "baubles:baubles-1.12:1.5.2:api" // #ihavenoideawhatimdoing #itjustworks + //runtime "baubles:baubles-1.12:1.5.2" // If in doubt, copy what already works + + //deobfProvided "antiqueatlas:antiqueatlas-1.12.2:4.5.1:src" + //runtime "antiqueatlas:antiqueatlas-1.12.2:4.5.1" // real examples //compile 'com.mod-buildcraft:buildcraft:6.0.8:dev' // adds buildcraft to the dev env diff --git a/gradle.properties b/gradle.properties index e9b9fd5a..b4ec0fb3 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,3 +1,5 @@ # Sets default memory used for gradle commands. Can be overridden by user or command line properties. # This is required to provide enough memory for the Minecraft decompilation process. org.gradle.jvmargs=-Xmx3G +mc_version=1.12.2 +jei_version=4.13.1.225 \ No newline at end of file diff --git a/gradlew b/gradlew index 91a7e269..ac7df23f 100644 --- a/gradlew +++ b/gradlew @@ -79,14 +79,14 @@ if [ -n "$JAVA_HOME" ] ; then die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME Please set the JAVA_HOME variable in your environment to match the -location of your Java installation." +locations of your Java installation." fi else JAVACMD="java" which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. Please set the JAVA_HOME variable in your environment to match the -location of your Java installation." +locations of your Java installation." fi # Increase the maximum file descriptors if we can. diff --git a/gradlew.bat b/gradlew.bat index 8a0b282a..5bb5d8ea 100644 --- a/gradlew.bat +++ b/gradlew.bat @@ -27,7 +27,7 @@ echo. echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. echo. echo Please set the JAVA_HOME variable in your environment to match the -echo location of your Java installation. +echo locations of your Java installation. goto fail @@ -41,7 +41,7 @@ echo. echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% echo. echo Please set the JAVA_HOME variable in your environment to match the -echo location of your Java installation. +echo locations of your Java installation. goto fail diff --git a/src/main/java/electroblob/wizardry/CommonProxy.java b/src/main/java/electroblob/wizardry/CommonProxy.java index 7e45ebe8..71165cc2 100644 --- a/src/main/java/electroblob/wizardry/CommonProxy.java +++ b/src/main/java/electroblob/wizardry/CommonProxy.java @@ -1,33 +1,32 @@ package electroblob.wizardry; -import electroblob.wizardry.client.particle.ParticleWizardry; import electroblob.wizardry.item.ItemSpectralBow; -import electroblob.wizardry.packet.PacketCastContinuousSpell; -import electroblob.wizardry.packet.PacketCastSpell; -import electroblob.wizardry.packet.PacketClairvoyance; -import electroblob.wizardry.packet.PacketGlyphData; -import electroblob.wizardry.packet.PacketNPCCastSpell.Message; -import electroblob.wizardry.packet.PacketPlayerSync; -import electroblob.wizardry.packet.PacketTransportation; -import electroblob.wizardry.registry.Spells; +import electroblob.wizardry.packet.*; import electroblob.wizardry.registry.WizardryItems; import electroblob.wizardry.spell.Spell; -import electroblob.wizardry.util.ParticleBuilder.Type; import net.minecraft.block.state.IBlockState; import net.minecraft.entity.Entity; +import net.minecraft.entity.EntityLivingBase; import net.minecraft.item.ItemStack; +import net.minecraft.util.ResourceLocation; +import net.minecraft.util.SoundCategory; import net.minecraft.util.SoundEvent; import net.minecraft.util.math.BlockPos; +import net.minecraft.util.text.Style; +import net.minecraft.util.text.TextFormatting; import net.minecraft.util.text.translation.I18n; import net.minecraft.world.World; import net.minecraftforge.common.config.Property; +import java.util.List; +import java.util.Set; + /** * The common proxy for wizardry, serving the usual purpose of dealing with all things that need to be handled * differently on the client and the server. A lot of the methods here appear to do absolutely nothing; this is because * they do client-only things which are only handled in the client proxy. * - * @see {@link electroblob.wizardry.client.ClientProxy} + * @see electroblob.wizardry.client.ClientProxy ClientProxy * @author Electroblob * @since Wizardry 1.0 */ @@ -51,15 +50,19 @@ public class CommonProxy { public void registerResourceReloadListeners(){} + public void registerSoundEventListener(){} + + public void registerAtlasMarkers(){} + // SECTION Particles // =============================================================================================================== /** Called from init() in the main mod class to initialise the particle factories. */ - public void initParticleFactories(){} // Does nothing since particles are client-side only + public void registerParticles(){} // Does nothing since particles are client-side only /** Creates a new particle of the specified type from the appropriate particle factory. Does not actually spawn the * particle; use {@link electroblob.wizardry.util.ParticleBuilder ParticleBuilder} to spawn particles. */ - public ParticleWizardry createParticle(Type type, World world, double x, double y, double z){ + public electroblob.wizardry.client.particle.ParticleWizardry createParticle(ResourceLocation type, World world, double x, double y, double z){ return null; } @@ -70,19 +73,23 @@ public class CommonProxy { // SECTION Items // =============================================================================================================== + public boolean shouldDisplayDiscovered(Spell spell, ItemStack stack){ + return false; + } + public net.minecraft.client.gui.FontRenderer getFontRenderer(ItemStack stack){ return null; } /** * Returns the translated name of the scroll, taking spell discovery into account. If, for some reason, this gets - * called server-side, it uses the deprecated server version of I18n, with a warning. Since any likely server-side - * use of this method will be for text-based logic purposes (like Bibliocraft's book checking system), and since no - * particular player instance can be accessed, spell discovery is ignored. + * called server-side, it uses the deprecated server version of I18n. Since any likely server-side + * use of this method will be for text-based logic purposes (like Bibliocraft's book checking system), and since + * no particular player instance can be accessed, spell discovery is ignored. */ public String getScrollDisplayName(ItemStack scroll){ - Spell spell = Spell.get(scroll.getItemDamage()); + Spell spell = Spell.byMetadata(scroll.getItemDamage()); return I18n.translateToLocalFormatted("item." + Wizardry.MODID + ":scroll.name", I18n.translateToLocal("spell." + spell.getUnlocalisedName())).trim(); @@ -92,29 +99,53 @@ public class CommonProxy { return ((ItemSpectralBow)WizardryItems.spectral_bow).getDefaultDurabilityForDisplay(stack); } + /** Like {@link CommonProxy#addMultiLineDescription(List, String, Style)}, but style defaults to light grey. */ + public void addMultiLineDescription(List tooltip, String key){ + this.addMultiLineDescription(tooltip, key, new Style().setColor(TextFormatting.GRAY)); + } + + /** + * Adds a multi-line description to the given tooltip list. The description is first translated using the given + * translation key, then the formatting code for the given style is appended, and finally the string is word-wrapped + * to the standard width (100). + * @param tooltip The tooltip list to add to + * @param key The translation key for the description + * @param style A style to apply + */ + public void addMultiLineDescription(List tooltip, String key, Style style){} + // SECTION Packet Handlers // =============================================================================================================== - public void handlePlayerSyncPacket(PacketPlayerSync.Message message){ - } + public void handlePlayerSyncPacket(PacketPlayerSync.Message message){} - public void handleGlyphDataPacket(PacketGlyphData.Message message){ - } + public void handleGlyphDataPacket(PacketGlyphData.Message message){} - public void handleCastSpellPacket(PacketCastSpell.Message message){ - } + public void handleEmitterDataPacket(PacketEmitterData.Message message){} - public void handleCastContinuousSpellPacket(PacketCastContinuousSpell.Message message){ - } + public void handleCastSpellPacket(PacketCastSpell.Message message){} - public void handleNPCCastSpellPacket(Message message){ - } + public void handleCastContinuousSpellPacket(PacketCastContinuousSpell.Message message){} - public void handleTransportationPacket(PacketTransportation.Message message){ - } + public void handleNPCCastSpellPacket(PacketNPCCastSpell.Message message){} - public void handleClairvoyancePacket(PacketClairvoyance.Message message){ - } + public void handleDispenserCastSpellPacket(PacketDispenserCastSpell.Message message){} + + public void handleCastSpellAtPosPacket(PacketCastSpellAtPos.Message message){} + + public void handleTransportationPacket(PacketTransportation.Message message){} + + public void handleClairvoyancePacket(PacketClairvoyance.Message message){} + + public void handleAdvancementSyncPacket(PacketSyncAdvancements.Message message){} + + public void handleEndSlowTimePacket(PacketEndSlowTime.Message message){} + + public void handleResurrectionPacket(PacketResurrection.Message message){} + + public void handlePossessionPacket(PacketPossession.Message message){} + + public void handleConquerShrinePacket(PacketConquerShrine.Message message){} // SECTION Misc // =============================================================================================================== @@ -122,6 +153,8 @@ public class CommonProxy { public void setToNumberSliderEntry(Property property){} public void setToHUDChooserEntry(Property property){} + + public void setToNamedBooleanEntry(Property property){} // public void setToEntityNameEntry(Property property){} @@ -137,6 +170,75 @@ public class CommonProxy { */ public void playMovingSound(Entity entity, SoundEvent sound, SoundCategory category, float volume, float pitch, boolean repeat){} + /** + * Plays a continuous spell sound which moves with the given entity. + * + * @param entity The source of the sound + * @param spell The spell this sound is associated with + * @param start The starting SoundEvent to play + * @param loop The main looped SoundEvent to play + * @param end The ending SoundEvent to play + * @param category The SoundCategory to use + * @param volume Volume relative to 1 + * @param pitch Pitch relative to 1 + */ + public void playSpellSoundLoop(EntityLivingBase entity, Spell spell, SoundEvent start, SoundEvent loop, SoundEvent end, SoundCategory category, float volume, float pitch){} + + /** + * Plays a continuous spell sound which moves with the given entity. + * + * @param entity The source of the sound + * @param spell The spell this sound is associated with + * @param sounds An array of the sound events to play, which must have three elements in the order: start, loop, end + * @param category The SoundCategory to use + * @param volume Volume relative to 1 + * @param pitch Pitch relative to 1 + * @throws IllegalArgumentException if the given array contains less than 3 sound events + */ + public void playSpellSoundLoop(EntityLivingBase entity, Spell spell, SoundEvent[] sounds, SoundCategory category, float volume, float pitch){ + if(sounds.length < 3) throw new IllegalArgumentException("Tried to play a continuous spell sound using an array " + + "of sound events, but the given array contained less than 3 sound events!"); + playSpellSoundLoop(entity, spell, sounds[0], sounds[1], sounds[2], category, volume, pitch); + } + + /** + * Plays a continuous spell sound at the given position. + * @param world The world in which to play the sound + * @param x The x coordinate to play the sound at + * @param y The y coordinate to play the sound at + * @param z The z coordinate to play the sound at + * @param spell The spell this sound is associated with + * @param start The starting SoundEvent to play + * @param loop The main looped SoundEvent to play + * @param end The ending SoundEvent to play + * @param category The SoundCategory to use + * @param volume Volume relative to 1 + * @param pitch Pitch relative to 1 + * @param duration The duration of the sound, or -1 to link it to a dispenser at the given coordinates + */ + public void playSpellSoundLoop(World world, double x, double y, double z, Spell spell, SoundEvent start, SoundEvent loop, SoundEvent end, SoundCategory category, float volume, float pitch, int duration){} + + /** + * Plays a continuous spell sound at the given position. + * + * @param world The world in which to play the sound + * @param x The x coordinate to play the sound at + * @param y The y coordinate to play the sound at + * @param z The z coordinate to play the sound at + * @param spell The spell this sound is associated with + * @param sounds An array of the sound events to play, which must have three elements in the order: start, loop, end + * @param category The SoundCategory to use + * @param volume Volume relative to 1 + * @param pitch Pitch relative to 1 + * @param duration The duration of the sound, or -1 to link it to a dispenser at the given coordinates + * @throws IllegalArgumentException if the given array contains less than 3 sound events + */ + public void playSpellSoundLoop(World world, double x, double y, double z, Spell spell, SoundEvent[] sounds, SoundCategory category, float volume, float pitch, int duration){ + if(sounds.length < 3) throw new IllegalArgumentException("Tried to play a continuous spell sound using an array " + + "of sound events, but the given array contained less than 3 sound events!"); + playSpellSoundLoop(world, x, y, z, spell, sounds[0], sounds[1], sounds[2], category, volume, pitch, duration); + } + /** * Gets the client side world using Minecraft.getMinecraft().world. Only to be called client side! Returns * null on the server side. diff --git a/src/main/java/electroblob/wizardry/Settings.java b/src/main/java/electroblob/wizardry/Settings.java index c8bc5585..8692cc0b 100644 --- a/src/main/java/electroblob/wizardry/Settings.java +++ b/src/main/java/electroblob/wizardry/Settings.java @@ -1,13 +1,9 @@ package electroblob.wizardry; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; -import java.util.Locale; - import electroblob.wizardry.packet.PacketSyncSettings; import electroblob.wizardry.packet.WizardryPacketHandler; import electroblob.wizardry.spell.Spell; +import electroblob.wizardry.util.AllyDesignationSystem.FriendlyFire; import electroblob.wizardry.util.MagicDamage; import electroblob.wizardry.util.MagicDamage.DamageType; import net.minecraft.entity.EntityList; @@ -19,14 +15,18 @@ import net.minecraftforge.common.config.Configuration; import net.minecraftforge.common.config.Property; import net.minecraftforge.fml.common.event.FMLPreInitializationEvent; import net.minecraftforge.fml.common.network.simpleimpl.IMessage; +import net.minecraftforge.fml.relauncher.Side; + +import java.util.*; +import java.util.regex.Pattern; /** * Singleton class which deals with everything related to wizardry's config file. To access individual settings, use * {@link Wizardry#settings}. Also stores a few string constants for easy access. - *

- * As part of the 1.2 update and code overhaul, the way the config settings work in multiplayer has been tightened up. + *

+ * As part of the 2.1 update and code overhaul, the way the config settings work in multiplayer has been tightened up. * Importantly, there are three different types of config options: - *

+ *

*
  • Server-only settings. These only affect server-side code and hence are not synced. Changing these locally only * has an effect if the local game is the host, i.e. a dedicated server, a LAN host or a singleplayer world. Examples * include worldgen, mob drops and commands. @@ -38,7 +38,7 @@ import net.minecraftforge.fml.common.network.simpleimpl.IMessage; *
  • Client-only settings. These settings only affect client-side code and hence are not synced. Each client obeys its * own values for these, and changing them on a dedicated server will have no effect. These are usually only display and * controls settings.
  • - *

    + *

    * Each of the settings fields in this class is marked with one of the above categories to indicate which it belongs to. * This in turn dictates which logical side it should be called from: client, server or both. Do not access a config * setting from the wrong side, because it may cause unexpected or strange behaviour. @@ -46,13 +46,14 @@ import net.minecraftforge.fml.common.network.simpleimpl.IMessage; * @since Wizardry 1.2 * @author Electroblob */ -// TODO: New plan: convert to the @Config system BUT separate the spells config out so it doesn't break stuff. (Maybe even -// make it a JSON instead? Either way, there's scope for then adding more options for adjusting the base attributes etc.) +// For the time being, I'm sticking with the old config system because @Config doesn't support custom config entry classes // @Config(modid = Wizardry.MODID) -@SuppressWarnings("deprecation") // Used server I18n deliberately; we want to write the comments in english. +@SuppressWarnings("deprecation") // Used server I18n deliberately; we want to write the comments in the actual config file in english. public final class Settings { // Category names + /** The unlocalised name of the gameplay config category. */ + public static final String GAMEPLAY_CATEGORY = "gameplay"; /** The unlocalised name of the spells config category. */ public static final String SPELLS_CATEGORY = "spells"; /** The unlocalised name of the resistances config category. */ @@ -63,8 +64,14 @@ public final class Settings { public static final String COMMANDS_CATEGORY = "commands"; /** The unlocalised name of the worldgen config category. */ public static final String WORLDGEN_CATEGORY = "worldgen"; - /** The unlocalised name of the gameplay config category. */ - public static final String GAMEPLAY_CATEGORY = "gameplay"; + /** The unlocalised name of the compatibility config category. */ + public static final String COMPATIBILITY_CATEGORY = "compatibility"; + + private static final String[] DEFAULT_LOOT_INJECTION_LOCATIONS = {"minecraft:chests/simple_dungeon", + "minecraft:chests/abandoned_mineshaft", "minecraft:chests/desert_pyramid", "minecraft:chests/jungle_temple", + "minecraft:chests/stronghold_corridor", "minecraft:chests/stronghold_crossing", + "minecraft:chests/stronghold_library", "minecraft:chests/igloo_chest", "minecraft:chests/woodland_mansion", + "minecraft:chests/end_city_treasure"}; /** The wizardry config file. */ private Configuration config; @@ -73,34 +80,88 @@ public final class Settings { // has an effect if the local game is the host, i.e. a dedicated server, a LAN host or a singleplayer world. // Worldgen + /** [Server-only] Whether to use faster worldgen at the cost of 'seamlessness'. */ + public boolean fastWorldgen = false; + /** [Server-only] List of dimension ids in which to generate wizard towers. */ + public int[] towerDimensions = {0}; /** [Server-only] The rarity of wizard towers, used by the world generator. Larger numbers are rarer. */ - public int towerRarity = 8; + public int towerRarity = 600; + /** [Server-only] List of structure file locations for wizard towers without loot chests. */ + public ResourceLocation[] towerFiles = {new ResourceLocation(Wizardry.MODID, "wizard_tower_0"), + new ResourceLocation(Wizardry.MODID, "wizard_tower_1"), + new ResourceLocation(Wizardry.MODID, "wizard_tower_2"), + new ResourceLocation(Wizardry.MODID, "wizard_tower_3")}; + /** [Server-only] List of structure file locations for wizard towers with loot chests. */ + public ResourceLocation[] towerWithChestFiles = {new ResourceLocation(Wizardry.MODID, "wizard_tower_chest_0"), + new ResourceLocation(Wizardry.MODID, "wizard_tower_chest_1"), + new ResourceLocation(Wizardry.MODID, "wizard_tower_chest_2"), + new ResourceLocation(Wizardry.MODID, "wizard_tower_chest_3")}; + /** [Server-only] List of dimension ids in which to generate obelisks. */ + public int[] obeliskDimensions = {0, -1}; + /** [Server-only] The rarity of obelisks, used by the world generator. Larger numbers are rarer. */ + public int obeliskRarity = 550; + /** [Server-only] List of structure file locations for obelisks. */ + public ResourceLocation[] obeliskFiles = {new ResourceLocation(Wizardry.MODID, "obelisk_0"), + new ResourceLocation(Wizardry.MODID, "obelisk_1"), + new ResourceLocation(Wizardry.MODID, "obelisk_2"), + new ResourceLocation(Wizardry.MODID, "obelisk_3"), + new ResourceLocation(Wizardry.MODID, "obelisk_4")}; + /** [Server-only] List of dimension ids in which to generate shrines. */ + public int[] shrineDimensions = {0, -1}; + /** [Server-only] The rarity of shrines, used by the world generator. Larger numbers are rarer. */ + public int shrineRarity = 1000; + /** [Server-only] List of structure file locations for shrines. */ + public ResourceLocation[] shrineFiles = {new ResourceLocation(Wizardry.MODID, "shrine_0"), + new ResourceLocation(Wizardry.MODID, "shrine_1"), + new ResourceLocation(Wizardry.MODID, "shrine_2"), + new ResourceLocation(Wizardry.MODID, "shrine_3"), + new ResourceLocation(Wizardry.MODID, "shrine_4"), + new ResourceLocation(Wizardry.MODID, "shrine_5"), + new ResourceLocation(Wizardry.MODID, "shrine_6"), + new ResourceLocation(Wizardry.MODID, "shrine_7")}; + /** [Server-only] The chance for wizard towers to generate with an evil wizard and chest inside. */ + public double evilWizardChance = 0.2; /** [Server-only] List of dimension ids in which to generate crystal ore. */ public int[] oreDimensions = {0}; - /** [Server-only] List of dimension ids in which to generate crystal ore. */ + /** [Server-only] List of dimension ids in which to generate crystal flowers. */ public int[] flowerDimensions = {0}; - /** [Server-only] List of dimension ids in which to generate crystal ore. */ - public int[] towerDimensions = {0}; /** - * [Server-only] Whether or not wizardry loot should generate in dungeon chests. Note that this does not - * affect the generation of loot in wizard towers. + * [Server-only] List of resource location strings for loot tables to inject wizardry loot into. Note that + * this does not affect the generation of loot in wizard towers. */ - public boolean generateLoot = true; + public ResourceLocation[] lootInjectionLocations = toResourceLocations(DEFAULT_LOOT_INJECTION_LOCATIONS); // Entities' drops, targeting, damage, etc. - /** [Server-only] Chance (out of 200) for mobs to drop spell books. */ - public int spellBookDropChance = 3; + /** [Server-only] Whitelist for loot tables to inject additional mob drops into. */ + public ResourceLocation[] mobLootTableWhitelist = {}; + /** [Server-only] Blacklist for loot tables to inject additional mob drops into. */ + public ResourceLocation[] mobLootTableBlacklist = toResourceLocations("entities/vex", "entities/ender_dragon", + "entities/wither", "entities/silverfish", "entities/endermite", + Wizardry.MODID + "entities/evil_wizard"); /** * [Server-only] Whether or not players can teleport through unbreakable blocks (e.g. bedrock) using the * phase step spell. */ public boolean teleportThroughUnbreakableBlocks = false; /** [Server-only] Whether to allow players to damage their designated allies using magic. */ - public boolean friendlyFire = true; + public FriendlyFire friendlyFire = FriendlyFire.ALL; /** [Server-only] Whether to allow players to disarm other players using the telekinesis spell. */ public boolean telekineticDisarmament = true; /** [Server-only] Whether summoned creatures can revenge attack their caster if their caster attacks them. */ public boolean minionRevengeTargeting = true; + /** [Server-only] Whether to allow players to change the world time using the speed time spell. */ + public boolean worldTimeManipulation = true; + /** [Server-only] Whether to allow players to move other players around using magic. */ + public boolean playersMoveEachOther = true; + /** [Server-only] Whether spells cast by players can destroy blocks in the world. */ + public boolean playerBlockDamage = true; + /** [Server-only] Whether to revert to the old wand upgrade system, which only requires tomes of arcana. */ + public boolean legacyWandLevelling = false; + /** [Server-only] Whether to replace Minecraft's own fireballs with wizardry fireballs. */ + public boolean replaceVanillaFireballs = true; + /** [Server-only] Whether to replace Minecraft's distance-based fall damage calculation with an equivalent, + * velocity-based one. */ + public boolean replaceVanillaFallDamage = true; /** * [Server-only] List of registry names of entities which summoned creatures are allowed to attack, in addition * to the defaults. @@ -110,18 +171,39 @@ public final class Settings { * [Server-only] List of registry names of entities which summoned creatures are specifically not allowed to * attack, overriding the defaults and the whitelist. */ - public ResourceLocation[] summonedCreatureTargetsBlacklist = {new ResourceLocation("creeper")}; + public ResourceLocation[] summonedCreatureTargetsBlacklist = toResourceLocations("creeper"); /** * [Server-only] List of registry names of entities which are immune to the mind control spell, in addition to * the defaults. */ public ResourceLocation[] mindControlTargetsBlacklist = {}; + /** + * [Server-only] List of registry names of items which cannot be smelted by the pocket furnace spell, in + * addition to armour, tools and weapons. + */ + public ResourceLocation[] pocketFurnaceItemBlacklist = toResourceLocations("cobblestone", "netherrack"); + /** [Server-only] List of registry names of blocks which can be detected by the divination spell. */ + public ResourceLocation[] divinationOreWhitelist = {}; + /** [Server-only] List of registry names of items which count as swords for imbuement spells. */ + public ResourceLocation[] swordItemWhitelist = {}; + /** [Server-only] List of registry names of items which count as bows for imbuement spells. */ + public ResourceLocation[] bowItemWhitelist = {}; + /** [Server-only] Map of items to values which wizard trades may use as currency. */ + public Map currencyItems = new HashMap<>(); /** [Server-only] Global damage scaling factor for all player magic damage. */ - public double playerDamageScale = 1.0f; + public double playerDamageScale = 1.0; /** [Server-only] Global damage scaling factor for all npc magic damage. */ - public double npcDamageScale = 1.0f; - /** [Server-only] List of dimension ids in which evil wizards can spawn. */ - public int[] evilWizardDimensions = {0}; + public double npcDamageScale = 1.0; + /** [Server-only] List of dimension ids in which wizardry's hostile mobs can spawn. */ + public int[] mobSpawnDimensions = {0}; + /** [Server-only] Spawn rate for naturally-spawned evil wizards; higher numbers mean more evil wizards will spawn. */ + public int evilWizardSpawnRate = 3; + /** [Server-only] Spawn rate for naturally-spawned evil wizards; higher numbers mean more evil wizards will spawn. */ + public int iceWraithSpawnRate = 3; + /** [Server-only] Spawn rate for naturally-spawned evil wizards; higher numbers mean more evil wizards will spawn. */ + public int lightningWraithSpawnRate = 1; + /** [Server-only] List of registry names of biomes in which wizardry's hostile mobs cannot spawn. */ + public ResourceLocation[] mobSpawnBiomeBlacklist = toResourceLocations("mushroom_island", "mushroom_island_shore"); // Commands (these don't need synchronising since typing a command always queries the server). /** @@ -138,6 +220,25 @@ public final class Settings { /** [Server-only] The name of the /allies command. */ public String alliesCommandName = "allies"; + /** + * [Server-only] List of damage source string identifiers to be ignored when re-applying damage. + */ + public String[] damageSourceBlacklist = {}; + /** [Server-only] Whether to print compatibility warnings to the console. */ + public boolean compatibilityWarnings = true; + /** [Server-only] Whether Baubles integration features are enabled. */ + public boolean baublesIntegration = true; +// /** [Server-only] Whether JEI integration features are enabled. */ +// public boolean jeiIntegration = true; + /** [Server-only] Whether Antique Atlas integration features are enabled. */ + public boolean antiqueAtlasIntegration = true; + /** [Server-only] Whether global markers for wizard towers are added to antique atlases. */ + public boolean autoTowerMarkers = true; + /** [Server-only] Whether global markers for obelisks are added to antique atlases. */ + public boolean autoObeliskMarkers = true; + /** [Server-only] Whether global markers for shrines are added to antique atlases. */ + public boolean autoShrineMarkers = true; + // Synchronised settings. These settings affect both client-side AND server-side code. Changing these locally // only has an effect if the local game is the host, i.e. a dedicated server, a LAN host or a singleplayer world. @@ -148,6 +249,18 @@ public final class Settings { * survival mode if this is false. */ public boolean discoveryMode = true; + /** + * [Synchronised] When set to true, players in creative mode can bypass arcane locks regardless of whether + * they are an op or not. + */ + public boolean creativeBypassesArcaneLock = true; + /** + * [Synchronised] When set to true, players will be slowed when a nearby player or entity has the slow time + * effect. + */ + public boolean slowTimeAffectsPlayers = true; + /** [Synchronised] Chance of 'misreading' an undiscovered spell and triggering a forfeit instead. */ + public double forfeitChance = 0.2; // Client-only settings. These settings only affect client-side code and hence are not synced. Each client obeys // its own values for these, and changing them on a dedicated server will have no effect. @@ -157,32 +270,46 @@ public final class Settings { * [Client-only] Whether the player can switch between spells on a wand by scrolling with the mouse wheel * while sneaking. */ - public boolean enableShiftScrolling = true; - /** [Client-only] Whether to reverse the spell switching scroll direction.*/ + public boolean shiftScrolling = true; + /** [Client-only] Whether to reverse the spell switching scroll direction. */ public boolean reverseScrollDirection = false; // Display /** [Client-only] Whether to show summoned creatures' names and owners above their heads. */ - public boolean showSummonedCreatureNames = true; + public boolean summonedCreatureNames = true; + /** + * [Client-only] When set to true, sections of The Wizard's Handbook are unlocked when a player + * gains the advancement that triggers them, and are hidden otherwise. When set to false, the entire handbook is + * readable regardless of advancement progress. + */ + public boolean handbookProgression = true; + /** [Client-only] Whether the various book GUIs pause the game in singleplayer worlds. */ + public boolean booksPauseGame = true; + /** [Client-only] Whether to use custom shaders for certain spells. */ + public boolean useShaders = true; /** [Client-only] The position of the spell HUD. */ public GuiPosition spellHUDPosition = GuiPosition.BOTTOM_LEFT; - + public static final String DEFAULT_HUD_SKIN_KEY = "default"; // Defined here so it's not in a client-only class. /** [Client-only] The string identifier of the skin used for the spell HUD. */ public String spellHUDSkin = DEFAULT_HUD_SKIN_KEY; - /** Set of constants for each of the four positions that the spell HUD can be in. */ + /** Set of constants for each of the eight positions that the spell HUD can be in. */ public enum GuiPosition { - BOTTOM_LEFT("Bottom left", false, false), - TOP_LEFT("Top left", false, true), - TOP_RIGHT("Top right", true, true), - BOTTOM_RIGHT("Bottom right", true, false); + BOTTOM_LEFT("Bottom left", false, false, false), + TOP_LEFT("Top left", false, true, false), + TOP_RIGHT("Top right", true, true, false), + BOTTOM_RIGHT("Bottom right", true, false, false), + FOLLOW_BOTTOM("Follow wand, bottom", false, false, true), + FOLLOW_TOP("Follow wand, top", false, true, true), + OPPOSITE_BOTTOM("Opposite wand, bottom", true, false, true), + OPPOSITE_TOP("Opposite wand, top", true, true, true); /** Constant array storing the names of each of the constants, in the order they are declared. */ public static final String[] names; - static{ + static { names = new String[values().length]; for(GuiPosition position : values()){ names[position.ordinal()] = position.name; @@ -191,13 +318,15 @@ public final class Settings { /** The readable name for this GUI position that will be displayed on the button in the config GUI. */ public final String name; - public boolean flipX; - public boolean flipY; + public final boolean flipX; + public final boolean flipY; + public final boolean dynamic; - GuiPosition(String name, boolean flipX, boolean flipY){ + GuiPosition(String name, boolean flipX, boolean flipY, boolean dynamic){ this.name = name; this.flipX = flipX; this.flipY = flipY; + this.dynamic = dynamic; } /** @@ -236,8 +365,9 @@ public final class Settings { setupGeneralConfig(); setupWorldgenConfig(); - setupClientConfig(); + if(event.getSide() == Side.CLIENT) setupClientConfig(); // Server has no spell HUD skins so this would crash it setupCommandsConfig(); + setupCompatibilityConfig(); config.save(); } @@ -252,9 +382,9 @@ public final class Settings { Wizardry.logger.info("Setting up spells config for " + Spell.getTotalSpellCount() + " spells"); setupSpellsConfig(); - + Wizardry.logger.info("Setting up resistances config"); - + setupResistancesConfig(); config.save(); @@ -269,6 +399,7 @@ public final class Settings { setupWorldgenConfig(); setupClientConfig(); setupCommandsConfig(); + setupCompatibilityConfig(); setupSpellsConfig(); setupResistancesConfig(); @@ -298,6 +429,7 @@ public final class Settings { I18n.translateToLocal("spell." + spell.getUnlocalisedName() + ".desc")); // Uses the same config key as the spell name, because - well, that's what it's called! property.setLanguageKey("spell." + spell.getUnlocalisedName()); + Wizardry.proxy.setToNamedBooleanEntry(property); spell.setEnabled(property.getBoolean()); } @@ -306,7 +438,7 @@ public final class Settings { private void setupGeneralConfig(){ // This trick is borrowed from forge; it sorts the config options into the order you want them. - List propOrder = new ArrayList(); + List propOrder = new ArrayList<>(); Property property; @@ -315,108 +447,251 @@ public final class Settings { property = config.get(GAMEPLAY_CATEGORY, "discoveryMode", true, "For those who like a sense of mystery! When set to true, spells you haven't cast yet will be unreadable until you cast them (on a per-world basis). Has no effect when in creative mode. Spells of identification will be unobtainable in survival mode if this is false."); property.setLanguageKey("config." + Wizardry.MODID + ".discovery_mode"); + Wizardry.proxy.setToNamedBooleanEntry(property); property.setRequiresWorldRestart(true); discoveryMode = property.getBoolean(); propOrder.add(property.getName()); - property = config.get(GAMEPLAY_CATEGORY, "friendlyFire", true, - "Whether to allow players to damage their designated allies using magic."); + property = config.get(GAMEPLAY_CATEGORY, "legacyWandLevelling", false, + "Controls whether wands are required to gain progression before they can be upgraded to the next tier. Enable this option to revert to the pre-4.2 system, which only requires tomes of arcana. Wands will still gain progression even when this is enabled, so if you go back to the new system you won't lose any progress."); + property.setLanguageKey("config." + Wizardry.MODID + ".legacy_wand_levelling"); + Wizardry.proxy.setToNamedBooleanEntry(property); + legacyWandLevelling = property.getBoolean(); + propOrder.add(property.getName()); + + property = config.get(GAMEPLAY_CATEGORY, "friendlyFire", FriendlyFire.ALL.name, "Controls which creatures may be damaged by your magic when allied to you. Your spells will not target your allies or creatures summoned/owned by them regardless of this setting, but this setting prevents all magic damage to allies.", FriendlyFire.names); property.setLanguageKey("config." + Wizardry.MODID + ".friendly_fire"); - friendlyFire = property.getBoolean(); - propOrder.add(property.getName()); - - property = config.get(GAMEPLAY_CATEGORY, "spellBookDropChance", 3, - "The chance for mobs to drop a spell book when killed. The greater this number, the more often they will drop. Set to 0 to disable spell book drops. Set to 200 for guaranteed drops.", - 0, 200); - property.setLanguageKey("config." + Wizardry.MODID + ".spell_book_drop_chance"); - Wizardry.proxy.setToNumberSliderEntry(property); - spellBookDropChance = property.getInt(); - propOrder.add(property.getName()); - - property = config.get(GAMEPLAY_CATEGORY, "evilWizardDimensions", new int[]{0}, - "List of dimension ids in which evil wizards can spawn."); - property.setLanguageKey("config." + Wizardry.MODID + ".evil_wizard_dimensions"); - property.setRequiresMcRestart(true); - evilWizardDimensions = property.getIntList(); - propOrder.add(property.getName()); - - // These two aren't sliders because using a slider makes it difficult to fine-tune the numbers; the nature of a - // scaling factor means that 0.5 is as big a change as 2.0, so whilst a slider is fine for increasing the - // damage, it doesn't give fine enough control for values less than 1. - property = config.get(GAMEPLAY_CATEGORY, "playerDamageScaling", 1.0, - "Global damage scaling factor for the damage dealt by players casting spells, relative to 1.", 0, 20); - property.setLanguageKey("config." + Wizardry.MODID + ".player_damage_scaling"); - playerDamageScale = property.getDouble(); - propOrder.add(property.getName()); - - property = config.get(GAMEPLAY_CATEGORY, "npcDamageScaling", 1.0, - "Global damage scaling factor for the damage dealt by NPCs casting spells, relative to 1.", 0, 20); - property.setLanguageKey("config." + Wizardry.MODID + ".npc_damage_scaling"); - npcDamageScale = property.getDouble(); + friendlyFire = FriendlyFire.fromName(property.getString()); propOrder.add(property.getName()); property = config.get(GAMEPLAY_CATEGORY, "minionRevengeTargeting", true, "Whether summoned creatures can revenge attack their owner if their owner attacks them."); property.setLanguageKey("config." + Wizardry.MODID + ".minion_revenge_targeting"); + Wizardry.proxy.setToNamedBooleanEntry(property); property.setRequiresWorldRestart(false); minionRevengeTargeting = property.getBoolean(); propOrder.add(property.getName()); - property = config.get(GAMEPLAY_CATEGORY, "summonedCreatureTargetsWhitelist", new String[0], - "List of names of entities which summoned creatures and wizards are allowed to attack, in addition to the defaults. Add mod creatures to this list if you want summoned creatures to attack them and they aren't already doing so. Entity names are not case sensitive. For mod entities, prefix with the mod ID (e.g. " + Wizardry.MODID + ":wizard)."); - property.setLanguageKey("config." + Wizardry.MODID + ".summoned_creature_targets_whitelist"); - property.setRequiresWorldRestart(true); - // Converts all strings in the list to a ResourceLocation. - summonedCreatureTargetsWhitelist = Arrays.stream(property.getStringList()).map(s -> new ResourceLocation(s.toLowerCase(Locale.ROOT).trim())).toArray(ResourceLocation[]::new); + property = config.get(GAMEPLAY_CATEGORY, "playersMoveEachOther", true, + "Whether to allow players to move other players around using magic."); + property.setLanguageKey("config." + Wizardry.MODID + ".players_move_each_other"); + Wizardry.proxy.setToNamedBooleanEntry(property); + playersMoveEachOther = property.getBoolean(); propOrder.add(property.getName()); - property = config.get(GAMEPLAY_CATEGORY, "summonedCreatureTargetsBlacklist", - new String[]{"creeper"}, - "List of names of entities which summoned creatures and wizards are specifically not allowed to attack, overriding the defaults and the whitelist. Add creatures to this list if allowing them to be attacked causes problems or is too destructive (removing creepers from this list is done at your own risk!). Entity names are not case sensitive. For mod entities, prefix with the mod ID (e.g. " + Wizardry.MODID + ":wizard)."); - property.setLanguageKey("config." + Wizardry.MODID + ".summoned_creature_targets_blacklist"); - property.setRequiresWorldRestart(true); - // Converts all strings in the list to a ResourceLocation. - summonedCreatureTargetsBlacklist = Arrays.stream(property.getStringList()).map(s -> new ResourceLocation(s.toLowerCase(Locale.ROOT).trim())).toArray(ResourceLocation[]::new); + property = config.get(GAMEPLAY_CATEGORY, "playerBlockDamage", true, + "Whether spells cast by players can destroy blocks in the world. Set to false to prevent griefing. To prevent non-players from destroying blocks with magic, use the mobGriefing gamerule."); + property.setLanguageKey("config." + Wizardry.MODID + ".player_block_damage"); + Wizardry.proxy.setToNamedBooleanEntry(property); + playerBlockDamage = property.getBoolean(); propOrder.add(property.getName()); property = config.get(GAMEPLAY_CATEGORY, "telekineticDisarmament", true, "Whether to allow players to disarm other players using the telekinesis spell. Set to false to prevent stealing of items."); property.setLanguageKey("config." + Wizardry.MODID + ".telekinetic_disarmament"); + Wizardry.proxy.setToNamedBooleanEntry(property); telekineticDisarmament = property.getBoolean(); propOrder.add(property.getName()); property = config.get(GAMEPLAY_CATEGORY, "teleportThroughUnbreakableBlocks", false, "Whether players are allowed to teleport through unbreakable blocks (e.g. bedrock) using the phase step spell."); property.setLanguageKey("config." + Wizardry.MODID + ".teleport_through_unbreakable_blocks"); + Wizardry.proxy.setToNamedBooleanEntry(property); teleportThroughUnbreakableBlocks = property.getBoolean(); propOrder.add(property.getName()); + property = config.get(GAMEPLAY_CATEGORY, "worldTimeManipulation", true, + "Whether players are allowed to change the world time with the speed time spell. If this is false, the speed time spell will not change the world time but will still speed up nearby block, entity and tile entity ticks."); + property.setLanguageKey("config." + Wizardry.MODID + ".world_time_manipulation"); + Wizardry.proxy.setToNamedBooleanEntry(property); + worldTimeManipulation = property.getBoolean(); + propOrder.add(property.getName()); + + property = config.get(GAMEPLAY_CATEGORY, "replaceVanillaFireballs", true, + "Whether to replace Minecraft's own fireballs with wizardry fireballs. If this is disabled, only wizardry spells will use the custom fireballs."); + property.setLanguageKey("config." + Wizardry.MODID + ".replace_vanilla_fireballs"); + Wizardry.proxy.setToNamedBooleanEntry(property); + replaceVanillaFireballs = property.getBoolean(); + propOrder.add(property.getName()); + + property = config.get(GAMEPLAY_CATEGORY, "replaceVanillaFallDamage", true, + "Whether to replace Minecraft's distance-based fall damage calculation with an equivalent, velocity-based one. This is done such that mobs in freefall will take exactly the same damage as normal, so it will not break falling-based mob farms. Disable this if you experience falling-related weirdness! If this is disabled, some spells will use a more simplistic method of resetting the player's fall damage in certain cases."); + property.setLanguageKey("config." + Wizardry.MODID + ".replace_vanilla_fall_damage"); + Wizardry.proxy.setToNamedBooleanEntry(property); + replaceVanillaFallDamage = property.getBoolean(); + propOrder.add(property.getName()); + + property = config.get(GAMEPLAY_CATEGORY, "creativeBypassesArcaneLock", true, + "Whether any player in creative mode can bypass arcane-locked blocks. If this is false, players must also be op in order to do so."); + property.setLanguageKey("config." + Wizardry.MODID + ".creative_bypasses_arcane_lock"); + Wizardry.proxy.setToNamedBooleanEntry(property); + creativeBypassesArcaneLock = property.getBoolean(); + propOrder.add(property.getName()); + + property = config.get(GAMEPLAY_CATEGORY, "slowTimeAffectsPlayers", true, + "Whether players are slowed when another nearby player uses the slow time spell. If this is false, mobs and projectiles will still be affected but players will move at normal speed."); + property.setLanguageKey("config." + Wizardry.MODID + ".slow_time_affects_players"); + Wizardry.proxy.setToNamedBooleanEntry(property); + slowTimeAffectsPlayers = property.getBoolean(); + propOrder.add(property.getName()); + + property = config.get(GAMEPLAY_CATEGORY, "mobLootTableWhitelist", new String[0], "Whitelist for loot tables to inject additional mob drops (as specified in loot_tables/entities/mob_additions.json) into. Wizardry makes a best guess as to which loot tables belong to hostile mobs, but this may not always be correct or appropriate; add loot table locations (not entity IDs) to this list to manually include them."); + property.setLanguageKey("config." + Wizardry.MODID + ".mob_loot_table_whitelist"); + property.setRequiresMcRestart(true); + mobLootTableWhitelist = getResourceLocationList(property); + propOrder.add(property.getName()); + + property = config.get(GAMEPLAY_CATEGORY, "mobLootTableBlacklist", new String[]{"entities/vex", "entities/ender_dragon", "entities/wither", Wizardry.MODID + ":entities/evil_wizard"}, "Blacklist for loot tables to inject additional mob drops (as specified in loot_tables/entities/mob_additions.json) into. Wizardry makes a best guess as to which loot tables belong to hostile mobs, but this may not always be correct or appropriate; add loot table locations (not entity IDs) to this list to manually exclude them."); + property.setLanguageKey("config." + Wizardry.MODID + ".mob_loot_table_blacklist"); + property.setRequiresMcRestart(true); + mobLootTableBlacklist = getResourceLocationList(property); + propOrder.add(property.getName()); + + property = config.get(GAMEPLAY_CATEGORY, "mobSpawnDimensions", new int[]{0}, + "List of dimension ids in which wizardry's hostile mobs can spawn."); + property.setLanguageKey("config." + Wizardry.MODID + ".mob_spawn_dimensions"); + property.setRequiresMcRestart(true); + mobSpawnDimensions = property.getIntList(); + propOrder.add(property.getName()); + + property = config.get(GAMEPLAY_CATEGORY, "mobSpawnBiomeBlacklist", new String[]{"mushroom_island", "mushroom_island_shore"}, + "List of names of biomes in which wizardry's hostile mobs cannot spawn. Biome names are not case-sensitive. For mod biomes, prefix with the mod ID (e.g. biomesoplenty:mystic_grove)."); + property.setLanguageKey("config." + Wizardry.MODID + ".mob_spawn_biome_blacklist"); + property.setRequiresMcRestart(true); + mobSpawnBiomeBlacklist = getResourceLocationList(property); + propOrder.add(property.getName()); + + property = config.get(GAMEPLAY_CATEGORY, "evilWizardSpawnRate", 3, + "Spawn rate for naturally-spawned evil wizards; higher numbers mean more evil wizards will spawn. 5 is equivalent to witches, 100 is equivalent to zombies, skeletons and creepers. Set to 0 to disable evil wizard spawning entirely.", + 0, 100); + property.setLanguageKey("config." + Wizardry.MODID + ".evil_wizard_spawn_rate"); + Wizardry.proxy.setToNumberSliderEntry(property); + property.setRequiresMcRestart(true); + evilWizardSpawnRate = property.getInt(); + propOrder.add(property.getName()); + + property = config.get(GAMEPLAY_CATEGORY, "iceWraithSpawnRate", 3, + "Spawn rate for naturally-spawned ice wraiths; higher numbers mean more ice wraiths will spawn. 5 is equivalent to witches, 100 is equivalent to zombies, skeletons and creepers. Set to 0 to disable ice wraith spawning entirely.", + 0, 100); + property.setLanguageKey("config." + Wizardry.MODID + ".ice_wraith_spawn_rate"); + Wizardry.proxy.setToNumberSliderEntry(property); + property.setRequiresMcRestart(true); + iceWraithSpawnRate = property.getInt(); + propOrder.add(property.getName()); + + property = config.get(GAMEPLAY_CATEGORY, "lightningWraithSpawnRate", 1, + "Spawn rate for naturally-spawned lightning wraiths; higher numbers mean more lightning wraiths will spawn. 5 is equivalent to witches, 100 is equivalent to zombies, skeletons and creepers. Set to 0 to disable lightning wraith spawning entirely.", + 0, 100); + property.setLanguageKey("config." + Wizardry.MODID + ".lightning_wraith_spawn_rate"); + Wizardry.proxy.setToNumberSliderEntry(property); + property.setRequiresMcRestart(true); + lightningWraithSpawnRate = property.getInt(); + propOrder.add(property.getName()); + + property = config.get(GAMEPLAY_CATEGORY, "forfeitChance", 0.2, + "The chance to 'misread' an undiscovered spell and trigger a forfeit instead. Setting this to 0 effectively disables the forfeit mechanic. Has no effect if discovery mode is disabled.", + 0, 1); + property.setLanguageKey("config." + Wizardry.MODID + ".forfeit_chance"); + Wizardry.proxy.setToNumberSliderEntry(property); + forfeitChance = property.getDouble(); + propOrder.add(property.getName()); + + // These two aren't sliders because using a slider makes it difficult to fine-tune the numbers; the nature of a + // scaling factor means that 0.5 is as big a change as 2.0, so whilst a slider is fine for increasing the + // damage, it doesn't give fine enough control for values less than 1. + property = config.get(GAMEPLAY_CATEGORY, "playerDamageScaling", 1.0, + "Global damage scaling factor for the damage dealt by players casting spells, relative to 1.", 0, 255); + property.setLanguageKey("config." + Wizardry.MODID + ".player_damage_scaling"); + playerDamageScale = property.getDouble(); + propOrder.add(property.getName()); + + property = config.get(GAMEPLAY_CATEGORY, "npcDamageScaling", 1.0, + "Global damage scaling factor for the damage dealt by NPCs casting spells, relative to 1.", 0, 255); + property.setLanguageKey("config." + Wizardry.MODID + ".npc_damage_scaling"); + npcDamageScale = property.getDouble(); + propOrder.add(property.getName()); + + property = config.get(GAMEPLAY_CATEGORY, "summonedCreatureTargetsWhitelist", new String[0], + "List of names of entities which summoned creatures and wizards are allowed to attack, in addition to the defaults. Add mod creatures to this list if you want summoned creatures to attack them and they aren't already doing so. SoundLoopSpellEntity names are not case sensitive. For mod entities, prefix with the mod ID (e.g. " + Wizardry.MODID + ":wizard)."); + property.setLanguageKey("config." + Wizardry.MODID + ".summoned_creature_targets_whitelist"); + property.setRequiresWorldRestart(true); + summonedCreatureTargetsWhitelist = getResourceLocationList(property); + propOrder.add(property.getName()); + + property = config.get(GAMEPLAY_CATEGORY, "summonedCreatureTargetsBlacklist", new String[]{"creeper"}, + "List of names of entities which summoned creatures and wizards are specifically not allowed to attack, overriding the defaults and the whitelist. Add creatures to this list if allowing them to be attacked causes problems or is too destructive (removing creepers from this list is done at your own risk!). SoundLoopSpellEntity names are not case sensitive. For mod entities, prefix with the mod ID (e.g. " + Wizardry.MODID + ":wizard)."); + property.setLanguageKey("config." + Wizardry.MODID + ".summoned_creature_targets_blacklist"); + property.setRequiresWorldRestart(true); + summonedCreatureTargetsBlacklist = getResourceLocationList(property); + propOrder.add(property.getName()); + property = config.get(GAMEPLAY_CATEGORY, "mindControlTargetsBlacklist", new String[]{}, - "List of names of entities which cannot be mind controlled, in addition to the defaults. Add creatures to this list if allowing them to be mind-controlled causes problems or could be exploited. Entity names are not case sensitive. For mod entities, prefix with the mod ID (e.g. " + Wizardry.MODID + ":wizard)."); + "List of names of entities which cannot be mind controlled, in addition to the defaults. Add creatures to this list if allowing them to be mind-controlled causes problems or could be exploited. SoundLoopSpellEntity names are not case sensitive. For mod entities, prefix with the mod ID (e.g. " + Wizardry.MODID + ":wizard)."); property.setLanguageKey("config." + Wizardry.MODID + ".mind_control_targets_blacklist"); property.setRequiresWorldRestart(true); - // Converts all strings in the list to a ResourceLocation. - mindControlTargetsBlacklist = Arrays.stream(property.getStringList()).map(s -> new ResourceLocation(s.toLowerCase(Locale.ROOT).trim())).toArray(ResourceLocation[]::new); + mindControlTargetsBlacklist = getResourceLocationList(property); propOrder.add(property.getName()); + property = config.get(GAMEPLAY_CATEGORY, "pocketFurnaceItemBlacklist", new String[]{"cobblestone", "netherrack"}, + "List of registry names of blocks or items which cannot be smelted by the pocket furnace spell, in addition to armour, tools and weapons. Block/item names are not case sensitive. For mod items, prefix with the mod ID (e.g. " + Wizardry.MODID + ":crystal_ore)."); + property.setLanguageKey("config." + Wizardry.MODID + ".pocket_furnace_item_blacklist"); + property.setRequiresWorldRestart(true); + pocketFurnaceItemBlacklist = getResourceLocationList(property); + propOrder.add(property.getName()); + + property = config.get(GAMEPLAY_CATEGORY, "divinationOreWhitelist", new String[0], "List of registry names of ore blocks which can be detected by the divination spell. Block names are not case sensitive. For mod blocks, prefix with the mod ID (e.g. " + Wizardry.MODID + ":crystal_ore)."); + property.setLanguageKey("config." + Wizardry.MODID + ".divination_ore_whitelist"); + property.setRequiresWorldRestart(true); + divinationOreWhitelist = getResourceLocationList(property); + propOrder.add(property.getName()); + + property = config.get(GAMEPLAY_CATEGORY, "swordItemWhitelist", new String[0], "List of registry names of items which should count as swords for imbuement spells. Most swords should work automatically, but those that don't can be added manually here. Item names are not case sensitive. For mod items, prefix with the mod ID (e.g. tconstruct:broadsword)."); + property.setLanguageKey("config." + Wizardry.MODID + ".sword_item_whitelist"); + property.setRequiresWorldRestart(true); + swordItemWhitelist = getResourceLocationList(property); + propOrder.add(property.getName()); + + property = config.get(GAMEPLAY_CATEGORY, "bowItemWhitelist", new String[0], "List of registry names of items which should count as bows for imbuement spells. Most bows should work automatically, but those that don't can be added manually here. Item names are not case sensitive. For mod items, prefix with the mod ID (e.g. tconstruct:shortbow)."); + property.setLanguageKey("config." + Wizardry.MODID + ".bow_item_whitelist"); + property.setRequiresWorldRestart(true); + bowItemWhitelist = getResourceLocationList(property); + propOrder.add(property.getName()); + + property = config.get(GAMEPLAY_CATEGORY, "currencyItems", new String[]{"gold_ingot 3", "emerald 6"}, "List of registry names of items which wizard trades can use as currency (in the first slot; the second slot is unaffected). Each entry in this list should consist of an item registry name, followed by a single space, then an integer which defines the 'value' of the item. Higher values mean fewer of that currency item are required for a given trade.", + Pattern.compile("[A-Za-z:_]+ [0-9]+")); + property.setLanguageKey("config." + Wizardry.MODID + ".currency_items"); + property.setRequiresWorldRestart(true); + propOrder.add(property.getName()); + currencyItems = new HashMap<>(); + for(String string : property.getStringList()){ + String[] args = string.split(" "); + if(args.length != 2){ + Wizardry.logger.warn("Invalid entry in currency items: {}", string); + continue; // Ignore invalid entries, the pattern above should ensure this never happens + } + try { + currencyItems.put(new ResourceLocation(args[0]), Integer.parseInt(args[1])); + }catch(NumberFormatException e){ + Wizardry.logger.warn("Invalid integer in currency items: {}", args[1]); + } + } + config.setCategoryPropertyOrder(GAMEPLAY_CATEGORY, propOrder); } - + private void setupWorldgenConfig(){ - // This trick is borrowed from forge; it sorts the config options into the order you want them. - List propOrder = new ArrayList(); + List propOrder = new ArrayList<>(); Property property; config.addCustomCategoryComment(WORLDGEN_CATEGORY, "Settings that affect world generation. In multiplayer, the server/LAN host settings will apply."); - - property = config.get(WORLDGEN_CATEGORY, "towerRarity", 8, "Rarity of wizard towers. Higher numbers are rarer. Set to 0 to disable wizard towers completely.", 0, 50); - property.setLanguageKey("config." + Wizardry.MODID + ".tower_rarity"); - property.setRequiresWorldRestart(true); - Wizardry.proxy.setToNumberSliderEntry(property); - towerRarity = property.getInt(); + + property = config.get(WORLDGEN_CATEGORY, "fastWorldgen", false, "Whether to use faster worldgen at the cost of 'seamlessness'. Enabling this option removes the checks for steep slopes and cleanup of floating trees that improve the look of worldgen. Performance improvement will vary depending on your setup. This option will affect randomisation; for any given seed, structures will not be the same as when it is turned off."); + property.setLanguageKey("config." + Wizardry.MODID + ".fast_worldgen"); + Wizardry.proxy.setToNamedBooleanEntry(property); + fastWorldgen = property.getBoolean(); propOrder.add(property.getName()); property = config.get(WORLDGEN_CATEGORY, "towerDimensions", new int[]{0}, "List of dimension ids in which wizard towers will generate."); @@ -425,6 +700,74 @@ public final class Settings { towerDimensions = property.getIntList(); propOrder.add(property.getName()); + property = config.get(WORLDGEN_CATEGORY, "towerRarity", 600, "Rarity of wizard towers. 1 in this many chunks will contain a wizard tower, meaning higher numbers are rarer.", 20, 5000); + property.setLanguageKey("config." + Wizardry.MODID + ".tower_rarity"); + property.setRequiresWorldRestart(true); + Wizardry.proxy.setToNumberSliderEntry(property); + towerRarity = property.getInt(); + propOrder.add(property.getName()); + + property = config.get(WORLDGEN_CATEGORY, "evilWizardChance", 0.2, "The chance for wizard towers to generate with an evil wizard and chest inside, instead of a friendly wizard.", 0, 1); + property.setLanguageKey("config." + Wizardry.MODID + ".evil_wizard_chance"); + property.setRequiresWorldRestart(true); + Wizardry.proxy.setToNumberSliderEntry(property); + evilWizardChance = property.getDouble(); + propOrder.add(property.getName()); + + property = config.get(WORLDGEN_CATEGORY, "towerFiles", new String[]{Wizardry.MODID + ":wizard_tower_0", Wizardry.MODID + ":wizard_tower_1", Wizardry.MODID + ":wizard_tower_2", Wizardry.MODID + ":wizard_tower_3"}, + "List of structure file locations for wizard towers without loot chests. One of these files will be randomly selected each time a wizard tower is generated. File locations are of the format [mod id]:[filename], which refers to the file assets/[mod id]/structures/[filename].nbt. Duplicate entries are permitted, allowing for simple weighting without duplicating the structure files themselves."); + property.setLanguageKey("config." + Wizardry.MODID + ".tower_files"); + property.setRequiresWorldRestart(true); + towerFiles = getResourceLocationList(property); + propOrder.add(property.getName()); + + property = config.get(WORLDGEN_CATEGORY, "towerWithChestFiles", new String[]{Wizardry.MODID + ":wizard_tower_chest_0", Wizardry.MODID + ":wizard_tower_chest_1", Wizardry.MODID + ":wizard_tower_chest_2", Wizardry.MODID + ":wizard_tower_chest_3"}, + "List of structure file locations for wizard towers with loot chests. One of these files will be randomly selected each time a wizard tower is generated. File locations are of the format [mod id]:[filename], which refers to the file assets/[mod id]/structures/[filename].nbt. Duplicate entries are permitted, allowing for simple weighting without duplicating the structure files themselves."); + property.setLanguageKey("config." + Wizardry.MODID + ".tower_with_chest_files"); + property.setRequiresWorldRestart(true); + towerWithChestFiles = getResourceLocationList(property); + propOrder.add(property.getName()); + + property = config.get(WORLDGEN_CATEGORY, "obeliskDimensions", new int[]{0, -1}, "List of dimension ids in which obelisks will generate."); + property.setLanguageKey("config." + Wizardry.MODID + ".obelisk_dimensions"); + property.setRequiresWorldRestart(true); + obeliskDimensions = property.getIntList(); + propOrder.add(property.getName()); + + property = config.get(WORLDGEN_CATEGORY, "obeliskRarity", 550, "Rarity of obelisks. 1 in this many chunks will contain an obelisk, meaning higher numbers are rarer.", 20, 5000); + property.setLanguageKey("config." + Wizardry.MODID + ".obelisk_rarity"); + property.setRequiresWorldRestart(true); + Wizardry.proxy.setToNumberSliderEntry(property); + obeliskRarity = property.getInt(); + propOrder.add(property.getName()); + + property = config.get(WORLDGEN_CATEGORY, "obeliskFiles", new String[]{Wizardry.MODID + ":obelisk_0", Wizardry.MODID + ":obelisk_1", Wizardry.MODID + ":obelisk_2", Wizardry.MODID + ":obelisk_3", Wizardry.MODID + ":obelisk_4"}, + "List of structure file locations for obelisks. One of these files will be randomly selected each time an obelisk is generated. File locations are of the format [mod id]:[filename], which refers to the file assets/[mod id]/structures/[filename].nbt. Duplicate entries are permitted, allowing for simple weighting without duplicating the structure files themselves."); + property.setLanguageKey("config." + Wizardry.MODID + ".obelisk_files"); + property.setRequiresWorldRestart(true); + obeliskFiles = getResourceLocationList(property); + propOrder.add(property.getName()); + + property = config.get(WORLDGEN_CATEGORY, "shrineDimensions", new int[]{0, -1}, "List of dimension ids in which shrines will generate."); + property.setLanguageKey("config." + Wizardry.MODID + ".shrine_dimensions"); + property.setRequiresWorldRestart(true); + shrineDimensions = property.getIntList(); + propOrder.add(property.getName()); + + property = config.get(WORLDGEN_CATEGORY, "shrineRarity", 1000, "Rarity of shrines. 1 in this many chunks will contain a shrine, meaning higher numbers are rarer.", 20, 5000); + property.setLanguageKey("config." + Wizardry.MODID + ".shrine_rarity"); + property.setRequiresWorldRestart(true); + Wizardry.proxy.setToNumberSliderEntry(property); + shrineRarity = property.getInt(); + propOrder.add(property.getName()); + + property = config.get(WORLDGEN_CATEGORY, "shrineFiles", new String[]{Wizardry.MODID + ":shrine_0", Wizardry.MODID + ":shrine_1", Wizardry.MODID + ":shrine_2", Wizardry.MODID + ":shrine_3", Wizardry.MODID + ":shrine_4", Wizardry.MODID + ":shrine_5", Wizardry.MODID + ":shrine_6", Wizardry.MODID + ":shrine_7"}, + "List of structure file locations for shrines. One of these files will be randomly selected each time a shrine is generated. File locations are of the format [mod id]:[filename], which refers to the file assets/[mod id]/structures/[filename].nbt. Duplicate entries are permitted, allowing for simple weighting without duplicating the structure files themselves."); + property.setLanguageKey("config." + Wizardry.MODID + ".shrine_files"); + property.setRequiresWorldRestart(true); + shrineFiles = getResourceLocationList(property); + propOrder.add(property.getName()); + property = config.get(WORLDGEN_CATEGORY, "oreDimensions", new int[]{0}, "List of dimension ids in which crystal ore will generate. Note that removing the overworld (id 0) from this list will make the mod VERY difficult to play!"); property.setLanguageKey("config." + Wizardry.MODID + ".ore_dimensions"); property.setRequiresWorldRestart(true); @@ -437,34 +780,35 @@ public final class Settings { flowerDimensions = property.getIntList(); propOrder.add(property.getName()); - property = config.get(WORLDGEN_CATEGORY, "generateLoot", true, "Whether to inject wizardry loot (as specified in loot_tables/chests/dungeon_additions.json) into the loot tables for vanilla dungeon chests."); - property.setLanguageKey("config." + Wizardry.MODID + ".generate_loot"); - property.setRequiresWorldRestart(true); - generateLoot = property.getBoolean(); + property = config.get(WORLDGEN_CATEGORY, "lootInjectionLocations", DEFAULT_LOOT_INJECTION_LOCATIONS, "List of loot tables to inject wizardry loot (as specified in loot_tables/chests/dungeon_additions.json) into."); + property.setLanguageKey("config." + Wizardry.MODID + ".loot_injection_locations"); + property.setRequiresMcRestart(true); + lootInjectionLocations = getResourceLocationList(property); propOrder.add(property.getName()); - + config.setCategoryPropertyOrder(WORLDGEN_CATEGORY, propOrder); } - + private void setupClientConfig(){ - // This trick is borrowed from forge; it sorts the config options into the order you want them. List propOrder = new ArrayList(); Property property; config.addCustomCategoryComment(CLIENT_CATEGORY, "Client-side settings that only affect the local minecraft game. If this file is on a dedicated server, these settings will have no effect; in multiplayer, each player obeys their own settings."); - property = config.get(CLIENT_CATEGORY, "enableShiftScrolling", true, + property = config.get(CLIENT_CATEGORY, "shiftScrolling", true, "Whether you can switch between spells on a wand by scrolling with the mouse wheel while sneaking. Note that this will only affect you; other players connected to the same server obey their own settings."); - property.setLanguageKey("config." + Wizardry.MODID + ".enable_shift_scrolling"); + property.setLanguageKey("config." + Wizardry.MODID + ".shift_scrolling"); property.setRequiresWorldRestart(false); - enableShiftScrolling = property.getBoolean(); + Wizardry.proxy.setToNamedBooleanEntry(property); + shiftScrolling = property.getBoolean(); propOrder.add(property.getName()); - - property = config.get(CLIENT_CATEGORY, "reverseScrollDirection", false, "Whether to reverse the scroll direction used to switch between spells on a wand while sneaking."); + + property = config.get(CLIENT_CATEGORY, "reverseScrollDirection", false, "The scroll direction used to switch between spells on a wand while sneaking."); property.setLanguageKey("config." + Wizardry.MODID + ".reverse_scroll_direction"); property.setRequiresWorldRestart(false); + Wizardry.proxy.setToNamedBooleanEntry(property); reverseScrollDirection = property.getBoolean(); propOrder.add(property.getName()); @@ -472,35 +816,51 @@ public final class Settings { property.setLanguageKey("config." + Wizardry.MODID + ".spell_hud_position"); spellHUDPosition = GuiPosition.fromName(property.getString()); propOrder.add(property.getName()); - + property = config.get(CLIENT_CATEGORY, "spellHUDSkin", DEFAULT_HUD_SKIN_KEY, "The skin used for the spell HUD.", Wizardry.proxy.getSpellHUDSkins().toArray(new String[0])); property.setLanguageKey("config." + Wizardry.MODID + ".spell_hud_skin"); Wizardry.proxy.setToHUDChooserEntry(property); spellHUDSkin = property.getString(); propOrder.add(property.getName()); - property = config.get(CLIENT_CATEGORY, "showSummonedCreatureNames", true, "Whether to show summoned creatures' names and owners above their heads."); - property.setLanguageKey("config." + Wizardry.MODID + ".show_summoned_creature_names"); - showSummonedCreatureNames = property.getBoolean(); + property = config.get(CLIENT_CATEGORY, "handbookProgression", true, "When set to true, sections of The Wizard's Handbook are unlocked when a player gains the advancement that triggers them, and are hidden otherwise. When set to false, the entire handbook is readable regardless of advancement progress."); + property.setLanguageKey("config." + Wizardry.MODID + ".handbook_progression"); + Wizardry.proxy.setToNamedBooleanEntry(property); + handbookProgression = property.getBoolean(); + propOrder.add(property.getName()); + + property = config.get(CLIENT_CATEGORY, "booksPauseGame", true, "Whether opening any of wizardry's books pauses the game in singleplayer. Has no effect on servers or LAN worlds."); + property.setLanguageKey("config." + Wizardry.MODID + ".books_pause_game"); + Wizardry.proxy.setToNamedBooleanEntry(property); + booksPauseGame = property.getBoolean(); + propOrder.add(property.getName()); + + property = config.get(CLIENT_CATEGORY, "summonedCreatureNames", true, "Whether to show summoned creatures' names and owners above their heads."); + property.setLanguageKey("config." + Wizardry.MODID + ".summoned_creature_names"); + Wizardry.proxy.setToNamedBooleanEntry(property); + summonedCreatureNames = property.getBoolean(); + propOrder.add(property.getName()); + + property = config.get(CLIENT_CATEGORY, "useShaders", true, "Whether to use custom shaders for certain spells. These use the vanilla shader system (like mob spectating shaders) and shouldn't have much of an effect on performance in most cases, but they may conflict with other shaders."); + property.setLanguageKey("config." + Wizardry.MODID + ".use_shaders"); + Wizardry.proxy.setToNamedBooleanEntry(property); + useShaders = property.getBoolean(); propOrder.add(property.getName()); config.setCategoryPropertyOrder(CLIENT_CATEGORY, propOrder); } - + private void setupCommandsConfig(){ - // This trick is borrowed from forge; it sorts the config options into the order you want them. List propOrder = new ArrayList(); Property property; config.addCustomCategoryComment(COMMANDS_CATEGORY, "Settings for the commands added by Wizardry. In multiplayer, the server/LAN host settings will apply."); - // This one isn't a slider either because people are likely to want exact values ("it must be at most 50.3" is a - // bit strange!). property = config.get(COMMANDS_CATEGORY, "castCommandMultiplierLimit", 20.0, "Upper limit for the multipliers passed into the /cast command. This is here to stop players from accidentally breaking a world/server. Large blast mutipliers can cause extreme lag - you have been warned!", - 1, 255); + 1, Integer.MAX_VALUE); // Sure, I mean you COULD set it to 2^31-1... what could possibly go wrong? property.setLanguageKey("config." + Wizardry.MODID + ".cast_command_multiplier_limit"); maxSpellCommandMultiplier = property.getDouble(); propOrder.add(property.getName()); @@ -532,7 +892,7 @@ public final class Settings { property.setRequiresWorldRestart(true); alliesCommandName = property.getString(); propOrder.add(property.getName()); - + config.setCategoryPropertyOrder(COMMANDS_CATEGORY, propOrder); } @@ -546,7 +906,7 @@ public final class Settings { "Settings which allow entities to be made immune to certain types of magic. In multiplayer, the server/LAN host settings will apply."); property = config.get(RESISTANCES_CATEGORY, "mobsImmuneToFire", new String[]{}, - "List of names of entities that are immune to fire, in addition to the defaults. Add mod creatures to this list if you want them to be immune to fire magic and they aren't already. Entity names are not case sensitive. For mod entities, prefix with the mod ID (e.g. " + Wizardry.MODID + ":wizard)."); + "List of names of entities that are immune to fire, in addition to the defaults. Add mod creatures to this list if you want them to be immune to fire magic and they aren't already. SoundLoopSpellEntity names are not case sensitive. For mod entities, prefix with the mod ID (e.g. " + Wizardry.MODID + ":wizard)."); property.setLanguageKey("config." + Wizardry.MODID + ".mobs_immune_to_fire"); property.setRequiresMcRestart(true); // Wizardry.proxy.setToEntityNameEntry(property); @@ -559,7 +919,7 @@ public final class Settings { propOrder.add(property.getName()); property = config.get(RESISTANCES_CATEGORY, "mobsImmuneToIce", new String[]{}, - "List of names of entities that are immune to ice, in addition to the defaults. Add mod creatures to this list if you want them to be immune to ice magic and they aren't already. Entity names are not case sensitive. For mod entities, prefix with the mod ID (e.g. " + Wizardry.MODID + ":wizard)."); + "List of names of entities that are immune to ice, in addition to the defaults. Add mod creatures to this list if you want them to be immune to ice magic and they aren't already. SoundLoopSpellEntity names are not case sensitive. For mod entities, prefix with the mod ID (e.g. " + Wizardry.MODID + ":wizard)."); property.setLanguageKey("config." + Wizardry.MODID + ".mobs_immune_to_ice"); property.setRequiresMcRestart(true); // Wizardry.proxy.setToEntityNameEntry(property); @@ -572,7 +932,7 @@ public final class Settings { propOrder.add(property.getName()); property = config.get(RESISTANCES_CATEGORY, "mobsImmuneToLightning", new String[]{}, - "List of names of entities that are immune to lightning, in addition to the defaults. Add mod creatures to this list if you want them to be immune to lightning magic and they aren't already. Entity names are not case sensitive. For mod entities, prefix with the mod ID (e.g. " + Wizardry.MODID + ":wizard)."); + "List of names of entities that are immune to lightning, in addition to the defaults. Add mod creatures to this list if you want them to be immune to lightning magic and they aren't already. SoundLoopSpellEntity names are not case sensitive. For mod entities, prefix with the mod ID (e.g. " + Wizardry.MODID + ":wizard)."); property.setLanguageKey("config." + Wizardry.MODID + ".mobs_immune_to_lightning"); property.setRequiresMcRestart(true); // Wizardry.proxy.setToEntityNameEntry(property); @@ -585,7 +945,7 @@ public final class Settings { propOrder.add(property.getName()); property = config.get(RESISTANCES_CATEGORY, "mobsImmuneToWither", new String[]{}, - "List of names of entities that are immune to wither effects, in addition to the defaults. Add mod creatures to this list if you want them to be immune to withering magic and they aren't already. Entity names are not case sensitive. For mod entities, prefix with the mod ID (e.g. " + Wizardry.MODID + ":wizard)."); + "List of names of entities that are immune to wither effects, in addition to the defaults. Add mod creatures to this list if you want them to be immune to withering magic and they aren't already. SoundLoopSpellEntity names are not case sensitive. For mod entities, prefix with the mod ID (e.g. " + Wizardry.MODID + ":wizard)."); property.setLanguageKey("config." + Wizardry.MODID + ".mobs_immune_to_wither"); property.setRequiresMcRestart(true); // Wizardry.proxy.setToEntityNameEntry(property); @@ -598,7 +958,7 @@ public final class Settings { propOrder.add(property.getName()); property = config.get(RESISTANCES_CATEGORY, "mobsImmuneToPoison", new String[]{}, - "List of names of entities that are immune to poison, in addition to the defaults. Add mod creatures to this list if you want them to be immune to poison magic and they aren't already. Entity names are not case sensitive. For mod entities, prefix with the mod ID (e.g. " + Wizardry.MODID + ":wizard)."); + "List of names of entities that are immune to poison, in addition to the defaults. Add mod creatures to this list if you want them to be immune to poison magic and they aren't already. SoundLoopSpellEntity names are not case sensitive. For mod entities, prefix with the mod ID (e.g. " + Wizardry.MODID + ":wizard)."); property.setLanguageKey("config." + Wizardry.MODID + ".mobs_immune_to_poison"); property.setRequiresMcRestart(true); // Wizardry.proxy.setToEntityNameEntry(property); @@ -613,4 +973,87 @@ public final class Settings { config.setCategoryPropertyOrder(RESISTANCES_CATEGORY, propOrder); } + private void setupCompatibilityConfig(){ + + List propOrder = new ArrayList(); + + Property property; + + config.addCustomCategoryComment(COMPATIBILITY_CATEGORY, "Settings that affect how wizardry interacts with other mods. In multiplayer, the server/LAN host settings will apply."); + + property = config.get(COMPATIBILITY_CATEGORY, "damageSourceBlacklist", new String[]{}, + "List of damage source string identifiers to be ignored when re-applying damage. Case-sensitive. A message will be logged if wizardry detects a damage source that should be added to this list. Otherwise, don't change unless instructed to do so."); + property.setLanguageKey("config." + Wizardry.MODID + ".damage_source_blacklist"); + property.setRequiresWorldRestart(true); + damageSourceBlacklist = property.getStringList(); + propOrder.add(property.getName()); + + property = config.get(COMPATIBILITY_CATEGORY, "compatibilityWarnings", true, + "Whether to print compatibility warnings to the console. Set to false if excessive messages are being printed."); + property.setLanguageKey("config." + Wizardry.MODID + ".compatibility_warnings"); + Wizardry.proxy.setToNamedBooleanEntry(property); + compatibilityWarnings = property.getBoolean(); + propOrder.add(property.getName()); + + property = config.get(COMPATIBILITY_CATEGORY, "baublesIntegration", true, + "If Baubles is installed, controls whether Baubles integration features are enabled. If this is disabled, wizardry will always behave as if Baubles is not installed."); + property.setLanguageKey("config." + Wizardry.MODID + ".baubles_integration"); + property.setRequiresMcRestart(true); + Wizardry.proxy.setToNamedBooleanEntry(property); + baublesIntegration = property.getBoolean(); + propOrder.add(property.getName()); + +// property = config.get(COMPATIBILITY_CATEGORY, "jeiIntegration", true, +// "If JEI (Just Enough Items) is installed, controls whether JEI integration features are enabled. If this is disabled, wizardry will always behave as if JEI is not installed."); +// property.setLanguageKey("config." + Wizardry.MODID + ".jei_integration"); +// property.setRequiresMcRestart(true); +// Wizardry.proxy.setToNamedBooleanEntry(property); +// jeiIntegration = property.getBoolean(); +// propOrder.add(property.getName()); + + property = config.get(COMPATIBILITY_CATEGORY, "antiqueAtlasIntegration", true, + "If Antique Atlas is installed, controls whether Antique Atlas integration features are enabled. If this is disabled, wizardry will always behave as if Antique Atlas is not installed."); + property.setLanguageKey("config." + Wizardry.MODID + ".antique_atlas_integration"); + property.setRequiresMcRestart(true); + Wizardry.proxy.setToNamedBooleanEntry(property); + antiqueAtlasIntegration = property.getBoolean(); + propOrder.add(property.getName()); + + property = config.get(COMPATIBILITY_CATEGORY, "autoPlaceTowerMarkers", true, + "Controls whether wizardry automatically places antique atlas markers at the locations of wizard towers."); + property.setLanguageKey("config." + Wizardry.MODID + ".auto_place_tower_markers"); + property.setRequiresMcRestart(true); + Wizardry.proxy.setToNamedBooleanEntry(property); + autoTowerMarkers = property.getBoolean(); + propOrder.add(property.getName()); + + property = config.get(COMPATIBILITY_CATEGORY, "autoPlaceObeliskMarkers", true, + "Controls whether wizardry automatically places antique atlas markers at the locations of obelisks."); + property.setLanguageKey("config." + Wizardry.MODID + ".auto_place_obelisk_markers"); + property.setRequiresMcRestart(true); + Wizardry.proxy.setToNamedBooleanEntry(property); + autoObeliskMarkers = property.getBoolean(); + propOrder.add(property.getName()); + + property = config.get(COMPATIBILITY_CATEGORY, "autoPlaceShrineMarkers", true, + "Controls whether wizardry automatically places antique atlas markers at the locations of shrines."); + property.setLanguageKey("config." + Wizardry.MODID + ".auto_place_shrine_markers"); + property.setRequiresMcRestart(true); + Wizardry.proxy.setToNamedBooleanEntry(property); + autoShrineMarkers = property.getBoolean(); + propOrder.add(property.getName()); + + config.setCategoryPropertyOrder(COMPATIBILITY_CATEGORY, propOrder); + + } + + /** Retrieves a string list from the given property and converts it to an array of {@link ResourceLocation}s. */ + public static ResourceLocation[] getResourceLocationList(Property property){ + return toResourceLocations(property.getStringList()); + } + + /** Converts the given strings to an array of {@link ResourceLocation}s */ + public static ResourceLocation[] toResourceLocations(String... strings){ + return Arrays.stream(strings).map(s -> new ResourceLocation(s.toLowerCase(Locale.ROOT).trim())).toArray(ResourceLocation[]::new); + } } diff --git a/src/main/java/electroblob/wizardry/Wizardry.java b/src/main/java/electroblob/wizardry/Wizardry.java index 732b36ae..1eeb4806 100644 --- a/src/main/java/electroblob/wizardry/Wizardry.java +++ b/src/main/java/electroblob/wizardry/Wizardry.java @@ -1,23 +1,22 @@ package electroblob.wizardry; -import org.apache.logging.log4j.Logger; - import electroblob.wizardry.command.CommandCastSpell; import electroblob.wizardry.command.CommandDiscoverSpell; import electroblob.wizardry.command.CommandSetAlly; import electroblob.wizardry.command.CommandViewAllies; +import electroblob.wizardry.data.DispenserCastingData; +import electroblob.wizardry.data.WizardData; +import electroblob.wizardry.integration.antiqueatlas.WizardryAntiqueAtlasIntegration; +import electroblob.wizardry.integration.baubles.WizardryBaublesIntegration; +import electroblob.wizardry.misc.Forfeit; import electroblob.wizardry.packet.WizardryPacketHandler; -import electroblob.wizardry.registry.WizardryAdvancementTriggers; -import electroblob.wizardry.registry.WizardryItems; -import electroblob.wizardry.registry.WizardryRegistry; -import electroblob.wizardry.registry.WizardryTabs; +import electroblob.wizardry.registry.*; +import electroblob.wizardry.spell.Spell; +import electroblob.wizardry.util.CustomSoundCategory; +import electroblob.wizardry.util.SpellProperties; +import electroblob.wizardry.worldgen.*; import net.minecraft.item.Item; -import net.minecraft.nbt.NBTBase; -import net.minecraft.util.EnumFacing; import net.minecraftforge.common.MinecraftForge; -import net.minecraftforge.common.capabilities.Capability; -import net.minecraftforge.common.capabilities.Capability.IStorage; -import net.minecraftforge.common.capabilities.CapabilityManager; import net.minecraftforge.event.RegistryEvent; import net.minecraftforge.fml.common.Mod; import net.minecraftforge.fml.common.Mod.EventHandler; @@ -30,12 +29,13 @@ import net.minecraftforge.fml.common.event.FMLServerStartingEvent; import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; import net.minecraftforge.fml.common.network.NetworkRegistry; import net.minecraftforge.fml.common.registry.GameRegistry; +import org.apache.logging.log4j.Logger; /** * "Electroblob's Wizardry adds an RPG-like system of spells to Minecraft, with the aim of being as playable as * possible. No crazy constructs, no perk trees, no complex recipes - simply find spell books, cast spells, and master * the arcane! - But you knew that, right?" - *

    + *

    * Main mod class for Wizardry. Contains the logger and settings instances, along with all the other stuff that's normally * in a main mod class. * @author Electroblob @@ -50,9 +50,9 @@ public class Wizardry { public static final String NAME = "Electroblob's Wizardry"; /** * The version number for this version of wizardry. The following system is used for version numbers: - *

    + *

    *
    [major Minecraft version].[major mod version].[minor mod version/patch] - *

    + *

    *
    The major mod version is consistent across Minecraft versions, i.e. Wizardry 1.1 has the same * features as Wizardry 2.1, but they are for different versions of Minecraft and have separate minor versioning. * 1.x.x represents Minecraft 1.7.x versions, 2.x.x represents Minecraft 1.10.x versions, 3.x.x represents Minecraft @@ -60,56 +60,28 @@ public class Wizardry { */ public static final String VERSION = "4.2.0"; - // IDEA: Improve the algorithm that finds a place to summon creatures to take walls into account. - // IDEA: Replace all uses of Math.cos and Math.sin with MathHelper versions // IDEA: Triggering of inbuilt Forge events in relevant places? // IDEA: Abstract the vanilla particles behind the particle builder - /* Minor bugs that need fixing at some point: - * - Player skin hat layer shows through wizard hats - Wizard armour breaks rather than just running out of mana (I - * can't seem to replicate this bug, but I have had it happen to me before...) - * - Shift-clicking a stack of special upgrades when in the arcane workbench causes the whole stack to be - * transferred when it should be just one (this is a bug with vanilla as well - try putting a stack of bottles into - * a brewing stand). I have at least made it so only one gets used now, so it has no impact on the game. - * - When a spell is on cooldown, you can't break blocks when holding a wand. */ - - // TODO: So somehow I have managed to overlook the fact that health is actually a float. What this means is that - // I can make the healing spells use damage multipliers - hurrah! - - // TODO: Switch from IInventory to IItemHandler (Or don't. It's only useful for automation really.) // TODO: Have particles obey Minecraft's particle setting where appropriate // (see https://github.com/RootsTeam/Embers/blob/master/src/main/java/teamroots/embers/particle/ParticleUtil.java) - // TODO: Go over all the worldgen code, use IWorldGenerator - // TODO: Implement a continuous sound system using MovingSoundEntity, allowing continuous spells to have a long sound - // loop as well as a start and end sound - // TODO: EntityMagicArrow needs attention - // TODO: Go over particle spawning on projectile impact and make sure hitvec is used wherever appropriate - // TODO: Replace spell IDs in packets with ResourceLocation strings - // TODO: Forcefield needs looking at, esp. with regards to projectiles and explosions // TODO: TileEntityArcaneWorkbench needs looking at, esp. regarding inventory and markDirty - // TODO: Fireskin somehow lost its particles - // TODO: Convert settings over to the @Config system - // TODO: Go through listeners of LivingHurtEvent and decide whether they should change to LivingDamageEvent - - // NOTE: Add melee upgrades to loot tables when they are added. + // TODO: See what can be done with the illager spell sounds (and go over sounds in general) + // TODO: Fix possession + // TODO: Fix charge /** Static instance of the {@link Settings} object for Wizardry. */ public static final Settings settings = new Settings(); /** Static instance of the {@link Logger} object for Wizardry. - *

    + *

    * Logging conventions for wizardry (only these levels are used currently): - *

    + *

    * - ERROR: Anything that threw an exception; may or may not crash the game.
    * - WARN: Anything that isn't supposed to happen during normal operation, but didn't throw an exception.
    * - INFO: Anything that might happen during normal mod operation that the user needs to know about. */ public static Logger logger; - // private static Pattern entityNamePattern; - - // EventManager - WizardryWorldGenerator generator = new WizardryWorldGenerator(); - // The instance of wizardry that Forge uses. @Instance(Wizardry.MODID) public static Wizardry instance; @@ -123,40 +95,27 @@ public class Wizardry { logger = event.getModLog(); - proxy.registerResourceReloadListener(); + proxy.registerResourceReloadListeners(); settings.initConfig(event); - // Yes - by the looks of it, having an interface is completely unnecessary in this case. - CapabilityManager.INSTANCE.register(WizardData.class, new IStorage(){ - // These methods are only called by Capability.writeNBT() or Capability.readNBT(), which in turn are - // NEVER CALLED. Unless I'm missing some reflective invocation, that means this entire class serves only - // to allow capabilities to be saved and loaded manually. What that would be useful for I don't know. - // (If an API forces most users to write redundant code for no reason, it's not user friendly, is it?) - // ... well, that's my rant for today! - @Override - public NBTBase writeNBT(Capability capability, WizardData instance, EnumFacing side){ - return null; - } - - @Override - public void readNBT(Capability capability, WizardData instance, EnumFacing side, NBTBase nbt){ - } - }, WizardData::new); - - WizardryRegistry.registerTileEntities(); - - WizardryRegistry.registerEntities(); - // The check for the generateLoot setting is now done within this method. - WizardryRegistry.registerLoot(); + // Capabilities + WizardData.register(); + DispenserCastingData.register(); + // Register things that don't have registries + WizardryBlocks.registerTileEntities(); + WizardryLoot.register(); WizardryAdvancementTriggers.register(); + Forfeit.register(); - // Moved to preInit, because apparently it has to be here now. + // Client-side stuff (via proxies) proxy.registerRenderers(); - // It seems this also has to be here proxy.registerKeyBindings(); + WizardryBaublesIntegration.init(); + WizardryAntiqueAtlasIntegration.init(); + } @EventHandler @@ -164,26 +123,41 @@ public class Wizardry { settings.initConfigExtras(); - // Event Handlers - GameRegistry.registerWorldGenerator(generator, 0); - MinecraftForge.EVENT_BUS.register(instance); + // World generators + // Weight is a misnomer, it's actually the priority (where lower numbers get generated first) + // Literally nothing on typical 'weight' values here, there isn't even an upper limit + // Examples I've managed to find: + // - Tinker's construct slime islands use 25 + GameRegistry.registerWorldGenerator(new WorldGenCrystalOre(), 0); + GameRegistry.registerWorldGenerator(new WorldGenCrystalFlower(), 50); + GameRegistry.registerWorldGenerator(new WorldGenWizardTower(), 20); + GameRegistry.registerWorldGenerator(new WorldGenObelisk(), 20); + GameRegistry.registerWorldGenerator(new WorldGenShrine(), 20); + + // This is for the config change and missing mappings events + MinecraftForge.EVENT_BUS.register(instance); // Since there's already an instance we might as well use it + NetworkRegistry.INSTANCE.registerGuiHandler(this, new WizardryGuiHandler()); WizardryPacketHandler.initPackets(); + // Post-registry extras + WizardryItems.populateWandMap(); + WizardryItems.populateArmourMap(); + WizardryItems.registerDispenseBehaviours(); + Spell.registry.forEach(Spell::init); + SpellProperties.init(); + + // Client-side stuff (via proxies) proxy.initGuiBits(); - proxy.initParticleFactories(); + proxy.registerParticles(); + proxy.registerSoundEventListener(); + + WizardrySounds.SPELLS = CustomSoundCategory.add(Wizardry.MODID + ":spells"); } @EventHandler public void postInit(FMLPostInitializationEvent event){ - // This needs to be here or it won't necessarily include all the mods' entities. - // TODO: Re-implement this when the Forge bug is fixed. - /* Doesn't seem to be doing anything... String entityNames = ""; for(Object name : - * EntityList.classToStringMapping.values()){ if(name instanceof String){ entityNames = entityNames + name + - * '|'; } } // Cuts off the last '|' entityNames = entityNames.substring(0, entityNames.length()-1); - * entityNamePattern = Pattern.compile(entityNames); */ proxy.initialiseLayers(); - WizardryTabs.sort(); } @EventHandler @@ -205,23 +179,30 @@ public class Wizardry { // 2.1 changed some item ids, so this fixes them for existing worlds // Nobody updates minecraft versions when using mods, but I may as well leave this here just in case. @SubscribeEvent - public static void onMissingMappingEvent(RegistryEvent.MissingMappings event){ + public static void onMissingItemMappingEvent(RegistryEvent.MissingMappings event){ // Just get, not getAll, since the mod id didn't change! for(RegistryEvent.MissingMappings.Mapping mapping : event.getAllMappings()){ - if(mapping.key.getResourceDomain().equals(Wizardry.MODID)){ + if(mapping.key.getNamespace().equals(Wizardry.MODID)){ Item replacement; - switch(mapping.key.getResourcePath()){ + switch(mapping.key.getPath()){ case "wand_basic": replacement = WizardryItems.magic_wand; break; - case "wand_basic_fire": replacement = WizardryItems.basic_fire_wand; break; - case "wand_basic_ice": replacement = WizardryItems.basic_ice_wand; break; - case "wand_basic_lightning": replacement = WizardryItems.basic_lightning_wand; break; - case "wand_basic_necromancy": replacement = WizardryItems.basic_necromancy_wand; break; - case "wand_basic_earth": replacement = WizardryItems.basic_earth_wand; break; - case "wand_basic_sorcery": replacement = WizardryItems.basic_sorcery_wand; break; - case "wand_basic_healing": replacement = WizardryItems.basic_healing_wand; break; + case "wand_basic_fire": replacement = WizardryItems.novice_fire_wand; break; + case "wand_basic_ice": replacement = WizardryItems.novice_ice_wand; break; + case "wand_basic_lightning": replacement = WizardryItems.novice_lightning_wand; break; + case "wand_basic_necromancy": replacement = WizardryItems.novice_necromancy_wand; break; + case "wand_basic_earth": replacement = WizardryItems.novice_earth_wand; break; + case "wand_basic_sorcery": replacement = WizardryItems.novice_sorcery_wand; break; + case "wand_basic_healing": replacement = WizardryItems.novice_healing_wand; break; + case "basic_fire_wand": replacement = WizardryItems.novice_fire_wand; break; + case "basic_ice_wand": replacement = WizardryItems.novice_ice_wand; break; + case "basic_lightning_wand": replacement = WizardryItems.novice_lightning_wand; break; + case "basic_necromancy_wand": replacement = WizardryItems.novice_necromancy_wand; break; + case "basic_earth_wand": replacement = WizardryItems.novice_earth_wand; break; + case "basic_sorcery_wand": replacement = WizardryItems.novice_sorcery_wand; break; + case "basic_healing_wand": replacement = WizardryItems.novice_healing_wand; break; case "wand_apprentice": replacement = WizardryItems.apprentice_wand; break; case "wand_apprentice_fire": replacement = WizardryItems.apprentice_fire_wand; break; case "wand_apprentice_ice": replacement = WizardryItems.apprentice_ice_wand; break; @@ -264,4 +245,13 @@ public class Wizardry { } } + @SubscribeEvent + public static void onMissingSpellMappingEvent(RegistryEvent.MissingMappings event){ + for(RegistryEvent.MissingMappings.Mapping mapping : event.getAllMappings()){ + if(mapping.key.getNamespace().equals(Wizardry.MODID)){ + if(mapping.key.getPath().equals("firestorm")) mapping.remap(Spells.fire_breath); + } + } + } + } \ No newline at end of file diff --git a/src/main/java/electroblob/wizardry/WizardryEventHandler.java b/src/main/java/electroblob/wizardry/WizardryEventHandler.java index ebebcb77..7a57ef9c 100644 --- a/src/main/java/electroblob/wizardry/WizardryEventHandler.java +++ b/src/main/java/electroblob/wizardry/WizardryEventHandler.java @@ -1,120 +1,137 @@ package electroblob.wizardry; import electroblob.wizardry.constants.Constants; -import electroblob.wizardry.entity.EntityArc; -import electroblob.wizardry.entity.living.EntityEvilWizard; +import electroblob.wizardry.data.SpellEmitterData; +import electroblob.wizardry.data.SpellGlyphData; +import electroblob.wizardry.data.WizardData; import electroblob.wizardry.entity.living.ISpellCaster; -import electroblob.wizardry.entity.living.ISummonedCreature; import electroblob.wizardry.event.DiscoverSpellEvent; import electroblob.wizardry.event.SpellCastEvent; import electroblob.wizardry.integration.DamageSafetyChecker; -import electroblob.wizardry.item.ItemWand; -import electroblob.wizardry.item.ItemWizardArmour; -import electroblob.wizardry.registry.Spells; -import electroblob.wizardry.registry.WizardryAdvancementTriggers; -import electroblob.wizardry.registry.WizardryEnchantments; -import electroblob.wizardry.registry.WizardryItems; -import electroblob.wizardry.registry.WizardryPotions; -import electroblob.wizardry.registry.WizardrySounds; +import electroblob.wizardry.item.IManaStoringItem; +import electroblob.wizardry.item.ItemArtefact; +import electroblob.wizardry.packet.PacketSyncAdvancements; +import electroblob.wizardry.packet.WizardryPacketHandler; +import electroblob.wizardry.registry.*; import electroblob.wizardry.spell.FreezingWeapon; +import electroblob.wizardry.spell.ImbueWeapon; import electroblob.wizardry.spell.Spell; +import electroblob.wizardry.util.*; import electroblob.wizardry.util.MagicDamage.DamageType; -import electroblob.wizardry.util.ParticleBuilder; -import electroblob.wizardry.util.SpellModifiers; -import electroblob.wizardry.util.WandHelper; import electroblob.wizardry.util.ParticleBuilder.Type; -import electroblob.wizardry.util.WizardryUtilities; +import net.minecraft.advancements.Advancement; import net.minecraft.enchantment.EnchantmentHelper; import net.minecraft.entity.EntityLiving; import net.minecraft.entity.EntityLivingBase; -import net.minecraft.entity.item.EntityItem; -import net.minecraft.entity.monster.IMob; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.entity.player.EntityPlayerMP; import net.minecraft.entity.projectile.EntityArrow; -import net.minecraft.init.SoundEvents; -import net.minecraft.inventory.ContainerPlayer; -import net.minecraft.inventory.ContainerWorkbench; -import net.minecraft.inventory.IInventory; import net.minecraft.item.ItemStack; -import net.minecraft.item.ItemSword; import net.minecraft.potion.PotionEffect; -import net.minecraft.util.DamageSource; import net.minecraft.util.EnumHand; -import net.minecraft.util.EnumParticleTypes; import net.minecraft.util.ResourceLocation; +import net.minecraft.util.math.Vec3d; import net.minecraft.util.text.TextComponentTranslation; import net.minecraft.world.World; -import net.minecraft.world.storage.loot.LootEntry; -import net.minecraft.world.storage.loot.LootEntryTable; -import net.minecraft.world.storage.loot.LootPool; -import net.minecraft.world.storage.loot.RandomValueRange; -import net.minecraft.world.storage.loot.conditions.LootCondition; import net.minecraftforge.common.MinecraftForge; import net.minecraftforge.common.util.FakePlayer; -import net.minecraftforge.event.LootTableLoadEvent; -import net.minecraftforge.event.entity.living.LivingAttackEvent; -import net.minecraftforge.event.entity.living.LivingDeathEvent; -import net.minecraftforge.event.entity.living.LivingDropsEvent; +import net.minecraftforge.event.entity.PlaySoundAtEntityEvent; +import net.minecraftforge.event.entity.living.*; import net.minecraftforge.event.entity.living.LivingEvent.LivingUpdateEvent; -import net.minecraftforge.event.entity.living.LivingHurtEvent; +import net.minecraftforge.event.entity.player.AdvancementEvent; +import net.minecraftforge.fml.common.Loader; import net.minecraftforge.fml.common.Mod; +import net.minecraftforge.fml.common.eventhandler.EventPriority; import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; import net.minecraftforge.fml.common.gameevent.PlayerEvent.PlayerLoggedInEvent; +import java.util.ArrayList; + /** - * As of Wizardry 2.1, most of the code in this class has been relocated somewhere sensible, leaving only a few - * miscellaneous things that don't make much sense anywhere else, or that are better kept together. Previously, this was - * a gigantic class with about half of the entire mod's logic in it! + * General-purpose event handler for things that don't fit anywhere else or groups of related behaviours that are better + * kept together. As of Wizardry 2.1, most of the code in this class has been relocated somewhere sensible, leaving only + * a few miscellaneous things that don't make much sense anywhere else, or that are better kept together (previously, + * this was a gigantic class with about half of the entire mod's logic in it!) * * @author Electroblob * @since Wizardry 1.0 */ +// The general rules for where event-based logic goes are: +// - If the logic relates only to vanilla things or is general (e.g. gameplay settings) it lives in here +// - If there is an obvious class for the thing relevant to the logic being performed, it goes in there for the sake +// of modularity/separation-of-concerns (e.g. armour cost reductions go in ItemWizardArmour) +// - If the thing has an instance but not a separate class (e.g. most custom potions), it goes in a related class +// where applicable (e.g. a spell class), or if not it goes in here +// - If several things share a significant amount of logic, to avoid duplicate code and potentially improve efficiency +// they should be kept together either in a class relevant to all of them (probably a common superclass) or in here +// - Client-side logic goes in WizardryClientEventHandler or another relevant client-side class @Mod.EventBusSubscriber public final class WizardryEventHandler { - // IDEA: Config option allowing users to specify loot locations - private static final String[] LOOT_INJECTION_LOCATIONS = {"minecraft:chests/simple_dungeon", - "minecraft:chests/abandoned_mineshaft", "minecraft:chests/desert_pyramid", "minecraft:chests/jungle_temple", - "minecraft:chests/stronghold_corridor", "minecraft:chests/stronghold_crossing", - "minecraft:chests/stronghold_library", "minecraft:chests/igloo_chest", "minecraft:chests/woodland_mansion", - "minecraft:chests/end_city_treasure"}; - - @SubscribeEvent - public static void onLootTableLoadEvent(LootTableLoadEvent event){ - if(Wizardry.settings.generateLoot){ - for(String location : LOOT_INJECTION_LOCATIONS){ - if(event.getName().toString().matches(location)){ - event.getTable().addPool(getAdditive(Wizardry.MODID + ":chests/dungeon_additions")); - } - } - } - } - - private static LootPool getAdditive(String entryName){ - return new LootPool(new LootEntry[]{getAdditiveEntry(entryName, 1)}, new LootCondition[0], - new RandomValueRange(1), new RandomValueRange(0, 1), Wizardry.MODID + "_additive_pool"); - } - - private static LootEntryTable getAdditiveEntry(String name, int weight){ - return new LootEntryTable(new ResourceLocation(name), weight, 0, new LootCondition[0], - Wizardry.MODID + "_additive_entry"); - } + private WizardryEventHandler(){} // No instances! @SubscribeEvent public static void onPlayerLoggedInEvent(PlayerLoggedInEvent event){ - // When a player logs in, they are sent the glyph data and the server's settings. + // When a player logs in, they are sent the glyph data, server settings and spell properties. if(event.player instanceof EntityPlayerMP){ SpellGlyphData.get(event.player.world).sync((EntityPlayerMP)event.player); + SpellEmitterData.get(event.player.world).sync((EntityPlayerMP)event.player); Wizardry.settings.sync((EntityPlayerMP)event.player); + syncAdvancements((EntityPlayerMP)event.player, false); + } + Spell.syncProperties(event.player); + } + + @SubscribeEvent(priority = EventPriority.HIGH) + public static void onPlaySoundAtEntityEvent(PlaySoundAtEntityEvent event){ + // Muffle (there's no spell class for it so it's here instead) + if(event.getEntity() instanceof EntityLivingBase + && ((EntityLivingBase)event.getEntity()).isPotionActive(WizardryPotions.muffle)){ + event.setCanceled(true); } } @SubscribeEvent + public static void onAdvancementEvent(AdvancementEvent event){ + // Forge has no hook for revoked advancements :( + // Guess we'll just have to make do + // Also, this seems to get fired on player login, so to prevent the toasts from appearing every login the + // only way I can see to do it is by testing the player has been around long enough. + if(event.getEntityPlayer() instanceof EntityPlayerMP && event.getEntityPlayer().ticksExisted > 0){ + syncAdvancements((EntityPlayerMP)event.getEntityPlayer(), true); + } + } + + private static void syncAdvancements(EntityPlayerMP player, boolean showToasts){ + + Wizardry.logger.info("Synchronising advancements for " + player.getName()); + + ArrayList advancements = new ArrayList<>(); + + for(Advancement advancement : player.getServer().getAdvancementManager().getAdvancements()){ + if(player.getAdvancements().getProgress(advancement).isDone()) advancements.add(advancement.getId()); + } + + WizardryPacketHandler.net.sendTo(new PacketSyncAdvancements.Message(showToasts, advancements.toArray(new ResourceLocation[0])), player); + } + + @SubscribeEvent(priority = EventPriority.HIGH) // Disabling of specific spells comes after arcane jammer but before everything else public static void onSpellCastPreEvent(SpellCastEvent.Pre event){ + + boolean enabled = true; + + switch(event.getSource()){ + case WAND: enabled = event.getSpell().isEnabled(SpellProperties.Context.WANDS); break; + case SCROLL: enabled = event.getSpell().isEnabled(SpellProperties.Context.SCROLL); break; + case COMMAND: enabled = event.getSpell().isEnabled(SpellProperties.Context.COMMANDS); break; + case NPC: enabled = event.getSpell().isEnabled(SpellProperties.Context.NPCS); break; + case DISPENSER: enabled = event.getSpell().isEnabled(SpellProperties.Context.DISPENSERS); break; + case OTHER: enabled = event.getSpell().isEnabled(); break; // Any enabled context will do for this one + } + // If a spell is disabled in the config, it will not work. - if(!event.getSpell().isEnabled()){ - if(!event.getEntityLiving().world.isRemote) event.getEntity().sendMessage( + if(!enabled){ + if(event.getCaster() != null && !event.getCaster().world.isRemote) event.getCaster().sendMessage( new TextComponentTranslation("spell.disabled", event.getSpell().getNameForTranslationFormatted())); event.setCanceled(true); } @@ -123,32 +140,36 @@ public final class WizardryEventHandler { @SubscribeEvent public static void onSpellCastPostEvent(SpellCastEvent.Post event){ - // Spell discovery (only players can discover spells, obviously) - if(event.getEntity() instanceof EntityPlayer){ + if(event.getCaster() instanceof EntityPlayer){ - EntityPlayer player = (EntityPlayer)event.getEntity(); + EntityPlayer player = (EntityPlayer)event.getCaster(); + // Advancement triggers + if(player instanceof EntityPlayerMP){ + WizardryAdvancementTriggers.cast_spell.trigger((EntityPlayerMP)player, event.getSpell(), player.getHeldItem(player.getActiveHand())); + } + + // Spell discovery (only players can discover spells, obviously) WizardData data = WizardData.get(player); if(data != null){ // Data is updated on both sides (This line was added client-side to fix a bug back in 1.1.3, so now // it's in common code, which is nice!) // Short-circuiting AND means that discoverSpell is only called if the event isn't cancelled. - if(!MinecraftForge.EVENT_BUS - .post(new DiscoverSpellEvent(player, event.getSpell(), DiscoverSpellEvent.Source.CASTING)) + if(!MinecraftForge.EVENT_BUS.post(new DiscoverSpellEvent(player, event.getSpell(), DiscoverSpellEvent.Source.CASTING)) && data.discoverSpell(event.getSpell())){ // If the spell wasn't already discovered, other stuff happens: if(event.getSource() == SpellCastEvent.Source.COMMAND){ // If the spell didn't send a packet itself, the extended player needs to be synced so the // spell discovery updates on the client. - if(!event.getSpell().doesSpellRequirePacket()) data.sync(); + if(!event.getSpell().requiresPacket()) data.sync(); - }else if(!event.getEntity().world.isRemote && !player.capabilities.isCreativeMode + }else if(!event.getCaster().world.isRemote && !player.isCreative() && Wizardry.settings.discoveryMode){ // Sound and text only happen server-side, in survival, with discovery mode on, and only when // the spell wasn't cast using commands. - WizardryUtilities.playSoundAtPlayer(player, SoundEvents.ENTITY_PLAYER_LEVELUP, 1.25f, 1); + WizardryUtilities.playSoundAtPlayer(player, WizardrySounds.MISC_DISCOVER_SPELL, 1.25f, 1); player.sendMessage(new TextComponentTranslation("spell.discover", event.getSpell().getNameForTranslationFormatted())); } @@ -157,33 +178,59 @@ public final class WizardryEventHandler { } } + @SubscribeEvent(priority = EventPriority.LOW) + public static void onDiscoverSpellEvent(DiscoverSpellEvent event){ + if(event.getEntityPlayer() instanceof EntityPlayerMP){ + WizardryAdvancementTriggers.discover_spell.trigger((EntityPlayerMP)event.getEntityPlayer(), event.getSpell(), event.getSource()); + } + } + + @SubscribeEvent + public static void onLivingSetAttackTargetEvent(LivingSetAttackTargetEvent event){ + + if(event.getTarget() != null && event.getEntityLiving() instanceof EntityLiving + && event.getTarget().isPotionActive(WizardryPotions.muffle)){ + + Vec3d vec = event.getTarget().getPositionEyes(1).subtract(event.getEntity().getPositionEyes(1)); + // Find the angle between the direction the mob is looking and the direction the player is in + // Angle between a and b = acos((a.b) / (|a|*|b|)) + double angle = Math.acos(vec.dotProduct(event.getEntity().getLookVec()) / vec.length()); + System.out.println(angle); + // If the player is not within the 144-degree arc in front of the mob, it won't detect them + if(angle > 0.4 * Math.PI){ + ((EntityLiving)event.getEntityLiving()).setAttackTarget(null); + } + } + } + /* There is a subtle but important difference between LivingAttackEvent and LivingHurtEvent - LivingAttackEvent * fires immediately when attackEntityFrom is called, whereas LivingHurtEvent only fires if the attack actually * succeeded, i.e. if the entity in question takes damage (though the event is fired before that so you can cancel - * the damage). Things are processed in the following order: * LivingAttackEvent * - Invulnerability - - * Already-dead-ness - Fire resistance - Helmets vs. falling things - Hurt resistant time - Invulnerability (again) - * * LivingHurtEvent * - Armour - Potions - Health is finally changed Of course, there are no guarantees that other + * the damage). Things are processed in the following order: + * + * * LivingAttackEvent * + * - Invulnerability + * - Already-dead-ness + * - Fire resistance + * - Helmets vs. falling things + * - Hurt resistant time + * - Invulnerability (again) + * * LivingHurtEvent * + * - Armour + * - Potions + * * LivingDamageEvent * + * - Health is finally changed + * + * Of course, there are no guarantees that other * mods hooking into these two events will be called before or after yours, but you can have some degree of control * by choosing which event to use. EDIT: Actually, there are. Firstly, you can set a priority in the @SubscribeEvent * annotation which defines how early (higher priority) or late (lower priority) the method is called. Methods with * the same priority are sorted alphabetically by mod id (so it's safe to assume wizardry would be fairly late on!). * I wonder if there are any conventions for what sort of things take what priority...? */ - @SubscribeEvent + @SubscribeEvent(priority = EventPriority.LOW) // Low priority in case the event gets cancelled at default priority public static void onLivingAttackEvent(LivingAttackEvent event){ - // Prevents any damage to allies from magic if friendly fire is disabled - if(!Wizardry.settings.friendlyFire && event.getSource() != null - && event.getSource().getTrueSource() instanceof EntityPlayer && event.getEntity() instanceof EntityPlayer - && event.getSource() instanceof IElementalDamage){ - if(WizardryUtilities.isPlayerAlly((EntityPlayer)event.getSource().getTrueSource(), - (EntityPlayer)event.getEntity())){ - event.setCanceled(true); - // This needs to be here, since if the event is cancelled nothing else needs to happen. - return; - } - } - // Retaliatory effects // These are better off here because the revenge effects are pretty similar, and I'd rather keep the (lengthy) // if statement in one place. @@ -194,38 +241,43 @@ public final class WizardryEventHandler { EntityLivingBase attacker = (EntityLivingBase)event.getSource().getTrueSource(); World world = event.getEntityLiving().world; - // Fireskin - if(event.getEntityLiving().isPotionActive(WizardryPotions.fireskin) - && !MagicDamage.isEntityImmune(DamageType.FIRE, event.getEntityLiving())) - attacker.setFire(5); + if(attacker.getDistance(event.getEntityLiving()) < 10){ - // Ice Shroud - if(event.getEntityLiving().isPotionActive(WizardryPotions.ice_shroud) - && !MagicDamage.isEntityImmune(DamageType.FROST, event.getEntityLiving()) - && !(event.getEntityLiving() instanceof FakePlayer)) - attacker.addPotionEffect(new PotionEffect(WizardryPotions.frost, 100, 0)); + // Fireskin + if(event.getEntityLiving().isPotionActive(WizardryPotions.fireskin) + && !MagicDamage.isEntityImmune(DamageType.FIRE, event.getEntityLiving())) + attacker.setFire(Spells.fire_breath.getProperty(Spell.BURN_DURATION).intValue()); - // Static Aura - if(event.getEntityLiving().isPotionActive(WizardryPotions.static_aura)){ + // Ice Shroud + if(event.getEntityLiving().isPotionActive(WizardryPotions.ice_shroud) + && !MagicDamage.isEntityImmune(DamageType.FROST, event.getEntityLiving()) + && !(attacker instanceof FakePlayer)) // Fake players cause problems + attacker.addPotionEffect(new PotionEffect(WizardryPotions.frost, + Spells.ice_shroud.getProperty(Spell.EFFECT_DURATION).intValue(), + Spells.ice_shroud.getProperty(Spell.EFFECT_STRENGTH).intValue())); - if(world.isRemote){ - - ParticleBuilder.create(Type.LIGHTNING).entity(event.getEntity()).pos(0, event.getEntity().height/2, 0) - .target(attacker).spawn(world); - - ParticleBuilder.spawnShockParticles(world, attacker.posX, - attacker.getEntityBoundingBox().minY + attacker.height, attacker.posZ); + // Static Aura + if(event.getEntityLiving().isPotionActive(WizardryPotions.static_aura)){ + + if(world.isRemote){ + + ParticleBuilder.create(Type.LIGHTNING).entity(event.getEntity()).pos(0, event.getEntity().height / 2, 0) + .target(attacker).spawn(world); + + ParticleBuilder.spawnShockParticles(world, attacker.posX, + attacker.getEntityBoundingBox().minY + attacker.height / 2, attacker.posZ); + } + + DamageSafetyChecker.attackEntitySafely(attacker, MagicDamage.causeDirectMagicDamage(event.getEntityLiving(), + DamageType.SHOCK, true), Spells.static_aura.getProperty(Spell.DAMAGE).floatValue(), event.getSource().getDamageType()); + attacker.playSound(WizardrySounds.SPELL_STATIC_AURA_RETALIATE, 1.0F, world.rand.nextFloat() * 0.4F + 1.5F); } - - DamageSafetyChecker.attackEntitySafely(attacker, MagicDamage.causeDirectMagicDamage(event.getEntityLiving(), - DamageType.SHOCK, true), 4.0f, event.getSource().getDamageType()); - attacker.playSound(WizardrySounds.SPELL_STATIC_AURA_RETALIATE, 1.0F, world.rand.nextFloat() * 0.4F + 1.5F); } } } - @SubscribeEvent + @SubscribeEvent(priority = EventPriority.LOW) // Again, we don't want these effects if the event is cancelled public static void onLivingHurtEvent(LivingHurtEvent event){ // Flaming and freezing swords @@ -234,7 +286,7 @@ public final class WizardryEventHandler { EntityLivingBase attacker = (EntityLivingBase)event.getSource().getTrueSource(); // Players can only ever attack with their main hand, so this is the right method to use here. - if(!attacker.getHeldItemMainhand().isEmpty() && attacker.getHeldItemMainhand().getItem() instanceof ItemSword){ + if(!attacker.getHeldItemMainhand().isEmpty() && ImbueWeapon.isSword(attacker.getHeldItemMainhand().getItem())){ int level = EnchantmentHelper.getEnchantmentLevel(WizardryEnchantments.flaming_weapon, attacker.getHeldItemMainhand()); @@ -275,30 +327,13 @@ public final class WizardryEventHandler { @SubscribeEvent public static void onLivingUpdateEvent(LivingUpdateEvent event){ - if(event.getEntityLiving() instanceof EntityPlayer){ - - EntityPlayer player = (EntityPlayer)event.getEntityLiving(); - - if(player.world.isRemote) hackilyFixContinuousSpellCasting(player); - - // Mana flask crafting - if(player.openContainer instanceof ContainerWorkbench){ - - IInventory craftMatrix = ((ContainerWorkbench)player.openContainer).craftMatrix; - ItemStack output = ((ContainerWorkbench)player.openContainer).craftResult.getStackInSlot(0); - processManaFlaskCrafting(craftMatrix, output); - - }else if(player.openContainer instanceof ContainerPlayer){ - - IInventory craftMatrix = ((ContainerPlayer)player.openContainer).craftMatrix; - ItemStack output = ((ContainerPlayer)player.openContainer).craftResult.getStackInSlot(0); - // Unfortunately I have no choice but to call this method every tick when the player isn't using another - // inventory, since the only thing tracking whether the player is looking at their inventory is the GUI - // itself, which is client-side only. - processManaFlaskCrafting(craftMatrix, output); - } - - } + // Experimental animation feature +// if(event.getEntityLiving().isHandActive() && event.getEntityLiving().getActiveItemStack().getItemUseAction() == WizardryUtilities.POINT){ +// event.getEntityLiving().isSwingInProgress = true; +// event.getEntityLiving().swingProgress = 1f; +// event.getEntityLiving().prevSwingProgress = 1; +// event.getEntityLiving().swingingHand = event.getEntityLiving().getActiveHand(); +// } if(event.getEntityLiving().world.isRemote){ @@ -309,13 +344,14 @@ public final class WizardryEventHandler { Spell spell = ((ISpellCaster)event.getEntity()).getContinuousSpell(); SpellModifiers modifiers = ((ISpellCaster)event.getEntity()).getModifiers(); - if(spell != null && spell != Spells.none){ + if(spell != null && spell != Spells.none){ // IntelliJ is wrong, do NOT remove the null check! - if(!MinecraftForge.EVENT_BUS.post(new SpellCastEvent.Tick(event.getEntityLiving(), spell, modifiers, - SpellCastEvent.Source.NPC, 0))){ + if(!MinecraftForge.EVENT_BUS.post(new SpellCastEvent.Tick(SpellCastEvent.Source.NPC, spell, event.getEntityLiving(), + modifiers, 0))){ spell.cast(event.getEntity().world, (EntityLiving)event.getEntity(), EnumHand.MAIN_HAND, 0, // TODO: This implementation of modifiers relies on them being accessible client-side. + // Right now that doesn't matter because NPCs don't use modifiers, but they might in future ((EntityLiving)event.getEntity()).getAttackTarget(), modifiers); } } @@ -323,7 +359,7 @@ public final class WizardryEventHandler { } } - @SubscribeEvent + @SubscribeEvent(priority = EventPriority.LOWEST) // No siphoning if the event is cancelled, that could be exploited... public static void onLivingDeathEvent(LivingDeathEvent event){ if(event.getSource().getTrueSource() instanceof EntityPlayer){ @@ -332,108 +368,83 @@ public final class WizardryEventHandler { for(ItemStack stack : WizardryUtilities.getPrioritisedHotbarAndOffhand(player)){ - if(stack.getItem() instanceof ItemWand && stack.isItemDamaged() + if(stack.getItem() instanceof IManaStoringItem && !((IManaStoringItem)stack.getItem()).isManaFull(stack) && WandHelper.getUpgradeLevel(stack, WizardryItems.siphon_upgrade) > 0){ - int damage = stack.getItemDamage() - - Constants.SIPHON_MANA_PER_LEVEL + + int mana = Constants.SIPHON_MANA_PER_LEVEL * WandHelper.getUpgradeLevel(stack, WizardryItems.siphon_upgrade) - - player.world.rand.nextInt(Constants.SIPHON_MANA_PER_LEVEL); - if(damage < 0) damage = 0; - stack.setItemDamage(damage); - break; + + player.world.rand.nextInt(Constants.SIPHON_MANA_PER_LEVEL); + + if(ItemArtefact.isArtefactActive(player, WizardryItems.ring_siphoning)) mana *= 1.3f; + + ((IManaStoringItem)stack.getItem()).rechargeMana(stack, mana); + + break; // Only recharge one item per kill + } + } + } + } + + // These two are lifted from EntityLivingBase#travel + private static final double LIVING_ENTITY_GRAVITY = 0.08; + private static final double LIVING_ENTITY_DRAG = 0.98; + + private static final double LIVING_ENTITY_TERMINAL_VELOCITY = 3.92; // From Minecraft Wiki! + + private static final double LOG_LIVING_ENTITY_DRAG = Math.log(LIVING_ENTITY_DRAG); + private static final double FALL_TICKS_ERROR_CORRECTION = 0.500841776608447; + + @SubscribeEvent // Priority doesn't matter here, we're only setting event fields so if it's cancelled it won't matter + public static void onLivingFallEvent(LivingFallEvent event){ + // Why is fall damage based on distance fallen? Why? Who on earth came up with that? It makes no sense whatsoever! + if(Wizardry.settings.replaceVanillaFallDamage && !Loader.isModLoaded("speedbasedfalldamage")){ + // We want to keep the fall damage EXACTLY THE SAME for free, uninterrupted falls, but fix the weirdness + // caused when something else changes the entity's velocity + // All living entities have a gravity of 0.08b/t^2 + // Therefore it would be simple to say v^2 = u^2 + 2gs gives the equivalent fall distance as motionY^2 / 0.16 + // However, Minecraft also has a drag of 0.02 * the velocity, so we actually expect a slightly different value + // Much maths later... + + double v = event.getEntity().motionY; + // Players are weird, their velocity somehow resets on the server just before this event fires so + // instead we're storing the y velocity from the previous tick in WizardData and retrieving it here + // Of course, if another mod screws things up and sets a player's velocity client-side only then this won't + // work ...but it's better than having clients calculate their own fall damage + if(event.getEntity() instanceof EntityPlayer){ + WizardData data = WizardData.get((EntityPlayer)event.getEntity()); + if(data != null){ + v = data.prevMotionY; } } - if(event.getEntityLiving() == player && event.getSource() instanceof IElementalDamage){ - WizardryAdvancementTriggers.self_destruct.triggerFor(player); - } - } - } + // At terminal velocity, there's no way of finding fall distance from velocity, and the entity is probably dead anyway! + if(v > -3.9){ - @SubscribeEvent - public static void onLivingDropsEvent(LivingDropsEvent event){ - // TODO: Really, this should be in a loot table (mob_additions), however I can't seem to find a way of - // automatically adding it to all subclasses of IMob. - // Evil wizards drop spell books themselves - if(event.getEntityLiving() instanceof IMob && !(event.getEntityLiving() instanceof EntityEvilWizard) - // TODO: Backport when you backport the new summoned creature system. - && !(event.getEntityLiving() instanceof ISummonedCreature) - && event.getSource().getTrueSource() instanceof EntityPlayer && Wizardry.settings.spellBookDropChance > 0){ + // Just to make the code more readable, java will replace them all with numbers anyway + double g = LIVING_ENTITY_GRAVITY; + double f = LIVING_ENTITY_DRAG; + double lnf = LOG_LIVING_ENTITY_DRAG; + double tv = LIVING_ENTITY_TERMINAL_VELOCITY; - // This does exactly what the entity drop method does, but with a different random number so that the - // spell book doesn't always drop with other rare drops. - int rareDropNumber = event.getEntity().world.rand.nextInt(200) - event.getLootingLevel(); - if(rareDropNumber < Wizardry.settings.spellBookDropChance){ - // Drops a spell book - int id = WizardryUtilities.getStandardWeightedRandomSpellId(event.getEntity().world.rand); + // Work backwards from y velocity to get fall time + // logs are probably slow but it's not like this gets calculated every tick, and we only need one log + double t = Math.log(((-v - tv) * lnf) / g) / lnf; // Log the number over log the base - event.getDrops() - .add(new EntityItem(event.getEntityLiving().world, event.getEntityLiving().posX, - event.getEntityLiving().posY, event.getEntityLiving().posZ, - new ItemStack(WizardryItems.spell_book, 1, id))); - } - } - } + // Because time is in discrete ticks, the above equation for t results in a constant error of + // +0.500841776608447, so I guess we can just subtract it... if it works it works I guess! + t -= FALL_TICKS_ERROR_CORRECTION; // Don't cast to int or perform any rounding - // Private helper methods - // ================================================================================================================ + // Now work forwards from t to find the effective fall distance, i.e. the distance the entity would + // have to freefall to reach the same velocity + // Don't ask me where the 196 is from, again, it just works! + double y = (g * Math.pow(f, t)) / (lnf*lnf) + tv * (t) - 196; - /** - * Detects inconsistencies between player.getActiveItemStack and the actual itemstack and forces them to be equal. - * Fixes issue #25. - * - * @param player - */ - private static void hackilyFixContinuousSpellCasting(EntityPlayer player){ - if(player.isHandActive() && player.getHeldItem(player.getActiveHand()).getItem() instanceof ItemWand - && WandHelper.getCurrentSpell(player.getHeldItem(player.getActiveHand())).isContinuous){ - if(player.getActiveItemStack() != player.getHeldItem(player.getActiveHand())){ - player.setHeldItem(player.getActiveHand(), player.getActiveItemStack()); - } - } - } + // DEBUG +// if(event.getEntity() instanceof EntityPlayer){ +// Wizardry.logger.info("Replaced fall distance {} with effective distance {} based on entity velocity", event.getDistance(), y); +// } - private static void processManaFlaskCrafting(IInventory craftMatrix, ItemStack output){ - - // Charges wand using mana flask. It is here rather than in the crafting handler so the result displays - // the proper damage before it is actually crafted. - - boolean flag = false; - ItemStack wand = ItemStack.EMPTY; - ItemStack armour = ItemStack.EMPTY; - - for(int i = 0; i < craftMatrix.getSizeInventory(); i++){ - - ItemStack itemstack = craftMatrix.getStackInSlot(i); - - if(itemstack.getItem() == WizardryItems.mana_flask){ - flag = true; - } - - if(itemstack.getItem() instanceof ItemWand){ - wand = itemstack; - } - - if(itemstack.getItem() instanceof ItemWizardArmour){ - armour = itemstack; - } - } - - if(output.getItem() instanceof ItemWand && flag && !wand.isEmpty()){ - output.setTagCompound((wand.getTagCompound())); - if(wand.getItemDamage() - Constants.MANA_PER_FLASK < 0){ - output.setItemDamage(0); - }else{ - output.setItemDamage(wand.getItemDamage() - Constants.MANA_PER_FLASK); - } - } - - if(output.getItem() instanceof ItemWizardArmour && flag && !armour.isEmpty()){ - output.setTagCompound((armour.getTagCompound())); - if(armour.getItemDamage() - Constants.MANA_PER_FLASK < 0){ - output.setItemDamage(0); - }else{ - output.setItemDamage(wand.getItemDamage() - Constants.MANA_PER_FLASK); + event.setDistance((float)y); } } } diff --git a/src/main/java/electroblob/wizardry/WizardryGuiFactory.java b/src/main/java/electroblob/wizardry/WizardryGuiFactory.java index 169c473e..a6ef1190 100644 --- a/src/main/java/electroblob/wizardry/WizardryGuiFactory.java +++ b/src/main/java/electroblob/wizardry/WizardryGuiFactory.java @@ -1,12 +1,12 @@ package electroblob.wizardry; -import java.util.Set; - -import electroblob.wizardry.client.gui.GuiConfigWizardry; +import electroblob.wizardry.client.gui.config.GuiConfigWizardry; import net.minecraft.client.Minecraft; import net.minecraft.client.gui.GuiScreen; import net.minecraftforge.fml.client.IModGuiFactory; +import java.util.Set; + public class WizardryGuiFactory implements IModGuiFactory { @Override diff --git a/src/main/java/electroblob/wizardry/WizardryGuiHandler.java b/src/main/java/electroblob/wizardry/WizardryGuiHandler.java index 5bd9364c..140ed107 100644 --- a/src/main/java/electroblob/wizardry/WizardryGuiHandler.java +++ b/src/main/java/electroblob/wizardry/WizardryGuiHandler.java @@ -1,6 +1,5 @@ package electroblob.wizardry; -import electroblob.wizardry.client.gui.handbook.GuiWizardHandbook; import electroblob.wizardry.item.ItemSpellBook; import electroblob.wizardry.item.ItemWizardHandbook; import electroblob.wizardry.spell.Spell; @@ -46,12 +45,12 @@ public class WizardryGuiHandler implements IGuiHandler { } }else if(id == WIZARD_HANDBOOK && (player.getHeldItemMainhand().getItem() instanceof ItemWizardHandbook || player.getHeldItemOffhand().getItem() instanceof ItemWizardHandbook)){ - return new GuiWizardHandbook(); + return new electroblob.wizardry.client.gui.handbook.GuiWizardHandbook(); }else if(id == SPELL_BOOK){ if(player.getHeldItemMainhand().getItem() instanceof ItemSpellBook){ - return new electroblob.wizardry.client.gui.GuiSpellBook(Spell.get(player.getHeldItemMainhand().getItemDamage())); + return new electroblob.wizardry.client.gui.GuiSpellBook(Spell.byMetadata(player.getHeldItemMainhand().getItemDamage())); }else if(player.getHeldItemOffhand().getItem() instanceof ItemSpellBook){ - return new electroblob.wizardry.client.gui.GuiSpellBook(Spell.get(player.getHeldItemOffhand().getItemDamage())); + return new electroblob.wizardry.client.gui.GuiSpellBook(Spell.byMetadata(player.getHeldItemOffhand().getItemDamage())); } }else if(id == PORTABLE_CRAFTING){ return new electroblob.wizardry.client.gui.GuiPortableCrafting(player.inventory, world, new BlockPos(x, y, z)); diff --git a/src/main/java/electroblob/wizardry/WizardryWorldGenerator.java b/src/main/java/electroblob/wizardry/WizardryWorldGenerator.java deleted file mode 100644 index 4283a41e..00000000 --- a/src/main/java/electroblob/wizardry/WizardryWorldGenerator.java +++ /dev/null @@ -1,949 +0,0 @@ -package electroblob.wizardry; - -import java.util.HashSet; -import java.util.Random; -import java.util.Set; - -import org.apache.commons.lang3.ArrayUtils; - -import electroblob.wizardry.entity.living.EntityEvilWizard; -import electroblob.wizardry.entity.living.EntityWizard; -import electroblob.wizardry.registry.WizardryBlocks; -import electroblob.wizardry.util.WizardryUtilities; -import net.minecraft.block.BlockChest; -import net.minecraft.block.BlockColored; -import net.minecraft.block.BlockLeaves; -import net.minecraft.block.BlockLiquid; -import net.minecraft.block.BlockPlanks; -import net.minecraft.block.BlockSlab; -import net.minecraft.block.BlockSlab.EnumBlockHalf; -import net.minecraft.block.BlockTorch; -import net.minecraft.block.state.IBlockState; -import net.minecraft.init.Biomes; -import net.minecraft.init.Blocks; -import net.minecraft.inventory.IInventory; -import net.minecraft.item.EnumDyeColor; -import net.minecraft.item.ItemDoor; -import net.minecraft.util.EnumFacing; -import net.minecraft.util.ResourceLocation; -import net.minecraft.util.math.BlockPos; -import net.minecraft.world.World; -import net.minecraft.world.WorldServer; -import net.minecraft.world.biome.Biome; -import net.minecraft.world.chunk.IChunkProvider; -import net.minecraft.world.gen.IChunkGenerator; -import net.minecraft.world.gen.feature.WorldGenMinable; -import net.minecraft.world.storage.loot.LootContext; -import net.minecraft.world.storage.loot.LootTable; -import net.minecraftforge.common.BiomeDictionary; -import net.minecraftforge.common.IPlantable; -import net.minecraftforge.fml.common.IWorldGenerator; - -public class WizardryWorldGenerator implements IWorldGenerator { - - /** The string identifier for wizard tower chests, used in ChestGenHooks. */ - public static final String WIZARD_TOWER = Wizardry.MODID + "wizardTower"; - - @Override - public void generate(Random random, int chunkX, int chunkZ, World world, IChunkGenerator chunkGenerator, - IChunkProvider chunkProvider){ - - for(int id : Wizardry.settings.oreDimensions){ - if(id == world.provider.getDimension()) this.addOreSpawn(WizardryBlocks.crystal_ore.getDefaultState(), - world, random, chunkX * 16, chunkZ * 16, 16, 16, 5, 7, 5, 30); - } - - for(int id : Wizardry.settings.flowerDimensions){ - if(id == world.provider.getDimension()) this.generatePlant(WizardryBlocks.crystal_flower.getDefaultState(), - world, random, chunkX * 16, chunkZ * 16, 2, 20); - } - - if(world.getWorldInfo().isMapFeaturesEnabled()){ - for(int id : Wizardry.settings.towerDimensions){ - if(id == world.provider.getDimension()) - this.generateWizardTower(world, random, chunkX * 16, chunkZ * 16); - } - } - } - - /** - * Adds an Ore Spawn to Minecraft. Simply register all Ores to spawn with this method in your Generation method in - * your IWorldGeneration extending Class - * - * @param The Block to spawn - * @param The World to spawn in - * @param A Random object for retrieving random positions within the world to spawn the Block - * @param An int for passing the X-Coordinate for the Generation method - * @param An int for passing the Z-Coordinate for the Generation method - * @param An int for setting the maximum X-Coordinate values for spawning on the X-Axis on a Per-Chunk basis - * @param An int for setting the maximum Z-Coordinate values for spawning on the Z-Axis on a Per-Chunk basis - * @param An int for setting the maximum size of a vein - * @param An int for the Number of chances available for the Block to spawn per-chunk - * @param An int for the minimum Y-Coordinate height at which this block may spawn - * @param An int for the maximum Y-Coordinate height at which this block may spawn - **/ - public void addOreSpawn(IBlockState state, World world, Random random, int blockXPos, int blockZPos, int maxX, - int maxZ, int maxVeinSize, int chancesToSpawn, int minY, int maxY){ - // int maxPossY = minY + (maxY - 1); - assert maxY > minY : "The maximum Y must be greater than the Minimum Y"; - assert maxX > 0 && maxX <= 16 : "addOreSpawn: The Maximum X must be greater than 0 and less than 16"; - assert minY > 0 : "addOreSpawn: The Minimum Y must be greater than 0"; - assert maxY < 256 && maxY > 0 : "addOreSpawn: The Maximum Y must be less than 256 but greater than 0"; - assert maxZ > 0 && maxZ <= 16 : "addOreSpawn: The Maximum Z must be greater than 0 and less than 16"; - - int diffBtwnMinMaxY = maxY - minY; - for(int x = 0; x < chancesToSpawn; x++){ - int posX = blockXPos + random.nextInt(maxX); - int posY = minY + random.nextInt(diffBtwnMinMaxY); - int posZ = blockZPos + random.nextInt(maxZ); - (new WorldGenMinable(state, maxVeinSize)).generate(world, random, new BlockPos(posX, posY, posZ)); - } - } - - /** - * Generates the specified plant randomly throughout the world. - * - * @param block The plant block - * @param world The world - * @param random A random instance - * @param x The x coord of the first block in the chunk - * @param z The y coord of the first block in the chunk - * @param chancesToSpawn Number of chances to spawn a flower patch - * @param groupSize The number of times to try generating a flower per flower patch spawn - */ - public void generatePlant(IBlockState state, World world, Random random, int x, int z, int chancesToSpawn, - int groupSize){ - - for(int i = 0; i < chancesToSpawn; i++){ - int randPosX = x + random.nextInt(16); - int randPosY = random.nextInt(256); - int randPosZ = z + random.nextInt(16); - for(int l = 0; l < groupSize; ++l){ - int i1 = randPosX + random.nextInt(8) - random.nextInt(8); - int j1 = randPosY + random.nextInt(4) - random.nextInt(4); - int k1 = randPosZ + random.nextInt(8) - random.nextInt(8); - - BlockPos pos = new BlockPos(i1, j1, k1); - - if(world.isBlockLoaded(pos) && world.isAirBlock(pos) && (!world.provider.isNether() || j1 < 127) - && state.getBlock().canPlaceBlockOnSide(world, pos, EnumFacing.UP)){ - - world.setBlockState(pos, state, 2); - } - } - } - } - - /** - * Generates wizard towers randomly throughout the world. - */ - public void generateWizardTower(World world, Random random, int chunkX, int chunkZ){ - - // Allows the config file to set the rarity value to 0 to disable tower generation completely. - if(Wizardry.settings.towerRarity == 0) return; - - // Compensates for the lack of space in forests. Math.max is required since treeless biomes have treesPerChunk = - // -999 - // double treeFactor = 70 - Math.max((double)world.getBiomeGenForCoords(chunkX, - // chunkZ).theBiomeDecorator.treesPerChunk, 0) * 1.5d; - - // Multiplied by 70 to (roughly) retain the old rarity scale - if(random.nextInt((int)(Wizardry.settings.towerRarity * 70)) == 0){ - - BlockPos origin = new BlockPos(chunkX + random.nextInt(16), 0, chunkZ + random.nextInt(16)); - - // Despite what its name suggests, this method does not return the position of a liquid. It is in fact - // exactly what is needed here since it is used for placing villages and stuff, and doesn't include leaves - // or other foliage. - origin = origin.up(world.getTopSolidOrLiquidBlock(origin).getY() - 1); - - int[][][] towerBlueprint = towerBlueprintSmall; - - switch(random.nextInt(4)){ - case 0: - towerBlueprint = towerBlueprintSmall; - break; - case 1: - towerBlueprint = towerBlueprintMedium; - break; - case 2: - towerBlueprint = towerBlueprintTall; - break; - case 3: - towerBlueprint = towerBlueprintDouble; - break; - } - - // 0 = West, 1 = North, 2 = East, 3 = South (The way you would face when walking out of the door) - EnumFacing orientation = EnumFacing.byHorizontalIndex(random.nextInt(4)); - boolean flip = random.nextBoolean(); - - if(checkSpaceForTower(world, origin, towerBlueprint, orientation, flip)){ - - // == Setup == - - boolean evilWizard = random.nextInt(5) == 0; - - IBlockState wallMaterial = Blocks.COBBLESTONE.getDefaultState(); - BlockPlanks.EnumType woodType = BlockPlanks.EnumType.OAK; - - Biome biome = world.getBiome(origin); - - // The order of these is somewhat important in that biomes can be many types, so the last of these - // checks - // that is true gets priority. Generally speaking, the later the check, the more specific it is. - if(BiomeDictionary.hasType(biome, BiomeDictionary.Type.DENSE)) - wallMaterial = Blocks.MOSSY_COBBLESTONE.getDefaultState(); - if(BiomeDictionary.hasType(biome, BiomeDictionary.Type.SWAMP)) - wallMaterial = Blocks.MOSSY_COBBLESTONE.getDefaultState(); - if(BiomeDictionary.hasType(biome, BiomeDictionary.Type.SANDY)) - wallMaterial = Blocks.SANDSTONE.getDefaultState(); - if(BiomeDictionary.hasType(biome, BiomeDictionary.Type.NETHER)) - wallMaterial = Blocks.NETHER_BRICK.getDefaultState(); - if(BiomeDictionary.hasType(biome, BiomeDictionary.Type.MOUNTAIN)) - wallMaterial = Blocks.STONEBRICK.getDefaultState(); - if(BiomeDictionary.hasType(biome, BiomeDictionary.Type.MESA)) - wallMaterial = Blocks.HARDENED_CLAY.getDefaultState(); - - // Unfortunately, I can't check all the wood types with the biome dictionary - if(BiomeDictionary.hasType(biome, BiomeDictionary.Type.CONIFEROUS)) - woodType = BlockPlanks.EnumType.SPRUCE; - if(biome == Biomes.BIRCH_FOREST || biome == Biomes.BIRCH_FOREST_HILLS) - woodType = BlockPlanks.EnumType.BIRCH; - if(BiomeDictionary.hasType(biome, BiomeDictionary.Type.JUNGLE)) woodType = BlockPlanks.EnumType.JUNGLE; - if(BiomeDictionary.hasType(biome, BiomeDictionary.Type.SAVANNA)) woodType = BlockPlanks.EnumType.ACACIA; - // Not technically a tree type, but I think it fits quite well anyway - if(BiomeDictionary.hasType(biome, BiomeDictionary.Type.SPOOKY)) - woodType = BlockPlanks.EnumType.DARK_OAK; - - IBlockState[] blockStateList = new IBlockState[]{null, Blocks.AIR.getDefaultState(), - Blocks.PLANKS.getDefaultState().withProperty(BlockPlanks.VARIANT, woodType), - Blocks.BOOKSHELF.getDefaultState(), - Blocks.STAINED_HARDENED_CLAY.getDefaultState().withProperty(BlockColored.COLOR, - EnumDyeColor.values()[random.nextInt(EnumDyeColor.values().length)]), - Blocks.WOODEN_SLAB.getDefaultState().withProperty(BlockSlab.HALF, EnumBlockHalf.BOTTOM), - Blocks.WOODEN_SLAB.getDefaultState().withProperty(BlockSlab.HALF, EnumBlockHalf.TOP), - wallMaterial, Blocks.GLASS_PANE.getDefaultState(), Blocks.OAK_DOOR.getDefaultState(), - WizardryBlocks.arcane_workbench.getDefaultState(), Blocks.TORCH.getDefaultState(), - evilWizard ? Blocks.CHEST.getDefaultState() : Blocks.BOOKSHELF.getDefaultState()}; - - Set blocksPlaced = new HashSet(); - - // == Foundations == - - // Fills in foundations. This is done first so the door always has something to be placed on. - boolean flag = true; - - // BlockPos is immutable, so I'm not sure if simply saying pos1 = pos will be sufficient. - BlockPos layerCentre = new BlockPos(origin); - - // Stop when the bottom of the world is reached - while(flag && layerCentre.getY() > 0){ - - flag = false; - - for(BlockPos offset : foundationLayer){ - if(!world.isBlockNormalCube(layerCentre.add(offset), false)){ - world.setBlockState(layerCentre.add(offset), wallMaterial); - blocksPlaced.add(layerCentre.add(offset)); - // Keeps going as long as something was filled in. - flag = true; - } - } - - layerCentre = layerCentre.down(); - } - - // == Main Structure == - - // It is assumed that the width of the blueprint is the same all the way up, and that the layers are - // square. - int width = towerBlueprint[0].length - 1; - - // x, y and z are the position the block is being put in. - // x1, y and z1 are the position in the blueprint which determines which block is being placed. - - int x1 = 0, z1 = 0; - - for(int y = 0; y < towerBlueprint.length; y++){ - for(int z = 0; z < towerBlueprint[y].length; z++){ - for(int x = 0; x < towerBlueprint[y][z].length; x++){ - - BlockPos pos = origin.add(x - width / 2, y, z - width / 2); - - switch(orientation){ - case WEST: - x1 = flip ? width - x : x; - z1 = z; - break; - case NORTH: - x1 = z; - z1 = flip ? x : width - x; - break; - case EAST: - x1 = flip ? x : width - x; - z1 = width - z; - break; - case SOUTH: - x1 = width - z; - z1 = flip ? width - x : x; - break; - default: - break; - } - - if(blockStateList[towerBlueprint[y][z1][x1]] != null - && blockStateList[towerBlueprint[y][z1][x1]].getBlock() != Blocks.TORCH - && blockStateList[towerBlueprint[y][z1][x1]].getBlock() != Blocks.CHEST){ - - if(blockStateList[towerBlueprint[y][z1][x1]].getBlock() == Blocks.OAK_DOOR){ - // Rotates the door depending on whether flip is true. - ItemDoor.placeDoor( - world, pos, flip - ? EnumFacing.byHorizontalIndex(3 - orientation.getHorizontalIndex()) - .getOpposite() - : orientation.rotateYCCW(), - Blocks.OAK_DOOR, false); - }else{ - world.setBlockState(pos, blockStateList[towerBlueprint[y][z1][x1]], 2); - } - - blocksPlaced.add(pos); - - } - } - } - } - - // == Extras == - - // Torches are done afterwards so they don't fall off - // Chests are also done afterwards, because for some reason the chest decides which way round to face - // itself, after it has been placed, based on the surrounding blocks... but if it was placed during - // the rest of the tower generation, some of those blocks wouldn't exist, hence it must be done here. - for(int y = 0; y < towerBlueprint.length; y++){ - for(int z = 0; z < towerBlueprint[y].length; z++){ - for(int x = 0; x < towerBlueprint[y][z].length; x++){ - - BlockPos pos = origin.add(x - width / 2, y, z - width / 2); - - switch(orientation){ - case WEST: - x1 = flip ? width - x : x; - z1 = z; - break; - case NORTH: - x1 = z; - z1 = flip ? x : width - x; - break; - case EAST: - x1 = flip ? x : width - x; - z1 = width - z; - break; - case SOUTH: - x1 = width - z; - z1 = flip ? width - x : x; - break; - default: - break; - } - - if(blockStateList[towerBlueprint[y][z1][x1]] != null){ - - if(blockStateList[towerBlueprint[y][z1][x1]].getBlock() == Blocks.TORCH){ - if(placeTorch(world, pos, true)){ - blocksPlaced.add(pos); - }else{ - Wizardry.logger.info("Attempted to generate a torch at " + pos + " in " + world - + ", but failed!"); - } - } - - // World should always be a WorldServer, but it's worth checking anyway. - if(blockStateList[towerBlueprint[y][z1][x1]].getBlock() == Blocks.CHEST - && world instanceof WorldServer){ - if(placeChest(world, pos)){ - blocksPlaced.add(pos); - LootTable table = world.getLootTableManager().getLootTableFromLocation( - new ResourceLocation(Wizardry.MODID, "chests/wizard_tower")); - IInventory inventory = (IInventory)world.getTileEntity(pos); - LootContext context = new LootContext.Builder((WorldServer)world).build(); - table.fillInventory(inventory, random, context); - }else{ - Wizardry.logger.info("Attempted to generate a chest at " + pos + " in " + world - + ", but failed!"); - } - } - } - } - } - } - - if(evilWizard){ - - EntityEvilWizard wizard = new EntityEvilWizard(world); - wizard.hasTower = true; - wizard.setLocationAndAngles(origin.getX() + 1.5, origin.getY() + towerBlueprint.length - 9.5, - origin.getZ() + 1.5, 0, 0); - wizard.onInitialSpawn(world.getDifficultyForLocation(origin), null); - - world.spawnEntity(wizard); - - }else{ - - EntityWizard wizard = new EntityWizard(world); - wizard.setLocationAndAngles(origin.getX() + 1.5, origin.getY() + towerBlueprint.length - 9.5, - origin.getZ() + 1.5, 0, 0); - wizard.onInitialSpawn(world.getDifficultyForLocation(origin), null); - wizard.setTowerBlocks(blocksPlaced); - - world.spawnEntity(wizard); - } - } - } - } - - /** - * Places a torch at the given position in the given world and automatically assigns an appropriate state. Order of - * priority is U-S-W-N-E, or S-W-N-E-U if wallPriority is true. - * - * @param world The world to place the torch in. - * @param pos The position to place the torch at. - * @param wallPriority True to prioritise wall torches, false to prioritise floor torches. - * @return True if the torch was placed, false if it is not possible. - */ - private static boolean placeTorch(World world, BlockPos pos, boolean wallPriority){ - - for(EnumFacing facing : ArrayUtils.add(EnumFacing.HORIZONTALS, wallPriority ? 4 : 0, EnumFacing.UP)){ - if(world.isSideSolid(pos.offset(facing.getOpposite()), facing)){ - world.setBlockState(pos, Blocks.TORCH.getDefaultState().withProperty(BlockTorch.FACING, facing)); - return true; - } - } - - return false; - } - - /** - * Places a chest at the given position in the given world and automatically assigns an appropriate state. Order of - * priority is S-W-N-E. - * - * @param world The world to chest the torch in. - * @param pos The position to chest the torch at. - * @return True if the chest was placed, false if it is not possible. - */ - private static boolean placeChest(World world, BlockPos pos){ - - for(EnumFacing facing : EnumFacing.HORIZONTALS){ - if(world.isAirBlock(pos.offset(facing))){ - world.setBlockState(pos, Blocks.CHEST.getDefaultState().withProperty(BlockChest.FACING, facing)); - return true; - } - } - - return false; - } - - /** - * Checks whether a tower generated at the given coordinates will intersect any solid or liquid blocks. Only tests - * for liquids (not solid blocks) for the first four layers to account for the floor and for sloping terrain. - * - * @return True if none of the blocks which the tower would replace are solid or liquid. Dirt, stone etc., water and - * lava count, as do logs, but leaves and plants don't. - */ - private static boolean checkSpaceForTower(World world, BlockPos pos, int[][][] towerBlueprint, - EnumFacing orientation, boolean flip){ - - // x, y and z are the position the block is being put in. - // x1, y and z1 are the position in the blueprint which determines which block is being placed. - - int x1 = 0, z1 = 0; - - // It is assumed that the width of the blueprint is the same all the way up, and that the layers are square. - int width = towerBlueprint[0].length - 1; - - for(int y = 0; y < towerBlueprint.length; y++){ - for(int z = 0; z < towerBlueprint[y].length; z++){ - for(int x = 0; x < towerBlueprint[y][z].length; x++){ - - BlockPos pos1 = pos.add(x - width / 2, y, z - width / 2); - - switch(orientation){ - case WEST: - x1 = flip ? width - x : x; - z1 = z; - break; - case NORTH: - x1 = z; - z1 = flip ? x : width - x; - break; - case EAST: - x1 = flip ? x : width - x; - z1 = width - z; - break; - case SOUTH: - x1 = width - z; - z1 = flip ? width - x : x; - break; - default: - break; - } - - if(towerBlueprint[y][z1][x1] != 0 && !WizardryUtilities.canBlockBeReplacedB(world, pos1) - // TODO: Is this a better replacement for the subsequent two lines? - // && !world.getBlockState(pos1).getBlock().isFoliage(world, pos1) - && !(world.getBlockState(pos1).getBlock() instanceof IPlantable) - && !(world.getBlockState(pos1).getBlock() instanceof BlockLeaves) - && (y > 3 || world.getBlockState(pos1).getBlock() instanceof BlockLiquid)){ - return false; - } - } - } - } - - return true; - } - - /** Array of relative positions of each block in a layer of foundations. */ - private static final BlockPos[] foundationLayer = new BlockPos[]{new BlockPos(-2, 0, -1), new BlockPos(-2, 0, 0), - new BlockPos(-2, 0, 1), new BlockPos(2, 0, -1), new BlockPos(2, 0, 0), new BlockPos(2, 0, 1), - new BlockPos(-1, 0, -2), new BlockPos(0, 0, -2), new BlockPos(1, 0, -2), new BlockPos(-1, 0, 2), - new BlockPos(0, 0, 2), new BlockPos(1, 0, 2),}; - - /** - * 3D matrix of integers representing the different blocks which make up the wizard tower. The blocks corresponding - * to each integer are as follows (note that some blocks change depending on the biome): - *

    - * 0 Nothing (keep existing block)
    - * 1 Air (remove existing block)
    - * 2 Floor (planks)
    - * 3 Bookshelf
    - * 4 Roof (stained clay)
    - * 5 Floor slab (lower half)
    - * 6 Floor slab (upper half)
    - * 7 Wall (cobblestone by default)
    - * 8 Glass pane
    - * 9 Door (metadata is handled by the built-in vanilla method)
    - * 10 Arcane workbench
    - * 11 Torch (metadata is handled separately depending on adjacent blocks)
    - * 12 Chest (only generates if the wizard is evil, otherwise places a bookshelf instead) - */ - private static final int[][][] towerBlueprintSmall = { - // x is horizontal, z is vertical, y is layers - {{0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0}, - {0, 0, 0, 2, 2, 2, 0, 0, 0}, {0, 0, 0, 2, 2, 2, 0, 0, 0}, {0, 0, 0, 2, 2, 2, 0, 0, 0}, - {0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0},}, - {{0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 7, 7, 7, 0, 0, 0}, - {0, 0, 7, 1, 6, 5, 7, 0, 0}, {0, 0, 7, 1, 1, 1, 7, 0, 0}, {0, 0, 7, 1, 1, 1, 7, 0, 0}, - {0, 0, 0, 7, 9, 7, 0, 0, 0}, {0, 0, 0, 1, 1, 1, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0},}, - {{0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 7, 7, 7, 0, 0, 0}, - {0, 0, 7, 5, 1, 1, 7, 0, 0}, {0, 0, 7, 6, 1, 1, 7, 0, 0}, {0, 0, 7, 1, 1, 1, 7, 0, 0}, - {0, 0, 0, 7, 0, 7, 0, 0, 0}, {0, 0, 0, 11, 1, 11, 0, 0, 0}, {0, 0, 0, 1, 1, 1, 0, 0, 0},}, - {{0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 7, 8, 7, 0, 0, 0}, - {0, 0, 7, 1, 1, 1, 7, 0, 0}, {0, 0, 7, 1, 1, 11, 7, 0, 0}, {0, 0, 7, 5, 6, 1, 7, 0, 0}, - {0, 0, 0, 7, 7, 7, 0, 0, 0}, {0, 0, 0, 1, 1, 1, 0, 0, 0}, {0, 0, 0, 1, 1, 1, 0, 0, 0},}, - {{0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 7, 7, 7, 0, 0, 0}, - {0, 0, 7, 1, 1, 1, 7, 0, 0}, {0, 0, 7, 1, 1, 6, 7, 0, 0}, {0, 0, 7, 1, 1, 5, 7, 0, 0}, - {0, 0, 0, 7, 7, 7, 0, 0, 0}, {0, 0, 0, 1, 1, 1, 0, 0, 0}, {0, 0, 0, 1, 1, 1, 0, 0, 0},}, - {{0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 7, 7, 7, 0, 0, 0}, - {0, 0, 7, 1, 6, 5, 7, 0, 0}, {0, 0, 7, 11, 1, 1, 7, 0, 0}, {0, 0, 7, 1, 1, 1, 7, 0, 0}, - {0, 0, 0, 7, 8, 7, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0},}, - {{0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 7, 7, 7, 0, 0, 0}, - {0, 0, 7, 5, 1, 1, 7, 0, 0}, {0, 0, 7, 1, 1, 1, 7, 0, 0}, {0, 0, 7, 1, 1, 1, 7, 0, 0}, - {0, 0, 0, 7, 7, 7, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0},}, - {{0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 7, 7, 7, 0, 0, 0}, {0, 0, 7, 2, 2, 2, 7, 0, 0}, - {0, 7, 1, 1, 1, 1, 2, 7, 0}, {0, 7, 5, 2, 2, 6, 2, 7, 0}, {0, 7, 2, 2, 2, 2, 2, 7, 0}, - {0, 0, 7, 2, 2, 2, 7, 0, 0}, {0, 0, 0, 7, 7, 7, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0},}, - {{0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 7, 7, 7, 0, 0, 0}, {0, 0, 7, 3, 3, 3, 7, 0, 0}, - {0, 7, 1, 1, 1, 1, 3, 7, 0}, {0, 7, 1, 1, 1, 1, 3, 7, 0}, {0, 7, 1, 1, 10, 1, 3, 7, 0}, - {0, 0, 7, 1, 1, 1, 7, 0, 0}, {0, 0, 0, 7, 7, 7, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0},}, - {{0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 7, 8, 7, 0, 0, 0}, {0, 0, 7, 11, 1, 11, 7, 0, 0}, - {0, 7, 1, 1, 1, 1, 3, 7, 0}, {0, 8, 1, 1, 1, 1, 3, 7, 0}, {0, 7, 1, 1, 1, 1, 3, 7, 0}, - {0, 0, 7, 11, 1, 11, 7, 0, 0}, {0, 0, 0, 7, 8, 7, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0},}, - {{0, 0, 0, 4, 4, 4, 0, 0, 0}, {0, 0, 4, 7, 7, 7, 4, 0, 0}, {0, 4, 7, 1, 1, 1, 7, 4, 0}, - {4, 7, 1, 1, 1, 1, 3, 7, 4}, {4, 7, 1, 1, 1, 1, 3, 7, 4}, {4, 7, 1, 1, 1, 1, 12, 7, 4}, - {0, 4, 7, 1, 1, 1, 7, 4, 0}, {0, 0, 4, 7, 7, 7, 4, 0, 0}, {0, 0, 0, 4, 4, 4, 0, 0, 0},}, - {{0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 4, 4, 4, 0, 0, 0}, {0, 0, 4, 1, 1, 1, 4, 0, 0}, - {0, 4, 1, 1, 1, 1, 1, 4, 0}, {0, 4, 1, 1, 1, 1, 1, 4, 0}, {0, 4, 1, 1, 1, 1, 1, 4, 0}, - {0, 0, 4, 1, 1, 1, 4, 0, 0}, {0, 0, 0, 4, 4, 4, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0},}, - {{0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 4, 4, 4, 0, 0, 0}, - {0, 0, 4, 1, 1, 1, 4, 0, 0}, {0, 0, 4, 1, 1, 1, 4, 0, 0}, {0, 0, 4, 1, 1, 1, 4, 0, 0}, - {0, 0, 0, 4, 4, 4, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0},}, - {{0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 4, 0, 0, 0, 0}, - {0, 0, 0, 4, 1, 4, 0, 0, 0}, {0, 0, 4, 1, 1, 1, 4, 0, 0}, {0, 0, 0, 4, 1, 4, 0, 0, 0}, - {0, 0, 0, 0, 4, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0},}, - {{0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0}, - {0, 0, 0, 4, 4, 4, 0, 0, 0}, {0, 0, 0, 4, 1, 4, 0, 0, 0}, {0, 0, 0, 4, 4, 4, 0, 0, 0}, - {0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0},}, - {{0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0}, - {0, 0, 0, 0, 4, 0, 0, 0, 0}, {0, 0, 0, 4, 1, 4, 0, 0, 0}, {0, 0, 0, 0, 4, 0, 0, 0, 0}, - {0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0},}, - {{0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0}, - {0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 4, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0}, - {0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0},}, - {{0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0}, - {0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 4, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0}, - {0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0},}}; - - /** - * 3D matrix of integers representing the different blocks which make up the wizard tower. The blocks corresponding - * to each integer are as follows (note that some blocks change depending on the biome): - *

    - * 0 Nothing (keep existing block)
    - * 1 Air (remove existing block)
    - * 2 Floor (planks)
    - * 3 Bookshelf
    - * 4 Roof (stained clay)
    - * 5 Floor slab (lower half)
    - * 6 Floor slab (upper half)
    - * 7 Wall (cobblestone by default)
    - * 8 Glass pane
    - * 9 Door (metadata is handled by the built-in vanilla method)
    - * 10 Arcane workbench
    - * 11 Torch (metadata is handled separately depending on adjacent blocks)
    - * 12 Chest (only generates if the wizard is evil, otherwise places a bookshelf instead) - */ - private static final int[][][] towerBlueprintMedium = { - // x is horizontal, z is vertical, y is layers - {{0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0}, - {0, 0, 0, 2, 2, 2, 0, 0, 0}, {0, 0, 0, 2, 2, 2, 0, 0, 0}, {0, 0, 0, 2, 2, 2, 0, 0, 0}, - {0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0},}, - {{0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 7, 7, 7, 0, 0, 0}, - {0, 0, 7, 1, 6, 5, 7, 0, 0}, {0, 0, 7, 1, 1, 1, 7, 0, 0}, {0, 0, 7, 1, 1, 1, 7, 0, 0}, - {0, 0, 0, 7, 9, 7, 0, 0, 0}, {0, 0, 0, 1, 1, 1, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0},}, - {{0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 7, 7, 7, 0, 0, 0}, - {0, 0, 7, 5, 1, 1, 7, 0, 0}, {0, 0, 7, 6, 1, 1, 7, 0, 0}, {0, 0, 7, 1, 1, 1, 7, 0, 0}, - {0, 0, 0, 7, 0, 7, 0, 0, 0}, {0, 0, 0, 11, 1, 11, 0, 0, 0}, {0, 0, 0, 1, 1, 1, 0, 0, 0},}, - {{0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 7, 8, 7, 0, 0, 0}, - {0, 0, 7, 1, 1, 1, 7, 0, 0}, {0, 0, 7, 1, 1, 11, 7, 0, 0}, {0, 0, 7, 5, 6, 1, 7, 0, 0}, - {0, 0, 0, 7, 7, 7, 0, 0, 0}, {0, 0, 0, 1, 1, 1, 0, 0, 0}, {0, 0, 0, 1, 1, 1, 0, 0, 0},}, - {{0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 7, 7, 7, 0, 0, 0}, - {0, 0, 7, 1, 1, 1, 7, 0, 0}, {0, 0, 7, 1, 1, 6, 7, 0, 0}, {0, 0, 7, 1, 1, 5, 7, 0, 0}, - {0, 0, 0, 7, 7, 7, 0, 0, 0}, {0, 0, 0, 1, 1, 1, 0, 0, 0}, {0, 0, 0, 1, 1, 1, 0, 0, 0},}, - {{0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 7, 7, 7, 0, 0, 0}, - {0, 0, 7, 1, 6, 5, 7, 0, 0}, {0, 0, 7, 11, 1, 1, 7, 0, 0}, {0, 0, 7, 1, 1, 1, 7, 0, 0}, - {0, 0, 0, 7, 8, 7, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0},}, - {{0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 7, 7, 7, 0, 0, 0}, - {0, 0, 7, 5, 1, 1, 7, 0, 0}, {0, 0, 7, 6, 1, 1, 7, 0, 0}, {0, 0, 7, 1, 1, 1, 7, 0, 0}, - {0, 0, 0, 7, 7, 7, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0},}, - {{0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 7, 8, 7, 0, 0, 0}, - {0, 0, 7, 1, 1, 1, 7, 0, 0}, {0, 0, 7, 1, 1, 11, 7, 0, 0}, {0, 0, 7, 5, 6, 1, 7, 0, 0}, - {0, 0, 0, 7, 7, 7, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0},}, - {{0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 7, 7, 7, 0, 0, 0}, - {0, 0, 7, 1, 1, 1, 7, 0, 0}, {0, 0, 7, 1, 1, 6, 7, 0, 0}, {0, 0, 7, 1, 1, 5, 7, 0, 0}, - {0, 0, 0, 7, 7, 7, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0},}, - {{0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 7, 7, 7, 0, 0, 0}, - {0, 0, 7, 1, 6, 5, 7, 0, 0}, {0, 0, 7, 11, 1, 1, 7, 0, 0}, {0, 0, 7, 1, 1, 1, 7, 0, 0}, - {0, 0, 0, 7, 8, 7, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0},}, - {{0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 7, 7, 7, 0, 0, 0}, - {0, 0, 7, 5, 1, 1, 7, 0, 0}, {0, 0, 7, 1, 1, 1, 7, 0, 0}, {0, 0, 7, 1, 1, 1, 7, 0, 0}, - {0, 0, 0, 7, 7, 7, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0},}, - {{0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 7, 7, 7, 0, 0, 0}, {0, 0, 7, 2, 2, 2, 7, 0, 0}, - {0, 7, 1, 1, 1, 1, 2, 7, 0}, {0, 7, 5, 2, 2, 6, 2, 7, 0}, {0, 7, 2, 2, 2, 2, 2, 7, 0}, - {0, 0, 7, 2, 2, 2, 7, 0, 0}, {0, 0, 0, 7, 7, 7, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0},}, - {{0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 7, 7, 7, 0, 0, 0}, {0, 0, 7, 3, 3, 3, 7, 0, 0}, - {0, 7, 1, 1, 1, 1, 3, 7, 0}, {0, 7, 1, 1, 1, 1, 3, 7, 0}, {0, 7, 1, 1, 10, 1, 3, 7, 0}, - {0, 0, 7, 1, 1, 1, 7, 0, 0}, {0, 0, 0, 7, 7, 7, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0},}, - {{0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 7, 8, 7, 0, 0, 0}, {0, 0, 7, 11, 1, 11, 7, 0, 0}, - {0, 7, 1, 1, 1, 1, 3, 7, 0}, {0, 8, 1, 1, 1, 1, 3, 7, 0}, {0, 7, 1, 1, 1, 1, 3, 7, 0}, - {0, 0, 7, 11, 1, 11, 7, 0, 0}, {0, 0, 0, 7, 8, 7, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0},}, - {{0, 0, 0, 4, 4, 4, 0, 0, 0}, {0, 0, 4, 7, 7, 7, 4, 0, 0}, {0, 4, 7, 1, 1, 1, 7, 4, 0}, - {4, 7, 1, 1, 1, 1, 3, 7, 4}, {4, 7, 1, 1, 1, 1, 3, 7, 4}, {4, 7, 1, 1, 1, 1, 12, 7, 4}, - {0, 4, 7, 1, 1, 1, 7, 4, 0}, {0, 0, 4, 7, 7, 7, 4, 0, 0}, {0, 0, 0, 4, 4, 4, 0, 0, 0},}, - {{0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 4, 4, 4, 0, 0, 0}, {0, 0, 4, 1, 1, 1, 4, 0, 0}, - {0, 4, 1, 1, 1, 1, 1, 4, 0}, {0, 4, 1, 1, 1, 1, 1, 4, 0}, {0, 4, 1, 1, 1, 1, 1, 4, 0}, - {0, 0, 4, 1, 1, 1, 4, 0, 0}, {0, 0, 0, 4, 4, 4, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0},}, - {{0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 4, 4, 4, 0, 0, 0}, - {0, 0, 4, 1, 1, 1, 4, 0, 0}, {0, 0, 4, 1, 1, 1, 4, 0, 0}, {0, 0, 4, 1, 1, 1, 4, 0, 0}, - {0, 0, 0, 4, 4, 4, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0},}, - {{0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 4, 0, 0, 0, 0}, - {0, 0, 0, 4, 1, 4, 0, 0, 0}, {0, 0, 4, 1, 1, 1, 4, 0, 0}, {0, 0, 0, 4, 1, 4, 0, 0, 0}, - {0, 0, 0, 0, 4, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0},}, - {{0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0}, - {0, 0, 0, 4, 4, 4, 0, 0, 0}, {0, 0, 0, 4, 1, 4, 0, 0, 0}, {0, 0, 0, 4, 4, 4, 0, 0, 0}, - {0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0},}, - {{0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0}, - {0, 0, 0, 0, 4, 0, 0, 0, 0}, {0, 0, 0, 4, 1, 4, 0, 0, 0}, {0, 0, 0, 0, 4, 0, 0, 0, 0}, - {0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0},}, - {{0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0}, - {0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 4, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0}, - {0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0},}, - {{0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0}, - {0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 4, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0}, - {0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0},}}; - - /** - * 3D matrix of integers representing the different blocks which make up the wizard tower. The blocks corresponding - * to each integer are as follows (note that some blocks change depending on the biome): - *

    - * 0 Nothing (keep existing block)
    - * 1 Air (remove existing block)
    - * 2 Floor (planks)
    - * 3 Bookshelf
    - * 4 Roof (stained clay)
    - * 5 Floor slab (lower half)
    - * 6 Floor slab (upper half)
    - * 7 Wall (cobblestone by default)
    - * 8 Glass pane
    - * 9 Door (metadata is handled by the built-in vanilla method)
    - * 10 Arcane workbench
    - * 11 Torch (metadata is handled separately depending on adjacent blocks)
    - * 12 Chest (only generates if the wizard is evil, otherwise places a bookshelf instead) - */ - private static final int[][][] towerBlueprintTall = { - // x is horizontal, z is vertical, y is layers - {{0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0}, - {0, 0, 0, 2, 2, 2, 0, 0, 0}, {0, 0, 0, 2, 2, 2, 0, 0, 0}, {0, 0, 0, 2, 2, 2, 0, 0, 0}, - {0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0},}, - {{0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 7, 7, 7, 0, 0, 0}, - {0, 0, 7, 1, 6, 5, 7, 0, 0}, {0, 0, 7, 1, 1, 1, 7, 0, 0}, {0, 0, 7, 1, 1, 1, 7, 0, 0}, - {0, 0, 0, 7, 9, 7, 0, 0, 0}, {0, 0, 0, 1, 1, 1, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0},}, - {{0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 7, 7, 7, 0, 0, 0}, - {0, 0, 7, 5, 1, 1, 7, 0, 0}, {0, 0, 7, 6, 1, 1, 7, 0, 0}, {0, 0, 7, 1, 1, 1, 7, 0, 0}, - {0, 0, 0, 7, 0, 7, 0, 0, 0}, {0, 0, 0, 11, 1, 11, 0, 0, 0}, {0, 0, 0, 1, 1, 1, 0, 0, 0},}, - {{0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 7, 8, 7, 0, 0, 0}, - {0, 0, 7, 1, 1, 1, 7, 0, 0}, {0, 0, 7, 1, 1, 11, 7, 0, 0}, {0, 0, 7, 5, 6, 1, 7, 0, 0}, - {0, 0, 0, 7, 7, 7, 0, 0, 0}, {0, 0, 0, 1, 1, 1, 0, 0, 0}, {0, 0, 0, 1, 1, 1, 0, 0, 0},}, - {{0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 7, 7, 7, 0, 0, 0}, - {0, 0, 7, 1, 1, 1, 7, 0, 0}, {0, 0, 7, 1, 1, 6, 7, 0, 0}, {0, 0, 7, 1, 1, 5, 7, 0, 0}, - {0, 0, 0, 7, 7, 7, 0, 0, 0}, {0, 0, 0, 1, 1, 1, 0, 0, 0}, {0, 0, 0, 1, 1, 1, 0, 0, 0},}, - {{0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 7, 7, 7, 0, 0, 0}, - {0, 0, 7, 1, 6, 5, 7, 0, 0}, {0, 0, 7, 11, 1, 1, 7, 0, 0}, {0, 0, 7, 1, 1, 1, 7, 0, 0}, - {0, 0, 0, 7, 8, 7, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0},}, - {{0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 7, 7, 7, 0, 0, 0}, - {0, 0, 7, 5, 1, 1, 7, 0, 0}, {0, 0, 7, 6, 1, 1, 7, 0, 0}, {0, 0, 7, 1, 1, 1, 7, 0, 0}, - {0, 0, 0, 7, 7, 7, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0},}, - {{0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 7, 8, 7, 0, 0, 0}, - {0, 0, 7, 1, 1, 1, 7, 0, 0}, {0, 0, 7, 1, 1, 11, 7, 0, 0}, {0, 0, 7, 5, 6, 1, 7, 0, 0}, - {0, 0, 0, 7, 7, 7, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0},}, - {{0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 7, 7, 7, 0, 0, 0}, - {0, 0, 7, 1, 1, 1, 7, 0, 0}, {0, 0, 7, 1, 1, 6, 7, 0, 0}, {0, 0, 7, 1, 1, 5, 7, 0, 0}, - {0, 0, 0, 7, 7, 7, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0},}, - {{0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 7, 7, 7, 0, 0, 0}, - {0, 0, 7, 1, 6, 5, 7, 0, 0}, {0, 0, 7, 11, 1, 1, 7, 0, 0}, {0, 0, 7, 1, 1, 1, 7, 0, 0}, - {0, 0, 0, 7, 8, 7, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0},}, - {{0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 7, 7, 7, 0, 0, 0}, - {0, 0, 7, 5, 1, 1, 7, 0, 0}, {0, 0, 7, 6, 1, 1, 7, 0, 0}, {0, 0, 7, 1, 1, 1, 7, 0, 0}, - {0, 0, 0, 7, 7, 7, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0},}, - {{0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 7, 8, 7, 0, 0, 0}, - {0, 0, 7, 1, 1, 1, 7, 0, 0}, {0, 0, 7, 1, 1, 11, 7, 0, 0}, {0, 0, 7, 5, 6, 1, 7, 0, 0}, - {0, 0, 0, 7, 7, 7, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0},}, - {{0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 7, 7, 7, 0, 0, 0}, - {0, 0, 7, 1, 1, 1, 7, 0, 0}, {0, 0, 7, 1, 1, 6, 7, 0, 0}, {0, 0, 7, 1, 1, 5, 7, 0, 0}, - {0, 0, 0, 7, 7, 7, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0},}, - {{0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 7, 7, 7, 0, 0, 0}, - {0, 0, 7, 1, 6, 5, 7, 0, 0}, {0, 0, 7, 11, 1, 1, 7, 0, 0}, {0, 0, 7, 1, 1, 1, 7, 0, 0}, - {0, 0, 0, 7, 8, 7, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0},}, - {{0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 7, 7, 7, 0, 0, 0}, - {0, 0, 7, 5, 1, 1, 7, 0, 0}, {0, 0, 7, 1, 1, 1, 7, 0, 0}, {0, 0, 7, 1, 1, 1, 7, 0, 0}, - {0, 0, 0, 7, 7, 7, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0},}, - {{0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 7, 7, 7, 0, 0, 0}, {0, 0, 7, 2, 2, 2, 7, 0, 0}, - {0, 7, 1, 1, 1, 1, 2, 7, 0}, {0, 7, 5, 2, 2, 6, 2, 7, 0}, {0, 7, 2, 2, 2, 2, 2, 7, 0}, - {0, 0, 7, 2, 2, 2, 7, 0, 0}, {0, 0, 0, 7, 7, 7, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0},}, - {{0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 7, 7, 7, 0, 0, 0}, {0, 0, 7, 3, 3, 3, 7, 0, 0}, - {0, 7, 1, 1, 1, 1, 3, 7, 0}, {0, 7, 1, 1, 1, 1, 3, 7, 0}, {0, 7, 1, 1, 10, 1, 3, 7, 0}, - {0, 0, 7, 1, 1, 1, 7, 0, 0}, {0, 0, 0, 7, 7, 7, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0},}, - {{0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 7, 8, 7, 0, 0, 0}, {0, 0, 7, 11, 1, 11, 7, 0, 0}, - {0, 7, 1, 1, 1, 1, 3, 7, 0}, {0, 8, 1, 1, 1, 1, 3, 7, 0}, {0, 7, 1, 1, 1, 1, 3, 7, 0}, - {0, 0, 7, 11, 1, 11, 7, 0, 0}, {0, 0, 0, 7, 8, 7, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0},}, - {{0, 0, 0, 4, 4, 4, 0, 0, 0}, {0, 0, 4, 7, 7, 7, 4, 0, 0}, {0, 4, 7, 1, 1, 1, 7, 4, 0}, - {4, 7, 1, 1, 1, 1, 3, 7, 4}, {4, 7, 1, 1, 1, 1, 3, 7, 4}, {4, 7, 1, 1, 1, 1, 12, 7, 4}, - {0, 4, 7, 1, 1, 1, 7, 4, 0}, {0, 0, 4, 7, 7, 7, 4, 0, 0}, {0, 0, 0, 4, 4, 4, 0, 0, 0},}, - {{0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 4, 4, 4, 0, 0, 0}, {0, 0, 4, 1, 1, 1, 4, 0, 0}, - {0, 4, 1, 1, 1, 1, 1, 4, 0}, {0, 4, 1, 1, 1, 1, 1, 4, 0}, {0, 4, 1, 1, 1, 1, 1, 4, 0}, - {0, 0, 4, 1, 1, 1, 4, 0, 0}, {0, 0, 0, 4, 4, 4, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0},}, - {{0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 4, 4, 4, 0, 0, 0}, - {0, 0, 4, 1, 1, 1, 4, 0, 0}, {0, 0, 4, 1, 1, 1, 4, 0, 0}, {0, 0, 4, 1, 1, 1, 4, 0, 0}, - {0, 0, 0, 4, 4, 4, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0},}, - {{0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 4, 0, 0, 0, 0}, - {0, 0, 0, 4, 1, 4, 0, 0, 0}, {0, 0, 4, 1, 1, 1, 4, 0, 0}, {0, 0, 0, 4, 1, 4, 0, 0, 0}, - {0, 0, 0, 0, 4, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0},}, - {{0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0}, - {0, 0, 0, 4, 4, 4, 0, 0, 0}, {0, 0, 0, 4, 1, 4, 0, 0, 0}, {0, 0, 0, 4, 4, 4, 0, 0, 0}, - {0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0},}, - {{0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0}, - {0, 0, 0, 0, 4, 0, 0, 0, 0}, {0, 0, 0, 4, 1, 4, 0, 0, 0}, {0, 0, 0, 0, 4, 0, 0, 0, 0}, - {0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0},}, - {{0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0}, - {0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 4, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0}, - {0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0},}, - {{0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0}, - {0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 4, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0}, - {0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0},}}; - - /** - * 3D matrix of integers representing the different blocks which make up the wizard tower. The blocks corresponding - * to each integer are as follows (note that some blocks change depending on the biome): - *

    - * 0 Nothing (keep existing block)
    - * 1 Air (remove existing block)
    - * 2 Floor (planks)
    - * 3 Bookshelf
    - * 4 Roof (stained clay)
    - * 5 Floor slab (lower half)
    - * 6 Floor slab (upper half)
    - * 7 Wall (cobblestone by default)
    - * 8 Glass pane
    - * 9 Door (metadata is handled by the built-in vanilla method)
    - * 10 Arcane workbench
    - * 11 Torch (metadata is handled separately depending on adjacent blocks)
    - * 12 Chest (only generates if the wizard is evil, otherwise places a bookshelf instead) - */ - private static final int[][][] towerBlueprintDouble = { - // x is horizontal, z is vertical, y is layers - {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, - {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, - {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 2, 2, 2, 0, 0, 0, 0, 0}, - {0, 0, 0, 0, 0, 2, 2, 2, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 2, 2, 2, 0, 0, 0, 0, 0}, - {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, - {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, - {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},}, - {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, - {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, - {0, 0, 0, 0, 0, 7, 7, 7, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 7, 1, 6, 5, 7, 0, 0, 0, 0}, - {0, 0, 0, 0, 7, 1, 1, 1, 7, 0, 0, 0, 0}, {0, 0, 0, 0, 7, 1, 1, 1, 7, 0, 0, 0, 0}, - {0, 0, 0, 0, 0, 7, 9, 7, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0}, - {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, - {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},}, - {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, - {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, - {0, 0, 0, 0, 0, 7, 7, 7, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 7, 5, 1, 1, 7, 0, 0, 0, 0}, - {0, 0, 0, 0, 7, 6, 1, 1, 7, 0, 0, 0, 0}, {0, 0, 0, 0, 7, 1, 1, 1, 7, 0, 0, 0, 0}, - {0, 0, 0, 0, 0, 7, 0, 7, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 11, 1, 11, 0, 0, 0, 0, 0}, - {0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, - {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},}, - {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, - {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, - {0, 0, 0, 0, 0, 7, 8, 7, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 7, 1, 1, 1, 7, 0, 0, 0, 0}, - {0, 0, 0, 0, 7, 1, 1, 11, 7, 0, 0, 0, 0}, {0, 0, 0, 0, 7, 5, 6, 1, 7, 0, 0, 0, 0}, - {0, 0, 0, 0, 0, 7, 7, 7, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0}, - {0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, - {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},}, - {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, - {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, - {0, 0, 0, 0, 0, 7, 7, 7, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 7, 1, 1, 1, 7, 0, 0, 0, 0}, - {0, 0, 0, 0, 7, 1, 1, 6, 7, 7, 7, 0, 0}, {0, 0, 0, 0, 7, 1, 1, 5, 7, 0, 0, 0, 0}, - {0, 0, 0, 0, 0, 7, 7, 7, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0}, - {0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, - {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},}, - {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, - {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, - {0, 0, 0, 0, 0, 7, 7, 7, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 7, 1, 6, 5, 7, 7, 7, 0, 0}, - {0, 0, 0, 0, 7, 11, 1, 1, 1, 1, 1, 7, 0}, {0, 0, 0, 0, 7, 1, 1, 1, 7, 7, 7, 0, 0}, - {0, 0, 0, 0, 0, 7, 8, 7, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, - {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, - {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},}, - {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, - {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, - {0, 0, 0, 0, 0, 7, 7, 7, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 7, 5, 1, 1, 7, 7, 8, 7, 0}, - {0, 0, 0, 0, 7, 6, 1, 1, 1, 1, 1, 8, 0}, {0, 0, 0, 0, 7, 1, 1, 1, 7, 7, 8, 7, 0}, - {0, 0, 0, 0, 0, 7, 7, 7, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, - {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, - {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},}, - {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, - {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, - {0, 0, 0, 0, 0, 7, 8, 7, 0, 4, 4, 4, 0}, {0, 0, 0, 0, 7, 1, 1, 1, 7, 7, 7, 7, 4}, - {0, 0, 0, 0, 7, 1, 1, 11, 7, 1, 1, 7, 4}, {0, 0, 0, 0, 7, 5, 6, 1, 7, 7, 7, 7, 4}, - {0, 0, 0, 0, 0, 7, 7, 7, 0, 4, 4, 4, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, - {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, - {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},}, - {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, - {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, - {0, 0, 0, 0, 0, 7, 7, 7, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 7, 1, 1, 1, 7, 4, 4, 4, 0}, - {0, 0, 0, 0, 7, 1, 1, 6, 7, 4, 1, 4, 0}, {0, 0, 0, 0, 7, 1, 1, 5, 7, 4, 4, 4, 0}, - {0, 0, 0, 0, 0, 7, 7, 7, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0}, - {0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, - {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},}, - {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, - {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, - {0, 0, 0, 0, 0, 7, 7, 7, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 7, 1, 6, 5, 7, 0, 4, 0, 0}, - {0, 0, 0, 0, 7, 11, 1, 1, 7, 4, 1, 4, 0}, {0, 0, 0, 0, 7, 1, 1, 1, 7, 0, 4, 0, 0}, - {0, 0, 0, 0, 0, 7, 8, 7, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, - {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, - {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},}, - {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, - {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, - {0, 0, 0, 0, 0, 7, 7, 7, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 7, 5, 1, 1, 7, 0, 0, 0, 0}, - {0, 0, 0, 0, 7, 1, 1, 1, 7, 0, 4, 0, 0}, {0, 0, 0, 0, 7, 1, 1, 1, 7, 0, 0, 0, 0}, - {0, 0, 0, 0, 0, 7, 7, 7, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, - {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, - {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},}, - {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, - {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 7, 7, 7, 0, 0, 0, 0, 0}, - {0, 0, 0, 0, 7, 2, 2, 2, 7, 0, 0, 0, 0}, {0, 0, 0, 7, 1, 1, 1, 1, 2, 7, 0, 0, 0}, - {0, 0, 0, 7, 5, 2, 2, 6, 2, 7, 4, 0, 0}, {0, 0, 0, 7, 2, 2, 2, 2, 2, 7, 0, 0, 0}, - {0, 0, 0, 0, 7, 2, 2, 2, 7, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 7, 7, 7, 0, 0, 0, 0, 0}, - {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, - {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},}, - {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, - {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 7, 7, 7, 0, 0, 0, 0, 0}, - {0, 0, 0, 0, 7, 3, 3, 3, 7, 0, 0, 0, 0}, {0, 0, 0, 7, 1, 1, 1, 1, 3, 7, 0, 0, 0}, - {0, 0, 0, 7, 1, 1, 1, 1, 3, 7, 0, 0, 0}, {0, 0, 0, 7, 1, 1, 10, 1, 3, 7, 0, 0, 0}, - {0, 0, 0, 0, 7, 1, 1, 1, 7, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 7, 7, 7, 0, 0, 0, 0, 0}, - {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, - {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},}, - {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, - {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 7, 8, 7, 0, 0, 0, 0, 0}, - {0, 0, 0, 0, 7, 11, 1, 11, 7, 0, 0, 0, 0}, {0, 0, 0, 7, 1, 1, 1, 1, 3, 7, 0, 0, 0}, - {0, 0, 0, 8, 1, 1, 1, 1, 3, 7, 0, 0, 0}, {0, 0, 0, 7, 1, 1, 1, 1, 3, 7, 0, 0, 0}, - {0, 0, 0, 0, 7, 11, 1, 11, 7, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 7, 8, 7, 0, 0, 0, 0, 0}, - {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, - {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},}, - {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, - {0, 0, 0, 0, 0, 4, 4, 4, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 4, 7, 7, 7, 4, 0, 0, 0, 0}, - {0, 0, 0, 4, 7, 1, 1, 1, 7, 4, 0, 0, 0}, {0, 0, 4, 7, 1, 1, 1, 1, 3, 7, 4, 0, 0}, - {0, 0, 4, 7, 1, 1, 1, 1, 3, 7, 4, 0, 0}, {0, 0, 4, 7, 1, 1, 1, 1, 12, 7, 4, 0, 0}, - {0, 0, 0, 4, 7, 1, 1, 1, 7, 4, 0, 0, 0}, {0, 0, 0, 0, 4, 7, 7, 7, 4, 0, 0, 0, 0}, - {0, 0, 0, 0, 0, 4, 4, 4, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, - {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},}, - {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, - {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 4, 4, 4, 0, 0, 0, 0, 0}, - {0, 0, 0, 0, 4, 1, 1, 1, 4, 0, 0, 0, 0}, {0, 0, 0, 4, 1, 1, 1, 1, 1, 4, 0, 0, 0}, - {0, 0, 0, 4, 1, 1, 1, 1, 1, 4, 0, 0, 0}, {0, 0, 0, 4, 1, 1, 1, 1, 1, 4, 0, 0, 0}, - {0, 0, 0, 0, 4, 1, 1, 1, 4, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 4, 4, 4, 0, 0, 0, 0, 0}, - {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, - {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},}, - {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, - {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, - {0, 0, 0, 0, 0, 4, 4, 4, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 4, 1, 1, 1, 4, 0, 0, 0, 0}, - {0, 0, 0, 0, 4, 1, 1, 1, 4, 0, 0, 0, 0}, {0, 0, 0, 0, 4, 1, 1, 1, 4, 0, 0, 0, 0}, - {0, 0, 0, 0, 0, 4, 4, 4, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, - {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, - {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},}, - {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, - {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, - {0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 4, 1, 4, 0, 0, 0, 0, 0}, - {0, 0, 0, 0, 4, 1, 1, 1, 4, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 4, 1, 4, 0, 0, 0, 0, 0}, - {0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, - {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, - {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},}, - {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, - {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, - {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 4, 4, 4, 0, 0, 0, 0, 0}, - {0, 0, 0, 0, 0, 4, 1, 4, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 4, 4, 4, 0, 0, 0, 0, 0}, - {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, - {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, - {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},}, - {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, - {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, - {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0}, - {0, 0, 0, 0, 0, 4, 1, 4, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0}, - {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, - {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, - {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},}, - {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, - {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, - {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, - {0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, - {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, - {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, - {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},}, - {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, - {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, - {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, - {0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, - {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, - {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, - {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},}}; - -} diff --git a/src/main/java/electroblob/wizardry/advancement/ArcaneWorkbenchTrigger.java b/src/main/java/electroblob/wizardry/advancement/ArcaneWorkbenchTrigger.java new file mode 100644 index 00000000..175f9cdf --- /dev/null +++ b/src/main/java/electroblob/wizardry/advancement/ArcaneWorkbenchTrigger.java @@ -0,0 +1,135 @@ +package electroblob.wizardry.advancement; + +import com.google.common.collect.Lists; +import com.google.common.collect.Maps; +import com.google.common.collect.Sets; +import com.google.gson.JsonDeserializationContext; +import com.google.gson.JsonObject; +import net.minecraft.advancements.ICriterionTrigger; +import net.minecraft.advancements.PlayerAdvancements; +import net.minecraft.advancements.critereon.AbstractCriterionInstance; +import net.minecraft.advancements.critereon.ItemPredicate; +import net.minecraft.entity.player.EntityPlayerMP; +import net.minecraft.item.ItemStack; +import net.minecraft.util.ResourceLocation; + +import java.util.List; +import java.util.Map; +import java.util.Set; + +/** Advancement trigger for things done in the arcane workbench. The majority of any + * ICriterionTrigger class is just boilerplate, and this is no exception. */ +public class ArcaneWorkbenchTrigger implements ICriterionTrigger { + + private final ResourceLocation id; + private final Map listeners = Maps.newHashMap(); + + public ArcaneWorkbenchTrigger(ResourceLocation id){ + this.id = id; + } + + public ResourceLocation getId(){ + return this.id; + } + + public void addListener(PlayerAdvancements advancements, Listener listener){ + + ArcaneWorkbenchTrigger.Listeners listeners = this.listeners.get(advancements); + + if(listeners == null){ + listeners = new ArcaneWorkbenchTrigger.Listeners(advancements); + this.listeners.put(advancements, listeners); + } + + listeners.add(listener); + } + + public void removeListener(PlayerAdvancements advancements, Listener listener){ + + ArcaneWorkbenchTrigger.Listeners listeners = this.listeners.get(advancements); + + if(listeners != null){ + listeners.remove(listener); + + if(listeners.isEmpty()){ + this.listeners.remove(advancements); + } + } + } + + public void removeAllListeners(PlayerAdvancements advancements){ + this.listeners.remove(advancements); + } + + public ArcaneWorkbenchTrigger.Instance deserializeInstance(JsonObject json, JsonDeserializationContext context){ + return new ArcaneWorkbenchTrigger.Instance(this.id, ItemPredicate.deserialize(json.get("item"))); + } + + public void trigger(EntityPlayerMP player, ItemStack stack){ + + ArcaneWorkbenchTrigger.Listeners listeners = this.listeners.get(player.getAdvancements()); + + if(listeners != null){ + listeners.trigger(stack); + } + } + + public static class Instance extends AbstractCriterionInstance { + + private final ItemPredicate item; + + public Instance(ResourceLocation criterionIn, ItemPredicate item){ + super(criterionIn); + this.item = item; + } + + public boolean test(ItemStack stack){ + return this.item.test(stack); + } + } + + static class Listeners { + + private final PlayerAdvancements playerAdvancements; + private final Set> listeners = Sets.newHashSet(); + + public Listeners(PlayerAdvancements advancements){ + this.playerAdvancements = advancements; + } + + public boolean isEmpty(){ + return this.listeners.isEmpty(); + } + + public void add(Listener listener){ + this.listeners.add(listener); + } + + public void remove(Listener listener){ + this.listeners.remove(listener); + } + + public void trigger(ItemStack stack){ + + List> list = null; + + for(Listener listener : this.listeners){ + + if(listener.getCriterionInstance().test(stack)){ + + if(list == null){ + list = Lists.newArrayList(); + } + + list.add(listener); + } + } + + if(list != null){ + for(Listener listener : list){ + listener.grantCriterion(this.playerAdvancements); + } + } + } + } +} \ No newline at end of file diff --git a/src/main/java/electroblob/wizardry/util/CustomAdvancementTrigger.java b/src/main/java/electroblob/wizardry/advancement/CustomAdvancementTrigger.java similarity index 96% rename from src/main/java/electroblob/wizardry/util/CustomAdvancementTrigger.java rename to src/main/java/electroblob/wizardry/advancement/CustomAdvancementTrigger.java index 8fb2693a..21a1cf99 100644 --- a/src/main/java/electroblob/wizardry/util/CustomAdvancementTrigger.java +++ b/src/main/java/electroblob/wizardry/advancement/CustomAdvancementTrigger.java @@ -1,10 +1,9 @@ -package electroblob.wizardry.util; +package electroblob.wizardry.advancement; import com.google.common.collect.HashMultimap; import com.google.common.collect.SetMultimap; import com.google.gson.JsonDeserializationContext; import com.google.gson.JsonObject; - import electroblob.wizardry.Wizardry; import net.minecraft.advancements.ICriterionInstance; import net.minecraft.advancements.ICriterionTrigger; @@ -34,7 +33,7 @@ public class CustomAdvancementTrigger implements ICriterionTrigger { + + private final ResourceLocation id; + private final Map listeners = Maps.newHashMap(); + + public SpellCastTrigger(ResourceLocation id){ + this.id = id; + } + + public ResourceLocation getId(){ + return this.id; + } + + public void addListener(PlayerAdvancements advancements, Listener listener){ + + SpellCastTrigger.Listeners listeners = this.listeners.get(advancements); + + if(listeners == null){ + listeners = new SpellCastTrigger.Listeners(advancements); + this.listeners.put(advancements, listeners); + } + + listeners.add(listener); + } + + public void removeListener(PlayerAdvancements advancements, Listener listener){ + + SpellCastTrigger.Listeners listeners = this.listeners.get(advancements); + + if(listeners != null){ + listeners.remove(listener); + + if(listeners.isEmpty()){ + this.listeners.remove(advancements); + } + } + } + + public void removeAllListeners(PlayerAdvancements advancements){ + this.listeners.remove(advancements); + } + + public SpellCastTrigger.Instance deserializeInstance(JsonObject json, JsonDeserializationContext context){ + return new SpellCastTrigger.Instance(this.id, SpellPredicate.deserialize(json.get("spell")), + ItemPredicate.deserialize(json.get("item"))); + } + + public void trigger(EntityPlayerMP player, Spell spell, ItemStack stack){ + + SpellCastTrigger.Listeners listeners = this.listeners.get(player.getAdvancements()); + + if(listeners != null){ + listeners.trigger(spell, stack); + } + } + + public static class Instance extends AbstractCriterionInstance { + + private final SpellPredicate spell; + private final ItemPredicate item; + + public Instance(ResourceLocation criterion, SpellPredicate spell, ItemPredicate item){ + super(criterion); + this.spell = spell; + this.item = item; + } + + public boolean test(Spell spell, ItemStack stack){ + return this.spell.test(spell) && item.test(stack); + } + } + + static class Listeners { + + private final PlayerAdvancements playerAdvancements; + private final Set> listeners = Sets.newHashSet(); + + public Listeners(PlayerAdvancements advancements){ + this.playerAdvancements = advancements; + } + + public boolean isEmpty(){ + return this.listeners.isEmpty(); + } + + public void add(Listener listener){ + this.listeners.add(listener); + } + + public void remove(Listener listener){ + this.listeners.remove(listener); + } + + public void trigger(Spell spell, ItemStack stack){ + + List> list = null; + + for(Listener listener : this.listeners){ + + if(listener.getCriterionInstance().test(spell, stack)){ + + if(list == null){ + list = Lists.newArrayList(); + } + + list.add(listener); + } + } + + if(list != null){ + for(Listener listener : list){ + listener.grantCriterion(this.playerAdvancements); + } + } + } + } +} \ No newline at end of file diff --git a/src/main/java/electroblob/wizardry/advancement/SpellDiscoveryTrigger.java b/src/main/java/electroblob/wizardry/advancement/SpellDiscoveryTrigger.java new file mode 100644 index 00000000..f24fef36 --- /dev/null +++ b/src/main/java/electroblob/wizardry/advancement/SpellDiscoveryTrigger.java @@ -0,0 +1,143 @@ +package electroblob.wizardry.advancement; + +import com.google.common.collect.Lists; +import com.google.common.collect.Maps; +import com.google.common.collect.Sets; +import com.google.gson.JsonDeserializationContext; +import com.google.gson.JsonObject; +import com.google.gson.JsonSyntaxException; +import electroblob.wizardry.event.DiscoverSpellEvent; +import electroblob.wizardry.spell.Spell; +import net.minecraft.advancements.ICriterionTrigger; +import net.minecraft.advancements.PlayerAdvancements; +import net.minecraft.advancements.critereon.AbstractCriterionInstance; +import net.minecraft.entity.player.EntityPlayerMP; +import net.minecraft.util.JsonUtils; +import net.minecraft.util.ResourceLocation; + +import java.util.List; +import java.util.Map; +import java.util.Set; + +/** Advancement trigger that is triggered when a spell is discovered. The majority of any + * ICriterionTrigger class is just boilerplate, and this is no exception. */ +public class SpellDiscoveryTrigger implements ICriterionTrigger { + + private final ResourceLocation id; + private final Map listeners = Maps.newHashMap(); + + public SpellDiscoveryTrigger(ResourceLocation id){ + this.id = id; + } + + public ResourceLocation getId(){ + return this.id; + } + + public void addListener(PlayerAdvancements advancements, Listener listener){ + + SpellDiscoveryTrigger.Listeners listeners = this.listeners.get(advancements); + + if(listeners == null){ + listeners = new SpellDiscoveryTrigger.Listeners(advancements); + this.listeners.put(advancements, listeners); + } + + listeners.add(listener); + } + + public void removeListener(PlayerAdvancements advancements, Listener listener){ + + SpellDiscoveryTrigger.Listeners listeners = this.listeners.get(advancements); + + if(listeners != null){ + listeners.remove(listener); + + if(listeners.isEmpty()){ + this.listeners.remove(advancements); + } + } + } + + public void removeAllListeners(PlayerAdvancements advancements){ + this.listeners.remove(advancements); + } + + public SpellDiscoveryTrigger.Instance deserializeInstance(JsonObject json, JsonDeserializationContext context){ + + String s = JsonUtils.getString(json, "source"); + DiscoverSpellEvent.Source source = DiscoverSpellEvent.Source.byName(s); + if(source == null) throw new JsonSyntaxException("No such spell discovery source: " + s); + return new SpellDiscoveryTrigger.Instance(this.id, SpellPredicate.deserialize(json.get("spell")), source); + } + + public void trigger(EntityPlayerMP player, Spell spell, DiscoverSpellEvent.Source source){ + + SpellDiscoveryTrigger.Listeners listeners = this.listeners.get(player.getAdvancements()); + + if(listeners != null){ + listeners.trigger(spell, source); + } + } + + public static class Instance extends AbstractCriterionInstance { + + private final SpellPredicate spell; + private final DiscoverSpellEvent.Source source; + + public Instance(ResourceLocation criterion, SpellPredicate spell, DiscoverSpellEvent.Source source){ + super(criterion); + this.spell = spell; + this.source = source; + } + + public boolean test(Spell spell, DiscoverSpellEvent.Source source){ + return this.spell.test(spell) && source == this.source; + } + } + + static class Listeners { + + private final PlayerAdvancements playerAdvancements; + private final Set> listeners = Sets.newHashSet(); + + public Listeners(PlayerAdvancements advancements){ + this.playerAdvancements = advancements; + } + + public boolean isEmpty(){ + return this.listeners.isEmpty(); + } + + public void add(Listener listener){ + this.listeners.add(listener); + } + + public void remove(Listener listener){ + this.listeners.remove(listener); + } + + public void trigger(Spell spell, DiscoverSpellEvent.Source source){ + + List> list = null; + + for(Listener listener : this.listeners){ + + if(listener.getCriterionInstance().test(spell, source)){ + + if(list == null){ + list = Lists.newArrayList(); + } + + list.add(listener); + } + } + + if(list != null){ + for(Listener listener : list){ + listener.grantCriterion(this.playerAdvancements); + } + } + } + } +} \ No newline at end of file diff --git a/src/main/java/electroblob/wizardry/advancement/SpellPredicate.java b/src/main/java/electroblob/wizardry/advancement/SpellPredicate.java new file mode 100644 index 00000000..24d6c694 --- /dev/null +++ b/src/main/java/electroblob/wizardry/advancement/SpellPredicate.java @@ -0,0 +1,117 @@ +package electroblob.wizardry.advancement; + +import com.google.common.collect.Streams; +import com.google.gson.JsonArray; +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import com.google.gson.JsonSyntaxException; +import electroblob.wizardry.constants.Element; +import electroblob.wizardry.constants.Tier; +import electroblob.wizardry.spell.Spell; +import net.minecraft.util.JsonUtils; + +import javax.annotation.Nullable; +import java.util.Arrays; + +/** Predicate used by advancement triggers to match spells. */ +public class SpellPredicate { + + public static final SpellPredicate ANY = new SpellPredicate(); + private final Spell spell; + private final Tier[] tiers; + private final Element[] elements; + + public SpellPredicate(){ + this.spell = null; + this.tiers = Tier.values(); + this.elements = Element.values(); + } + + public SpellPredicate(@Nullable Spell spell, Tier[] tiers, Element[] elements){ + this.spell = spell; + this.tiers = tiers; + this.elements = elements; + } + + public boolean test(Spell spell){ + + if(this.spell != null && spell != this.spell){ + return false; + }else if(!Arrays.asList(this.tiers).contains(spell.getTier())){ + return false; + }else if(!Arrays.asList(this.elements).contains(spell.getElement())){ + return false; + } + + return true; + } + + public static SpellPredicate deserialize(@Nullable JsonElement element){ + + if(element != null && !element.isJsonNull()){ + + JsonObject jsonobject = JsonUtils.getJsonObject(element, "spell"); + + Spell spell = null; + + if(jsonobject.has("spell")){ + + String s = JsonUtils.getString(jsonobject, "spell"); + spell = Spell.get(s); + + if(spell == null){ + throw new JsonSyntaxException("Unknown spell id '" + s + "'"); + } + } + + Tier[] tiers = Tier.values(); + + if(jsonobject.has("tiers")){ + try{ + JsonArray array = JsonUtils.getJsonArray(jsonobject, "tiers"); + tiers = Streams.stream(array) + .map(je -> Tier.fromName(JsonUtils.getString(je, "element of array tiers"))) + .toArray(Tier[]::new); + }catch(IllegalArgumentException e){ + throw new JsonSyntaxException("Incorrect spell predicate value", e); + } + } + + Element[] elements = Element.values(); + + if(jsonobject.has("elements")){ + try{ + JsonArray array = JsonUtils.getJsonArray(jsonobject, "elements"); + elements = Streams.stream(array) + .map(je -> Element.fromName(JsonUtils.getString(je, "element of array elements"))) + .toArray(Element[]::new); + }catch(IllegalArgumentException e){ + throw new JsonSyntaxException("Incorrect spell predicate value", e); + } + } + + return new SpellPredicate(spell, tiers, elements); + + }else{ + return ANY; + } + } + + public static SpellPredicate[] deserializeArray(@Nullable JsonElement element){ + + if(element != null && !element.isJsonNull()){ + + JsonArray jsonarray = JsonUtils.getJsonArray(element, "spells"); + SpellPredicate[] predicates = new SpellPredicate[jsonarray.size()]; + + for(int i = 0; i < predicates.length; ++i){ + predicates[i] = deserialize(jsonarray.get(i)); + } + + return predicates; + + }else{ + return new SpellPredicate[0]; + } + } +} \ No newline at end of file diff --git a/src/main/java/electroblob/wizardry/advancement/StructureTrigger.java b/src/main/java/electroblob/wizardry/advancement/StructureTrigger.java new file mode 100644 index 00000000..aedcd6a4 --- /dev/null +++ b/src/main/java/electroblob/wizardry/advancement/StructureTrigger.java @@ -0,0 +1,136 @@ +package electroblob.wizardry.advancement; + +import com.google.common.collect.Lists; +import com.google.common.collect.Maps; +import com.google.common.collect.Sets; +import com.google.gson.JsonDeserializationContext; +import com.google.gson.JsonObject; +import electroblob.wizardry.worldgen.WorldGenSurfaceStructure; +import net.minecraft.advancements.ICriterionTrigger; +import net.minecraft.advancements.PlayerAdvancements; +import net.minecraft.advancements.critereon.AbstractCriterionInstance; +import net.minecraft.entity.player.EntityPlayerMP; +import net.minecraft.util.JsonUtils; +import net.minecraft.util.ResourceLocation; +import net.minecraft.world.WorldServer; + +import java.util.List; +import java.util.Map; +import java.util.Set; + +/** Copied from PositionTrigger and modified to work with wizardry's structures. The majority of any + * ICriterionTrigger class is just boilerplate, and this is no exception. */ +public class StructureTrigger implements ICriterionTrigger { + + private final ResourceLocation id; + private final Map listeners = Maps.newHashMap(); + + public StructureTrigger(ResourceLocation id){ + this.id = id; + } + + public ResourceLocation getId(){ + return this.id; + } + + public void addListener(PlayerAdvancements advancements, Listener listener){ + + StructureTrigger.Listeners listeners = this.listeners.get(advancements); + + if(listeners == null){ + listeners = new StructureTrigger.Listeners(advancements); + this.listeners.put(advancements, listeners); + } + + listeners.add(listener); + } + + public void removeListener(PlayerAdvancements advancements, Listener listener){ + + StructureTrigger.Listeners listeners = this.listeners.get(advancements); + + if(listeners != null){ + listeners.remove(listener); + + if(listeners.isEmpty()){ + this.listeners.remove(advancements); + } + } + } + + public void removeAllListeners(PlayerAdvancements advancements){ + this.listeners.remove(advancements); + } + + public StructureTrigger.Instance deserializeInstance(JsonObject json, JsonDeserializationContext context){ + return new StructureTrigger.Instance(this.id, JsonUtils.getString(json, "structure_type")); + } + + public void trigger(EntityPlayerMP player){ + + StructureTrigger.Listeners listeners = this.listeners.get(player.getAdvancements()); + + if(listeners != null){ + listeners.trigger(player.getServerWorld(), player.posX, player.posY, player.posZ); + } + } + + public static class Instance extends AbstractCriterionInstance { + + private final WorldGenSurfaceStructure structureType; + + public Instance(ResourceLocation criterionIn, String name){ + super(criterionIn); + this.structureType = WorldGenSurfaceStructure.byName(name); + } + + public boolean test(WorldServer world, double x, double y, double z){ + return structureType.isInsideStructure(world, x, y, z); + } + } + + static class Listeners { + + private final PlayerAdvancements playerAdvancements; + private final Set> listeners = Sets.newHashSet(); + + public Listeners(PlayerAdvancements advancements){ + this.playerAdvancements = advancements; + } + + public boolean isEmpty(){ + return this.listeners.isEmpty(); + } + + public void add(Listener listener){ + this.listeners.add(listener); + } + + public void remove(Listener listener){ + this.listeners.remove(listener); + } + + public void trigger(WorldServer world, double x, double y, double z){ + + List> list = null; + + for(Listener listener : this.listeners){ + + if(listener.getCriterionInstance().test(world, x, y, z)){ + + if(list == null){ + list = Lists.newArrayList(); + } + + list.add(listener); + } + } + + if(list != null){ + for(Listener listener : list){ + listener.grantCriterion(this.playerAdvancements); + } + } + } + } +} \ No newline at end of file diff --git a/src/main/java/electroblob/wizardry/api/WizardryEnumHelper.java b/src/main/java/electroblob/wizardry/api/WizardryEnumHelper.java new file mode 100644 index 00000000..4c73f606 --- /dev/null +++ b/src/main/java/electroblob/wizardry/api/WizardryEnumHelper.java @@ -0,0 +1,96 @@ +package electroblob.wizardry.api; + +import electroblob.wizardry.constants.Element; +import electroblob.wizardry.constants.SpellType; +import electroblob.wizardry.constants.Tier; +import electroblob.wizardry.util.SpellProperties; +import net.minecraft.util.text.Style; +import net.minecraftforge.common.util.EnumHelper; + +/** + * This class contains methods similar to those in {@link EnumHelper} specific to wizardry's enum types. + * + * @author Electroblob + * @since Wizardry 4.2 + */ +public final class WizardryEnumHelper { + + // Make sure these are updated if the relevant constructors are updated! + // Can't we do some kind of reflection to access them and generate these arrays? + private static final Class[] TIER_ARGUMENTS = new Class[]{Integer.class, Integer.class, Integer.class, Style.class, String.class}; + private static final Class[] ELEMENT_ARGUMENTS = new Class[]{Style.class, String.class, String.class}; + private static final Class[] SPELL_TYPE_ARGUMENTS = new Class[]{String.class}; + private static final Class[] SPELL_CONTEXT_ARGUMENTS = new Class[]{String.class}; + + /** + * Wrapper for the generic method {@link EnumHelper#addEnum(Class, String, Class[], Object...)} which is + * specifically for adding new tiers. Use this method in preference to the generic one in case the constructor + * parameters change for {@code Tier}. + *

    + * As of version 4.2, wizardry now has partial support for externally-added tiers; you'll need to do some of the + * legwork yourself though. + * + * @param codeName The name of the enum constant in the code. This will be returned if you call toString() on the + * resulting enum constant; other than that it doesn't really make much difference. + * @param maxCharge The maximum charge for wands of this tier. + * @param upgradeLimit The maximum total number of special upgrades that can be applied to wands of this tier. + * @param weight The weight of this tier in the standard weighting. + * @param colour The colour of text associated with this tier, as a style object. + * @param name The unlocalised name of this tier, as used in translation keys. + * @return The resulting {@code Tier} enum constant. + */ + public static Tier addTier(String codeName, int maxCharge, int upgradeLimit, int weight, Style colour, String name){ + return EnumHelper.addEnum(Tier.class, codeName, TIER_ARGUMENTS, maxCharge, upgradeLimit, weight, colour, name); + } + + /** + * Wrapper for the generic method {@link EnumHelper#addEnum(Class, String, Class[], Object...)} which is + * specifically for adding new elements. Use this method in preference to the generic one in case the constructor + * parameters change for {@code Element}. + *

    + * As of version 4.2, wizardry now has full support for externally-added elements. + * + * @param codeName The name of the enum constant in the code. This will be returned if you call toString() on the + * resulting enum constant; other than that it doesn't really make much difference. + * @param colour The colour of text associated with this element, as a style object. + * @param name The unlocalised name of this element, as used in translation keys. + * @param modID The mod ID of the mod that added this element, for icon rendering purposes. + * @return The resulting {@code Element} enum constant. + */ + // This is the only one that needs the mod ID argument because elements are the only ones that have icons + // For some reason Minecraft doesn't seem to care about the resource domain for lang files, it just pools them + public static Element addElement(String codeName, Style colour, String name, String modID){ + return EnumHelper.addEnum(Element.class, codeName, ELEMENT_ARGUMENTS, colour, name, modID); + } + + /** + * Wrapper for the generic method {@link EnumHelper#addEnum(Class, String, Class[], Object...)} which is + * specifically for adding new spell types. Use this method in preference to the generic one in case the constructor + * parameters change for {@code SpellType}. + *

    + * As of version 4.2, wizardry now has full support for externally-added spell types. + * + * @param codeName The name of the enum constant in the code. This will be returned if you call toString() on the + * resulting enum constant; other than that it doesn't really make much difference. + * @param name The unlocalised name of this spell type, as used in translation keys. + * @return The resulting {@code SpellType} enum constant. + */ + public static SpellType addSpellType(String codeName, String name){ + return EnumHelper.addEnum(SpellType.class, codeName, SPELL_TYPE_ARGUMENTS, name); + } + + /** + * Wrapper for the generic method {@link EnumHelper#addEnum(Class, String, Class[], Object...)} which is + * specifically for adding new spell contexts (for use in spell property JSON files). Use this method in preference + * to the generic one in case the constructor parameters change for {@code Context}. + * + * @param codeName The name of the enum constant in the code. This will be returned if you call toString() on the + * resulting enum constant; other than that it doesn't really make much difference. + * @param name The identifier for this spell context, as used in the JSON file. + * @return The resulting {@code Context} enum constant. + */ + public static SpellProperties.Context addSpellContext(String codeName, String name){ + return EnumHelper.addEnum(SpellProperties.Context.class, codeName, SPELL_CONTEXT_ARGUMENTS, name); + } + +} diff --git a/src/main/java/electroblob/wizardry/block/BlockArcaneWorkbench.java b/src/main/java/electroblob/wizardry/block/BlockArcaneWorkbench.java index d2407cff..8e76c803 100644 --- a/src/main/java/electroblob/wizardry/block/BlockArcaneWorkbench.java +++ b/src/main/java/electroblob/wizardry/block/BlockArcaneWorkbench.java @@ -5,6 +5,7 @@ import electroblob.wizardry.WizardryGuiHandler; import electroblob.wizardry.tileentity.TileEntityArcaneWorkbench; import net.minecraft.block.BlockContainer; import net.minecraft.block.material.Material; +import net.minecraft.block.state.BlockFaceShape; import net.minecraft.block.state.IBlockState; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.inventory.InventoryHelper; @@ -51,6 +52,16 @@ public class BlockArcaneWorkbench extends BlockContainer { return false; } + @Override + public boolean isFullCube(IBlockState state){ + return false; + } + + @Override + public BlockFaceShape getBlockFaceShape(IBlockAccess world, IBlockState state, BlockPos pos, EnumFacing face){ + return face == EnumFacing.DOWN ? BlockFaceShape.SOLID : BlockFaceShape.UNDEFINED; + } + @Override public boolean onBlockActivated(World world, BlockPos pos, IBlockState block, EntityPlayer player, EnumHand hand, EnumFacing side, float hitX, float hitY, float hitZ){ diff --git a/src/main/java/electroblob/wizardry/block/BlockCrystal.java b/src/main/java/electroblob/wizardry/block/BlockCrystal.java new file mode 100644 index 00000000..2d0f4dd9 --- /dev/null +++ b/src/main/java/electroblob/wizardry/block/BlockCrystal.java @@ -0,0 +1,76 @@ +package electroblob.wizardry.block; + +import electroblob.wizardry.constants.Element; +import electroblob.wizardry.registry.WizardryTabs; +import net.minecraft.block.Block; +import net.minecraft.block.material.MapColor; +import net.minecraft.block.material.Material; +import net.minecraft.block.properties.PropertyEnum; +import net.minecraft.block.state.BlockStateContainer; +import net.minecraft.block.state.IBlockState; +import net.minecraft.creativetab.CreativeTabs; +import net.minecraft.item.ItemStack; +import net.minecraft.util.NonNullList; +import net.minecraft.util.math.BlockPos; +import net.minecraft.world.IBlockAccess; + +import java.util.EnumMap; + +public class BlockCrystal extends Block { + + public static final PropertyEnum ELEMENT = PropertyEnum.create("element", Element.class); + + private static final EnumMap map_colours = new EnumMap<>(Element.class); + + static { + map_colours.put(Element.MAGIC, MapColor.PINK); + map_colours.put(Element.FIRE, MapColor.ORANGE_STAINED_HARDENED_CLAY); + map_colours.put(Element.ICE, MapColor.LIGHT_BLUE); + map_colours.put(Element.LIGHTNING, MapColor.CYAN); + map_colours.put(Element.NECROMANCY, MapColor.PURPLE); + map_colours.put(Element.EARTH, MapColor.GREEN); + map_colours.put(Element.SORCERY, MapColor.LIME); + map_colours.put(Element.HEALING, MapColor.YELLOW); + } + + public BlockCrystal(Material material){ + super(material); + this.setDefaultState(this.blockState.getBaseState().withProperty(ELEMENT, Element.MAGIC)); + this.setCreativeTab(WizardryTabs.WIZARDRY); + this.setHarvestLevel("pickaxe", 2); + } + + @Override + public int damageDropped(IBlockState state){ + return (state.getValue(ELEMENT)).ordinal(); + } + + @Override + public MapColor getMapColor(IBlockState state, IBlockAccess world, BlockPos pos){ + return map_colours.get(state.getProperties().get(ELEMENT)); + } + + @Override + public void getSubBlocks(CreativeTabs tab, NonNullList items){ + if(this.getCreativeTab() == tab){ + for(Element element : Element.values()){ + items.add(new ItemStack(this, 1, element.ordinal())); + } + } + } + + @Override + public IBlockState getStateFromMeta(int metadata){ + return this.getDefaultState().withProperty(ELEMENT, Element.values()[metadata]); + } + + @Override + public int getMetaFromState(IBlockState state){ + return (state.getValue(ELEMENT)).ordinal(); + } + + @Override + protected BlockStateContainer createBlockState(){ + return new BlockStateContainer(this, ELEMENT); + } +} diff --git a/src/main/java/electroblob/wizardry/block/BlockCrystalFlower.java b/src/main/java/electroblob/wizardry/block/BlockCrystalFlower.java index a10aa77e..ed9a09d3 100644 --- a/src/main/java/electroblob/wizardry/block/BlockCrystalFlower.java +++ b/src/main/java/electroblob/wizardry/block/BlockCrystalFlower.java @@ -1,7 +1,5 @@ package electroblob.wizardry.block; -import java.util.Random; - import electroblob.wizardry.registry.WizardryBlocks; import electroblob.wizardry.util.ParticleBuilder; import electroblob.wizardry.util.ParticleBuilder.Type; @@ -19,6 +17,8 @@ import net.minecraftforge.event.entity.player.BonemealEvent; import net.minecraftforge.fml.common.Mod; import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; +import java.util.Random; + // Extending BlockBush allows me to remove nearly everything from this class. @Mod.EventBusSubscriber public class BlockCrystalFlower extends BlockBush { diff --git a/src/main/java/electroblob/wizardry/block/BlockCrystalOre.java b/src/main/java/electroblob/wizardry/block/BlockCrystalOre.java index 916b6564..a96c9d1a 100644 --- a/src/main/java/electroblob/wizardry/block/BlockCrystalOre.java +++ b/src/main/java/electroblob/wizardry/block/BlockCrystalOre.java @@ -1,7 +1,5 @@ package electroblob.wizardry.block; -import java.util.Random; - import electroblob.wizardry.registry.WizardryItems; import net.minecraft.block.Block; import net.minecraft.block.SoundType; @@ -13,6 +11,8 @@ import net.minecraft.util.math.MathHelper; import net.minecraft.world.IBlockAccess; import net.minecraft.world.World; +import java.util.Random; + public class BlockCrystalOre extends Block { public BlockCrystalOre(Material material){ diff --git a/src/main/java/electroblob/wizardry/block/BlockDryFrostedIce.java b/src/main/java/electroblob/wizardry/block/BlockDryFrostedIce.java new file mode 100644 index 00000000..8e80b5ae --- /dev/null +++ b/src/main/java/electroblob/wizardry/block/BlockDryFrostedIce.java @@ -0,0 +1,28 @@ +package electroblob.wizardry.block; + +import net.minecraft.block.BlockFrostedIce; +import net.minecraft.block.state.IBlockState; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.MathHelper; +import net.minecraft.world.World; + +import java.util.Random; + +/** Like {@link BlockFrostedIce}, but melting does not depend on light level or neighbouring blocks, and it just + * disappears instead of turning to water. */ +public class BlockDryFrostedIce extends BlockFrostedIce { + + @Override + protected void turnIntoWater(World world, BlockPos pos){ + world.destroyBlock(pos, false); + } + + @Override + public void updateTick(World worldIn, BlockPos pos, IBlockState state, Random rand){ + if(rand.nextInt(3) == 0){ + this.slightlyMelt(worldIn, pos, state, rand, true); + }else{ + worldIn.scheduleUpdate(pos, this, MathHelper.getInt(rand, 20, 40)); + } + } +} diff --git a/src/main/java/electroblob/wizardry/block/BlockMagicLight.java b/src/main/java/electroblob/wizardry/block/BlockMagicLight.java index 77974eec..72dd8a5e 100644 --- a/src/main/java/electroblob/wizardry/block/BlockMagicLight.java +++ b/src/main/java/electroblob/wizardry/block/BlockMagicLight.java @@ -1,23 +1,31 @@ package electroblob.wizardry.block; +import electroblob.wizardry.item.ISpellCastingItem; +import electroblob.wizardry.item.ItemArtefact; +import electroblob.wizardry.registry.WizardryItems; import electroblob.wizardry.tileentity.TileEntityMagicLight; -import net.minecraft.block.BlockContainer; +import net.minecraft.block.Block; +import net.minecraft.block.ITileEntityProvider; import net.minecraft.block.material.Material; import net.minecraft.block.state.IBlockState; +import net.minecraft.entity.player.EntityPlayer; import net.minecraft.tileentity.TileEntity; import net.minecraft.util.EnumBlockRenderType; +import net.minecraft.util.EnumFacing; +import net.minecraft.util.EnumHand; import net.minecraft.util.math.AxisAlignedBB; import net.minecraft.util.math.BlockPos; import net.minecraft.world.IBlockAccess; import net.minecraft.world.World; -public class BlockMagicLight extends BlockContainer { +public class BlockMagicLight extends Block implements ITileEntityProvider { - private static final AxisAlignedBB AABB = new AxisAlignedBB(0, 0, 0, 0, 0, 0); + //private static final AxisAlignedBB AABB = new AxisAlignedBB(0, 0, 0, 0, 0, 0); - public BlockMagicLight(Material par2Material){ - super(par2Material); + public BlockMagicLight(Material material){ + super(material); this.setLightLevel(1.0f); + this.setBlockUnbreakable(); } @Override @@ -28,13 +36,38 @@ public class BlockMagicLight extends BlockContainer { } @Override - public AxisAlignedBB getBoundingBox(IBlockState state, IBlockAccess source, BlockPos pos){ - return AABB; + public boolean onBlockActivated(World world, BlockPos pos, IBlockState state, EntityPlayer player, EnumHand hand, EnumFacing facing, float hitX, float hitY, float hitZ){ + // Let the player dispel any lights if they have the lantern charm, not just the permanent ones because that would be annoying! + if(player.getHeldItem(hand).getItem() instanceof ISpellCastingItem && ItemArtefact.isArtefactActive(player, WizardryItems.charm_light)){ + + world.setBlockToAir(pos); + return true; + + }else{ + return super.onBlockActivated(world, pos, state, player, hand, facing, hitX, hitY, hitZ); + } } +// @Override +// public AxisAlignedBB getBoundingBox(IBlockState state, IBlockAccess source, BlockPos pos){ +// return AABB; +// } + @Override public boolean isCollidable(){ - return false; + // This method has nothing to do with entity movement, it's just for raytracing + return true; + } + + @Override + public boolean addDestroyEffects(World world, BlockPos pos, net.minecraft.client.particle.ParticleManager manager){ + if(world.getBlockState(pos).getBlock() == this) return true; // No break particles! + else return super.addDestroyEffects(world, pos, manager); + } + + @Override + public boolean hasTileEntity(IBlockState state){ + return true; } @Override diff --git a/src/main/java/electroblob/wizardry/block/BlockObsidianCrust.java b/src/main/java/electroblob/wizardry/block/BlockObsidianCrust.java new file mode 100644 index 00000000..269459bc --- /dev/null +++ b/src/main/java/electroblob/wizardry/block/BlockObsidianCrust.java @@ -0,0 +1,116 @@ +package electroblob.wizardry.block; + +import net.minecraft.block.Block; +import net.minecraft.block.BlockObsidian; +import net.minecraft.block.properties.PropertyInteger; +import net.minecraft.block.state.BlockStateContainer; +import net.minecraft.block.state.IBlockState; +import net.minecraft.init.Blocks; +import net.minecraft.item.ItemStack; +import net.minecraft.util.EnumFacing; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.MathHelper; +import net.minecraft.world.World; + +import java.util.Random; + +/** Like {@link net.minecraft.block.BlockFrostedIce}, but for lava instead of water. */ +// This is mostly copied from that class, with a few changes +public class BlockObsidianCrust extends BlockObsidian { + + public static final PropertyInteger AGE = PropertyInteger.create("age", 0, 3); + + public BlockObsidianCrust(){ + this.setDefaultState(this.blockState.getBaseState().withProperty(AGE, 0)); + } + + @Override + public int getMetaFromState(IBlockState state){ + return state.getValue(AGE); + } + + @Override + public IBlockState getStateFromMeta(int meta){ + return this.getDefaultState().withProperty(AGE, MathHelper.clamp(meta, 0, 3)); + } + + @Override + public void updateTick(World world, BlockPos pos, IBlockState state, Random random){ + if((random.nextInt(3) == 0 || this.countNeighbors(world, pos) < 4) && world.getLightFromNeighbors(pos) > 11 - state.getValue(AGE) - state.getLightOpacity()){ + this.slightlyMelt(world, pos, state, random, true); + }else{ + world.scheduleUpdate(pos, this, MathHelper.getInt(random, 20, 40)); + } + } + + @Override + public void neighborChanged(IBlockState state, World world, BlockPos pos, Block block, BlockPos fromPos){ + if(block == this){ + int i = this.countNeighbors(world, pos); + + if(i < 2){ + this.melt(world, pos); + } + } + } + + private int countNeighbors(World world, BlockPos pos){ + + int i = 0; + + for(EnumFacing enumfacing : EnumFacing.values()){ + if(world.getBlockState(pos.offset(enumfacing)).getBlock() == this){ + ++i; + + if(i >= 4){ + return i; + } + } + } + + return i; + } + + protected void slightlyMelt(World world, BlockPos pos, IBlockState state, Random random, boolean meltNeighbours){ + + int i = state.getValue(AGE); + + if(i < 3){ + + world.setBlockState(pos, state.withProperty(AGE, i + 1), 2); + world.scheduleUpdate(pos, this, MathHelper.getInt(random, 20, 40)); + + }else{ + + this.melt(world, pos); + + if(meltNeighbours){ + + for(EnumFacing enumfacing : EnumFacing.values()){ + + BlockPos blockpos = pos.offset(enumfacing); + IBlockState iblockstate = world.getBlockState(blockpos); + + if(iblockstate.getBlock() == this){ + this.slightlyMelt(world, blockpos, iblockstate, random, false); + } + } + } + } + } + + protected void melt(World world, BlockPos pos){ + world.setBlockState(pos, Blocks.LAVA.getDefaultState()); + world.neighborChanged(pos, Blocks.LAVA, pos); + } + + @Override + protected BlockStateContainer createBlockState(){ + return new BlockStateContainer(this, AGE); + } + + @Override + public ItemStack getItem(World world, BlockPos pos, IBlockState state){ + return ItemStack.EMPTY; + } +} diff --git a/src/main/java/electroblob/wizardry/block/BlockPedestal.java b/src/main/java/electroblob/wizardry/block/BlockPedestal.java new file mode 100644 index 00000000..9da9c6f5 --- /dev/null +++ b/src/main/java/electroblob/wizardry/block/BlockPedestal.java @@ -0,0 +1,123 @@ +package electroblob.wizardry.block; + +import electroblob.wizardry.constants.Element; +import electroblob.wizardry.registry.WizardryTabs; +import electroblob.wizardry.tileentity.TileEntityShrineCore; +import net.minecraft.block.Block; +import net.minecraft.block.ITileEntityProvider; +import net.minecraft.block.material.MapColor; +import net.minecraft.block.material.Material; +import net.minecraft.block.properties.PropertyBool; +import net.minecraft.block.properties.PropertyEnum; +import net.minecraft.block.state.BlockStateContainer; +import net.minecraft.block.state.IBlockState; +import net.minecraft.creativetab.CreativeTabs; +import net.minecraft.entity.Entity; +import net.minecraft.item.ItemStack; +import net.minecraft.tileentity.TileEntity; +import net.minecraft.util.BlockRenderLayer; +import net.minecraft.util.NonNullList; +import net.minecraft.util.math.BlockPos; +import net.minecraft.world.Explosion; +import net.minecraft.world.IBlockAccess; +import net.minecraft.world.World; + +import javax.annotation.Nullable; +import java.util.Arrays; +import java.util.EnumMap; + +public class BlockPedestal extends Block implements ITileEntityProvider { + + public static final PropertyEnum ELEMENT = PropertyEnum.create("element", Element.class, + Arrays.copyOfRange(Element.values(), 1, Element.values().length)); // Everything except MAGIC + + // A 'natural' pedestal is one that was generated as part of a structure, is unbreakable and has a tileentity + public static final PropertyBool NATURAL = PropertyBool.create("natural"); + + private static final EnumMap map_colours = new EnumMap<>(Element.class); + + static { + map_colours.put(Element.FIRE, MapColor.RED_STAINED_HARDENED_CLAY); + map_colours.put(Element.ICE, MapColor.LIGHT_BLUE_STAINED_HARDENED_CLAY); + map_colours.put(Element.LIGHTNING, MapColor.CYAN_STAINED_HARDENED_CLAY); + map_colours.put(Element.NECROMANCY, MapColor.PURPLE_STAINED_HARDENED_CLAY); + map_colours.put(Element.EARTH, MapColor.BROWN_STAINED_HARDENED_CLAY); + map_colours.put(Element.SORCERY, MapColor.GRAY); + map_colours.put(Element.HEALING, MapColor.YELLOW_STAINED_HARDENED_CLAY); + } + + public BlockPedestal(Material material){ + super(material); + this.setDefaultState(this.blockState.getBaseState().withProperty(ELEMENT, Element.FIRE).withProperty(NATURAL, false)); + this.setCreativeTab(WizardryTabs.WIZARDRY); + this.setHardness(1.5F); + this.setResistance(10.0F); + } + + @Override + public int damageDropped(IBlockState state){ + return state.getValue(ELEMENT).ordinal(); // Ignore the NATURAL state here, it's unobtainable + } + + @Override + public MapColor getMapColor(IBlockState state, IBlockAccess world, BlockPos pos){ + return map_colours.get(state.getProperties().get(ELEMENT)); + } + + @Override + public void getSubBlocks(CreativeTabs tab, NonNullList items){ + // Ignore the NATURAL state here, it's unobtainable + if(this.getCreativeTab() == tab){ + for(Element element : Arrays.copyOfRange(Element.values(), 1, Element.values().length)){ + items.add(new ItemStack(this, 1, element.ordinal())); + } + } + } + + @Override + public BlockRenderLayer getRenderLayer(){ + return BlockRenderLayer.CUTOUT; // Required to shade parts of the block faces differently to others + } + + @Override + public float getBlockHardness(IBlockState state, World world, BlockPos pos){ + return state.getValue(NATURAL) ? -1 : super.getBlockHardness(state, world, pos); + } + + @Override + public float getExplosionResistance(World world, BlockPos pos, @Nullable Entity exploder, Explosion explosion){ + return world.getBlockState(pos).getValue(NATURAL) ? 6000000.0F : super.getExplosionResistance(world, pos, exploder, explosion); + } + + @Override + public boolean hasTileEntity(IBlockState state){ + return state.getValue(NATURAL); // Only naturally-generated pedestals have a (shrine core) tile entity + } + + @Nullable + @Override + public TileEntity createNewTileEntity(World world, int meta){ + return new TileEntityShrineCore(); + } + + @Override + public IBlockState getStateFromMeta(int metadata){ + boolean natural = false; + if(metadata > ELEMENT.getAllowedValues().size()){ + natural = true; + metadata -= ELEMENT.getAllowedValues().size(); + } + return this.getDefaultState().withProperty(ELEMENT, Element.values()[metadata]).withProperty(NATURAL, natural); + } + + @Override + public int getMetaFromState(IBlockState state){ + return state.getValue(ELEMENT).ordinal() + (state.getValue(NATURAL) ? ELEMENT.getAllowedValues().size() : 0); + } + + @Override + protected BlockStateContainer createBlockState(){ + return new BlockStateContainer(this, ELEMENT, NATURAL); + } + +} diff --git a/src/main/java/electroblob/wizardry/block/BlockRunestone.java b/src/main/java/electroblob/wizardry/block/BlockRunestone.java new file mode 100644 index 00000000..996eaa52 --- /dev/null +++ b/src/main/java/electroblob/wizardry/block/BlockRunestone.java @@ -0,0 +1,85 @@ +package electroblob.wizardry.block; + +import electroblob.wizardry.constants.Element; +import electroblob.wizardry.registry.WizardryTabs; +import net.minecraft.block.Block; +import net.minecraft.block.material.MapColor; +import net.minecraft.block.material.Material; +import net.minecraft.block.properties.PropertyEnum; +import net.minecraft.block.state.BlockStateContainer; +import net.minecraft.block.state.IBlockState; +import net.minecraft.creativetab.CreativeTabs; +import net.minecraft.item.ItemStack; +import net.minecraft.util.BlockRenderLayer; +import net.minecraft.util.NonNullList; +import net.minecraft.util.math.BlockPos; +import net.minecraft.world.IBlockAccess; + +import java.util.Arrays; +import java.util.EnumMap; + +public class BlockRunestone extends Block { + + public static final PropertyEnum ELEMENT = PropertyEnum.create("element", Element.class, + Arrays.copyOfRange(Element.values(), 1, Element.values().length)); // Everything except MAGIC + + private static final EnumMap map_colours = new EnumMap<>(Element.class); + + static { + map_colours.put(Element.FIRE, MapColor.RED_STAINED_HARDENED_CLAY); + map_colours.put(Element.ICE, MapColor.LIGHT_BLUE_STAINED_HARDENED_CLAY); + map_colours.put(Element.LIGHTNING, MapColor.CYAN_STAINED_HARDENED_CLAY); + map_colours.put(Element.NECROMANCY, MapColor.PURPLE_STAINED_HARDENED_CLAY); + map_colours.put(Element.EARTH, MapColor.BROWN_STAINED_HARDENED_CLAY); + map_colours.put(Element.SORCERY, MapColor.GRAY); + map_colours.put(Element.HEALING, MapColor.YELLOW_STAINED_HARDENED_CLAY); + } + + public BlockRunestone(Material material){ + super(material); + this.setDefaultState(this.blockState.getBaseState().withProperty(ELEMENT, Element.FIRE)); + this.setCreativeTab(WizardryTabs.WIZARDRY); + this.setHardness(1.5F); + this.setResistance(10.0F); + } + + @Override + public int damageDropped(IBlockState state){ + return state.getValue(ELEMENT).ordinal(); + } + + @Override + public MapColor getMapColor(IBlockState state, IBlockAccess world, BlockPos pos){ + return map_colours.get(state.getProperties().get(ELEMENT)); + } + + @Override + public void getSubBlocks(CreativeTabs tab, NonNullList items){ + if(this.getCreativeTab() == tab){ + for(Element element : Arrays.copyOfRange(Element.values(), 1, Element.values().length)){ + items.add(new ItemStack(this, 1, element.ordinal())); + } + } + } + + @Override + public BlockRenderLayer getRenderLayer(){ + return BlockRenderLayer.CUTOUT; // Required to shade parts of the block faces differently to others + } + + @Override + public IBlockState getStateFromMeta(int metadata){ + return this.getDefaultState().withProperty(ELEMENT, Element.values()[metadata]); + } + + @Override + public int getMetaFromState(IBlockState state){ + return state.getValue(ELEMENT).ordinal(); + } + + @Override + protected BlockStateContainer createBlockState(){ + return new BlockStateContainer(this, ELEMENT); + } + +} diff --git a/src/main/java/electroblob/wizardry/block/BlockSnare.java b/src/main/java/electroblob/wizardry/block/BlockSnare.java index 878826df..a10df677 100644 --- a/src/main/java/electroblob/wizardry/block/BlockSnare.java +++ b/src/main/java/electroblob/wizardry/block/BlockSnare.java @@ -1,13 +1,13 @@ package electroblob.wizardry.block; -import java.util.Random; - +import electroblob.wizardry.registry.Spells; +import electroblob.wizardry.spell.Spell; import electroblob.wizardry.tileentity.TileEntityPlayerSave; +import electroblob.wizardry.util.AllyDesignationSystem; import electroblob.wizardry.util.MagicDamage; import electroblob.wizardry.util.MagicDamage.DamageType; -import electroblob.wizardry.util.WizardryUtilities; import net.minecraft.block.Block; -import net.minecraft.block.BlockContainer; +import net.minecraft.block.ITileEntityProvider; import net.minecraft.block.SoundType; import net.minecraft.block.material.Material; import net.minecraft.block.state.IBlockState; @@ -25,8 +25,9 @@ import net.minecraft.util.math.BlockPos; import net.minecraft.world.IBlockAccess; import net.minecraft.world.World; -// TODO: Apparently you shouldn't extend BlockContainer. I feel like BlockArcaneWorkbench should, but what about the rest? -public class BlockSnare extends BlockContainer { +import java.util.Random; + +public class BlockSnare extends Block implements ITileEntityProvider { private static final AxisAlignedBB AABB = new AxisAlignedBB(0.0f, 0.0f, 0.0f, 1.0f, 0.0625f, 1.0f); @@ -58,10 +59,14 @@ public class BlockSnare extends BlockContainer { TileEntityPlayerSave tileentity = (TileEntityPlayerSave)world.getTileEntity(pos); - if(WizardryUtilities.isValidTarget(tileentity.getCaster(), entity)){ - ((EntityLivingBase)entity).attackEntityFrom( - MagicDamage.causeDirectMagicDamage(tileentity.getCaster(), DamageType.MAGIC), 6); - ((EntityLivingBase)entity).addPotionEffect(new PotionEffect(MobEffects.SLOWNESS, 100, 2)); + if(AllyDesignationSystem.isValidTarget(tileentity.getCaster(), entity)){ + + entity.attackEntityFrom(MagicDamage.causeDirectMagicDamage(tileentity.getCaster(), DamageType.MAGIC), + Spells.snare.getProperty(Spell.DAMAGE).floatValue()); + + ((EntityLivingBase)entity).addPotionEffect(new PotionEffect(MobEffects.SLOWNESS, + Spells.snare.getProperty(Spell.EFFECT_DURATION).intValue(), + Spells.snare.getProperty(Spell.EFFECT_STRENGTH).intValue())); world.destroyBlock(pos, false); } diff --git a/src/main/java/electroblob/wizardry/block/BlockSpectral.java b/src/main/java/electroblob/wizardry/block/BlockSpectral.java index 5724f610..fe34473a 100644 --- a/src/main/java/electroblob/wizardry/block/BlockSpectral.java +++ b/src/main/java/electroblob/wizardry/block/BlockSpectral.java @@ -1,13 +1,11 @@ package electroblob.wizardry.block; -import java.util.Random; - import electroblob.wizardry.registry.WizardryBlocks; import electroblob.wizardry.tileentity.TileEntityTimer; import electroblob.wizardry.util.ParticleBuilder; import electroblob.wizardry.util.ParticleBuilder.Type; import net.minecraft.block.Block; -import net.minecraft.block.BlockContainer; +import net.minecraft.block.ITileEntityProvider; import net.minecraft.block.SoundType; import net.minecraft.block.material.Material; import net.minecraft.block.state.IBlockState; @@ -24,10 +22,10 @@ import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; import net.minecraftforge.fml.relauncher.Side; import net.minecraftforge.fml.relauncher.SideOnly; -// For future reference - extend BlockContainer whenever possible because it has methods for removing tile entities on -// block break. +import java.util.Random; + @Mod.EventBusSubscriber -public class BlockSpectral extends BlockContainer { +public class BlockSpectral extends Block implements ITileEntityProvider { public BlockSpectral(Material material){ super(material); @@ -76,6 +74,11 @@ public class BlockSpectral extends BlockContainer { return 15; } + @Override + public boolean hasTileEntity(IBlockState state){ + return true; + } + @Override public TileEntity createNewTileEntity(World world, int metadata){ return new TileEntityTimer(1200); diff --git a/src/main/java/electroblob/wizardry/block/BlockStatue.java b/src/main/java/electroblob/wizardry/block/BlockStatue.java index 07956970..cf5b7dee 100644 --- a/src/main/java/electroblob/wizardry/block/BlockStatue.java +++ b/src/main/java/electroblob/wizardry/block/BlockStatue.java @@ -1,11 +1,9 @@ package electroblob.wizardry.block; -import java.util.Random; - import electroblob.wizardry.tileentity.TileEntityStatue; import electroblob.wizardry.util.WizardryUtilities; import net.minecraft.block.Block; -import net.minecraft.block.BlockContainer; +import net.minecraft.block.ITileEntityProvider; import net.minecraft.block.SoundType; import net.minecraft.block.material.Material; import net.minecraft.block.state.IBlockState; @@ -21,12 +19,16 @@ import net.minecraft.world.World; import net.minecraftforge.fml.relauncher.Side; import net.minecraftforge.fml.relauncher.SideOnly; -public class BlockStatue extends BlockContainer { +import java.util.Random; + +public class BlockStatue extends Block implements ITileEntityProvider { private boolean isIce; - + /** The NBT tag name for storing the petrified flag (used for rendering) in the target's tag compound. */ - public static final String NBT_KEY = "petrified"; + public static final String PETRIFIED_NBT_KEY = "petrified"; + /** The NBT tag name for storing the frozen flag (used for rendering) in the target's tag compound. */ + public static final String FROZEN_NBT_KEY = "frozen"; public BlockStatue(Material material){ super(material); @@ -110,6 +112,11 @@ public class BlockStatue extends BlockContainer { return this.isIce ? EnumBlockRenderType.MODEL : EnumBlockRenderType.ENTITYBLOCK_ANIMATED; } + @Override + public boolean hasTileEntity(IBlockState state){ + return true; + } + @Override public TileEntity createNewTileEntity(World world, int metadata){ return new TileEntityStatue(this.isIce); @@ -150,7 +157,7 @@ public class BlockStatue extends BlockContainer { // This is only when position == 1 because world.destroyBlock calls this function for the other blocks. if(tileentity != null && tileentity.position == 1 && tileentity.creature != null){ - tileentity.creature.getEntityData().removeTag(BlockStatue.NBT_KEY); + tileentity.creature.getEntityData().removeTag(BlockStatue.PETRIFIED_NBT_KEY); tileentity.creature.isDead = false; world.spawnEntity(tileentity.creature); } @@ -198,7 +205,7 @@ public class BlockStatue extends BlockContainer { ((TileEntityStatue)world.getTileEntity(pos)).setLifetime(duration); } - if(!this.isIce) entity.getEntityData().setBoolean(NBT_KEY, true); + entity.getEntityData().setBoolean(this.isIce ? FROZEN_NBT_KEY : PETRIFIED_NBT_KEY, true); entity.setDead(); return true; } @@ -216,8 +223,8 @@ public class BlockStatue extends BlockContainer { if(world.getTileEntity(pos.up()) instanceof TileEntityStatue){ ((TileEntityStatue)world.getTileEntity(pos.up())).setCreatureAndPart(entity, 2, 2); } - - if(!this.isIce) entity.getEntityData().setBoolean(NBT_KEY, true); + + entity.getEntityData().setBoolean(this.isIce ? FROZEN_NBT_KEY : PETRIFIED_NBT_KEY, true); entity.setDead(); return true; } @@ -241,8 +248,8 @@ public class BlockStatue extends BlockContainer { if(world.getTileEntity(pos.up(2)) instanceof TileEntityStatue){ ((TileEntityStatue)world.getTileEntity(pos.up(2))).setCreatureAndPart(entity, 3, 3); } - - if(!this.isIce) entity.getEntityData().setBoolean(NBT_KEY, true); + + entity.getEntityData().setBoolean(this.isIce ? FROZEN_NBT_KEY : PETRIFIED_NBT_KEY, true); entity.setDead(); return true; } diff --git a/src/main/java/electroblob/wizardry/block/BlockThorns.java b/src/main/java/electroblob/wizardry/block/BlockThorns.java new file mode 100644 index 00000000..0ceb6035 --- /dev/null +++ b/src/main/java/electroblob/wizardry/block/BlockThorns.java @@ -0,0 +1,181 @@ +package electroblob.wizardry.block; + +import electroblob.wizardry.registry.Spells; +import electroblob.wizardry.registry.WizardryBlocks; +import electroblob.wizardry.spell.Spell; +import electroblob.wizardry.tileentity.TileEntityPlayerSaveTimed; +import electroblob.wizardry.util.AllyDesignationSystem; +import electroblob.wizardry.util.MagicDamage; +import net.minecraft.block.*; +import net.minecraft.block.BlockDoublePlant.EnumBlockHalf; +import net.minecraft.block.properties.PropertyEnum; +import net.minecraft.block.properties.PropertyInteger; +import net.minecraft.block.state.BlockStateContainer; +import net.minecraft.block.state.IBlockState; +import net.minecraft.entity.Entity; +import net.minecraft.entity.EntityLivingBase; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.init.Items; +import net.minecraft.item.Item; +import net.minecraft.item.ItemStack; +import net.minecraft.tileentity.TileEntity; +import net.minecraft.util.DamageSource; +import net.minecraft.util.math.AxisAlignedBB; +import net.minecraft.util.math.BlockPos; +import net.minecraft.world.IBlockAccess; +import net.minecraft.world.World; +import net.minecraftforge.event.entity.player.PlayerInteractEvent; +import net.minecraftforge.fml.common.Mod; +import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; + +import java.util.Random; + +@Mod.EventBusSubscriber +public class BlockThorns extends BlockBush implements ITileEntityProvider { + + public static final int GROWTH_STAGES = 8; + + public static final PropertyInteger AGE = PropertyInteger.create("age", 0, GROWTH_STAGES-1); + public static final PropertyEnum HALF = PropertyEnum.create("half", EnumBlockHalf.class); + + public BlockThorns(){ + this.setDefaultState(this.blockState.getBaseState().withProperty(HALF, EnumBlockHalf.LOWER).withProperty(AGE, 7)); + this.setHardness(4); + this.setSoundType(SoundType.PLANT); + this.setCreativeTab(null); + } + + @Override + public AxisAlignedBB getBoundingBox(IBlockState state, IBlockAccess source, BlockPos pos){ + return FULL_BLOCK_AABB; + } + + @Override + public IBlockState getStateFromMeta(int meta){ + return this.getDefaultState().withProperty(HALF, EnumBlockHalf.values()[meta / GROWTH_STAGES]).withProperty(AGE, meta % GROWTH_STAGES); + } + + @Override + public int getMetaFromState(IBlockState state){ + return state.getValue(HALF).ordinal() * GROWTH_STAGES + state.getValue(AGE); + } + +// @Override +// public void updateTick(World world, BlockPos pos, IBlockState state, Random rand){ +// +// super.updateTick(world, pos, state, rand); +// +// // Update the state, including on the client, but don't do a block update since it's only visual +// if(state.getValue(AGE) < GROWTH_STAGES-1) world.setBlockState(pos, state.withProperty(AGE, state.getValue(AGE) + 1), 2); +// } + + @Override + protected BlockStateContainer createBlockState(){ + return new BlockStateContainer(this, HALF, AGE); + } + + public void placeAt(World world, BlockPos lowerPos, int flags){ + world.setBlockState(lowerPos, this.getDefaultState().withProperty(HALF, EnumBlockHalf.LOWER).withProperty(AGE, 0), flags); + world.setBlockState(lowerPos.up(), this.getDefaultState().withProperty(HALF, EnumBlockHalf.UPPER).withProperty(AGE, 0), flags); + } + + @Override + public void onBlockPlacedBy(World world, BlockPos pos, IBlockState state, EntityLivingBase placer, ItemStack stack){ + world.setBlockState(pos.up(), this.getDefaultState().withProperty(HALF, EnumBlockHalf.UPPER), 2); + } + + @Override + public void breakBlock(World world, BlockPos pos, IBlockState state){ + super.breakBlock(world, pos, state); + if(state.getValue(HALF) == EnumBlockHalf.LOWER){ + if(world.getBlockState(pos.up()).getBlock() == this){ + world.destroyBlock(pos.up(), false); + } + }else{ + if(world.getBlockState(pos.down()).getBlock() == this){ + world.destroyBlock(pos.down(), false); + } + } + } + + public boolean canBlockStay(World worldIn, BlockPos pos, IBlockState state){ + if(state.getValue(HALF) == BlockDoublePlant.EnumBlockHalf.UPPER){ + return worldIn.getBlockState(pos.down()).getBlock() == this; + }else{ + IBlockState iblockstate = worldIn.getBlockState(pos.up()); + return iblockstate.getBlock() == this && this.canSustainBush(worldIn.getBlockState(pos.down())); + } + } + +// @Override +// public IBlockState getActualState(IBlockState state, IBlockAccess world, BlockPos pos){ +// // Copied from BlockFlowerPot on authority of the Forge docs, which says this check is necessary +// SoundLoopSpellDispenser tileentity = world instanceof ChunkCache ? ((ChunkCache)world).getTileEntity(pos, Chunk.EnumCreateEntityType.CHECK) : world.getTileEntity(pos); +// +// if(tileentity instanceof TileEntityPlayerSaveTimed){ +// state = state.withProperty(AGE, Math.min(7, ((TileEntityPlayerSaveTimed)tileentity).timer/2)); +// }else{ +// state = state.withProperty(AGE, 7); +// } +// +// return state; +// } + + @Override + public void onEntityCollision(World world, BlockPos pos, IBlockState state, Entity entity){ + if(!world.isRemote){ + if(applyThornDamage(world, pos, entity)){ + entity.setInWeb(); + } + } + } + + private static boolean applyThornDamage(World world, BlockPos pos, Entity target){ + + DamageSource source = DamageSource.CACTUS; + + TileEntity tileentity = world.getTileEntity(pos); + + if(tileentity instanceof TileEntityPlayerSaveTimed){ + if(AllyDesignationSystem.isValidTarget(((TileEntityPlayerSaveTimed)tileentity).getCaster(), target)){ + source = MagicDamage.causeDirectMagicDamage(((TileEntityPlayerSaveTimed)tileentity).getCaster(), + MagicDamage.DamageType.MAGIC); + }else{ + return false; // Don't attack or slow allies of the caster + } + } + + if(world.getTotalWorldTime() % 20 == 0) target.attackEntityFrom(source, Spells.forest_of_thorns.getProperty(Spell.DAMAGE).floatValue()); + + return true; + } + + @Override + public Block.EnumOffsetType getOffsetType(){ + return Block.EnumOffsetType.XZ; + } + + @Override + public TileEntity createNewTileEntity(World world, int metadata){ + return new TileEntityPlayerSaveTimed(600); + } + + @Override + public boolean hasTileEntity(IBlockState state){ + return true; + } + + @Override public boolean isReplaceable(IBlockAccess world, BlockPos pos){ return false; } + @Override protected boolean canSustainBush(IBlockState state){ return state.isNormalCube(); } + @Override public Item getItemDropped(IBlockState state, Random rand, int fortune){ return Items.AIR; } + @Override public boolean canSilkHarvest(World world, BlockPos pos, IBlockState state, EntityPlayer player){ return false; } + + @SubscribeEvent + public static void onLeftClickBlockEvent(PlayerInteractEvent.LeftClickBlock event){ + if(!event.getWorld().isRemote && event.getWorld().getTotalWorldTime() % 20 == 0 + && event.getWorld().getBlockState(event.getPos()).getBlock() == WizardryBlocks.thorns){ + applyThornDamage(event.getWorld(), event.getPos(), event.getEntity()); + } + } + +} diff --git a/src/main/java/electroblob/wizardry/block/BlockTransportationStone.java b/src/main/java/electroblob/wizardry/block/BlockTransportationStone.java index 84c0c9c0..ea0595a1 100644 --- a/src/main/java/electroblob/wizardry/block/BlockTransportationStone.java +++ b/src/main/java/electroblob/wizardry/block/BlockTransportationStone.java @@ -1,12 +1,16 @@ package electroblob.wizardry.block; -import java.util.Random; - -import electroblob.wizardry.WizardData; import electroblob.wizardry.Wizardry; -import electroblob.wizardry.item.ItemWand; +import electroblob.wizardry.data.WizardData; +import electroblob.wizardry.item.ISpellCastingItem; +import electroblob.wizardry.item.ItemArtefact; import electroblob.wizardry.registry.Spells; import electroblob.wizardry.registry.WizardryBlocks; +import electroblob.wizardry.registry.WizardryItems; +import electroblob.wizardry.spell.Transportation; +import electroblob.wizardry.util.Location; +import electroblob.wizardry.util.ParticleBuilder; +import electroblob.wizardry.util.WizardryUtilities; import net.minecraft.block.Block; import net.minecraft.block.material.Material; import net.minecraft.block.state.IBlockState; @@ -20,6 +24,10 @@ import net.minecraft.util.text.TextComponentTranslation; import net.minecraft.world.IBlockAccess; import net.minecraft.world.World; +import java.util.ArrayList; +import java.util.List; +import java.util.Random; + public class BlockTransportationStone extends Block { private static final AxisAlignedBB AABB = new AxisAlignedBB(0.0625f * 5, 0, 0.0625f * 5, 0.0625f * 11, 0.0625f * 6, @@ -103,7 +111,7 @@ public class BlockTransportationStone extends Block { ItemStack stack = player.getHeldItem(hand); - if(stack.getItem() instanceof ItemWand){ + if(stack.getItem() instanceof ISpellCastingItem){ if(WizardData.get(player) != null){ WizardData data = WizardData.get(player); @@ -112,17 +120,59 @@ public class BlockTransportationStone extends Block { for(int z = -1; z <= 1; z++){ BlockPos pos1 = pos.add(x, 0, z); if(testForCircle(world, pos1)){ - data.setStoneCircleLocation(pos1, world.provider.getDimension()); - if(!world.isRemote) player.sendMessage( - new TextComponentTranslation("tile." + Wizardry.MODID + ":transportation_stone.confirm", - Spells.transportation.getNameForTranslationFormatted())); + + Location here = new Location(pos1, player.dimension); + + List locations = data.getVariable(Transportation.LOCATIONS_KEY); + if(locations == null) data.setVariable(Transportation.LOCATIONS_KEY, locations = new ArrayList<>(Transportation.MAX_REMEMBERED_LOCATIONS)); + + if(ItemArtefact.isArtefactActive(player, WizardryItems.charm_transportation)){ + + if(locations.contains(here)){ + locations.remove(here); + if(!world.isRemote) player.sendStatusMessage(new TextComponentTranslation("tile." + Wizardry.MODID + ":transportation_stone.forget", here.pos.getX(), here.pos.getY(), here.pos.getZ(), here.dimension), true); + + }else{ + + locations.add(here); + if(!world.isRemote) player.sendStatusMessage(new TextComponentTranslation("tile." + Wizardry.MODID + ":transportation_stone.remember", here.pos.getX(), here.pos.getY(), here.pos.getZ(), here.dimension), true); + + if(locations.size() > Transportation.MAX_REMEMBERED_LOCATIONS){ + Location removed = locations.remove(0); + if(!world.isRemote) player.sendStatusMessage(new TextComponentTranslation("tile." + Wizardry.MODID + ":transportation_stone.forget", removed.pos.getX(), removed.pos.getY(), removed.pos.getZ(), removed.dimension), true); + } + } + + }else{ + if(locations.isEmpty()) locations.add(here); + else{ + locations.remove(here); // Prevents duplicates + locations.set(locations.size() - 1, here); + } + if(!world.isRemote) player.sendStatusMessage(new TextComponentTranslation("tile." + Wizardry.MODID + ":transportation_stone.confirm", Spells.transportation.getNameForTranslationFormatted()), true); + } + return true; } } } - if(!world.isRemote) - player.sendMessage(new TextComponentTranslation("tile." + Wizardry.MODID + ":transportation_stone.invalid")); + if(!world.isRemote){ + player.sendStatusMessage(new TextComponentTranslation("tile." + Wizardry.MODID + ":transportation_stone.invalid"), true); + }else{ + + BlockPos centre = findMostLikelyCircle(world, pos); + // Displays particles in the required shape + for(int x = -1; x <= 1; x++){ + for(int z = -1; z <= 1; z++){ + if(x == 0 && z == 0) continue; + ParticleBuilder.create(ParticleBuilder.Type.PATH) + .pos(WizardryUtilities.getCentre(centre).add(x, -0.3125, z)).clr(0x86ff65) + .time(200).scale(2).spawn(world); + } + } + } + return true; } } @@ -136,12 +186,47 @@ public class BlockTransportationStone extends Block { for(int x = -1; x <= 1; x++){ for(int z = -1; z <= 1; z++){ + if(x == 0 && z == 0) continue; if(world.getBlockState(pos.add(x, 0, z)).getBlock() != WizardryBlocks.transportation_stone){ - if(x != 0 || z != 0) return false; + return false; } } } return true; } + + private static BlockPos findMostLikelyCircle(World world, BlockPos pos){ + + int bestSoFar = 0; + BlockPos result = null; + + for(int x = -1; x <= 1; x++){ + for(int z = -1; z <= 1; z++){ + if(x == 0 && z == 0) continue; + BlockPos pos1 = pos.add(x, 0, z); + int n = getCircleCompleteness(world, pos1); + if(n > bestSoFar){ + bestSoFar = n; + result = pos1; + } + } + } + + return result; + } + + private static int getCircleCompleteness(World world, BlockPos pos){ + + int n = 0; + + for(int x = -1; x <= 1; x++){ + for(int z = -1; z <= 1; z++){ + if(x == 0 && z == 0) continue; + if(world.getBlockState(pos.add(x, 0, z)).getBlock() == WizardryBlocks.transportation_stone) n++; + } + } + + return n; + } } diff --git a/src/main/java/electroblob/wizardry/block/BlockVanishingCobweb.java b/src/main/java/electroblob/wizardry/block/BlockVanishingCobweb.java index 131134db..c8532ced 100644 --- a/src/main/java/electroblob/wizardry/block/BlockVanishingCobweb.java +++ b/src/main/java/electroblob/wizardry/block/BlockVanishingCobweb.java @@ -1,9 +1,8 @@ package electroblob.wizardry.block; -import java.util.Random; - import electroblob.wizardry.tileentity.TileEntityTimer; -import net.minecraft.block.BlockContainer; +import net.minecraft.block.Block; +import net.minecraft.block.ITileEntityProvider; import net.minecraft.block.material.Material; import net.minecraft.block.state.IBlockState; import net.minecraft.entity.Entity; @@ -17,15 +16,17 @@ import net.minecraft.world.World; import net.minecraftforge.fml.relauncher.Side; import net.minecraftforge.fml.relauncher.SideOnly; -// For future reference - extend BlockContainer whenever possible because it has methods for removing tile entities on block break. -public class BlockVanishingCobweb extends BlockContainer { +import java.util.Random; + +public class BlockVanishingCobweb extends Block implements ITileEntityProvider { public BlockVanishingCobweb(Material material){ super(material); } @SideOnly(Side.CLIENT) - public BlockRenderLayer getBlockLayer(){ + @Override + public BlockRenderLayer getRenderLayer(){ return BlockRenderLayer.CUTOUT; } @@ -49,6 +50,11 @@ public class BlockVanishingCobweb extends BlockContainer { return false; } + @Override + public boolean hasTileEntity(IBlockState state){ + return true; + } + @Override public TileEntity createNewTileEntity(World world, int metadata){ return new TileEntityTimer(400); diff --git a/src/main/java/electroblob/wizardry/client/ClientProxy.java b/src/main/java/electroblob/wizardry/client/ClientProxy.java index 910938eb..ee3b2be0 100644 --- a/src/main/java/electroblob/wizardry/client/ClientProxy.java +++ b/src/main/java/electroblob/wizardry/client/ClientProxy.java @@ -1,115 +1,54 @@ package electroblob.wizardry.client; -import java.lang.ref.WeakReference; -import java.util.HashMap; -import java.util.Map; - -import org.lwjgl.input.Keyboard; - import electroblob.wizardry.CommonProxy; -import electroblob.wizardry.SpellGlyphData; -import electroblob.wizardry.WizardData; import electroblob.wizardry.Wizardry; +import electroblob.wizardry.client.audio.MovingSoundEntity; +import electroblob.wizardry.client.audio.SoundLoop; +import electroblob.wizardry.client.audio.SoundLoopSpell; import electroblob.wizardry.client.gui.GuiSpellDisplay; -import electroblob.wizardry.client.gui.GuiWizardHandbook; +import electroblob.wizardry.client.gui.config.NamedBooleanEntry; +import electroblob.wizardry.client.gui.config.SpellHUDSkinChooserEntry; +import electroblob.wizardry.client.gui.handbook.GuiWizardHandbook; import electroblob.wizardry.client.model.ModelWizardArmour; import electroblob.wizardry.client.particle.*; import electroblob.wizardry.client.particle.ParticleWizardry.IWizardryParticleFactory; -import electroblob.wizardry.client.renderer.LayerStone; -import electroblob.wizardry.client.renderer.RenderArcaneWorkbench; -import electroblob.wizardry.client.renderer.RenderBlackHole; -import electroblob.wizardry.client.renderer.RenderBlank; -import electroblob.wizardry.client.renderer.RenderBubble; -import electroblob.wizardry.client.renderer.RenderDecay; -import electroblob.wizardry.client.renderer.RenderDecoy; -import electroblob.wizardry.client.renderer.RenderEvilWizard; -import electroblob.wizardry.client.renderer.RenderFireRing; -import electroblob.wizardry.client.renderer.RenderForceArrow; -import electroblob.wizardry.client.renderer.RenderHammer; -import electroblob.wizardry.client.renderer.RenderIceGiant; -import electroblob.wizardry.client.renderer.RenderIceSpike; -import electroblob.wizardry.client.renderer.RenderLightningDisc; -import electroblob.wizardry.client.renderer.RenderMagicArrow; -import electroblob.wizardry.client.renderer.RenderMagicLight; -import electroblob.wizardry.client.renderer.RenderPhoenix; -import electroblob.wizardry.client.renderer.RenderProjectile; -import electroblob.wizardry.client.renderer.RenderSigil; -import electroblob.wizardry.client.renderer.RenderSpiritHorse; -import electroblob.wizardry.client.renderer.RenderSpiritWolf; -import electroblob.wizardry.client.renderer.RenderStatue; -import electroblob.wizardry.client.renderer.RenderWizard; +import electroblob.wizardry.client.renderer.*; +import electroblob.wizardry.command.SpellEmitter; +import electroblob.wizardry.data.DispenserCastingData; +import electroblob.wizardry.data.SpellEmitterData; +import electroblob.wizardry.data.SpellGlyphData; +import electroblob.wizardry.data.WizardData; import electroblob.wizardry.entity.EntityShield; -import electroblob.wizardry.entity.construct.EntityArrowRain; -import electroblob.wizardry.entity.construct.EntityBlackHole; -import electroblob.wizardry.entity.construct.EntityBlizzard; -import electroblob.wizardry.entity.construct.EntityBubble; -import electroblob.wizardry.entity.construct.EntityDecay; -import electroblob.wizardry.entity.construct.EntityEarthquake; -import electroblob.wizardry.entity.construct.EntityFireRing; -import electroblob.wizardry.entity.construct.EntityFireSigil; -import electroblob.wizardry.entity.construct.EntityForcefield; -import electroblob.wizardry.entity.construct.EntityFrostSigil; -import electroblob.wizardry.entity.construct.EntityHailstorm; -import electroblob.wizardry.entity.construct.EntityHammer; -import electroblob.wizardry.entity.construct.EntityHealAura; -import electroblob.wizardry.entity.construct.EntityIceSpike; -import electroblob.wizardry.entity.construct.EntityLightningSigil; -import electroblob.wizardry.entity.construct.EntityTornado; -import electroblob.wizardry.entity.living.EntityDecoy; -import electroblob.wizardry.entity.living.EntityEvilWizard; -import electroblob.wizardry.entity.living.EntityIceGiant; -import electroblob.wizardry.entity.living.EntityIceWraith; -import electroblob.wizardry.entity.living.EntityLightningWraith; -import electroblob.wizardry.entity.living.EntityPhoenix; -import electroblob.wizardry.entity.living.EntityShadowWraith; -import electroblob.wizardry.entity.living.EntitySpiritHorse; -import electroblob.wizardry.entity.living.EntitySpiritWolf; -import electroblob.wizardry.entity.living.EntityStormElemental; -import electroblob.wizardry.entity.living.EntityWizard; -import electroblob.wizardry.entity.living.ISpellCaster; -import electroblob.wizardry.entity.living.ISummonedCreature; -import electroblob.wizardry.entity.projectile.EntityDarknessOrb; -import electroblob.wizardry.entity.projectile.EntityDart; -import electroblob.wizardry.entity.projectile.EntityFirebolt; -import electroblob.wizardry.entity.projectile.EntityFirebomb; -import electroblob.wizardry.entity.projectile.EntityForceArrow; -import electroblob.wizardry.entity.projectile.EntityForceOrb; -import electroblob.wizardry.entity.projectile.EntityIceCharge; -import electroblob.wizardry.entity.projectile.EntityIceLance; -import electroblob.wizardry.entity.projectile.EntityIceShard; -import electroblob.wizardry.entity.projectile.EntityLightningArrow; -import electroblob.wizardry.entity.projectile.EntityLightningDisc; -import electroblob.wizardry.entity.projectile.EntityMagicMissile; -import electroblob.wizardry.entity.projectile.EntityPoisonBomb; -import electroblob.wizardry.entity.projectile.EntitySmokeBomb; -import electroblob.wizardry.entity.projectile.EntitySpark; -import electroblob.wizardry.entity.projectile.EntitySparkBomb; -import electroblob.wizardry.entity.projectile.EntityThunderbolt; +import electroblob.wizardry.entity.construct.*; +import electroblob.wizardry.entity.living.*; +import electroblob.wizardry.entity.projectile.*; import electroblob.wizardry.event.SpellCastEvent; import electroblob.wizardry.event.SpellCastEvent.Source; +import electroblob.wizardry.integration.antiqueatlas.WizardryAntiqueAtlasIntegration; import electroblob.wizardry.item.ItemScroll; import electroblob.wizardry.item.ItemSpellBook; import electroblob.wizardry.item.ItemWand; -import electroblob.wizardry.packet.PacketCastContinuousSpell; -import electroblob.wizardry.packet.PacketCastSpell; -import electroblob.wizardry.packet.PacketNPCCastSpell; -import electroblob.wizardry.packet.PacketPlayerSync.Message; -import electroblob.wizardry.packet.PacketTransportation; +import electroblob.wizardry.packet.*; +import electroblob.wizardry.potion.PotionSlowTime; import electroblob.wizardry.registry.Spells; -import electroblob.wizardry.spell.Clairvoyance; -import electroblob.wizardry.spell.None; -import electroblob.wizardry.spell.Spell; +import electroblob.wizardry.registry.WizardrySounds; +import electroblob.wizardry.spell.*; import electroblob.wizardry.tileentity.TileEntityArcaneWorkbench; import electroblob.wizardry.tileentity.TileEntityMagicLight; +import electroblob.wizardry.tileentity.TileEntityShrineCore; import electroblob.wizardry.tileentity.TileEntityStatue; import electroblob.wizardry.util.ParticleBuilder; import electroblob.wizardry.util.ParticleBuilder.Type; import electroblob.wizardry.util.WandHelper; import net.minecraft.block.state.IBlockState; import net.minecraft.client.Minecraft; +import net.minecraft.client.entity.EntityPlayerSP; import net.minecraft.client.gui.FontRenderer; +import net.minecraft.client.gui.GuiMerchant; import net.minecraft.client.model.ModelBiped; import net.minecraft.client.renderer.entity.RenderBlaze; +import net.minecraft.client.renderer.entity.RenderHusk; +import net.minecraft.client.renderer.entity.RenderSkeleton; import net.minecraft.client.resources.I18n; import net.minecraft.client.resources.IReloadableResourceManager; import net.minecraft.client.resources.IResourceManager; @@ -119,19 +58,33 @@ import net.minecraft.entity.EntityLiving; import net.minecraft.entity.EntityLivingBase; import net.minecraft.entity.monster.EntityBlaze; import net.minecraft.entity.player.EntityPlayer; -import net.minecraft.init.SoundEvents; +import net.minecraft.inventory.ContainerMerchant; import net.minecraft.item.Item; import net.minecraft.item.ItemStack; +import net.minecraft.tileentity.TileEntity; +import net.minecraft.tileentity.TileEntityDispenser; import net.minecraft.util.EnumParticleTypes; import net.minecraft.util.ResourceLocation; +import net.minecraft.util.SoundCategory; import net.minecraft.util.SoundEvent; import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.MathHelper; +import net.minecraft.util.text.Style; +import net.minecraft.util.text.TextComponentTranslation; +import net.minecraft.village.MerchantRecipeList; import net.minecraft.world.World; import net.minecraftforge.common.MinecraftForge; import net.minecraftforge.common.config.Property; import net.minecraftforge.fml.client.config.GuiConfigEntries.NumberSliderEntry; import net.minecraftforge.fml.client.registry.ClientRegistry; import net.minecraftforge.fml.client.registry.RenderingRegistry; +import org.lwjgl.input.Keyboard; + +import java.lang.ref.WeakReference; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Set; /** * The client proxy for wizardry. @@ -145,7 +98,7 @@ public class ClientProxy extends CommonProxy { public static MixedFontRenderer mixedFontRenderer; /** Static particle factory map */ - private static Map factories; + private static final Map factories = new HashMap<>(); // Key Bindings public static final KeyBinding NEXT_SPELL = new KeyBinding("key." + Wizardry.MODID + ".next_spell", Keyboard.KEY_N, "key.categories." + Wizardry.MODID); @@ -154,6 +107,9 @@ public class ClientProxy extends CommonProxy { // Armour Model public static final ModelBiped WIZARD_ARMOUR_MODEL = new ModelWizardArmour(0.75f); + /** The wrap width for standard multi-line descriptions (see {@link ClientProxy#addMultiLineDescription(List, String, Style)}). */ + private static final int TOOLTIP_WRAP_WIDTH = 140; + // SECTION Registry // =============================================================================================================== @@ -178,9 +134,18 @@ public class ClientProxy extends CommonProxy { public void registerResourceReloadListeners(){ IResourceManager manager = Minecraft.getMinecraft().getResourceManager(); if(manager instanceof IReloadableResourceManager){ - ((IReloadableResourceManager)manager).registerReloadListener(GuiSpellDisplay::loadSkins); - ((IReloadableResourceManager)manager).registerReloadListener(GuiWizardHandbook::loadHandbookFile); - } + ((IReloadableResourceManager)manager).registerReloadListener(GuiSpellDisplay::loadSkins); + ((IReloadableResourceManager)manager).registerReloadListener(GuiWizardHandbook::loadHandbookFile); + } + } + +// @Override +// public void registerSoundEventListener(){ +// Minecraft.getMinecraft().getSoundHandler().addListener(ContinuousSpellSoundEntity::soundPlayed); +// } + + public void registerAtlasMarkers(){ + WizardryAntiqueAtlasIntegration.registerMarkers(); } // SECTION Misc @@ -196,16 +161,35 @@ public class ClientProxy extends CommonProxy { property.setConfigEntryClass(SpellHUDSkinChooserEntry.class); } + @Override + public void setToNamedBooleanEntry(Property property){ + property.setConfigEntryClass(NamedBooleanEntry.class); + } + @Override public World getTheWorld(){ return Minecraft.getMinecraft().world; } @Override - public void playMovingSound(Entity entity, SoundEvent sound, float volume, float pitch, boolean repeat){ - Minecraft.getMinecraft().getSoundHandler().playSound(new MovingSoundEntity(entity, sound, volume, pitch, repeat)); + public void playMovingSound(Entity entity, SoundEvent sound, SoundCategory category, float volume, float pitch, boolean repeat){ + Minecraft.getMinecraft().getSoundHandler().playSound(new MovingSoundEntity<>(entity, sound, category, volume, pitch, repeat)); } + @Override + public void playSpellSoundLoop(EntityLivingBase entity, Spell spell, SoundEvent start, SoundEvent loop, SoundEvent end, SoundCategory category, float volume, float pitch){ + SoundLoop.addLoop(new SoundLoopSpell.SoundLoopSpellEntity(start, loop, end, spell, entity, volume, pitch)); + } + + @Override + public void playSpellSoundLoop(World world, double x, double y, double z, Spell spell, SoundEvent start, SoundEvent loop, SoundEvent end, SoundCategory category, float volume, float pitch, int duration){ + if(duration == -1){ + SoundLoop.addLoop(new SoundLoopSpell.SoundLoopSpellDispenser(start, loop, end, spell, world, x, y, z, volume, pitch)); + }else{ + SoundLoop.addLoop(new SoundLoopSpell.SoundLoopSpellPosTimed(start, loop, end, spell, duration, x, y, z, volume, pitch)); + } + } + @Override public Set getSpellHUDSkins(){ return GuiSpellDisplay.getSkinKeys(); @@ -214,6 +198,40 @@ public class ClientProxy extends CommonProxy { // SECTION Items // =============================================================================================================== + @Override + public boolean shouldDisplayDiscovered(Spell spell, ItemStack stack){ + + EntityPlayerSP player = Minecraft.getMinecraft().player; + + if(player == null) return false; + + // Displayed recipe + if(Minecraft.getMinecraft().currentScreen instanceof GuiMerchant){ + // It doesn't actually matter if the recipe is selected or not, since the itemstack will only ever + // match one of them anyway - and we'd have to reflect into GuiMerchant to get the selected recipe + MerchantRecipeList recipes = ((GuiMerchant)Minecraft.getMinecraft().currentScreen).getMerchant().getRecipes(player); + if(recipes != null && recipes.stream().anyMatch(r -> r.getItemToSell() == stack)){ + // Spell books are always discovered when wizards are selling them + return true; + } + } + + // Recipe output slot + // Required or players would be able to find out what the spell is without actually completing the trade + if(player.openContainer instanceof ContainerMerchant){ + + if(((ContainerMerchant)player.openContainer).getMerchantInventory().getStackInSlot(2) == stack){ + return true; + } + } + + if(!Wizardry.settings.discoveryMode) return true; + if(player.isCreative()) return true; + if(WizardData.get(player) != null && WizardData.get(player).hasSpellBeenDiscovered(spell)) return true; + + return false; + } + @Override public FontRenderer getFontRenderer(ItemStack stack){ @@ -222,12 +240,10 @@ public class ClientProxy extends CommonProxy { if(stack.getItem() instanceof ItemWand){ spell = WandHelper.getCurrentSpell(stack); }else if(stack.getItem() instanceof ItemSpellBook || stack.getItem() instanceof ItemScroll){ - spell = Spell.get(stack.getItemDamage()); + spell = Spell.byMetadata(stack.getItemDamage()); } - if(Minecraft.getMinecraft().player != null && Wizardry.settings.discoveryMode && WizardData.get(Minecraft.getMinecraft().player) != null - && !Minecraft.getMinecraft().player.capabilities.isCreativeMode - && !WizardData.get(Minecraft.getMinecraft().player).hasSpellBeenDiscovered(spell)){ + if(!shouldDisplayDiscovered(spell, stack)){ return mixedFontRenderer; } @@ -237,14 +253,14 @@ public class ClientProxy extends CommonProxy { @Override public String getScrollDisplayName(ItemStack scroll){ - Spell spell = Spell.get(scroll.getItemDamage()); + Spell spell = Spell.byMetadata(scroll.getItemDamage()); EntityPlayer player = Minecraft.getMinecraft().player; boolean discovered = true; // It seems that this method is called when the world is loading, before thePlayer has been initialised. // If the player is null, the spell is assumed to be discovered. - if(player != null && Wizardry.settings.discoveryMode && !player.capabilities.isCreativeMode && WizardData.get(player) != null + if(player != null && Wizardry.settings.discoveryMode && !player.isCreative() && WizardData.get(player) != null && !WizardData.get(player).hasSpellBeenDiscovered(spell)){ discovered = false; } @@ -265,37 +281,50 @@ public class ClientProxy extends CommonProxy { return super.getConjuredBowDurability(stack); } + @Override + public void addMultiLineDescription(List tooltip, String key, Style style){ + String description = style.getFormattingCode() + I18n.format(key); + tooltip.addAll(Minecraft.getMinecraft().fontRenderer.listFormattedStringToWidth(description, TOOLTIP_WRAP_WIDTH)); + } + // SECTION Particles // =============================================================================================================== + /** Use {@link ParticleWizardry#registerParticle(ResourceLocation, IWizardryParticleFactory)}, this is internal. */ + // I mean, it does exactly the same thing but I might want to make it do something else in future... + public static void addParticleFactory(ResourceLocation name, IWizardryParticleFactory factory){ + factories.put(name, factory); + } + @Override - public void initParticleFactories(){ - - factories = new HashMap<>(); - - factories.put(Type.BEAM, ParticleBeam::new); - factories.put(Type.BUFF, ParticleBuff::new); - factories.put(Type.DARK_MAGIC, ParticleDarkMagic::new); - factories.put(Type.DUST, ParticleDust::new); - factories.put(Type.FLASH, ParticleFlash::new); - factories.put(Type.ICE, ParticleIce::new); - factories.put(Type.LEAF, ParticleLeaf::new); - factories.put(Type.LIGHTNING, ParticleLightning::new); - factories.put(Type.LIGHTNING_PULSE, ParticleLightningPulse::new); - factories.put(Type.MAGIC_BUBBLE, ParticleMagicBubble::new); - factories.put(Type.MAGIC_FIRE, ParticleMagicFlame::new); - factories.put(Type.PATH, ParticlePath::new); - factories.put(Type.SCORCH, ParticleScorch::new); - factories.put(Type.SNOW, ParticleSnow::new); - factories.put(Type.SPARK, ParticleSpark::new); - factories.put(Type.SPARKLE, ParticleSparkle::new); + public void registerParticles(){ + // I'll be a good programmer and use the API method rather than the one above. Lead by example, as they say... + ParticleWizardry.registerParticle(Type.BEAM, ParticleBeam::new); + ParticleWizardry.registerParticle(Type.BUFF, ParticleBuff::new); + ParticleWizardry.registerParticle(Type.DARK_MAGIC, ParticleDarkMagic::new); + ParticleWizardry.registerParticle(Type.DUST, ParticleDust::new); + ParticleWizardry.registerParticle(Type.FLASH, ParticleFlash::new); + ParticleWizardry.registerParticle(Type.ICE, ParticleIce::new); + ParticleWizardry.registerParticle(Type.LEAF, ParticleLeaf::new); + ParticleWizardry.registerParticle(Type.LIGHTNING, ParticleLightning::new); + ParticleWizardry.registerParticle(Type.LIGHTNING_PULSE, ParticleLightningPulse::new); + ParticleWizardry.registerParticle(Type.MAGIC_BUBBLE, ParticleMagicBubble::new); + ParticleWizardry.registerParticle(Type.MAGIC_FIRE, ParticleMagicFlame::new); + ParticleWizardry.registerParticle(Type.PATH, ParticlePath::new); + ParticleWizardry.registerParticle(Type.SCORCH, ParticleScorch::new); + ParticleWizardry.registerParticle(Type.SNOW, ParticleSnow::new); + ParticleWizardry.registerParticle(Type.SPARK, ParticleSpark::new); + ParticleWizardry.registerParticle(Type.SPARKLE, ParticleSparkle::new); + ParticleWizardry.registerParticle(Type.SPHERE, ParticleSphere::new); + ParticleWizardry.registerParticle(Type.SUMMON, ParticleSummon::new); + ParticleWizardry.registerParticle(Type.VINE, ParticleVine::new); } @Override - public ParticleWizardry createParticle(Type type, World world, double x, double y, double z){ + public ParticleWizardry createParticle(ResourceLocation type, World world, double x, double y, double z){ IWizardryParticleFactory factory = factories.get(type); if(factory == null){ - Wizardry.logger.warn("Unrecognised particle type %s ! Ensure the particle is properly registered.", type); + Wizardry.logger.warn("Unrecognised particle type {} ! Ensure the particle is properly registered.", type); return null; } return factory.createParticle(world, x, y, z); @@ -315,14 +344,12 @@ public class ClientProxy extends CommonProxy { World world = Minecraft.getMinecraft().world; Entity caster = world.getEntityByID(message.casterID); - Spell spell = Spell.get(message.spellID); + Spell spell = Spell.byNetworkID(message.spellID); // Should always be true if(caster instanceof EntityPlayer){ ((EntityPlayer)caster).setActiveHand(message.hand); - // Duration isn't needed because it only ever affects things server-side, and anything that is - // seen client-side gets synced elsewhere. spell.cast(world, (EntityPlayer)caster, message.hand, 0, message.modifiers); Source source = Source.OTHER; @@ -337,19 +364,34 @@ public class ClientProxy extends CommonProxy { // No need to check if the spell succeeded, because the packet is only ever sent when it succeeds. // The handler for this event now deals with discovery. - MinecraftForge.EVENT_BUS.post(new SpellCastEvent.Post((EntityPlayer)caster, spell, message.modifiers, source)); + MinecraftForge.EVENT_BUS.post(new SpellCastEvent.Post(source, spell, (EntityPlayer)caster, message.modifiers)); }else{ Wizardry.logger.warn("Recieved a PacketCastSpell, but the caster ID was not the ID of a player"); } } + @Override + public void handleCastSpellAtPosPacket(PacketCastSpellAtPos.Message message){ + + World world = Minecraft.getMinecraft().world; + Spell spell = Spell.byNetworkID(message.spellID); + + spell.cast(world, message.position.x, message.position.y, message.position.z, message.direction, 0, message.duration, message.modifiers); + + MinecraftForge.EVENT_BUS.post(new SpellCastEvent.Post(Source.COMMAND, spell, world, message.position.x, message.position.y, message.position.z, message.direction, message.modifiers)); + + if(spell.isContinuous){ + SpellEmitter.add(spell, world, message.position.x, message.position.y, message.position.z, message.direction, message.duration, message.modifiers); + } + } + @Override public void handleCastContinuousSpellPacket(PacketCastContinuousSpell.Message message){ World world = Minecraft.getMinecraft().world; Entity caster = world.getEntityByID(message.casterID); - Spell spell = Spell.get(message.spellID); + Spell spell = Spell.byNetworkID(message.spellID); // Should always be true if(caster instanceof EntityPlayer){ @@ -359,7 +401,7 @@ public class ClientProxy extends CommonProxy { if(data.isCasting()){ WizardData.get((EntityPlayer)caster).stopCastingContinuousSpell(); }else{ - WizardData.get((EntityPlayer)caster).startCastingContinuousSpell(spell, message.modifiers); + WizardData.get((EntityPlayer)caster).startCastingContinuousSpell(spell, message.modifiers, message.duration); } } }else{ @@ -373,7 +415,7 @@ public class ClientProxy extends CommonProxy { World world = Minecraft.getMinecraft().world; Entity caster = world.getEntityByID(message.casterID); Entity target = message.targetID == -1 ? null : world.getEntityByID(message.targetID); - Spell spell = Spell.get(message.spellID); + Spell spell = Spell.byNetworkID(message.spellID); // Should always be true if(caster instanceof EntityLiving){ @@ -382,7 +424,7 @@ public class ClientProxy extends CommonProxy { spell.cast(world, (EntityLiving)caster, message.hand, 0, (EntityLivingBase)target, message.modifiers); // Again, no need to check if the spell succeeded, because the packet is only ever sent when it // succeeds. - MinecraftForge.EVENT_BUS.post(new SpellCastEvent.Post((EntityLiving)caster, spell, message.modifiers, Source.NPC)); + MinecraftForge.EVENT_BUS.post(new SpellCastEvent.Post(Source.NPC, spell, (EntityLiving)caster, message.modifiers)); } if(caster instanceof ISpellCaster){ @@ -391,10 +433,41 @@ public class ClientProxy extends CommonProxy { ((EntityLiving)caster).setAttackTarget((EntityLivingBase)target); } } - }else{ + }else if(caster != null){ Wizardry.logger.warn("Recieved a PacketNPCCastSpell, but the caster ID was not the ID of an EntityLiving"); } } + + @Override + public void handleDispenserCastSpellPacket(PacketDispenserCastSpell.Message message){ + + World world = Minecraft.getMinecraft().world; + + if(world.getTileEntity(message.pos) instanceof TileEntityDispenser){ // Should always be true + + Spell spell = Spell.byNetworkID(message.spellID); + + spell.cast(world, message.x, message.y, message.z, message.direction, 0, -1, message.modifiers); + // No need to check if the spell succeeded, because the packet is only ever sent when it succeeds. + MinecraftForge.EVENT_BUS.post(new SpellCastEvent.Post(Source.DISPENSER, spell, world, message.x, message.y, + message.z, message.direction, message.modifiers)); + + if(spell.isContinuous || spell instanceof None){ + + DispenserCastingData data = DispenserCastingData.get((TileEntityDispenser)world.getTileEntity(message.pos)); + + if(spell.isContinuous){ + data.startCasting(spell, message.x, message.y, message.z, message.duration, message.modifiers); + }else{ + data.stopCasting(); + } + } + + }else{ + Wizardry.logger.warn("Recieved a PacketDispenserCastSpell, but no tileEntity was found at the supplied location."); + } + + } @Override public void handleTransportationPacket(PacketTransportation.Message message){ @@ -402,78 +475,150 @@ public class ClientProxy extends CommonProxy { World world = Minecraft.getMinecraft().world; Entity caster = world.getEntityByID(message.casterID); // Moved from when the packet is sent to when it is received; fixes the sound not playing in first person. - caster.playSound(SoundEvents.BLOCK_PORTAL_TRAVEL, 1, 1); + caster.playSound(WizardrySounds.SPELL_TRANSPORTATION_TRAVEL, 1, 1); for(int i = 0; i < 20; i++){ double radius = 1; - double angle = world.rand.nextDouble() * Math.PI * 2; - double x = caster.posX + radius * Math.cos(angle); + float angle = world.rand.nextFloat() * (float)Math.PI * 2; + double x = caster.posX + radius * MathHelper.cos(angle); double y = caster.getEntityBoundingBox().minY + world.rand.nextDouble() * 2; - double z = caster.posZ + radius * Math.sin(angle); + double z = caster.posZ + radius * MathHelper.sin(angle); ParticleBuilder.create(Type.SPARKLE).pos(x, y, z).vel(0, 0.02, 0).clr(0.6f, 1, 0.6f) .time(80 + world.rand.nextInt(10)).spawn(world); } for(int i = 0; i < 20; i++){ double radius = 1; - double angle = world.rand.nextDouble() * Math.PI * 2; - double x = caster.posX + radius * Math.cos(angle); + float angle = world.rand.nextFloat() * (float)Math.PI * 2; + double x = caster.posX + radius * MathHelper.cos(angle); double y = caster.getEntityBoundingBox().minY + world.rand.nextDouble() * 2; - double z = caster.posZ + radius * Math.sin(angle); + double z = caster.posZ + radius * MathHelper.sin(angle); world.spawnParticle(EnumParticleTypes.VILLAGER_HAPPY, x, y, z, 0, 0.02, 0); } for(int i = 0; i < 20; i++){ double radius = 1; - double angle = world.rand.nextDouble() * Math.PI * 2; - double x = caster.posX + radius * Math.cos(angle); + float angle = world.rand.nextFloat() * (float)Math.PI * 2; + double x = caster.posX + radius * MathHelper.cos(angle); double y = caster.getEntityBoundingBox().minY + world.rand.nextDouble() * 2; - double z = caster.posZ + radius * Math.sin(angle); + double z = caster.posZ + radius * MathHelper.sin(angle); world.spawnParticle(EnumParticleTypes.ENCHANTMENT_TABLE, x, y, z, 0, 0.02, 0); } } @Override - public void handlePlayerSyncPacket(Message message){ + public void handlePlayerSyncPacket(PacketPlayerSync.Message message){ - WizardData properties = WizardData.get(Minecraft.getMinecraft().player); + WizardData data = WizardData.get(Minecraft.getMinecraft().player); - if(properties != null){ + if(data != null){ - properties.spellsDiscovered = message.spellsDiscovered; + data.synchronisedRandom.setSeed(message.seed); + data.spellsDiscovered = message.spellsDiscovered; + + message.spellData.forEach(data::setVariable); if(message.selectedMinionID == -1){ - properties.selectedMinion = null; + data.selectedMinion = null; }else{ Entity entity = Minecraft.getMinecraft().world.getEntityByID(message.selectedMinionID); if(entity instanceof ISummonedCreature){ - properties.selectedMinion = new WeakReference((ISummonedCreature)entity); + data.selectedMinion = new WeakReference<>((ISummonedCreature)entity); }else{ - properties.selectedMinion = null; + data.selectedMinion = null; } } } } @Override - public void handleGlyphDataPacket(electroblob.wizardry.packet.PacketGlyphData.Message message){ + public void handleGlyphDataPacket(PacketGlyphData.Message message){ SpellGlyphData data = SpellGlyphData.get(Minecraft.getMinecraft().world); - data.randomNames = new HashMap(); - data.randomDescriptions = new HashMap(); + data.randomNames = new HashMap<>(); + data.randomDescriptions = new HashMap<>(); for(Spell spell : Spell.getSpells(Spell.allSpells)){ // -1 because the none spell isn't included - data.randomNames.put(spell, message.names.get(spell.id() - 1)); - data.randomDescriptions.put(spell, message.descriptions.get(spell.id() - 1)); + // This is a case where we must use the network ID, not the metadata + data.randomNames.put(spell, message.names.get(spell.networkID() - 1)); + data.randomDescriptions.put(spell, message.descriptions.get(spell.networkID() - 1)); } } @Override - public void handleClairvoyancePacket(electroblob.wizardry.packet.PacketClairvoyance.Message message){ + public void handleEmitterDataPacket(PacketEmitterData.Message message){ + message.emitters.forEach(e -> e.setWorld(Minecraft.getMinecraft().world)); // Do this as soon as possible! + SpellEmitterData data = SpellEmitterData.get(Minecraft.getMinecraft().world); + // We shouldn't need to clear the emitters because when a player logs in or changes dimension the client world + // is wiped anyway, so the call to get() above should result in a fresh SpellEmitterData instance + message.emitters.forEach(data::add); + } + + @Override + public void handleClairvoyancePacket(PacketClairvoyance.Message message){ Clairvoyance.spawnPathPaticles(Minecraft.getMinecraft().world, message.path, message.durationMultiplier); } + @Override + public void handleAdvancementSyncPacket(PacketSyncAdvancements.Message message){ + GuiWizardHandbook.updateUnlockStatus(message.showToasts, message.completedAdvancements); + } + + @Override + public void handleEndSlowTimePacket(PacketEndSlowTime.Message message){ + Entity entity = Minecraft.getMinecraft().world.getEntityByID(message.hostID); + if(entity instanceof EntityLivingBase) PotionSlowTime.unblockNearbyEntities((EntityLivingBase)entity); + else Wizardry.logger.warn("Received a PacketEndSlowTime, but the entity ID did not match any living entity"); + } + + @Override + public void handleResurrectionPacket(PacketResurrection.Message message){ + Entity entity = Minecraft.getMinecraft().world.getEntityByID(message.playerID); + if(entity instanceof EntityPlayer){ + ((Resurrection)Spells.resurrection).resurrect((EntityPlayer)entity); + if(entity == Minecraft.getMinecraft().player){ + Minecraft.getMinecraft().world.spawnEntity(entity); + Minecraft.getMinecraft().displayGuiScreen(null); + } + } + else Wizardry.logger.warn("Received a PacketResurrection, but the entity ID did not match any player"); + } + + @Override + public void handlePossessionPacket(PacketPossession.Message message){ + + Entity entity = Minecraft.getMinecraft().world.getEntityByID(message.playerID); + + if(entity instanceof EntityPlayer){ + + EntityPlayer player = (EntityPlayer)entity; + + if(message.targetID == -1){ + ((Possession)Spells.possession).endPossession(player); + }else{ + Entity target = Minecraft.getMinecraft().world.getEntityByID(message.targetID); + if(target instanceof EntityLiving){ + ((Possession)Spells.possession).possess(player, (EntityLiving)target, message.duration); + player.sendStatusMessage(new TextComponentTranslation("spell." + Spells.possession.getRegistryName() + + ".success", Minecraft.getMinecraft().gameSettings.keyBindSneak.getDisplayName()), true); + } + else Wizardry.logger.warn("Received a PacketPossession, but the target ID did not match any living entity"); + } + } + else Wizardry.logger.warn("Received a PacketPossession, but the player ID did not match any player"); + } + + public void handleConquerShrinePacket(PacketConquerShrine.Message message){ + + TileEntity tileEntity = Minecraft.getMinecraft().world.getTileEntity(new BlockPos(message.x, message.y, message.z)); + + if(tileEntity instanceof TileEntityShrineCore){ + ((TileEntityShrineCore)tileEntity).conquer(); + + }else Wizardry.logger.warn("Received a PacketConquerShrine, but there was no shrine core at the position sent"); + } + // SECTION Rendering // =============================================================================================================== @@ -486,6 +631,7 @@ public class ClientProxy extends CommonProxy { @Override public void initialiseLayers(){ LayerStone.initialiseLayers(); + LayerFrost.initialiseLayers(); } @Override @@ -495,6 +641,12 @@ public class ClientProxy extends CommonProxy { // Yet another advantage to the new system: turns out you don't even need to register the renderer if you // just want the vanilla one for the mob you're extending. + // Luckily for us, the vanilla husk renderer is only parametrised to EntityZombie + RenderingRegistry.registerEntityRenderingHandler(EntityHuskMinion.class, RenderHusk::new); + // This now extends AbstractSkeleton so we need to bind the renderer ourselves + RenderingRegistry.registerEntityRenderingHandler(EntitySkeletonMinion.class, RenderSkeleton::new); + RenderingRegistry.registerEntityRenderingHandler(EntityStrayMinion.class, RenderStrayMinion::new); + // An anonymous class in a lambda expression! No point writing a separate class really, is there? RenderingRegistry.registerEntityRenderingHandler(EntityLightningWraith.class, manager -> new RenderBlaze(manager){ @Override @@ -536,7 +688,7 @@ public class ClientProxy extends CommonProxy { // Throwables RenderingRegistry.registerEntityRenderingHandler(EntitySparkBomb.class, - manager -> new RenderProjectile(manager, 0.6f, new ResourceLocation(Wizardry.MODID, "textures/entity/spark_bomb.png"), false)); + manager -> new RenderProjectile(manager, 0.6f, new ResourceLocation(Wizardry.MODID, "textures/items/spark_bomb.png"), false)); RenderingRegistry.registerEntityRenderingHandler(EntityFirebomb.class, manager -> new RenderProjectile(manager, 0.6f, new ResourceLocation(Wizardry.MODID, "textures/items/firebomb.png"), false)); RenderingRegistry.registerEntityRenderingHandler(EntityPoisonBomb.class, @@ -555,6 +707,14 @@ public class ClientProxy extends CommonProxy { manager -> new RenderLightningDisc(manager, new ResourceLocation(Wizardry.MODID, "textures/entity/lightning_sigil.png"), 2.0f)); RenderingRegistry.registerEntityRenderingHandler(EntitySmokeBomb.class, manager -> new RenderProjectile(manager, 0.6f, new ResourceLocation(Wizardry.MODID, "textures/items/smoke_bomb.png"), false)); + RenderingRegistry.registerEntityRenderingHandler(EntityEmber.class, + manager -> new RenderProjectile(manager, 0.15f, new ResourceLocation(Wizardry.MODID, "textures/entity/ember.png"), false)); + RenderingRegistry.registerEntityRenderingHandler(EntityMagicFireball.class, + manager -> new RenderProjectile(manager, 0.7f, new ResourceLocation(Wizardry.MODID, "textures/entity/fireball.png"), false)); + RenderingRegistry.registerEntityRenderingHandler(EntityLargeMagicFireball.class, + manager -> new RenderProjectile(manager, 1.5f, new ResourceLocation(Wizardry.MODID, "textures/entity/fireball.png"), false)); + RenderingRegistry.registerEntityRenderingHandler(EntityIceball.class, + manager -> new RenderProjectile(manager, 0.7f, new ResourceLocation(Wizardry.MODID, "textures/entity/iceball.png"), false)); // Effects and constructs RenderingRegistry.registerEntityRenderingHandler(EntityBlackHole.class, RenderBlackHole::new); @@ -562,13 +722,14 @@ public class ClientProxy extends CommonProxy { RenderingRegistry.registerEntityRenderingHandler(EntityBubble.class, RenderBubble::new); RenderingRegistry.registerEntityRenderingHandler(EntityHammer.class, RenderHammer::new); RenderingRegistry.registerEntityRenderingHandler(EntityIceSpike.class, RenderIceSpike::new); + RenderingRegistry.registerEntityRenderingHandler(EntityForcefield.class, RenderForcefield::new); + //RenderingRegistry.registerEntityRenderingHandler(EntityContainmentField.class, RenderContainmentField::new); // Stuff that doesn't render RenderingRegistry.registerEntityRenderingHandler(EntityBlizzard.class, RenderBlank::new); RenderingRegistry.registerEntityRenderingHandler(EntityTornado.class, RenderBlank::new); RenderingRegistry.registerEntityRenderingHandler(EntityArrowRain.class, RenderBlank::new); RenderingRegistry.registerEntityRenderingHandler(EntityShadowWraith.class, RenderBlank::new); - RenderingRegistry.registerEntityRenderingHandler(EntityForcefield.class, RenderBlank::new); RenderingRegistry.registerEntityRenderingHandler(EntityThunderbolt.class, RenderBlank::new); RenderingRegistry.registerEntityRenderingHandler(EntityStormElemental.class, RenderBlank::new); RenderingRegistry.registerEntityRenderingHandler(EntityEarthquake.class, RenderBlank::new); @@ -586,6 +747,8 @@ public class ClientProxy extends CommonProxy { RenderingRegistry.registerEntityRenderingHandler(EntityFireRing.class, manager -> new RenderFireRing(manager, new ResourceLocation(Wizardry.MODID, "textures/entity/ring_of_fire.png"), 5.0f)); RenderingRegistry.registerEntityRenderingHandler(EntityDecay.class, RenderDecay::new); + RenderingRegistry.registerEntityRenderingHandler(EntityCombustionRune.class, + manager -> new RenderSigil(manager, new ResourceLocation(Wizardry.MODID, "textures/entity/combustion_rune.png"), 2.0f, true)); // TESRs ClientRegistry.bindTileEntitySpecialRenderer(TileEntityArcaneWorkbench.class, new RenderArcaneWorkbench()); diff --git a/src/main/java/electroblob/wizardry/client/DrawingUtils.java b/src/main/java/electroblob/wizardry/client/DrawingUtils.java index 382fba75..20b99a60 100644 --- a/src/main/java/electroblob/wizardry/client/DrawingUtils.java +++ b/src/main/java/electroblob/wizardry/client/DrawingUtils.java @@ -1,19 +1,13 @@ package electroblob.wizardry.client; -import org.lwjgl.opengl.GL11; - import net.minecraft.client.Minecraft; import net.minecraft.client.gui.FontRenderer; import net.minecraft.client.gui.inventory.GuiContainer; -import net.minecraft.client.renderer.BufferBuilder; -import net.minecraft.client.renderer.GlStateManager; -import net.minecraft.client.renderer.RenderHelper; -import net.minecraft.client.renderer.RenderItem; -import net.minecraft.client.renderer.Tessellator; +import net.minecraft.client.renderer.*; import net.minecraft.client.renderer.vertex.DefaultVertexFormats; import net.minecraft.item.ItemStack; -import net.minecraftforge.fml.relauncher.Side; -import net.minecraftforge.fml.relauncher.SideOnly; +import net.minecraft.util.math.MathHelper; +import org.lwjgl.opengl.GL11; /** * Utility class containing some useful static methods for drawing GUIs. Previously these were spread across the main @@ -23,7 +17,7 @@ import net.minecraftforge.fml.relauncher.SideOnly; * @since Wizardry 4.2 * @see MixedFontRenderer */ -@SideOnly(Side.CLIENT) +//@SideOnly(Side.CLIENT) public final class DrawingUtils { /** @@ -130,6 +124,31 @@ public final class DrawingUtils { tessellator.draw(); } + /** + * Mixes the two given opaque colours in the proportion specified. + * @param colour1 The first colour to mix, as a 6-digit hexadecimal. + * @param colour2 The second colour to mix, as a 6-digit hexadecimal. + * @param proportion The proportion of the second colour; will be clamped to between 0 and 1. + * @return The resulting colour, as a 6-digit hexadecimal. + */ + public static int mix(int colour1, int colour2, float proportion){ + + proportion = MathHelper.clamp(proportion, 0, 1); + + int r1 = colour1 >> 16 & 255; + int g1 = colour1 >> 8 & 255; + int b1 = colour1 & 255; + int r2 = colour2 >> 16 & 255; + int g2 = colour2 >> 8 & 255; + int b2 = colour2 & 255; + + int r = (int)(r1 + (r2-r1) * proportion); + int g = (int)(g1 + (g2-g1) * proportion); + int b = (int)(b1 + (b2-b1) * proportion); + + return (r << 16) + (g << 8) + b; + } + /** * Makes the given opaque colour translucent with the given opacity. * @param colour An integer colour code, should be a 6-digit hexadecimal (i.e. opaque). diff --git a/src/main/java/electroblob/wizardry/client/MixedFontRenderer.java b/src/main/java/electroblob/wizardry/client/MixedFontRenderer.java index ee098490..ff637a1c 100644 --- a/src/main/java/electroblob/wizardry/client/MixedFontRenderer.java +++ b/src/main/java/electroblob/wizardry/client/MixedFontRenderer.java @@ -5,15 +5,13 @@ import net.minecraft.client.gui.FontRenderer; import net.minecraft.client.renderer.texture.TextureManager; import net.minecraft.client.settings.GameSettings; import net.minecraft.util.ResourceLocation; -import net.minecraftforge.fml.relauncher.Side; -import net.minecraftforge.fml.relauncher.SideOnly; /** * Font renderer that renders parts of strings surrounded by '#' (without quotes) in the SGA instead of normal text. * * @since Wizardry 1.1 */ -@SideOnly(Side.CLIENT) +//@SideOnly(Side.CLIENT) public class MixedFontRenderer extends FontRenderer { public MixedFontRenderer(GameSettings p_i1035_1_, ResourceLocation p_i1035_2_, TextureManager p_i1035_3_, diff --git a/src/main/java/electroblob/wizardry/client/MovingSoundEntity.java b/src/main/java/electroblob/wizardry/client/MovingSoundEntity.java deleted file mode 100644 index 0fdd1165..00000000 --- a/src/main/java/electroblob/wizardry/client/MovingSoundEntity.java +++ /dev/null @@ -1,52 +0,0 @@ -package electroblob.wizardry.client; - -import net.minecraft.client.audio.MovingSound; -import net.minecraft.entity.Entity; -import net.minecraft.util.SoundCategory; -import net.minecraft.util.SoundEvent; -import net.minecraft.util.math.MathHelper; -import net.minecraftforge.fml.relauncher.Side; -import net.minecraftforge.fml.relauncher.SideOnly; - -// Copied from MovingSoundMinecart; if it ever breaks between updates take a look at that. -@SideOnly(Side.CLIENT) -public class MovingSoundEntity extends MovingSound { - private final Entity source; - private float distance = 0.0F; - - public MovingSoundEntity(Entity entity, SoundEvent sound, float volume, float pitch, boolean repeat){ - // Uses BLOCKS because that's the closest thing to inanimate entities. Could use NEUTRAL like - // MovingSoundMinecart. - super(sound, SoundCategory.BLOCKS); - this.source = entity; - this.repeat = repeat; - this.volume = volume; - this.pitch = pitch; - this.repeatDelay = 0; - } - - /** - * Updates the JList with a new model. - */ - @Override - public void update(){ - if(this.source.isDead && repeat){ - this.donePlaying = true; - }else{ - this.xPosF = (float)this.source.posX; - this.yPosF = (float)this.source.posY; - this.zPosF = (float)this.source.posZ; - float f = MathHelper.sqrt(this.source.motionX * this.source.motionX - + this.source.motionY * this.source.motionY + this.source.motionZ * this.source.motionZ); - - // Is this something to do with the Doppler effect? - if((double)f >= 0.01D){ - this.distance = MathHelper.clamp(this.distance + 0.0025F, 0.0F, 1.0F); - this.volume = 0.0F + MathHelper.clamp(f, 0.0F, 0.5F) * 0.7F; - }else{ - // this.pitch = 0.0F; - // this.volume = 0.0F; - } - } - } -} \ No newline at end of file diff --git a/src/main/java/electroblob/wizardry/client/WizardryClientEventHandler.java b/src/main/java/electroblob/wizardry/client/WizardryClientEventHandler.java index b06ef376..a024f95e 100644 --- a/src/main/java/electroblob/wizardry/client/WizardryClientEventHandler.java +++ b/src/main/java/electroblob/wizardry/client/WizardryClientEventHandler.java @@ -1,51 +1,52 @@ package electroblob.wizardry.client; -import org.lwjgl.opengl.GL11; - -import electroblob.wizardry.WizardData; import electroblob.wizardry.Wizardry; +import electroblob.wizardry.block.BlockMagicLight; import electroblob.wizardry.constants.Constants; +import electroblob.wizardry.data.DispenserCastingData; +import electroblob.wizardry.data.SpellEmitterData; +import electroblob.wizardry.data.WizardData; +import electroblob.wizardry.item.ISpellCastingItem; +import electroblob.wizardry.item.ItemArtefact; import electroblob.wizardry.item.ItemSpectralBow; -import electroblob.wizardry.item.ItemWand; +import electroblob.wizardry.registry.Spells; import electroblob.wizardry.registry.WizardryItems; import electroblob.wizardry.registry.WizardryPotions; -import electroblob.wizardry.spell.Flight; -import electroblob.wizardry.spell.ShadowWard; -import electroblob.wizardry.spell.Shield; -import electroblob.wizardry.tileentity.ContainerArcaneWorkbench; -import electroblob.wizardry.util.WandHelper; +import electroblob.wizardry.spell.*; +import electroblob.wizardry.util.RayTracer; import electroblob.wizardry.util.WizardryUtilities; import net.minecraft.client.Minecraft; import net.minecraft.client.gui.GuiMerchant; -import net.minecraft.client.gui.inventory.GuiContainer; import net.minecraft.client.renderer.BufferBuilder; import net.minecraft.client.renderer.GlStateManager; import net.minecraft.client.renderer.OpenGlHelper; -import net.minecraft.client.renderer.RenderHelper; -import net.minecraft.client.renderer.RenderItem; import net.minecraft.client.renderer.Tessellator; import net.minecraft.client.renderer.entity.RenderManager; import net.minecraft.client.renderer.vertex.DefaultVertexFormats; +import net.minecraft.client.settings.KeyBinding; +import net.minecraft.entity.EntityLiving; import net.minecraft.entity.EntityLivingBase; +import net.minecraft.entity.SharedMonsterAttributes; +import net.minecraft.entity.ai.attributes.AttributeModifier; import net.minecraft.entity.item.EntityArmorStand; -import net.minecraft.entity.player.EntityPlayer; import net.minecraft.inventory.Slot; import net.minecraft.item.ItemStack; +import net.minecraft.tileentity.TileEntity; +import net.minecraft.tileentity.TileEntityDispenser; import net.minecraft.util.ResourceLocation; import net.minecraft.util.math.RayTraceResult; +import net.minecraft.util.math.Vec3d; import net.minecraft.village.MerchantRecipe; -import net.minecraftforge.client.event.FOVUpdateEvent; -import net.minecraftforge.client.event.GuiContainerEvent; -import net.minecraftforge.client.event.RenderGameOverlayEvent; -import net.minecraftforge.client.event.RenderLivingEvent; -import net.minecraftforge.client.event.RenderPlayerEvent; -import net.minecraftforge.client.event.RenderWorldLastEvent; -import net.minecraftforge.client.event.TextureStitchEvent; -import net.minecraftforge.event.entity.living.LivingEvent.LivingUpdateEvent; +import net.minecraft.world.World; +import net.minecraftforge.client.event.*; import net.minecraftforge.fml.common.Mod; +import net.minecraftforge.fml.common.ObfuscationReflectionHelper; import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; +import net.minecraftforge.fml.common.gameevent.TickEvent; import net.minecraftforge.fml.relauncher.Side; -import net.minecraftforge.fml.relauncher.SideOnly; +import org.lwjgl.opengl.GL11; + +import java.lang.reflect.Method; /** * Event handler responsible for client-side only events, mostly rendering. @@ -53,13 +54,10 @@ import net.minecraftforge.fml.relauncher.SideOnly; * @author Electroblob * @since Wizardry 1.0 */ -@SideOnly(Side.CLIENT) +//@SideOnly(Side.CLIENT) @Mod.EventBusSubscriber(Side.CLIENT) public final class WizardryClientEventHandler { - private static final ResourceLocation shieldTexture = new ResourceLocation(Wizardry.MODID, "textures/entity/shield.png"); - private static final ResourceLocation wingTexture = new ResourceLocation(Wizardry.MODID, "textures/entity/wing.png"); - private static final ResourceLocation shadowWardTexture = new ResourceLocation(Wizardry.MODID, "textures/entity/shadow_ward.png"); private static final ResourceLocation sixthSenseTexture = new ResourceLocation(Wizardry.MODID, "textures/entity/sixth_sense.png"); private static final ResourceLocation sixthSenseOverlayTexture = new ResourceLocation(Wizardry.MODID, "textures/gui/sixth_sense_overlay.png"); private static final ResourceLocation frostOverlayTexture = new ResourceLocation(Wizardry.MODID, "textures/gui/frost_overlay.png"); @@ -73,6 +71,12 @@ public final class WizardryClientEventHandler { private static int blinkEffectTimer; /** The number of ticks the blink effect lasts for. */ private static final int BLINK_EFFECT_DURATION = 8; + + private static final Method unpressKey; + + static { + unpressKey = ObfuscationReflectionHelper.findMethod(KeyBinding.class, "func_74505_d", void.class); + } /** Starts the first person blink overlay effect. */ public static void playBlinkEffect(){ @@ -80,21 +84,97 @@ public final class WizardryClientEventHandler { } @SubscribeEvent - public static void onLivingUpdateEvent(LivingUpdateEvent event){ - if(event.getEntity() == Minecraft.getMinecraft().player){ + public static void onPlayerTickEvent(TickEvent.PlayerTickEvent event){ + + if(event.player == Minecraft.getMinecraft().player){ + if(blinkEffectTimer > 0) blinkEffectTimer--; + + // Only seems to work here... +// EntityLiving victim = Possession.getPossessee(Minecraft.getMinecraft().player); +// if(victim != null && victim.getHeldItemMainhand().isEmpty()){ +// Minecraft.getMinecraft().player.setHeldItem(EnumHand.MAIN_HAND, ItemStack.EMPTY); +// } + + // Reset shaders if their respective potions aren't active + // This is a player so the potion effects are synced by vanilla + if(Minecraft.getMinecraft().entityRenderer.getShaderGroup() != null){ + + String activeShader = Minecraft.getMinecraft().entityRenderer.getShaderGroup().getShaderGroupName(); + + if((activeShader.equals(SlowTime.SHADER.toString()) && !Minecraft.getMinecraft().player.isPotionActive(WizardryPotions.slow_time)) + || (activeShader.equals(SixthSense.SHADER.toString()) && !Minecraft.getMinecraft().player.isPotionActive(WizardryPotions.sixth_sense)) + || (activeShader.equals(Transience.SHADER.toString()) && !Minecraft.getMinecraft().player.isPotionActive(WizardryPotions.transience))){ + + if(activeShader.equals(SixthSense.SHADER.toString()) + || activeShader.equals(Transience.SHADER.toString())) playBlinkEffect(); + + Minecraft.getMinecraft().entityRenderer.stopUseShader(); + } + } } } @SubscribeEvent - public static void onTextureStitchEvent(TextureStitchEvent.Pre event){ + public static void onRenderHandEvent(RenderHandEvent event){ - event.getMap().registerSprite(ContainerArcaneWorkbench.EMPTY_SLOT_CRYSTAL); - event.getMap().registerSprite(ContainerArcaneWorkbench.EMPTY_SLOT_UPGRADE); + EntityLiving victim = Possession.getPossessee(Minecraft.getMinecraft().player); -// for(int i=0; i<7; i++){ -// event.getMap().registerSprite(new ResourceLocation(Wizardry.MODID, "particle/ice_" + i)); -// } + if(victim != null){ + + victim.rotationYawHead = Minecraft.getMinecraft().player.rotationYaw; + + if(Minecraft.getMinecraft().player.getHeldItemMainhand().isEmpty()){ + event.setCanceled(true); + } + } + } + + // This event is called every tick, not just when a movement key is pressed + @SubscribeEvent + public static void onInputUpdateEvent(InputUpdateEvent event){ + // Prevents the player moving when paralysed + if(event.getEntityPlayer().isPotionActive(WizardryPotions.paralysis)){ + event.getMovementInput().moveForward = 0; + event.getMovementInput().moveStrafe = 0; + event.getMovementInput().jump = false; + event.getMovementInput().sneak = false; + } + } + + @SubscribeEvent + public static void onClientTickEvent(TickEvent.ClientTickEvent event){ + + if(event.phase == TickEvent.Phase.END && !net.minecraft.client.Minecraft.getMinecraft().isGamePaused()){ + + World world = net.minecraft.client.Minecraft.getMinecraft().world; + + if(world == null) return; + + for(TileEntity tileentity : world.loadedTileEntityList){ + if(tileentity instanceof TileEntityDispenser){ + if(DispenserCastingData.get((TileEntityDispenser)tileentity) != null){ + DispenserCastingData.get((TileEntityDispenser)tileentity).update(); + } + } + } + + SpellEmitterData.update(world); + } + } + + @SubscribeEvent + public static void onMouseEvent(MouseEvent event){ + + // Prevents the player looking around when paralysed + if(Minecraft.getMinecraft().player.isPotionActive(WizardryPotions.paralysis) + && Minecraft.getMinecraft().inGameHasFocus){ + event.setCanceled(true); + Minecraft.getMinecraft().player.prevRotationYaw = 0; + Minecraft.getMinecraft().player.prevRotationPitch = 0; + Minecraft.getMinecraft().player.rotationYaw = 0; + Minecraft.getMinecraft().player.rotationPitch = 0; + } } @SubscribeEvent @@ -121,11 +201,26 @@ public final class WizardryClientEventHandler { event.setNewfov(event.getFov() + f * f * 0.7f); } } - + + @SubscribeEvent + public static void onDrawBlockHighlightEvent(DrawBlockHighlightEvent event){ + // Hide the block outline for magic light blocks unless the player can dispel them + if(event.getTarget().typeOfHit == RayTraceResult.Type.BLOCK + && event.getPlayer().world.getBlockState(event.getTarget().getBlockPos()).getBlock() instanceof BlockMagicLight){ + + if((!(event.getPlayer().getHeldItemMainhand().getItem() instanceof ISpellCastingItem) + && !(event.getPlayer().getHeldItemOffhand().getItem() instanceof ISpellCastingItem)) + || !ItemArtefact.isArtefactActive(event.getPlayer(), WizardryItems.charm_light)){ + + event.setCanceled(true); + } + } + } + // Brute-force fix for crystals not showing up when a wizard is given a spell book in the trade GUI. @SubscribeEvent public static void onGuiDrawForegroundEvent(GuiContainerEvent.DrawForeground event){ - + if(event.getGuiContainer() instanceof GuiMerchant){ GuiMerchant gui = (GuiMerchant)event.getGuiContainer(); @@ -138,81 +233,35 @@ public final class WizardryClientEventHandler { for(MerchantRecipe trade : gui.getMerchant().getRecipes(Minecraft.getMinecraft().player)){ if(trade.getItemToBuy().getItem() == WizardryItems.spell_book && trade.getSecondItemToBuy().isEmpty()){ Slot slot = gui.inventorySlots.getSlot(2); - // Uses reflection to draw the itemstack // It still doesn't look quite right because the slot highlight is behind the item, but it'll do // until/unless I find a better solution. - renderItemAndTooltip(gui, trade.getItemToSell(), slot.xPos, slot.yPos, event.getMouseX(), event.getMouseY(), + DrawingUtils.drawItemAndTooltip(gui, trade.getItemToSell(), slot.xPos, slot.yPos, event.getMouseX(), event.getMouseY(), gui.getSlotUnderMouse() == slot); } } } } } - - private static void renderItemAndTooltip(GuiContainer gui, ItemStack stack, int x, int y, int mouseX, int mouseY, boolean tooltip){ - - RenderItem renderItem = Minecraft.getMinecraft().getRenderItem(); - GlStateManager.pushMatrix(); - RenderHelper.enableGUIStandardItemLighting(); - GlStateManager.disableLighting(); - GlStateManager.enableRescaleNormal(); - GlStateManager.enableColorMaterial(); - GlStateManager.enableLighting(); - renderItem.zLevel = 100.0F; - - if(!stack.isEmpty()){ - renderItem.renderItemAndEffectIntoGUI(stack, x, y); - renderItem.renderItemOverlays(Minecraft.getMinecraft().fontRenderer, stack, x, y); - - if(tooltip){ - gui.drawHoveringText(gui.getItemToolTip(stack), mouseX + gui.getXSize()/2 - gui.width/2, - mouseY + gui.getYSize()/2 - gui.height/2); - } - } - - GlStateManager.popMatrix(); - GlStateManager.enableLighting(); - GlStateManager.enableDepth(); - RenderHelper.enableStandardItemLighting(); - } - - // Third person - @SubscribeEvent - public static void onRenderPlayerEvent(RenderPlayerEvent.Post event){ - renderShieldIfActive(event.getEntityPlayer()); - renderWingsIfActive(event.getEntityPlayer(), event.getPartialRenderTick()); - renderShadowWardIfActive(event.getEntityPlayer()); - } - - // First person - @SubscribeEvent - public static void onRenderWorldLastEvent(RenderWorldLastEvent event){ - // Now only fires in first person. - if(Minecraft.getMinecraft().gameSettings.thirdPersonView == 0){ - renderShieldFirstPerson(Minecraft.getMinecraft().player); - renderShadowWardFirstPerson(Minecraft.getMinecraft().player); - } - } @SubscribeEvent public static void onRenderLivingEvent(RenderLivingEvent.Post event){ Minecraft mc = Minecraft.getMinecraft(); - WizardData properties = WizardData.get(mc.player); + WizardData data = WizardData.get(mc.player); RenderManager renderManager = event.getRenderer().getRenderManager(); ItemStack wand = mc.player.getHeldItemMainhand(); - if(!(wand.getItem() instanceof ItemWand)){ + if(!(wand.getItem() instanceof ISpellCastingItem)){ wand = mc.player.getHeldItemOffhand(); } // Target selection pointer - if(mc.player.isSneaking() && wand.getItem() instanceof ItemWand && WizardryUtilities.isLiving(event.getEntity()) - && properties != null && properties.selectedMinion != null){ + if(mc.player.isSneaking() && wand.getItem() instanceof ISpellCastingItem && WizardryUtilities.isLiving(event.getEntity()) + && data != null && data.selectedMinion != null){ // -> Moved this in here so it isn't called every tick - RayTraceResult rayTrace = WizardryUtilities.standardEntityRayTrace(mc.world, mc.player, 16, false); + RayTraceResult rayTrace = RayTracer.standardEntityRayTrace(mc.world, mc.player, 16, false); if(rayTrace != null && rayTrace.entityHit == event.getEntity()){ @@ -256,7 +305,7 @@ public final class WizardryClientEventHandler { } // Summoned creature selection pointer - if(properties != null && properties.selectedMinion != null && properties.selectedMinion.get() == event.getEntity()){ + if(data != null && data.selectedMinion != null && data.selectedMinion.get() == event.getEntity()){ Tessellator tessellator = Tessellator.getInstance(); BufferBuilder buffer = tessellator.getBuffer(); @@ -297,8 +346,9 @@ public final class WizardryClientEventHandler { } // Sixth sense - if(mc.player.isPotionActive(WizardryPotions.sixth_sense) && !(event.getEntity() instanceof EntityArmorStand) && event.getEntity() != mc.player - && mc.player.getActivePotionEffect(WizardryPotions.sixth_sense) != null && event.getEntity().getDistance(mc.player) < 20 + if(mc.player.isPotionActive(WizardryPotions.sixth_sense) && !(event.getEntity() instanceof EntityArmorStand) + && event.getEntity() != mc.player && mc.player.getActivePotionEffect(WizardryPotions.sixth_sense) != null + && event.getEntity().getDistance(mc.player) < Spells.sixth_sense.getProperty(Spell.EFFECT_RADIUS).floatValue() * (1 + mc.player.getActivePotionEffect(WizardryPotions.sixth_sense).getAmplifier() * Constants.RANGE_INCREASE_PER_LEVEL)){ Tessellator tessellator = Tessellator.getInstance(); @@ -413,322 +463,4 @@ public final class WizardryClientEventHandler { GlStateManager.popMatrix(); } - // FIXME: Something in here is making the first person shadow ward rather translucent. - private static void renderShadowWardFirstPerson(EntityPlayer entityplayer){ - ItemStack wand = entityplayer.getActiveItemStack(); - if(WizardData.get(entityplayer) != null && WizardData.get(entityplayer).currentlyCasting() instanceof ShadowWard - || (entityplayer.isHandActive() && wand.getItemDamage() < wand.getMaxDamage() && wand.getItem() instanceof ItemWand - && WandHelper.getCurrentSpell(wand) instanceof ShadowWard)){ - - GlStateManager.pushMatrix(); - - GlStateManager.enableBlend(); - GlStateManager.blendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA); - GlStateManager.shadeModel(GL11.GL_SMOOTH); - GlStateManager.disableLighting(); - GlStateManager.disableAlpha(); - OpenGlHelper.setLightmapTextureCoords(OpenGlHelper.lightmapTexUnit, 240f, 240f); - - GlStateManager.translate(0, 1.2, 0); - GlStateManager.rotate(-entityplayer.rotationYaw, 0, 1, 0); - GlStateManager.rotate(entityplayer.rotationPitch, 1, 0, 0); - - Minecraft.getMinecraft().renderEngine.bindTexture(shadowWardTexture); - - GlStateManager.pushMatrix(); - - GlStateManager.translate(0, 0, 1.2); - GlStateManager.rotate(entityplayer.world.getWorldTime() * -2, 0, 0, 1); - GlStateManager.scale(1.1, 1.1, 1.1); - - Tessellator tessellator = Tessellator.getInstance(); - BufferBuilder buffer = tessellator.getBuffer(); - - buffer.begin(GL11.GL_QUADS, DefaultVertexFormats.POSITION_TEX); - - buffer.pos(-0.5, 0.5, -0.5).tex(0, 0).endVertex(); - buffer.pos(0.5, 0.5, -0.5).tex(1, 0).endVertex(); - buffer.pos(0.5, -0.5, -0.5).tex(1, 1).endVertex(); - buffer.pos(-0.5, -0.5, -0.5).tex(0, 1).endVertex(); - - tessellator.draw(); - - buffer.begin(GL11.GL_QUADS, DefaultVertexFormats.POSITION_TEX); - - buffer.pos(-0.5, 0.5, -0.5).tex(0, 0).endVertex(); - buffer.pos(-0.5, -0.5, -0.5).tex(0, 1).endVertex(); - buffer.pos(0.5, -0.5, -0.5).tex(1, 1).endVertex(); - buffer.pos(0.5, 0.5, -0.5).tex(1, 0).endVertex(); - - tessellator.draw(); - - GlStateManager.popMatrix(); - - GlStateManager.shadeModel(GL11.GL_FLAT); - GlStateManager.enableLighting(); - GlStateManager.disableBlend(); - - GlStateManager.popMatrix(); - - } - } - - private static void renderShadowWardIfActive(EntityPlayer entityplayer){ - ItemStack wand = entityplayer.getActiveItemStack(); - if(WizardData.get(entityplayer).currentlyCasting() instanceof ShadowWard - || (entityplayer.isHandActive() && wand.getItemDamage() < wand.getMaxDamage() && wand.getItem() instanceof ItemWand - && WandHelper.getCurrentSpell(wand) instanceof ShadowWard)){ - - GlStateManager.pushMatrix(); - - GlStateManager.enableBlend(); - GlStateManager.blendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA); - GlStateManager.disableLighting(); - OpenGlHelper.setLightmapTextureCoords(OpenGlHelper.lightmapTexUnit, 240f, 240f); - - GlStateManager.rotate(180, 0, 1, 0); - GlStateManager.rotate(-entityplayer.renderYawOffset, 0, 1, 0); - - Minecraft.getMinecraft().renderEngine.bindTexture(shadowWardTexture); - - Tessellator tessellator = Tessellator.getInstance(); - BufferBuilder buffer = tessellator.getBuffer(); - - GlStateManager.translate(0, 1.2, 0); - GlStateManager.rotate(entityplayer.world.getWorldTime() * -2, 0, 0, 1); - GlStateManager.scale(1.1, 1.1, 1.1); - - buffer.begin(GL11.GL_QUADS, DefaultVertexFormats.POSITION_TEX); - - buffer.pos(-0.5, 0.5, -0.5).tex(0, 0).endVertex(); - buffer.pos(0.5, 0.5, -0.5).tex(1, 0).endVertex(); - buffer.pos(0.5, -0.5, -0.5).tex(1, 1).endVertex(); - buffer.pos(-0.5, -0.5, -0.5).tex(0, 1).endVertex(); - - tessellator.draw(); - - buffer.begin(GL11.GL_QUADS, DefaultVertexFormats.POSITION_TEX); - - buffer.pos(-0.5, 0.5, -0.5).tex(0, 0).endVertex(); - buffer.pos(-0.5, -0.5, -0.5).tex(0, 1).endVertex(); - buffer.pos(0.5, -0.5, -0.5).tex(1, 1).endVertex(); - buffer.pos(0.5, 0.5, -0.5).tex(1, 0).endVertex(); - - tessellator.draw(); - - GlStateManager.enableLighting(); - GlStateManager.disableBlend(); - - GlStateManager.popMatrix(); - - } - } - - private static void renderWingsIfActive(EntityPlayer entityplayer, float partialTickTime){ - ItemStack wand = entityplayer.getActiveItemStack(); - if(WizardData.get(entityplayer).currentlyCasting() instanceof Flight - || (entityplayer.isHandActive() && wand.getItemDamage() < wand.getMaxDamage() && wand.getItem() instanceof ItemWand - && WandHelper.getCurrentSpell(wand) instanceof Flight)){ - - GlStateManager.pushMatrix(); - - GlStateManager.enableBlend(); - GlStateManager.blendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA); - GlStateManager.disableLighting(); - OpenGlHelper.setLightmapTextureCoords(OpenGlHelper.lightmapTexUnit, 240f, 240f); - - // GlStateManager.rotate(-entityplayer.rotationYawHead, 0, 1, 0); - GlStateManager.rotate(-entityplayer.renderYawOffset, 0, 1, 0); - // GlStateManager.rotate(180, 1, 0, 0); - - Minecraft.getMinecraft().renderEngine.bindTexture(wingTexture); - Tessellator tessellator = Tessellator.getInstance(); - BufferBuilder buffer = tessellator.getBuffer(); - - GlStateManager.pushMatrix(); - - GlStateManager.translate(0.1, 0.4, -0.15); - GlStateManager.rotate(20 + 20 * (float)Math.sin(entityplayer.world.getWorldTime() * 0.3), 0, 1, 0); - - buffer.begin(GL11.GL_QUADS, DefaultVertexFormats.POSITION_TEX); - - buffer.pos(0, 2, 0).tex(0, 0).endVertex(); - buffer.pos(2, 2, 0).tex(1, 0).endVertex(); - buffer.pos(2, 0, 0).tex(1, 1).endVertex(); - buffer.pos(0, 0, 0).tex(0, 1).endVertex(); - - tessellator.draw(); - - buffer.begin(GL11.GL_QUADS, DefaultVertexFormats.POSITION_TEX); - - buffer.pos(0, 2, 0).tex(0, 0).endVertex(); - buffer.pos(0, 0, 0).tex(0, 1).endVertex(); - buffer.pos(2, 0, 0).tex(1, 1).endVertex(); - buffer.pos(2, 2, 0).tex(1, 0).endVertex(); - - tessellator.draw(); - - GlStateManager.popMatrix(); - - GlStateManager.pushMatrix(); - - GlStateManager.translate(-0.1, 0.4, -0.15); - GlStateManager.rotate(-200 - 20 * (float)Math.sin(entityplayer.world.getWorldTime() * 0.3), 0, 1, 0); - - buffer.begin(GL11.GL_QUADS, DefaultVertexFormats.POSITION_TEX); - - buffer.pos(0, 2, 0).tex(0, 0).endVertex(); - buffer.pos(2, 2, 0).tex(1, 0).endVertex(); - buffer.pos(2, 0, 0).tex(1, 1).endVertex(); - buffer.pos(0, 0, 0).tex(0, 1).endVertex(); - - tessellator.draw(); - - buffer.begin(GL11.GL_QUADS, DefaultVertexFormats.POSITION_TEX); - - buffer.pos(0, 2, 0).tex(0, 0).endVertex(); - buffer.pos(0, 0, 0).tex(0, 1).endVertex(); - buffer.pos(2, 0, 0).tex(1, 1).endVertex(); - buffer.pos(2, 2, 0).tex(1, 0).endVertex(); - - tessellator.draw(); - - GlStateManager.popMatrix(); - - GlStateManager.enableLighting(); - GlStateManager.disableBlend(); - - GlStateManager.popMatrix(); - } - } - - private static void renderShieldFirstPerson(EntityPlayer entityplayer){ - ItemStack wand = entityplayer.getActiveItemStack(); - if(WizardData.get(entityplayer) != null && WizardData.get(entityplayer).shield != null - && (WizardData.get(entityplayer).currentlyCasting() instanceof Shield - || (entityplayer.isHandActive() && wand.getItemDamage() < wand.getMaxDamage() && wand.getItem() instanceof ItemWand - && WandHelper.getCurrentSpell(wand) instanceof Shield))){ - - GlStateManager.pushMatrix(); - - GlStateManager.disableCull(); - GlStateManager.enableBlend(); - GlStateManager.blendFunc(GL11.GL_ONE, GL11.GL_SRC_ALPHA); - GlStateManager.shadeModel(GL11.GL_SMOOTH); - GlStateManager.disableLighting(); - OpenGlHelper.setLightmapTextureCoords(OpenGlHelper.lightmapTexUnit, 240f, 240f); - - GlStateManager.translate(0, 1.4, 0); - - GlStateManager.rotate(-entityplayer.rotationYaw, 0, 1, 0); - GlStateManager.rotate(entityplayer.rotationPitch, 1, 0, 0); - - GlStateManager.translate(0, 0, 0.8); - - Tessellator tessellator = Tessellator.getInstance(); - - Minecraft.getMinecraft().renderEngine.bindTexture(shieldTexture); - - renderShield(tessellator); - - GlStateManager.enableLighting(); - - GlStateManager.shadeModel(GL11.GL_FLAT); - GlStateManager.enableCull(); - GlStateManager.disableBlend(); - // RenderHelper.enableStandardItemLighting(); - - GlStateManager.popMatrix(); - } - } - - private static void renderShieldIfActive(EntityPlayer entityplayer){ - ItemStack wand = entityplayer.getActiveItemStack(); - if(WizardData.get(entityplayer).shield != null && (WizardData.get(entityplayer).currentlyCasting() instanceof Shield - || (entityplayer.isHandActive() && wand.getItemDamage() < wand.getMaxDamage() && wand.getItem() instanceof ItemWand - && WandHelper.getCurrentSpell(wand) instanceof Shield))){ - - GlStateManager.pushMatrix(); - - GlStateManager.disableCull(); - GlStateManager.enableBlend(); - // For some reason, the old blend function (GL11.GL_SRC_ALPHA, GL11.GL_SRC_ALPHA) caused the inner - // edges to appear black, so I have changed it to this, which looks very slightly different. - GlStateManager.blendFunc(GL11.GL_ONE, GL11.GL_SRC_ALPHA); - GlStateManager.shadeModel(GL11.GL_SMOOTH); - GlStateManager.disableLighting(); - OpenGlHelper.setLightmapTextureCoords(OpenGlHelper.lightmapTexUnit, 240f, 240f); - - GlStateManager.translate(0, 1.3, 0); - - // GlStateManager.rotate(180, 0, 1, 0); - GlStateManager.rotate(-entityplayer.renderYawOffset, 0, 1, 0); - // GlStateManager.rotate(-entityplayer.rotationPitch, 1, 0, 0); - - GlStateManager.translate(0, 0, 0.8); - - Tessellator tessellator = Tessellator.getInstance(); - - Minecraft.getMinecraft().renderEngine.bindTexture(shieldTexture); - - renderShield(tessellator); - - GlStateManager.enableLighting(); - - GlStateManager.shadeModel(GL11.GL_FLAT); - GlStateManager.enableCull(); - GlStateManager.disableBlend(); - // RenderHelper.enableStandardItemLighting(); - - GlStateManager.popMatrix(); - } - } - - private static void renderShield(Tessellator tessellator){ - - BufferBuilder buffer = tessellator.getBuffer(); - - double widthOuter = 0.6d; - double heightOuter = 0.7d; - double widthInner = 0.3d; - double heightInner = 0.4d; - double depth = 0.2d; - - buffer.begin(GL11.GL_TRIANGLE_STRIP, DefaultVertexFormats.POSITION_TEX_COLOR); - - buffer.pos(-widthOuter, heightInner, -depth).tex(0, 0.2).color(0, 0, 0, 255).endVertex(); - buffer.pos(-widthInner, heightInner, 0).tex(0.2, 0.2).color(200, 200, 255, 255).endVertex(); - buffer.pos(-widthInner, heightOuter, -depth).tex(0.2, 0).color(0, 0, 0, 255).endVertex(); - buffer.pos(-widthInner, heightInner, 0).tex(0.2, 0.2).color(200, 200, 255, 255).endVertex(); - - buffer.pos(widthInner, heightOuter, -depth).tex(0.8, 0).color(0, 0, 0, 255).endVertex(); - buffer.pos(widthInner, heightInner, 0).tex(0.8, 0.2).color(200, 200, 255, 255).endVertex(); - buffer.pos(widthOuter, heightInner, -depth).tex(1, 0.2).color(0, 0, 0, 255).endVertex(); - buffer.pos(widthInner, heightInner, 0).tex(0.8, 0.2).color(200, 200, 255, 255).endVertex(); - - buffer.pos(widthOuter, -heightInner, -depth).tex(1, 0.8).color(0, 0, 0, 255).endVertex(); - buffer.pos(widthInner, -heightInner, 0).tex(0.8, 0.8).color(200, 200, 255, 255).endVertex(); - buffer.pos(widthInner, -heightOuter, -depth).tex(0.8, 1).color(0, 0, 0, 255).endVertex(); - buffer.pos(widthInner, -heightInner, 0).tex(0.8, 0.8).color(200, 200, 255, 255).endVertex(); - - buffer.pos(-widthInner, -heightOuter, -depth).tex(0.2, 1).color(0, 0, 0, 255).endVertex(); - buffer.pos(-widthInner, -heightInner, 0).tex(0.2, 0.8).color(200, 200, 255, 255).endVertex(); - buffer.pos(-widthOuter, -heightInner, -depth).tex(0, 0.8).color(0, 0, 0, 255).endVertex(); - buffer.pos(-widthInner, -heightInner, 0).tex(0.2, 0.8).color(200, 200, 255, 255).endVertex(); - - buffer.pos(-widthOuter, heightInner, -depth).tex(0, 0.2).color(0, 0, 0, 255).endVertex(); - buffer.pos(-widthInner, heightInner, 0).tex(0.2, 0.2).color(200, 200, 255, 255).endVertex(); - - tessellator.draw(); - - buffer.begin(GL11.GL_TRIANGLE_STRIP, DefaultVertexFormats.POSITION_TEX_COLOR); - - buffer.pos(-widthInner, heightInner, 0).tex(0.2, 0.2).color(200, 200, 255, 255).endVertex(); - buffer.pos(widthInner, heightInner, 0).tex(0.8, 0.2).color(200, 200, 255, 255).endVertex(); - buffer.pos(-widthInner, -heightInner, 0).tex(0.2, 0.8).color(200, 200, 255, 255).endVertex(); - buffer.pos(widthInner, -heightInner, 0).tex(0.8, 0.8).color(200, 200, 255, 255).endVertex(); - - tessellator.draw(); - } - } diff --git a/src/main/java/electroblob/wizardry/client/WizardryControlHandler.java b/src/main/java/electroblob/wizardry/client/WizardryControlHandler.java index ce212de8..7b98aca0 100644 --- a/src/main/java/electroblob/wizardry/client/WizardryControlHandler.java +++ b/src/main/java/electroblob/wizardry/client/WizardryControlHandler.java @@ -1,14 +1,11 @@ package electroblob.wizardry.client; -import org.lwjgl.input.Keyboard; - import electroblob.wizardry.Wizardry; import electroblob.wizardry.client.gui.GuiSpellDisplay; -import electroblob.wizardry.item.ItemWand; +import electroblob.wizardry.item.ISpellCastingItem; import electroblob.wizardry.packet.PacketControlInput; import electroblob.wizardry.packet.WizardryPacketHandler; import electroblob.wizardry.registry.WizardrySounds; -import electroblob.wizardry.util.WandHelper; import net.minecraft.client.Minecraft; import net.minecraft.client.audio.PositionedSoundRecord; import net.minecraft.entity.player.EntityPlayer; @@ -16,72 +13,54 @@ import net.minecraft.item.ItemStack; import net.minecraftforge.client.event.MouseEvent; import net.minecraftforge.fml.common.Mod; import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; -import net.minecraftforge.fml.common.gameevent.InputEvent; +import net.minecraftforge.fml.common.gameevent.TickEvent; import net.minecraftforge.fml.common.network.simpleimpl.IMessage; import net.minecraftforge.fml.relauncher.Side; -import net.minecraftforge.fml.relauncher.SideOnly; /** Event handler class responsible for handling wizardry's controls. */ -@SideOnly(Side.CLIENT) +//@SideOnly(Side.CLIENT) @Mod.EventBusSubscriber(Side.CLIENT) public class WizardryControlHandler { static boolean NkeyPressed = false; static boolean BkeyPressed = false; - static boolean NkeyAlreadyPressed = false; - static boolean BkeyAlreadyPressed = false; + // Changed to a tick event to allow mouse button keybinds + // The 'lag' that happened previously was actually because the code only fired when a keyboard key was pressed! @SubscribeEvent - public static void onKeyInput(InputEvent.KeyInputEvent event){ + public static void onTickEvent(TickEvent.ClientTickEvent event){ - // Key pressed - if(Keyboard.getEventKeyState()){ + if(event.phase == TickEvent.Phase.END) return; // Only really needs to be once per tick - if(Wizardry.proxy instanceof ClientProxy){ - - EntityPlayer player = Minecraft.getMinecraft().player; - ItemStack wand = player.getHeldItemMainhand(); + if(Wizardry.proxy instanceof ClientProxy){ - if(!(wand.getItem() instanceof ItemWand)){ - wand = player.getHeldItemOffhand(); - // If the player isn't holding a wand, then nothing else needs to be done. - if(!(wand.getItem() instanceof ItemWand)) return; - } + EntityPlayer player = Minecraft.getMinecraft().player; - if(ClientProxy.NEXT_SPELL.isPressed() && Minecraft.getMinecraft().inGameHasFocus){ + if(player != null){ + + ItemStack wand = getWandInUse(player); + if(wand == null) return; + + if(ClientProxy.NEXT_SPELL.isKeyDown() && Minecraft.getMinecraft().inGameHasFocus){ if(!NkeyPressed){ NkeyPressed = true; - }else{ - NkeyAlreadyPressed = true; - } - if(!NkeyAlreadyPressed){ selectNextSpell(wand); } + }else{ + NkeyPressed = false; } - if(ClientProxy.PREVIOUS_SPELL.isPressed() && Minecraft.getMinecraft().inGameHasFocus){ + if(ClientProxy.PREVIOUS_SPELL.isKeyDown() && Minecraft.getMinecraft().inGameHasFocus){ if(!BkeyPressed){ BkeyPressed = true; - }else{ - BkeyAlreadyPressed = true; - } - if(!BkeyAlreadyPressed){ + // Packet building selectPreviousSpell(wand); } + }else{ + BkeyPressed = false; } } } - - // Key released - else{ - if(NkeyPressed){ - NkeyPressed = false; - NkeyAlreadyPressed = false; - }else if(BkeyPressed){ - BkeyPressed = false; - BkeyAlreadyPressed = false; - } - } } // Shift-scrolling to change spells @@ -89,16 +68,11 @@ public class WizardryControlHandler { public static void onMouseEvent(MouseEvent event){ EntityPlayer player = Minecraft.getMinecraft().player; - ItemStack wand = player.getHeldItemMainhand(); - - if(!(wand.getItem() instanceof ItemWand)){ - wand = player.getHeldItemOffhand(); - // If the player isn't holding a wand, then nothing else needs to be done. - if(!(wand.getItem() instanceof ItemWand)) return; - } + ItemStack wand = getWandInUse(player); + if(wand == null) return; if(Minecraft.getMinecraft().inGameHasFocus && !wand.isEmpty() && event.getDwheel() != 0 && player.isSneaking() - && Wizardry.settings.enableShiftScrolling){ + && Wizardry.settings.shiftScrolling){ event.setCanceled(true); @@ -111,15 +85,28 @@ public class WizardryControlHandler { } } } + + private static ItemStack getWandInUse(EntityPlayer player){ + + ItemStack wand = player.getHeldItemMainhand(); + + // Only bother sending packets if the player is holding a spellcasting item with more than one spell slot + if(!(wand.getItem() instanceof ISpellCastingItem) || ((ISpellCastingItem)wand.getItem()).getSpells(wand).length < 2){ + wand = player.getHeldItemOffhand(); + if(!(wand.getItem() instanceof ISpellCastingItem) || ((ISpellCastingItem)wand.getItem()).getSpells(wand).length < 2) return null; + } + + return wand; + } private static void selectNextSpell(ItemStack wand){ // Packet building IMessage msg = new PacketControlInput.Message(PacketControlInput.ControlType.NEXT_SPELL_KEY); WizardryPacketHandler.net.sendToServer(msg); // GUI switch animation - WandHelper.selectNextSpell(wand); // Makes sure the spell is set immediately for the client + ((ISpellCastingItem)wand.getItem()).selectNextSpell(wand); // Makes sure the spell is set immediately for the client GuiSpellDisplay.playSpellSwitchAnimation(true); - Minecraft.getMinecraft().getSoundHandler().playSound(PositionedSoundRecord.getMasterRecord(WizardrySounds.SELECT_SPELL, 1)); + Minecraft.getMinecraft().getSoundHandler().playSound(PositionedSoundRecord.getMasterRecord(WizardrySounds.ITEM_WAND_SWITCH_SPELL, 1)); } private static void selectPreviousSpell(ItemStack wand){ @@ -127,8 +114,8 @@ public class WizardryControlHandler { IMessage msg = new PacketControlInput.Message(PacketControlInput.ControlType.PREVIOUS_SPELL_KEY); WizardryPacketHandler.net.sendToServer(msg); // GUI switch animation - WandHelper.selectPreviousSpell(wand); // Makes sure the spell is set immediately for the client + ((ISpellCastingItem)wand.getItem()).selectPreviousSpell(wand); // Makes sure the spell is set immediately for the client GuiSpellDisplay.playSpellSwitchAnimation(false); - Minecraft.getMinecraft().getSoundHandler().playSound(PositionedSoundRecord.getMasterRecord(WizardrySounds.SELECT_SPELL, 1)); + Minecraft.getMinecraft().getSoundHandler().playSound(PositionedSoundRecord.getMasterRecord(WizardrySounds.ITEM_WAND_SWITCH_SPELL, 1)); } } diff --git a/src/main/java/electroblob/wizardry/client/audio/MovingSoundEntity.java b/src/main/java/electroblob/wizardry/client/audio/MovingSoundEntity.java new file mode 100644 index 00000000..11291f26 --- /dev/null +++ b/src/main/java/electroblob/wizardry/client/audio/MovingSoundEntity.java @@ -0,0 +1,35 @@ +package electroblob.wizardry.client.audio; + +import net.minecraft.client.audio.MovingSound; +import net.minecraft.entity.Entity; +import net.minecraft.util.SoundCategory; +import net.minecraft.util.SoundEvent; + +// Copied from MovingSoundMinecart; if it ever breaks between updates take a look at that. +//@SideOnly(Side.CLIENT) +public class MovingSoundEntity extends MovingSound { + + protected final T source; + protected float distance = 0.0F; + + public MovingSoundEntity(T entity, SoundEvent sound, SoundCategory category, float volume, float pitch, boolean repeat){ + super(sound, category); + this.source = entity; + this.repeat = repeat; + this.volume = volume; + this.pitch = pitch; + this.repeatDelay = 0; + } + + @Override + public void update(){ + + if(this.source.isDead){ + this.donePlaying = true; + }else{ + this.xPosF = (float)this.source.posX; + this.yPosF = (float)this.source.posY; + this.zPosF = (float)this.source.posZ; + } + } +} \ No newline at end of file diff --git a/src/main/java/electroblob/wizardry/client/audio/SoundLoop.java b/src/main/java/electroblob/wizardry/client/audio/SoundLoop.java new file mode 100644 index 00000000..651fb7fb --- /dev/null +++ b/src/main/java/electroblob/wizardry/client/audio/SoundLoop.java @@ -0,0 +1,94 @@ +package electroblob.wizardry.client.audio; + +import net.minecraft.client.Minecraft; +import net.minecraft.client.audio.ISound; +import net.minecraft.util.ITickable; +import net.minecraft.util.SoundCategory; +import net.minecraft.util.SoundEvent; +import net.minecraftforge.fml.common.Mod; +import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; +import net.minecraftforge.fml.common.gameevent.TickEvent; +import net.minecraftforge.fml.relauncher.Side; + +import java.util.HashSet; +import java.util.Set; + +/** + * Instances of this class represent a set of sounds which together form a looped sound: start, loop and end. + * Currently this is only used for continuous spell sounds in wizardry itself, but feel free to make your own + * implementations - this class will take care of the internals. + * + * @since Wizardry 4.2 + * @author Electroblob + */ +// See MusicTicker, this is the same idea of just storing the sounds statically client-side and ticking them +@Mod.EventBusSubscriber(Side.CLIENT) +public abstract class SoundLoop implements ITickable { + + private static final Set activeLoops = new HashSet<>(); + + private final ISound start; + private final ISound loop; + private final ISound end; + + private boolean looping = false; + private boolean needsRemoving = false; + + public SoundLoop(SoundEvent start, SoundEvent loop, SoundEvent end, SoundCategory category, ISoundFactory factory){ + // The reason I've gone to the effort of having a factory for these is that we need SoundLoop to have control + // over which sounds are repeated and which aren't whilst keeping them private. + this.start = factory.create(start, category, false); + this.loop = factory.create(loop, category, true); + this.end = factory.create(end, category, false); + } + + @Override + public void update(){ + // Check every tick if the start sound is done playing and if so, start the loop sound + if(!looping && !Minecraft.getMinecraft().getSoundHandler().isSoundPlaying(start)){ + Minecraft.getMinecraft().getSoundHandler().playSound(loop); + looping = true; + } + } + + /** Stops the loop part of the sound immediately and starts playing the end part. This may be called from subclasses + * or externally depending on the implementation. */ + // For continuous spell sounds it's internally + public void endLoop(){ + Minecraft.getMinecraft().getSoundHandler().stopSound(start); + Minecraft.getMinecraft().getSoundHandler().stopSound(loop); + Minecraft.getMinecraft().getSoundHandler().playSound(end); + // Can't modify activeLoops directly since we'll probably be calling this method from update(), which is + // during iteration of activeLoops so it could cause a ConcurrentModificationException + this.markForRemoval(); + } + + /** Marks this sound loop to be removed next tick. */ + protected void markForRemoval(){ + this.needsRemoving = true; + } + + // Static methods + + public static void addLoop(SoundLoop loop){ + activeLoops.add(loop); + // Do this here rather than in the constructor in case someone wants to play the loop later or reuse it + Minecraft.getMinecraft().getSoundHandler().playSound(loop.start); + } + + @SubscribeEvent + public static void tick(TickEvent.ClientTickEvent event){ + // Using the END phase means we can check for stopped sounds as soon as they are stopped (effectively), + // meaning we don't get the 'cut' between the start and loop sounds + // FIXME: Apparently this only works for dispensers. What the heck is the difference?! + if(event.phase == TickEvent.Phase.END){ + activeLoops.forEach(SoundLoop::update); + activeLoops.removeIf(s -> s.needsRemoving); + } + } + + @FunctionalInterface + public interface ISoundFactory { + ISound create(SoundEvent sound, SoundCategory category, boolean repeat); + } +} diff --git a/src/main/java/electroblob/wizardry/client/audio/SoundLoopSpell.java b/src/main/java/electroblob/wizardry/client/audio/SoundLoopSpell.java new file mode 100644 index 00000000..bb4d9b44 --- /dev/null +++ b/src/main/java/electroblob/wizardry/client/audio/SoundLoopSpell.java @@ -0,0 +1,117 @@ +package electroblob.wizardry.client.audio; + +import electroblob.wizardry.data.DispenserCastingData; +import electroblob.wizardry.registry.WizardrySounds; +import electroblob.wizardry.spell.Spell; +import electroblob.wizardry.util.WizardryUtilities; +import net.minecraft.client.audio.PositionedSound; +import net.minecraft.entity.EntityLivingBase; +import net.minecraft.tileentity.TileEntity; +import net.minecraft.tileentity.TileEntityDispenser; +import net.minecraft.util.SoundEvent; +import net.minecraft.util.math.BlockPos; +import net.minecraft.world.World; + +/** Abstract base class for sound loops associated with spells; see subclasses below for implementations. */ +public abstract class SoundLoopSpell extends SoundLoop { + + private final Spell spell; + + public SoundLoopSpell(SoundEvent start, SoundEvent loop, SoundEvent end, ISoundFactory factory, Spell spell){ + super(start, loop, end, WizardrySounds.SPELLS, factory); + this.spell = spell; + } + + @Override + public void update(){ + // This may be a bit overkill but I might as well put functionality in superclasses where possible + if(stillCasting(spell)){ + // This can't called in the same tick as endLoop because otherwise, if the spell casting stops during the + // same tick as the transition to the loop sound it will try and stop the loop immediately after it has + // started - and for whatever reason, this causes the 'Channel null in method stop' error. + super.update(); + }else{ + endLoop(); + } + } + + protected abstract boolean stillCasting(Spell spell); + + /** Implements a sound loop for continuous spells cast by entities. */ + public static class SoundLoopSpellEntity extends SoundLoopSpell { + + private final EntityLivingBase source; + + public SoundLoopSpellEntity(SoundEvent start, SoundEvent loop, SoundEvent end, Spell spell, EntityLivingBase source, float volume, float pitch){ + super(start, loop, end, (sound, category, repeat) -> new MovingSoundEntity<>(source, sound, category, volume, pitch, repeat), spell); + this.source = source; + } + + @Override + protected boolean stillCasting(Spell spell){ + return WizardryUtilities.isCasting(source, spell); + } + } + + public static abstract class SoundLoopSpellPosition extends SoundLoopSpell { + + public SoundLoopSpellPosition (SoundEvent start, SoundEvent loop, SoundEvent end, Spell spell, + double x, double y, double z, float sndVolume, float sndPitch){ + // Huh, I actually found a use for a non-static initialiser block - hence the double curly brackets... + super(start, loop, end, (sound, category, r) -> new PositionedSound(sound, category){{ + // ...et voila, we can just set protected fields as we please using external variables + this.xPosF = (float)x; + this.yPosF = (float)y; + this.zPosF = (float)z; + this.repeat = r; + this.volume = sndVolume; + this.pitch = sndPitch; + }}, spell); + } + } + + /** Implements a sound loop for continuous spells cast by dispensers. */ + public static class SoundLoopSpellDispenser extends SoundLoopSpellPosition { + + private final TileEntityDispenser source; + + public SoundLoopSpellDispenser(SoundEvent start, SoundEvent loop, SoundEvent end, Spell spell, World world, + double x, double y, double z, float sndVolume, float sndPitch){ + super(start, loop, end, spell, x, y, z, sndVolume, sndPitch); + + TileEntity tileentity = world.getTileEntity(new BlockPos(x, y, z)); + + if(tileentity instanceof TileEntityDispenser) this.source = (TileEntityDispenser)tileentity; + else throw new NullPointerException(String.format("Playing continuous spell sound: no dispenser found at %s, %s, %s", x, y, z)); + } + + @Override + protected boolean stillCasting(Spell spell){ + return DispenserCastingData.get(source).currentlyCasting() == spell; + } + + } + + /** Implements a sound loop for continuous spells cast at a position (via commands). */ + public static class SoundLoopSpellPosTimed extends SoundLoopSpellPosition { + + private int timeLeft; + + public SoundLoopSpellPosTimed(SoundEvent start, SoundEvent loop, SoundEvent end, Spell spell, int duration, + double x, double y, double z, float sndVolume, float sndPitch){ + super(start, loop, end, spell, x, y, z, sndVolume, sndPitch); + this.timeLeft = duration; + } + + @Override + public void update(){ + super.update(); + timeLeft--; + } + + @Override + protected boolean stillCasting(Spell spell){ + return timeLeft > 0; + } + } +} diff --git a/src/main/java/electroblob/wizardry/client/gui/GuiArcaneWorkbench.java b/src/main/java/electroblob/wizardry/client/gui/GuiArcaneWorkbench.java index 43d1a5c2..9fe07cb1 100644 --- a/src/main/java/electroblob/wizardry/client/gui/GuiArcaneWorkbench.java +++ b/src/main/java/electroblob/wizardry/client/gui/GuiArcaneWorkbench.java @@ -1,23 +1,27 @@ package electroblob.wizardry.client.gui; -import org.lwjgl.input.Keyboard; - -import electroblob.wizardry.SpellGlyphData; -import electroblob.wizardry.WizardData; import electroblob.wizardry.Wizardry; +import electroblob.wizardry.client.DrawingUtils; import electroblob.wizardry.constants.Element; -import electroblob.wizardry.item.ItemWand; +import electroblob.wizardry.data.SpellGlyphData; +import electroblob.wizardry.data.WizardData; +import electroblob.wizardry.item.IManaStoringItem; +import electroblob.wizardry.item.ISpellCastingItem; +import electroblob.wizardry.item.IWorkbenchItem; import electroblob.wizardry.packet.PacketControlInput; import electroblob.wizardry.packet.WizardryPacketHandler; +import electroblob.wizardry.registry.WizardrySounds; import electroblob.wizardry.spell.Spell; import electroblob.wizardry.tileentity.ContainerArcaneWorkbench; import electroblob.wizardry.tileentity.TileEntityArcaneWorkbench; import electroblob.wizardry.util.WandHelper; -import electroblob.wizardry.util.WizardryUtilities; import net.minecraft.client.Minecraft; +import net.minecraft.client.audio.PositionedSoundRecord; import net.minecraft.client.gui.GuiButton; import net.minecraft.client.gui.inventory.GuiContainer; import net.minecraft.client.renderer.GlStateManager; +import net.minecraft.client.renderer.GlStateManager.DestFactor; +import net.minecraft.client.renderer.GlStateManager.SourceFactor; import net.minecraft.client.resources.I18n; import net.minecraft.entity.player.InventoryPlayer; import net.minecraft.inventory.IInventory; @@ -25,131 +29,260 @@ import net.minecraft.inventory.Slot; import net.minecraft.item.Item; import net.minecraft.item.ItemStack; import net.minecraft.util.ResourceLocation; +import net.minecraftforge.client.event.TextureStitchEvent; +import net.minecraftforge.fml.common.Mod; +import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; import net.minecraftforge.fml.common.network.simpleimpl.IMessage; +import net.minecraftforge.fml.relauncher.Side; +import org.lwjgl.input.Keyboard; +@Mod.EventBusSubscriber(Side.CLIENT) public class GuiArcaneWorkbench extends GuiContainer { private GuiButton applyBtn; - private static final ResourceLocation texture = new ResourceLocation(Wizardry.MODID, + public static final ResourceLocation texture = new ResourceLocation(Wizardry.MODID, "textures/gui/arcane_workbench.png"); private IInventory playerInventory; private IInventory arcaneWorkbenchInventory; - private final int tooltipWidth = 164; + private static final int TOOLTIP_WIDTH = 164; - // We report the actual size of the GUI to Minecraft when a wand is in so JEI doesn't overdraw it. - // For calculations, we use the size without the tooltip. - private final int xSizeNoTip = 176; + /** We report the actual size of the GUI to Minecraft when a wand is in so JEI doesn't overdraw it. + * For calculations, we use the size without the tooltip, which is stored in this constant. */ + private static final int MAIN_GUI_WIDTH = 176; + + private static final int RUNE_LEFT = 38; + private static final int RUNE_TOP = 22; + private static final int RUNE_WIDTH = 100; + private static final int RUNE_HEIGHT = 100; + + private static final int HALO_DIAMETER = 156; + + private static final int TEXTURE_WIDTH = 512; + private static final int TEXTURE_HEIGHT = 256; + + private int animationTimer = 0; + private static final int ANIMATION_DURATION = 20; public GuiArcaneWorkbench(InventoryPlayer invPlayer, TileEntityArcaneWorkbench entity){ super(new ContainerArcaneWorkbench(invPlayer, entity)); this.playerInventory = invPlayer; this.arcaneWorkbenchInventory = entity; - xSize = xSizeNoTip; + xSize = MAIN_GUI_WIDTH; ySize = 220; } + // Huh, didn't realise this method existed. Pretty neat. @Override - public void drawScreen(int p_73863_1_, int p_73863_2_, float p_73863_3_){ - - this.drawDefaultBackground(); - - // Tests if there is a wand in the workbench and edits the positioning accordingly - if(this.inventorySlots.getSlot(ContainerArcaneWorkbench.CENTRE_SLOT).getHasStack() && this.inventorySlots - .getSlot(ContainerArcaneWorkbench.CENTRE_SLOT).getStack().getItem() instanceof ItemWand){ - xSize = xSizeNoTip + tooltipWidth; - guiLeft = (this.width - this.xSize) / 2; - this.applyBtn.x = (this.width - tooltipWidth) / 2 + 48; - }else{ - xSize = xSizeNoTip; - guiLeft = (this.width - this.xSize) / 2; - this.applyBtn.x = this.width / 2 + 48; - } - - if(this.inventorySlots.getSlot(ContainerArcaneWorkbench.CENTRE_SLOT).getHasStack()){ - this.applyBtn.enabled = true; - }else{ - this.applyBtn.enabled = false; - } - - super.drawScreen(p_73863_1_, p_73863_2_, p_73863_3_); - - // Required now, or item mouseover tooltips won't render. - this.renderHoveredToolTip(p_73863_1_, p_73863_2_); + public void updateScreen(){ + if(animationTimer > 0) animationTimer--; } @Override - public void drawGuiContainerBackgroundLayer(float f, int mouseX, int mouseY){ + public void drawScreen(int mouseX, int mouseY, float partialTicks){ - GlStateManager.color(1F, 1F, 1F, 1F); + this.drawDefaultBackground(); + + GlStateManager.color(1, 1, 1, 1); // Just in case + + Slot slot = this.inventorySlots.getSlot(ContainerArcaneWorkbench.CENTRE_SLOT); + + // Tests if there is a wand in the workbench and edits the positioning accordingly + if(slot.getHasStack() && slot.getStack().getItem() instanceof IWorkbenchItem + && ((IWorkbenchItem)slot.getStack().getItem()).showTooltip(slot.getStack())){ + xSize = MAIN_GUI_WIDTH + TOOLTIP_WIDTH; + guiLeft = (this.width - this.xSize) / 2; + this.applyBtn.x = (this.width - TOOLTIP_WIDTH) / 2 + 64; + }else{ + xSize = MAIN_GUI_WIDTH; + guiLeft = (this.width - this.xSize) / 2; + this.applyBtn.x = this.width / 2 + 64; + } + + this.applyBtn.enabled = slot.getHasStack(); + + super.drawScreen(mouseX, mouseY, partialTicks); + + // Required now, or item mouseover tooltips won't render. + this.renderHoveredToolTip(mouseX, mouseY); + } + + @Override + public void drawGuiContainerBackgroundLayer(float partialTicks, int mouseX, int mouseY){ + + GlStateManager.color(1, 1, 1, 1); Minecraft.getMinecraft().renderEngine.bindTexture(texture); + + // Animation + + // Grey background + DrawingUtils.drawTexturedRect(guiLeft + RUNE_LEFT, guiTop + RUNE_TOP, MAIN_GUI_WIDTH + TOOLTIP_WIDTH, 0, + RUNE_WIDTH, RUNE_HEIGHT, TEXTURE_WIDTH, TEXTURE_HEIGHT); + + // Yellow 'halo' + if(animationTimer > 0){ + + GlStateManager.pushMatrix(); + GlStateManager.enableBlend(); + GlStateManager.blendFunc(SourceFactor.SRC_ALPHA, DestFactor.ONE_MINUS_SRC_ALPHA); + + int x = guiLeft + RUNE_LEFT + RUNE_WIDTH/2; + int y = guiTop + RUNE_TOP + RUNE_HEIGHT/2; + + float scale = (animationTimer + partialTicks)/ANIMATION_DURATION; + scale = (float)(1 - Math.pow(1-scale, 1.4f)); // Makes it slower at the start and speed up + GlStateManager.scale(scale, scale, 1); + GlStateManager.translate(x/scale, y/scale, 0); + + DrawingUtils.drawTexturedRect(-HALO_DIAMETER /2, -HALO_DIAMETER /2, MAIN_GUI_WIDTH + TOOLTIP_WIDTH, RUNE_HEIGHT, + HALO_DIAMETER, HALO_DIAMETER, TEXTURE_WIDTH, TEXTURE_HEIGHT); + + GlStateManager.disableBlend(); + GlStateManager.popMatrix(); + } // Main inventory DrawingUtils.drawTexturedRect(guiLeft, guiTop, 0, 0, MAIN_GUI_WIDTH, ySize, TEXTURE_WIDTH, TEXTURE_HEIGHT); + float opacity = (animationTimer + partialTicks)/ANIMATION_DURATION; + // Changing slots for(int i = 0; i < ContainerArcaneWorkbench.CRYSTAL_SLOT; i++){ + Slot slot = this.inventorySlots.getSlot(i); - if(slot.xPos >= 0 && slot.yPos >= 0) - this.drawTexturedModalRect(guiLeft + slot.xPos - 10, guiTop + slot.yPos - 10, 0, 220, 36, 36); + + if(slot.xPos >= 0 && slot.yPos >= 0){ + // Slot background + DrawingUtils.drawTexturedRect(guiLeft + slot.xPos - 10, guiTop + slot.yPos - 10, 0, 220, 36, 36, TEXTURE_WIDTH, TEXTURE_HEIGHT); + + // Slot animation + // IDEA: Somehow replace with intelligent check for whether the spell actually got applied + if(animationTimer > 0 && slot.getHasStack()){ + + GlStateManager.pushMatrix(); + GlStateManager.enableBlend(); + GlStateManager.blendFunc(SourceFactor.SRC_ALPHA, DestFactor.ONE_MINUS_SRC_ALPHA); + GlStateManager.color(1, 1, 1, opacity); + + DrawingUtils.drawTexturedRect(guiLeft + slot.xPos - 10, guiTop + slot.yPos - 10, 36, 220, 36, 36, TEXTURE_WIDTH, TEXTURE_HEIGHT); + + GlStateManager.color(1, 1, 1, 1); + GlStateManager.disableBlend(); + GlStateManager.popMatrix(); + } + } + } + + // Crystal + upgrade slot animations + if(animationTimer > 0){ + + Slot crystals = this.inventorySlots.getSlot(ContainerArcaneWorkbench.CRYSTAL_SLOT); + Slot upgrades = this.inventorySlots.getSlot(ContainerArcaneWorkbench.UPGRADE_SLOT); + + if(crystals.getHasStack()){ + + GlStateManager.pushMatrix(); + GlStateManager.enableBlend(); + GlStateManager.blendFunc(SourceFactor.SRC_ALPHA, DestFactor.ONE_MINUS_SRC_ALPHA); + GlStateManager.color(1, 1, 1, opacity); + + DrawingUtils.drawTexturedRect(guiLeft + crystals.xPos - 8, guiTop + crystals.yPos - 8, + MAIN_GUI_WIDTH + TOOLTIP_WIDTH + RUNE_WIDTH, 0, 32, 32, TEXTURE_WIDTH, TEXTURE_HEIGHT); + + GlStateManager.color(1, 1, 1, 1); + GlStateManager.disableBlend(); + GlStateManager.popMatrix(); + } + + if(upgrades.getHasStack()){ + + GlStateManager.pushMatrix(); + GlStateManager.enableBlend(); + GlStateManager.blendFunc(SourceFactor.SRC_ALPHA, DestFactor.ONE_MINUS_SRC_ALPHA); + GlStateManager.color(1, 1, 1, opacity); + + DrawingUtils.drawTexturedRect(guiLeft + upgrades.xPos - 8, guiTop + upgrades.yPos - 8, + MAIN_GUI_WIDTH + TOOLTIP_WIDTH + RUNE_WIDTH, 0, 32, 32, TEXTURE_WIDTH, TEXTURE_HEIGHT); + + GlStateManager.color(1, 1, 1, 1); + GlStateManager.disableBlend(); + GlStateManager.popMatrix(); + } } // Tooltip only drawn if there is a wand - if(this.inventorySlots.getSlot(ContainerArcaneWorkbench.CENTRE_SLOT).getHasStack() && this.inventorySlots - .getSlot(ContainerArcaneWorkbench.CENTRE_SLOT).getStack().getItem() instanceof ItemWand){ + if(this.inventorySlots.getSlot(ContainerArcaneWorkbench.CENTRE_SLOT).getHasStack()){ - // Tooltip box - drawTexturedModalRect(guiLeft + xSizeNoTip, guiTop, xSizeNoTip, 0, 256 - xSizeNoTip - 4, ySize); - drawTexturedModalRect(guiLeft + 252, guiTop, xSizeNoTip + 4, 0, tooltipWidth - 2 * (256 - xSizeNoTip - 4), ySize); - drawTexturedModalRect(guiLeft + xSize - (256 - xSizeNoTip - 4), guiTop, xSizeNoTip + 4, 0, - 256 - xSizeNoTip - 4, ySize); + ItemStack stack = this.inventorySlots.getSlot(ContainerArcaneWorkbench.CENTRE_SLOT).getStack(); - ItemStack wand = this.inventorySlots.getSlot(ContainerArcaneWorkbench.CENTRE_SLOT).getStack(); - - Spell[] spells = WandHelper.getSpells(wand); - - int i = 0; - - for(Spell spell : spells){ - - boolean discovered = true; - - if(!this.mc.player.capabilities.isCreativeMode && WizardData.get(this.mc.player) != null){ - discovered = WizardData.get(this.mc.player).hasSpellBeenDiscovered(spell); - } - // As of Wizardry 1.2, the icons have been split off into their own texture files to allow for add-on - // mods to add their own. - Minecraft.getMinecraft().renderEngine - .bindTexture(discovered ? spell.element.getIcon() : Element.MAGIC.getIcon()); - - // Renders the little element icon - DrawingUtils.drawTexturedRect(guiLeft + MAIN_GUI_WIDTH + 5, guiTop + 34 + 10 * i++, 8, 8); + if(!(stack.getItem() instanceof IWorkbenchItem)){ + Wizardry.logger.warn("Invalid item in central slot of arcane workbench, how did that get there?!"); + return; } - int x = 0; - int y = guiTop + 50 + spells.length * 10; + if(((IWorkbenchItem)stack.getItem()).showTooltip(stack)){ - // Look how much shorter this is with the WandHelper class! - for(Item item : WandHelper.getSpecialUpgrades()){ + // Tooltip box + DrawingUtils.drawTexturedRect(guiLeft + MAIN_GUI_WIDTH, guiTop, MAIN_GUI_WIDTH, 0, TOOLTIP_WIDTH, ySize, TEXTURE_WIDTH, TEXTURE_HEIGHT); - int level = WandHelper.getUpgradeLevel(wand, item); + int y = guiTop + 20; - if(level > 0){ - ItemStack stack = new ItemStack(item, level); - GlStateManager.enableDepth(); - this.itemRender.renderItemAndEffectIntoGUI(stack, guiLeft + xSizeNoTip + 6 + x, y); - this.itemRender.renderItemOverlayIntoGUI(this.fontRenderer, stack, guiLeft + xSizeNoTip + 6 + x, y, - null); - x += 18; - GlStateManager.disableDepth(); + if(stack.getItem() instanceof IManaStoringItem && ((IManaStoringItem)stack.getItem()).showManaInWorkbench(this.mc.player, stack)){ + y += 14; + } + + if(stack.getItem() instanceof ISpellCastingItem && ((ISpellCastingItem)stack.getItem()).showSpellsInWorkbench(this.mc.player, stack)){ + + Spell[] spells = ((ISpellCastingItem)stack.getItem()).getSpells(stack); + + GlStateManager.enableBlend(); + + for(Spell spell : spells){ + + boolean discovered = true; + + if(!this.mc.player.isCreative() && WizardData.get(this.mc.player) != null){ + discovered = WizardData.get(this.mc.player).hasSpellBeenDiscovered(spell); + } + // As of Wizardry 1.2, the icons have been split off into their own texture files to allow for add-on + // mods to add their own. + Minecraft.getMinecraft().renderEngine + .bindTexture(discovered ? spell.getElement().getIcon() : Element.MAGIC.getIcon()); + + // Renders the little element icon + DrawingUtils.drawTexturedRect(guiLeft + MAIN_GUI_WIDTH + 5, y, 8, 8); + + y += 10; + } + } + + GlStateManager.disableBlend(); + + int x = 0; + y += 16; + + // Look how much shorter this is with the WandHelper class! + for(Item item : WandHelper.getSpecialUpgrades()){ + + int level = WandHelper.getUpgradeLevel(stack, item); + + if(level > 0){ + ItemStack stack1 = new ItemStack(item, level); + GlStateManager.enableDepth(); + this.itemRender.renderItemAndEffectIntoGUI(stack1, guiLeft + MAIN_GUI_WIDTH + 6 + x, y); + this.itemRender.renderItemOverlayIntoGUI(this.fontRenderer, stack1, guiLeft + MAIN_GUI_WIDTH + 6 + x, y, + null); + x += 18; + GlStateManager.disableDepth(); + } } } } Minecraft.getMinecraft().renderEngine.bindTexture(texture); - // Fixes the bug that caused the slot hightlight to render opaque. I don't know why it works, it just works! + // Fixes the bug that caused the slot highlight to render opaque. I don't know why it works, it just works! GlStateManager.disableBlend(); GlStateManager.enableAlpha(); } @@ -157,64 +290,86 @@ public class GuiArcaneWorkbench extends GuiContainer { @Override protected void drawGuiContainerForegroundLayer(int mouseX, int mouseY){ + GlStateManager.color(1, 1, 1, 1); // Just in case + this.fontRenderer .drawString(this.arcaneWorkbenchInventory.hasCustomName() ? this.arcaneWorkbenchInventory.getName() : I18n.format(this.arcaneWorkbenchInventory.getName()), 8, 6, 4210752); this.fontRenderer.drawString(this.playerInventory.hasCustomName() ? this.playerInventory.getName() : I18n.format(this.playerInventory.getName()), 8, this.ySize - 96 + 2, 4210752); - if(this.inventorySlots.getSlot(ContainerArcaneWorkbench.CENTRE_SLOT).getHasStack() && this.inventorySlots - .getSlot(ContainerArcaneWorkbench.CENTRE_SLOT).getStack().getItem() instanceof ItemWand){ + if(this.inventorySlots.getSlot(ContainerArcaneWorkbench.CENTRE_SLOT).getHasStack()){ - ItemStack wand = this.inventorySlots.getSlot(ContainerArcaneWorkbench.CENTRE_SLOT).getStack(); + ItemStack stack = this.inventorySlots.getSlot(ContainerArcaneWorkbench.CENTRE_SLOT).getStack(); - this.fontRenderer.drawStringWithShadow("\u00A7f" + wand.getDisplayName(), xSizeNoTip + 6, 6, 0); - this.fontRenderer.drawStringWithShadow( - "\u00A77" + I18n.format("container." + Wizardry.MODID + ":arcane_workbench.mana") + " " - + (wand.getMaxDamage() - wand.getItemDamage()) + "/" + wand.getMaxDamage(), - xSizeNoTip + 6, 20, 0); - - Spell[] spells = WandHelper.getSpells(wand); - - int y = 34; - - for(Spell spell : spells){ - - boolean discovered = true; - - if(!this.mc.player.capabilities.isCreativeMode && WizardData.get(this.mc.player) != null){ - discovered = WizardData.get(this.mc.player).hasSpellBeenDiscovered(spell); - } - - if(discovered){ - this.fontRenderer.drawStringWithShadow(spell.getDisplayNameWithFormatting(), xSizeNoTip + 16, y, 0); - }else{ - this.mc.standardGalacticFontRenderer.drawStringWithShadow( - "\u00A79" + SpellGlyphData.getGlyphName(spell, this.mc.world), xSizeNoTip + 16, y, 0); - } - y += 10; + if(!(stack.getItem() instanceof IWorkbenchItem)){ + Wizardry.logger.warn("Invalid item in central slot of arcane workbench, how did that get there?!"); + return; } - if(WandHelper.getTotalUpgrades(wand) > 0){ + if(((IWorkbenchItem)stack.getItem()).showTooltip(stack)){ - this.fontRenderer.drawStringWithShadow( - "\u00A7f" + I18n.format("container." + Wizardry.MODID + ":arcane_workbench.upgrades"), xSizeNoTip + 6, y + 6, 0); + int y = 6; - int x = 0; - y = 50 + spells.length * 10; - // Wand upgrade tooltips - for(Item item : WandHelper.getSpecialUpgrades()){ + this.fontRenderer.drawStringWithShadow("\u00A7f" + stack.getDisplayName(), MAIN_GUI_WIDTH + 6, y, 0); - int level = WandHelper.getUpgradeLevel(wand, item); + if(stack.getItem() instanceof IManaStoringItem && ((IManaStoringItem)stack.getItem()).showManaInWorkbench(this.mc.player, stack)){ + y += 14; + this.fontRenderer.drawStringWithShadow( + "\u00A77" + I18n.format("container." + Wizardry.MODID + ":arcane_workbench.mana") + + " " + ((IManaStoringItem)stack.getItem()).getMana(stack) + "/" + + ((IManaStoringItem)stack.getItem()).getManaCapacity(stack), + MAIN_GUI_WIDTH + 6, y, 0); + } - if(level > 0){ - // The javadoc for isPointInRegion is ambiguous; what it means is that the REGION is - // relative to the GUI but the POINT isn't. - if(isPointInRegion(xSizeNoTip + 6 + x, y, 16, 16, mouseX, mouseY)){ - ItemStack stack = new ItemStack(item, level); - this.renderToolTip(stack, mouseX - guiLeft, mouseY - guiTop); + y += 14; + + if(stack.getItem() instanceof ISpellCastingItem && ((ISpellCastingItem)stack.getItem()).showSpellsInWorkbench(this.mc.player, stack)){ + + Spell[] spells = ((ISpellCastingItem)stack.getItem()).getSpells(stack); + + for(Spell spell : spells){ + + boolean discovered = true; + + if(!this.mc.player.isCreative() && WizardData.get(this.mc.player) != null){ + discovered = WizardData.get(this.mc.player).hasSpellBeenDiscovered(spell); + } + + if(discovered){ + this.fontRenderer.drawStringWithShadow(spell.getDisplayNameWithFormatting(), MAIN_GUI_WIDTH + 16, y, 0); + }else{ + this.mc.standardGalacticFontRenderer.drawStringWithShadow( + "\u00A79" + SpellGlyphData.getGlyphName(spell, this.mc.world), MAIN_GUI_WIDTH + 16, y, 0); + } + y += 10; + } + } + + if(WandHelper.getTotalUpgrades(stack) > 0){ + + y += 6; + + this.fontRenderer.drawStringWithShadow("\u00A7f" + I18n.format("container." + + Wizardry.MODID + ":arcane_workbench.upgrades"), MAIN_GUI_WIDTH + 6, y, 0); + + int x = 0; + y += 10; + + // Wand upgrade tooltips + for(Item item : WandHelper.getSpecialUpgrades()){ + + int level = WandHelper.getUpgradeLevel(stack, item); + + if(level > 0){ + // The javadoc for isPointInRegion is ambiguous; what it means is that the REGION is + // relative to the GUI but the POINT isn't. + if(isPointInRegion(MAIN_GUI_WIDTH + 6 + x, y, 16, 16, mouseX, mouseY)){ + ItemStack stack1 = new ItemStack(item, level); + this.renderToolTip(stack1, mouseX - guiLeft, mouseY - guiTop); + } + x += 18; } - x += 18; } } } @@ -228,7 +383,7 @@ public class GuiArcaneWorkbench extends GuiContainer { this.guiTop = (this.height - this.ySize) / 2; Keyboard.enableRepeatEvents(true); this.buttonList.clear(); - this.buttonList.add(this.applyBtn = new GuiButtonApply(0, this.width / 2 + 48, this.height / 2 + 3)); + this.buttonList.add(this.applyBtn = new GuiButtonApply(0, this.width / 2 + 64, this.height / 2 + 3)); } @Override @@ -244,8 +399,51 @@ public class GuiArcaneWorkbench extends GuiContainer { // Packet building IMessage msg = new PacketControlInput.Message(PacketControlInput.ControlType.APPLY_BUTTON); WizardryPacketHandler.net.sendToServer(msg); + // Sound + Minecraft.getMinecraft().getSoundHandler().playSound(PositionedSoundRecord.getMasterRecord( + WizardrySounds.BLOCK_ARCANE_WORKBENCH_SPELLBIND, 1)); + // Animation + animationTimer = 20; } } } + private class GuiButtonApply extends GuiButton { + + public GuiButtonApply(int id, int x, int y){ + super(id, x, y, 16, 16, I18n.format("container." + Wizardry.MODID + ":arcane_workbench.apply")); + } + + @Override + public void drawButton(Minecraft minecraft, int mouseX, int mouseY, float partialTicks){ + + // Whether the button is highlighted + this.hovered = mouseX >= this.x && mouseY >= this.y && mouseX < this.x + this.width && mouseY < this.y + this.height; + + int k = 72; + int l = 220; + //int colour = 14737632; + + if(this.enabled){ + if(this.hovered){ + k += this.width * 2; + //colour = 16777120; + } + }else{ + k += this.width; + //colour = 10526880; + } + + DrawingUtils.drawTexturedRect(this.x, this.y, k, l, this.width, this.height, 512, 256); + //this.drawCenteredString(minecraft.fontRenderer, this.displayString, this.x + this.width / 2, + // this.y + (this.height - 8) / 2, colour); + } + } + + @SubscribeEvent + public static void onTextureStitchEvent(TextureStitchEvent.Pre event){ + event.getMap().registerSprite(ContainerArcaneWorkbench.EMPTY_SLOT_CRYSTAL); + event.getMap().registerSprite(ContainerArcaneWorkbench.EMPTY_SLOT_UPGRADE); + } + } \ No newline at end of file diff --git a/src/main/java/electroblob/wizardry/client/gui/GuiButtonInvisible.java b/src/main/java/electroblob/wizardry/client/gui/GuiButtonInvisible.java index a65e71da..7156bb36 100644 --- a/src/main/java/electroblob/wizardry/client/gui/GuiButtonInvisible.java +++ b/src/main/java/electroblob/wizardry/client/gui/GuiButtonInvisible.java @@ -2,10 +2,8 @@ package electroblob.wizardry.client.gui; import net.minecraft.client.Minecraft; import net.minecraft.client.gui.GuiButton; -import net.minecraftforge.fml.relauncher.Side; -import net.minecraftforge.fml.relauncher.SideOnly; -@SideOnly(Side.CLIENT) +//@SideOnly(Side.CLIENT) public class GuiButtonInvisible extends GuiButton { public GuiButtonInvisible(int id, int x, int y, int width, int height){ diff --git a/src/main/java/electroblob/wizardry/client/gui/GuiButtonResurrect.java b/src/main/java/electroblob/wizardry/client/gui/GuiButtonResurrect.java new file mode 100644 index 00000000..bf50192c --- /dev/null +++ b/src/main/java/electroblob/wizardry/client/gui/GuiButtonResurrect.java @@ -0,0 +1,90 @@ +package electroblob.wizardry.client.gui; + +import electroblob.wizardry.item.ISpellCastingItem; +import electroblob.wizardry.item.ItemArtefact; +import electroblob.wizardry.packet.PacketControlInput; +import electroblob.wizardry.packet.WizardryPacketHandler; +import electroblob.wizardry.registry.Spells; +import electroblob.wizardry.registry.WizardryItems; +import electroblob.wizardry.spell.Resurrection; +import electroblob.wizardry.util.SpellModifiers; +import electroblob.wizardry.util.WizardryUtilities; +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.GuiButton; +import net.minecraft.client.gui.GuiGameOver; +import net.minecraft.client.resources.I18n; +import net.minecraft.item.ItemStack; +import net.minecraft.util.EnumHand; +import net.minecraftforge.client.event.GuiScreenEvent; +import net.minecraftforge.fml.common.Mod; +import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; +import net.minecraftforge.fml.common.gameevent.TickEvent; +import net.minecraftforge.fml.relauncher.Side; + +@Mod.EventBusSubscriber(Side.CLIENT) +public class GuiButtonResurrect extends GuiButton { + + private static int timeSinceDeath = -1; + + private final String translationKey; + + public GuiButtonResurrect(int id, int x, int y, String translationKey){ + super(id, x, y, I18n.format(translationKey + "_wait", Resurrection.getRemainingWaitTime(timeSinceDeath))); + this.translationKey = translationKey; + } + + @Override + public void drawButton(Minecraft mc, int mouseX, int mouseY, float partialTicks){ + int waitTime = Resurrection.getRemainingWaitTime(timeSinceDeath); + this.enabled = waitTime == 0; + this.displayString = I18n.format(translationKey + (waitTime == 0 ? "_ready" : "_wait"), waitTime); + super.drawButton(mc, mouseX, mouseY, partialTicks); + } + + // Event handlers + + @SubscribeEvent + public static void onClientTickEvent(TickEvent.ClientTickEvent event){ + if(event.phase == TickEvent.Phase.START && timeSinceDeath >= 0) timeSinceDeath++; + } + + @SubscribeEvent + public static void onGuiScreenInitEvent(GuiScreenEvent.InitGuiEvent event){ + + if(event.getGui() instanceof GuiGameOver && ItemArtefact.isArtefactActive(Minecraft.getMinecraft().player, WizardryItems.amulet_resurrection) + && WizardryUtilities.getHotbar(Minecraft.getMinecraft().player).stream().anyMatch(s -> Resurrection.canStackResurrect(s, Minecraft.getMinecraft().player))){ + + event.getButtonList().add(new GuiButtonResurrect(event.getButtonList().size(), event.getGui().width / 2 - 100, + event.getGui().height / 4 + 120, "spell." + Spells.resurrection.getRegistryName() + ".button")); + timeSinceDeath = 0; + } + } + + @SubscribeEvent + public static void onGuiScreenActionPerformedEvent(GuiScreenEvent.ActionPerformedEvent event){ + + if(event.getGui() instanceof GuiGameOver){ + + ItemStack stack = WizardryUtilities.getHotbar(Minecraft.getMinecraft().player).stream() + .filter(s -> Resurrection.canStackResurrect(s, Minecraft.getMinecraft().player)).findFirst().orElse(null); + + if(stack != null){ + + if(event.getButton() instanceof GuiButtonResurrect && timeSinceDeath >= 0){ + // Cast resurrection on the client player and notify the server to do the same + // ISpellCastingItem#canCast already checked in Resurrection#canStackResurrect + ((ISpellCastingItem)stack.getItem()).cast(stack, Spells.resurrection, Minecraft.getMinecraft().player, EnumHand.MAIN_HAND, 0, new SpellModifiers()); + WizardryPacketHandler.net.sendToServer(new PacketControlInput.Message(PacketControlInput.ControlType.RESURRECT_BUTTON)); + + }else if(!Minecraft.getMinecraft().world.getGameRules().getBoolean("keepInventory")){ + // Any other button drops the wand (N.B. this should be inside the stack != null check or it'll send + // packets unnecessarily and generate incorrect warnings + WizardryPacketHandler.net.sendToServer(new PacketControlInput.Message(PacketControlInput.ControlType.CANCEL_RESURRECT)); + } + + timeSinceDeath = -1; + } + } + } + +} diff --git a/src/main/java/electroblob/wizardry/client/gui/GuiSpellBook.java b/src/main/java/electroblob/wizardry/client/gui/GuiSpellBook.java index 0b2bb487..306abffb 100644 --- a/src/main/java/electroblob/wizardry/client/gui/GuiSpellBook.java +++ b/src/main/java/electroblob/wizardry/client/gui/GuiSpellBook.java @@ -1,25 +1,34 @@ package electroblob.wizardry.client.gui; -import org.lwjgl.input.Keyboard; - -import electroblob.wizardry.SpellGlyphData; -import electroblob.wizardry.WizardData; +import com.google.common.collect.ImmutableMap; import electroblob.wizardry.Wizardry; +import electroblob.wizardry.client.DrawingUtils; import electroblob.wizardry.constants.Tier; +import electroblob.wizardry.data.SpellGlyphData; +import electroblob.wizardry.data.WizardData; import electroblob.wizardry.registry.Spells; +import electroblob.wizardry.registry.WizardrySounds; import electroblob.wizardry.spell.Spell; -import electroblob.wizardry.util.WizardryUtilities; import net.minecraft.client.Minecraft; +import net.minecraft.client.audio.PositionedSoundRecord; import net.minecraft.client.gui.GuiScreen; +import net.minecraft.client.renderer.GlStateManager; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.util.ResourceLocation; +import org.lwjgl.input.Keyboard; + +import java.util.Map; public class GuiSpellBook extends GuiScreen { private int xSize, ySize; private Spell spell; - private static final ResourceLocation texture = new ResourceLocation(Wizardry.MODID, "textures/gui/spellbook.png"); + private static final Map textures = ImmutableMap.of( + Tier.NOVICE, new ResourceLocation(Wizardry.MODID, "textures/gui/spell_book_novice.png"), + Tier.APPRENTICE, new ResourceLocation(Wizardry.MODID, "textures/gui/spell_book_apprentice.png"), + Tier.ADVANCED, new ResourceLocation(Wizardry.MODID, "textures/gui/spell_book_advanced.png"), + Tier.MASTER, new ResourceLocation(Wizardry.MODID, "textures/gui/spell_book_master.png")); public GuiSpellBook(Spell spell){ super(); @@ -39,45 +48,47 @@ public class GuiSpellBook extends GuiScreen { EntityPlayer player = Minecraft.getMinecraft().player; boolean discovered = true; - if(Wizardry.settings.discoveryMode && !player.capabilities.isCreativeMode && WizardData.get(player) != null + if(Wizardry.settings.discoveryMode && !player.isCreative() && WizardData.get(player) != null && !WizardData.get(player).hasSpellBeenDiscovered(spell)){ discovered = false; } + GlStateManager.color(1, 1, 1, 1); // Just in case + // Draws spell illustration on opposite page, underneath the book so it shows through the hole. Minecraft.getMinecraft().renderEngine.bindTexture(discovered ? spell.getIcon() : Spells.none.getIcon()); DrawingUtils.drawTexturedRect(xPos + 146, yPos + 20, 0, 0, 128, 128, 128, 128); - Minecraft.getMinecraft().renderEngine.bindTexture(textures.get(spell.tier)); + Minecraft.getMinecraft().renderEngine.bindTexture(textures.get(spell.getTier())); DrawingUtils.drawTexturedRect(xPos, yPos, 0, 0, xSize, ySize, xSize, 256); super.drawScreen(par1, par2, par3); if(discovered){ this.fontRenderer.drawString(spell.getDisplayName(), xPos + 17, yPos + 15, 0); - this.fontRenderer.drawString(spell.type.getDisplayName(), xPos + 17, yPos + 26, 0x777777); + this.fontRenderer.drawString(spell.getType().getDisplayName(), xPos + 17, yPos + 26, 0x777777); }else{ this.mc.standardGalacticFontRenderer.drawString(SpellGlyphData.getGlyphName(spell, player.world), xPos + 17, yPos + 15, 0); - this.mc.standardGalacticFontRenderer.drawString(spell.type.getDisplayName(), xPos + 17, yPos + 26, + this.mc.standardGalacticFontRenderer.drawString(spell.getType().getDisplayName(), xPos + 17, yPos + 26, 0x777777); } - this.fontRenderer.drawString("-------------------", xPos + 17, yPos + 35, 0); + //this.fontRenderer.drawString("-------------------", xPos + 17, yPos + 35, 0); - if(spell.tier == Tier.BASIC){ + if(spell.getTier() == Tier.NOVICE){ // Basic is usually white but this doesn't show up. - this.fontRenderer.drawString("Tier: \u00A77" + Tier.BASIC.getDisplayName(), xPos + 17, yPos + 45, 0); + this.fontRenderer.drawString("Tier: \u00A77" + Tier.NOVICE.getDisplayName(), xPos + 17, yPos + 45, 0); }else{ - this.fontRenderer.drawString("Tier: " + spell.tier.getDisplayNameWithFormatting(), xPos + 17, yPos + 45, 0); + this.fontRenderer.drawString("Tier: " + spell.getTier().getDisplayNameWithFormatting(), xPos + 17, yPos + 45, 0); } - String element = "Element: " + spell.element.getFormattingCode() + spell.element.getDisplayName(); + String element = "Element: " + spell.getElement().getFormattingCode() + spell.getElement().getDisplayName(); if(!discovered) element = "Element: ?"; this.fontRenderer.drawString(element, xPos + 17, yPos + 57, 0); - String manaCost = "Mana Cost: " + spell.cost; - if(spell.isContinuous) manaCost = "Mana Cost: " + spell.cost + "/second"; + String manaCost = "Mana Cost: " + spell.getCost(); + if(spell.isContinuous) manaCost = "Mana Cost: " + spell.getCost() + "/second"; if(!discovered) manaCost = "Mana Cost: ?"; this.fontRenderer.drawString(manaCost, xPos + 17, yPos + 69, 0); @@ -93,10 +104,18 @@ public class GuiSpellBook extends GuiScreen { super.initGui(); Keyboard.enableRepeatEvents(true); this.buttonList.clear(); + + this.mc.getSoundHandler().playSound(PositionedSoundRecord.getMasterRecord(WizardrySounds.MISC_BOOK_OPEN, 1)); } public void onGuiClosed(){ super.onGuiClosed(); Keyboard.enableRepeatEvents(false); } + + @Override + public boolean doesGuiPauseGame(){ + return Wizardry.settings.booksPauseGame; + } + } diff --git a/src/main/java/electroblob/wizardry/client/gui/GuiSpellDisplay.java b/src/main/java/electroblob/wizardry/client/gui/GuiSpellDisplay.java index 6d2a0c6d..85e2aa61 100644 --- a/src/main/java/electroblob/wizardry/client/gui/GuiSpellDisplay.java +++ b/src/main/java/electroblob/wizardry/client/gui/GuiSpellDisplay.java @@ -1,30 +1,17 @@ package electroblob.wizardry.client.gui; -import java.io.BufferedReader; -import java.io.IOException; -import java.io.InputStreamReader; -import java.util.Collections; -import java.util.LinkedHashMap; -import java.util.List; -import java.util.Map; -import java.util.Map.Entry; -import java.util.Set; - import com.google.gson.Gson; import com.google.gson.JsonElement; import com.google.gson.JsonObject; - import electroblob.wizardry.Settings; -import electroblob.wizardry.SpellGlyphData; -import electroblob.wizardry.WizardData; import electroblob.wizardry.Wizardry; import electroblob.wizardry.client.ClientProxy; import electroblob.wizardry.client.DrawingUtils; import electroblob.wizardry.client.MixedFontRenderer; -import electroblob.wizardry.constants.Constants; -import electroblob.wizardry.item.ItemWand; +import electroblob.wizardry.data.SpellGlyphData; +import electroblob.wizardry.data.WizardData; +import electroblob.wizardry.item.ISpellCastingItem; import electroblob.wizardry.registry.Spells; -import electroblob.wizardry.registry.WizardryItems; import electroblob.wizardry.registry.WizardryPotions; import electroblob.wizardry.spell.Spell; import electroblob.wizardry.util.WandHelper; @@ -37,14 +24,22 @@ import net.minecraft.client.resources.IResource; import net.minecraft.client.resources.IResourceManager; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.item.ItemStack; +import net.minecraft.util.EnumHandSide; import net.minecraft.util.JsonUtils; import net.minecraft.util.ResourceLocation; +import net.minecraft.util.math.MathHelper; import net.minecraftforge.client.event.RenderGameOverlayEvent; import net.minecraftforge.event.entity.living.LivingEvent.LivingUpdateEvent; import net.minecraftforge.fml.common.Mod; import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; import net.minecraftforge.fml.relauncher.Side; +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; +import java.util.*; +import java.util.Map.Entry; + @Mod.EventBusSubscriber(Side.CLIENT) public class GuiSpellDisplay { @@ -53,8 +48,9 @@ public class GuiSpellDisplay { /** A map which stores all loaded HUD skin objects. This gets wiped on resource pack reload and repopulated with * mappings as specified by {@code _index.json} (these stack between resource packs). The keys in the map correspond * to the keys in {@code _index.json}, and are sorted in that order, with skins belonging to resource packs sorted - * from lowest to highest priority. The skins in the base mod will therefore always be first. */ - private static final Map skins = new LinkedHashMap<>(12); // 12 is the number of skins packaged with the mod + * from lowest to highest priority. The skins in the base mod will therefore always be first. (It should be noted, + * however, that in the gui itself the skins are always sorted in alphabetical order for some reason.) */ + private static final Map skins = new LinkedHashMap<>(14); // 14 is the number of skins packaged with the mod private static final Gson gson = new Gson(); @@ -66,6 +62,9 @@ public class GuiSpellDisplay { private static final float SPELL_NAME_SCALE = 0.5f; /** Opacity of the next/previous spell names, as a fraction. */ private static final float SPELL_NAME_OPACITY = 0.3f; + + private static final int HALF_HOTBAR_WIDTH = 97; // Half the width of the hotbar, plus a bit for clearance + private static final int OFFHAND_SLOT_WIDTH = 29; // Width of the offhand slot plus the gap between it and the hotbar /** Controls the spell switching animation. Positive when switching to the next spell, negative when switching to * the previous spell. Decremented in magnitude by 1 each tick until it reaches 0 again. */ @@ -103,14 +102,18 @@ public class GuiSpellDisplay { EntityPlayer player = mc.player; + if(player.isSpectator()) return; // Spectators shouldn't have the spell HUD! + // If the player has a wand in each hand, only displays for the one in the main hand. ItemStack wand = player.getHeldItemMainhand(); + boolean mainHand = true; - if(!(wand.getItem() instanceof ItemWand)){ + if(!(wand.getItem() instanceof ISpellCastingItem && ((ISpellCastingItem)wand.getItem()).showSpellHUD(player, wand))){ wand = player.getHeldItemOffhand(); - // If the player isn't holding a wand, then nothing else needs to be done. - if(!(wand.getItem() instanceof ItemWand)) return; + mainHand = false; + // If the player isn't holding a spellcasting item that shows the HUD, then nothing else needs to be done. + if(!(wand.getItem() instanceof ISpellCastingItem && ((ISpellCastingItem)wand.getItem()).showSpellHUD(player, wand))) return; } int width = event.getResolution().getScaledWidth(); @@ -118,6 +121,11 @@ public class GuiSpellDisplay { boolean flipX = Wizardry.settings.spellHUDPosition.flipX; boolean flipY = Wizardry.settings.spellHUDPosition.flipY; + + if(Wizardry.settings.spellHUDPosition.dynamic){ + // ............. | This bit is true if the wand is on the left, false if it is on the right + flipX = flipX == ((mainHand ? player.getPrimaryHand() : player.getPrimaryHand().opposite()) == EnumHandSide.LEFT); + } Skin skin = skins.get(Wizardry.settings.spellHUDSkin); @@ -134,13 +142,32 @@ public class GuiSpellDisplay { return; } } + + GlStateManager.pushMatrix(); // 'Origin' of the spell hud (bottom left corner of the actual texture, always in the corner of the screen) int x = flipX ? width : 0; int y = flipY ? 0: height; + // The space available to render the spell HUD + float xSpace = (float)(width/2 - HALF_HOTBAR_WIDTH); + if(!player.getHeldItemOffhand().isEmpty() + // Tests whether the offhand slot is rendered on the same side of the hotbar as the spell HUD + && (player.getPrimaryHand() == EnumHandSide.LEFT) == flipX){ + xSpace -= OFFHAND_SLOT_WIDTH; + } + + // If the skin is at the bottom and the screen width is too small, scale it to avoid the hotbar and offhand + if(!flipY && skin.getWidth() > xSpace){ // width/2 - 91 - 29 taken from GuiInGame line 547 + float scale = xSpace / skin.getWidth(); + GlStateManager.scale(scale, scale, 1); + x = MathHelper.ceil(x/scale); + y = MathHelper.ceil(y/scale); + } + Spell spell = WandHelper.getCurrentSpell(wand); int cooldown = WandHelper.getCurrentCooldown(wand); + int maxCooldown = WandHelper.getCurrentMaxCooldown(wand); if(event.getType() == RenderGameOverlayEvent.ElementType.TEXT){ @@ -155,16 +182,9 @@ public class GuiSpellDisplay { }else if(event.getType() == RenderGameOverlayEvent.ElementType.HOTBAR){ - float cooldownMultiplier = 1.0f - WandHelper.getUpgradeLevel(wand, WizardryItems.cooldown_upgrade) * Constants.COOLDOWN_REDUCTION_PER_LEVEL; - - if(player.isPotionActive(WizardryPotions.font_of_mana)){ - // Dividing by this rather than setting it takes upgrades and font of mana into account simultaneously - cooldownMultiplier /= 2 + player.getActivePotionEffect(WizardryPotions.font_of_mana).getAmplifier(); - } - boolean discovered = true; - if(!player.capabilities.isCreativeMode && WizardData.get(player) != null){ + if(!player.isCreative() && WizardData.get(player) != null){ discovered = WizardData.get(player).hasSpellBeenDiscovered(spell); } @@ -172,31 +192,23 @@ public class GuiSpellDisplay { float progress = 1; // Doesn't really matter what progress is when in creative, but we might as well avoid the calculation. - if(!player.capabilities.isCreativeMode && !spell.isContinuous){ + if(!player.isCreative() && !spell.isContinuous){ // Subtracted partial tick time to make it smoother - progress = (spell.cooldown * cooldownMultiplier - (float)cooldown + event.getPartialTicks()) - /(spell.cooldown * cooldownMultiplier); + progress = maxCooldown == 0 ? 1 : (maxCooldown - (float)cooldown + event.getPartialTicks()) / maxCooldown; } - skin.drawBackground(x, y, flipX, flipY, icon, progress, player.capabilities.isCreativeMode); + skin.drawBackground(x, y, flipX, flipY, icon, progress, player.isCreative()); } + + GlStateManager.popMatrix(); } /** - * Makes the given opaque colour translucent with the given opacity. - * @param colour An integer colour code, should be a 6-digit hexadecimal (i.e. opaque). - * @param opacity The opacity to apply to the given colour, as a fraction between 0 and 1. - * @return The resulting integer colour code, which will be an 8-digit hexadecimal. - */ - private static int makeTranslucent(int colour, float opacity){ - return colour + ((int)(0xff * opacity * 0x01000000)); - } - - /** Gets the name of the given spell, with formatted added according to its cooldown and whether the given player + * Gets the name of the given spell, with formatting added according to its cooldown and whether the given player * has discovered it. * @param spell The spell to get the name of. - * @param The player to test for having discovered the given spell. + * @param player The player to test for having discovered the given spell. * @param cooldown The spell's current cooldown. * @return The spell name, with relevant formatting added, for use with the {@link MixedFontRenderer}. */ @@ -204,12 +216,12 @@ public class GuiSpellDisplay { boolean discovered = true; - if(!player.capabilities.isCreativeMode && WizardData.get(player) != null){ + if(!player.isCreative() && WizardData.get(player) != null){ discovered = WizardData.get(player).hasSpellBeenDiscovered(spell); } // Makes spells greyed out if they are in cooldown or if the player has the arcane jammer effect - String format = cooldown > 0 || player.isPotionActive(WizardryPotions.arcane_jammer) ? "\u00A78" : spell.element.getFormattingCode(); + String format = cooldown > 0 || player.isPotionActive(WizardryPotions.arcane_jammer) ? "\u00A78" : spell.getElement().getFormattingCode(); if(!discovered) format = "\u00A79"; String name = discovered ? spell.getDisplayName() : SpellGlyphData.getGlyphName(spell, player.world); @@ -274,10 +286,15 @@ public class GuiSpellDisplay { } } - /** Instances of this class represent individual HUD skins, complete with texture and all necessary metadata. This + /** + * Instances of this class represent individual HUD skins, complete with texture and all necessary metadata. This * class serves to separate the logic behind the spell HUD from its actual rendering. * All information and processing done within this class relates only to the actual drawing; spells and such like - * must be queried outside of this class and fed into the methods as appropriate. */ + * must be queried outside of this class and fed into the methods as appropriate. + * + * @author Electroblob + * @since Wizardry 4.2 + */ public static class Skin { /** The texture file for this skin. */ diff --git a/src/main/java/electroblob/wizardry/client/EntityNameEntry.java b/src/main/java/electroblob/wizardry/client/gui/config/EntityNameEntry.java similarity index 90% rename from src/main/java/electroblob/wizardry/client/EntityNameEntry.java rename to src/main/java/electroblob/wizardry/client/gui/config/EntityNameEntry.java index e6b647f5..483c23cb 100644 --- a/src/main/java/electroblob/wizardry/client/EntityNameEntry.java +++ b/src/main/java/electroblob/wizardry/client/gui/config/EntityNameEntry.java @@ -1,21 +1,17 @@ -package electroblob.wizardry.client; - -import java.util.Map; -import java.util.Map.Entry; -import java.util.stream.Collectors; +package electroblob.wizardry.client.gui.config; import net.minecraft.client.Minecraft; import net.minecraft.client.resources.I18n; import net.minecraft.util.ResourceLocation; -import net.minecraftforge.fml.client.config.GuiButtonExt; -import net.minecraftforge.fml.client.config.GuiEditArray; -import net.minecraftforge.fml.client.config.GuiEditArrayEntries; +import net.minecraftforge.fml.client.config.*; import net.minecraftforge.fml.client.config.GuiEditArrayEntries.StringEntry; -import net.minecraftforge.fml.client.config.GuiSelectString; -import net.minecraftforge.fml.client.config.IConfigElement; import net.minecraftforge.fml.common.registry.EntityEntry; import net.minecraftforge.fml.common.registry.ForgeRegistries; +import java.util.Map; +import java.util.Map.Entry; +import java.util.stream.Collectors; + /** * [NYI] Intended as a way of choosing entities by name from all those currently registered, within the config file, so * that users don't have to look up the entity IDs. I can't get this to work correctly at the moment. diff --git a/src/main/java/electroblob/wizardry/client/gui/GuiConfigWizardry.java b/src/main/java/electroblob/wizardry/client/gui/config/GuiConfigWizardry.java similarity index 90% rename from src/main/java/electroblob/wizardry/client/gui/GuiConfigWizardry.java rename to src/main/java/electroblob/wizardry/client/gui/config/GuiConfigWizardry.java index 7e7fc01e..7f76ad1d 100644 --- a/src/main/java/electroblob/wizardry/client/gui/GuiConfigWizardry.java +++ b/src/main/java/electroblob/wizardry/client/gui/config/GuiConfigWizardry.java @@ -1,7 +1,4 @@ -package electroblob.wizardry.client.gui; - -import java.util.ArrayList; -import java.util.List; +package electroblob.wizardry.client.gui.config; import electroblob.wizardry.Settings; import electroblob.wizardry.Wizardry; @@ -15,6 +12,9 @@ import net.minecraftforge.fml.client.config.GuiConfigEntries; import net.minecraftforge.fml.client.config.GuiConfigEntries.CategoryEntry; import net.minecraftforge.fml.client.config.IConfigElement; +import java.util.ArrayList; +import java.util.List; + public class GuiConfigWizardry extends GuiConfig { public GuiConfigWizardry(GuiScreen parent){ @@ -33,7 +33,8 @@ public class GuiConfigWizardry extends GuiConfig { configList.add(new DummyCategoryElement("clientConfig", "config." + Wizardry.MODID + ".category." + Settings.CLIENT_CATEGORY, ClientCategory.class)); configList.add(new DummyCategoryElement("spellsConfig", "config." + Wizardry.MODID + ".category." + Settings.SPELLS_CATEGORY, SpellsCategory.class)); configList.add(new DummyCategoryElement("resistancesConfig", "config." + Wizardry.MODID + ".category." + Settings.RESISTANCES_CATEGORY, ResistancesCategory.class)); - + configList.add(new DummyCategoryElement("compatibilityConfig", "config." + Wizardry.MODID + ".category." + Settings.COMPATIBILITY_CATEGORY, CompatibilityCategory.class)); + configList.addAll(new ConfigElement(Wizardry.settings.getConfigCategory(Configuration.CATEGORY_GENERAL)).getChildElements()); return configList; @@ -41,7 +42,7 @@ public class GuiConfigWizardry extends GuiConfig { // The reason this system is so convoluted is that it's designed for use with the @Config annotation. The problem is, // I'm not sure whether that will play well with the load phases. Hmmm... - + public static abstract class CategoryBase extends CategoryEntry { public CategoryBase(GuiConfig owningScreen, GuiConfigEntries owningEntryList, IConfigElement prop){ @@ -77,6 +78,36 @@ public class GuiConfigWizardry extends GuiConfig { @Override protected String getCategory() { return Settings.GAMEPLAY_CATEGORY; } } + + /** Worldgen category of the config gui. */ + public static class WorldgenCategory extends CategoryBase { + + public WorldgenCategory(GuiConfig owningScreen, GuiConfigEntries owningEntryList, IConfigElement prop){ + super(owningScreen, owningEntryList, prop); + } + + @Override protected String getCategory() { return Settings.WORLDGEN_CATEGORY; } + } + + /** Commands category of the config gui. */ + public static class CommandsCategory extends CategoryBase { + + public CommandsCategory(GuiConfig owningScreen, GuiConfigEntries owningEntryList, IConfigElement prop){ + super(owningScreen, owningEntryList, prop); + } + + @Override protected String getCategory() { return Settings.COMMANDS_CATEGORY; } + } + + /** Client category of the config gui. */ + public static class ClientCategory extends CategoryBase { + + public ClientCategory(GuiConfig owningScreen, GuiConfigEntries owningEntryList, IConfigElement prop){ + super(owningScreen, owningEntryList, prop); + } + + @Override protected String getCategory() { return Settings.CLIENT_CATEGORY; } + } /** Spells category of the config gui. */ public static class SpellsCategory extends CategoryBase { @@ -97,34 +128,14 @@ public class GuiConfigWizardry extends GuiConfig { @Override protected String getCategory() { return Settings.RESISTANCES_CATEGORY; } } - - /** Worldgen category of the config gui. */ - public static class WorldgenCategory extends CategoryBase { - - public WorldgenCategory(GuiConfig owningScreen, GuiConfigEntries owningEntryList, IConfigElement prop){ - super(owningScreen, owningEntryList, prop); - } - - @Override protected String getCategory() { return Settings.WORLDGEN_CATEGORY; } - } - - /** Client category of the config gui. */ - public static class ClientCategory extends CategoryBase { - - public ClientCategory(GuiConfig owningScreen, GuiConfigEntries owningEntryList, IConfigElement prop){ - super(owningScreen, owningEntryList, prop); - } - - @Override protected String getCategory() { return Settings.CLIENT_CATEGORY; } - } - + /** Commands category of the config gui. */ - public static class CommandsCategory extends CategoryBase { - - public CommandsCategory(GuiConfig owningScreen, GuiConfigEntries owningEntryList, IConfigElement prop){ + public static class CompatibilityCategory extends CategoryBase { + + public CompatibilityCategory(GuiConfig owningScreen, GuiConfigEntries owningEntryList, IConfigElement prop){ super(owningScreen, owningEntryList, prop); } - - @Override protected String getCategory() { return Settings.COMMANDS_CATEGORY; } + + @Override protected String getCategory() { return Settings.COMPATIBILITY_CATEGORY; } } } diff --git a/src/main/java/electroblob/wizardry/client/gui/GuiSelectHUDSkin.java b/src/main/java/electroblob/wizardry/client/gui/config/GuiSelectHUDSkin.java similarity index 95% rename from src/main/java/electroblob/wizardry/client/gui/GuiSelectHUDSkin.java rename to src/main/java/electroblob/wizardry/client/gui/config/GuiSelectHUDSkin.java index 92a1fbe8..985d1594 100644 --- a/src/main/java/electroblob/wizardry/client/gui/GuiSelectHUDSkin.java +++ b/src/main/java/electroblob/wizardry/client/gui/config/GuiSelectHUDSkin.java @@ -1,12 +1,8 @@ -package electroblob.wizardry.client.gui; - -import java.util.Map; - -import javax.annotation.Nullable; +package electroblob.wizardry.client.gui.config; import com.google.common.collect.Lists; - import electroblob.wizardry.Wizardry; +import electroblob.wizardry.client.gui.GuiSpellDisplay; import electroblob.wizardry.client.gui.GuiSpellDisplay.Skin; import electroblob.wizardry.registry.Spells; import net.minecraft.client.gui.GuiButton; @@ -16,6 +12,9 @@ import net.minecraft.client.resources.I18n; import net.minecraftforge.fml.client.config.GuiSelectString; import net.minecraftforge.fml.client.config.IConfigElement; +import javax.annotation.Nullable; +import java.util.Map; + public class GuiSelectHUDSkin extends GuiSelectString { public GuiSelectHUDSkin(GuiScreen parentScreen, IConfigElement configElement, int slotIndex, Map selectableValues, Object currentValue, boolean enabled){ @@ -50,7 +49,7 @@ public class GuiSelectHUDSkin extends GuiSelectString { if(this.currentValue instanceof String){ - this.drawString(this.fontRenderer, I18n.format("config." + Wizardry.MODID + ":spell_hud_skin.preview"), 170, 44, 0xffffff); + this.drawString(this.fontRenderer, I18n.format("config." + Wizardry.MODID + ".spell_hud_skin.preview"), 170, 44, 0xffffff); int previewLeft = 170; int previewRight = width-10; diff --git a/src/main/java/electroblob/wizardry/client/gui/config/NamedBooleanEntry.java b/src/main/java/electroblob/wizardry/client/gui/config/NamedBooleanEntry.java new file mode 100644 index 00000000..0e9fd5ed --- /dev/null +++ b/src/main/java/electroblob/wizardry/client/gui/config/NamedBooleanEntry.java @@ -0,0 +1,93 @@ +package electroblob.wizardry.client.gui.config; + +import net.minecraft.client.resources.I18n; +import net.minecraftforge.fml.client.config.GuiConfig; +import net.minecraftforge.fml.client.config.GuiConfigEntries; +import net.minecraftforge.fml.client.config.GuiUtils; +import net.minecraftforge.fml.client.config.IConfigElement; + +/** + * Same as {@link net.minecraftforge.fml.client.config.GuiConfigEntries.BooleanEntry}, but instead of simply + * displaying 'true' or 'false', allows the two display strings to be specified in the lang file. + */ +// BooleanEntry's constructors are private, so I had to copy the whole goddamn class to change one method. Thanks Forge. +public class NamedBooleanEntry extends GuiConfigEntries.ButtonEntry { + + protected final boolean beforeValue; + protected boolean currentValue; + + private static final String DEFAULT_KEY = "config.ebwizardry.generic"; + + public NamedBooleanEntry(GuiConfig owningScreen, GuiConfigEntries owningEntryList, IConfigElement configElement){ + super(owningScreen, owningEntryList, configElement); + this.beforeValue = Boolean.valueOf(configElement.get().toString()); + this.currentValue = beforeValue; + this.btnValue.enabled = enabled(); + updateValueButtonText(); + } + + // This is the only method that's any different + @Override + public void updateValueButtonText(){ + + String langKey = configElement.getLanguageKey() + "." + currentValue; + this.btnValue.displayString = I18n.format(langKey); + // If the key is unspecified, it defaults to the generic 'Enabled'/'Disabled' keys and adds a red/green colour + if(this.btnValue.displayString.equals(langKey)){ + this.btnValue.displayString = I18n.format(DEFAULT_KEY + "." + currentValue); + btnValue.packedFGColour = currentValue ? GuiUtils.getColorCode('a', true) : GuiUtils.getColorCode('c', true); + } + } + + // Everything from here down is the same as BooleanEntry + + @Override + public void valueButtonPressed(int slotIndex){ + if(enabled()) currentValue = !currentValue; + } + + @Override + public boolean isDefault(){ + return currentValue == Boolean.valueOf(configElement.getDefault().toString()); + } + + @Override + public void setToDefault(){ + if(enabled()){ + currentValue = Boolean.valueOf(configElement.getDefault().toString()); + updateValueButtonText(); + } + } + + @Override + public boolean isChanged(){ + return currentValue != beforeValue; + } + + @Override + public void undoChanges(){ + if(enabled()){ + currentValue = beforeValue; + updateValueButtonText(); + } + } + + @Override + public boolean saveConfigElement(){ + if(enabled() && isChanged()){ + configElement.set(currentValue); + return configElement.requiresMcRestart(); + } + return false; + } + + @Override + public Boolean getCurrentValue(){ + return currentValue; + } + + @Override + public Boolean[] getCurrentValues(){ + return new Boolean[]{getCurrentValue()}; + } +} diff --git a/src/main/java/electroblob/wizardry/client/SpellHUDSkinChooserEntry.java b/src/main/java/electroblob/wizardry/client/gui/config/SpellHUDSkinChooserEntry.java similarity index 85% rename from src/main/java/electroblob/wizardry/client/SpellHUDSkinChooserEntry.java rename to src/main/java/electroblob/wizardry/client/gui/config/SpellHUDSkinChooserEntry.java index a6872673..e2ddb3ed 100644 --- a/src/main/java/electroblob/wizardry/client/SpellHUDSkinChooserEntry.java +++ b/src/main/java/electroblob/wizardry/client/gui/config/SpellHUDSkinChooserEntry.java @@ -1,10 +1,5 @@ -package electroblob.wizardry.client; +package electroblob.wizardry.client.gui.config; -import java.util.Map; -import java.util.Map.Entry; -import java.util.stream.Collectors; - -import electroblob.wizardry.client.gui.GuiSelectHUDSkin; import electroblob.wizardry.client.gui.GuiSpellDisplay; import net.minecraftforge.client.gui.ForgeGuiFactory.ForgeConfigGui.ModIDEntry; import net.minecraftforge.fml.client.config.GuiConfig; @@ -12,17 +7,19 @@ import net.minecraftforge.fml.client.config.GuiConfigEntries; import net.minecraftforge.fml.client.config.GuiConfigEntries.SelectValueEntry; import net.minecraftforge.fml.client.config.IConfigElement; +import java.util.Map; +import java.util.Map.Entry; +import java.util.stream.Collectors; + /** * Custom config GUI for spell HUD skin selection; displays a list of all the loaded skins and a preview of the currently * selected skin. based off of {@link ModIDEntry} from Forge. */ public class SpellHUDSkinChooserEntry extends SelectValueEntry { - public SpellHUDSkinChooserEntry(GuiConfig owningScreen, GuiConfigEntries owningEntryList, IConfigElement prop) - { + public SpellHUDSkinChooserEntry(GuiConfig owningScreen, GuiConfigEntries owningEntryList, IConfigElement prop){ super(owningScreen, owningEntryList, prop, getSelectableValues()); - if (this.selectableValues.size() == 0) - this.btnValue.enabled = false; + if(this.selectableValues.size() == 0) this.btnValue.enabled = false; } private static Map getSelectableValues(){ diff --git a/src/main/java/electroblob/wizardry/client/gui/handbook/Contents.java b/src/main/java/electroblob/wizardry/client/gui/handbook/Contents.java index 2ef67821..1853e5a1 100644 --- a/src/main/java/electroblob/wizardry/client/gui/handbook/Contents.java +++ b/src/main/java/electroblob/wizardry/client/gui/handbook/Contents.java @@ -27,6 +27,7 @@ class Contents { // Final fields are mandatory, the rest are optional final String id; + final Section section; private boolean hyperlinks = true; private boolean pageNumbers = true; private String separator = "."; @@ -37,10 +38,14 @@ class Contents { private final List
    entries; - private Contents(String id){ + private List
    visibleEntries; + + private Contents(String id, Section section){ this.id = id; + this.section = section; this.entries = new ArrayList<>(); this.buttons = new ArrayList<>(); + this.visibleEntries = new ArrayList<>(); } /** Returns an unmodifiable, flattened collection of all the buttons in this contents. */ @@ -83,26 +88,29 @@ class Contents { for(int page : visiblePages){ - if(page >= 0 && page < entries.size() / maxLineNumber + 1){ + if(page >= 0 && page < visibleEntries.size() / maxLineNumber + 1){ int x = left + (GuiWizardHandbook.isRightPage(startPage + page) ? GuiWizardHandbook.GUI_WIDTH - GuiWizardHandbook.TEXT_INSET_X - GuiWizardHandbook.PAGE_WIDTH : GuiWizardHandbook.TEXT_INSET_X); int y = top + GuiWizardHandbook.TEXT_INSET_Y + startLine * font.FONT_HEIGHT; - for(Section entry : this.entries){ + for(Section entry : this.visibleEntries){ - int nameWidth = font.getStringWidth(entry.title); + if(entry.isUnlocked()){ - String dotsAndNumber = " " + entry.startPage; + int nameWidth = font.getStringWidth(entry.title); - while(font.getStringWidth(dotsAndNumber) < GuiWizardHandbook.PAGE_WIDTH - nameWidth - 2){ - dotsAndNumber = separator + dotsAndNumber; + String dotsAndNumber = " " + entry.startPage; + + while(font.getStringWidth(dotsAndNumber) < GuiWizardHandbook.PAGE_WIDTH - nameWidth - 2){ + dotsAndNumber = separator + dotsAndNumber; + } + + font.drawString(dotsAndNumber, x + GuiWizardHandbook.PAGE_WIDTH - font.getStringWidth(dotsAndNumber), y, DrawingUtils.BLACK, false); + + if(!hyperlinks) font.drawString(entry.title, x, y, DrawingUtils.BLACK, false); + + y += font.FONT_HEIGHT; } - - font.drawString(dotsAndNumber, x + GuiWizardHandbook.PAGE_WIDTH - font.getStringWidth(dotsAndNumber), y, DrawingUtils.BLACK, false); - - if(!hyperlinks) font.drawString(entry.title, x, y, DrawingUtils.BLACK, false); - - y += font.FONT_HEIGHT; } } } @@ -124,6 +132,10 @@ class Contents { this.buttons.clear(); + this.visibleEntries = new ArrayList<>(entries); // Need to copy the collection first! + + this.visibleEntries.removeIf(s -> !s.isUnlocked()); + if(hyperlinks){ // FONT_HEIGHT may change between fonts, so this is calculated here. With the default font it's 14. @@ -134,12 +146,12 @@ class Contents { List list = new ArrayList<>(maxLineNumber); - for(Section entry : this.entries){ + for(Section entry : this.visibleEntries){ int x = GuiWizardHandbook.isRightPage(startPage) ? left + GuiWizardHandbook.GUI_WIDTH - GuiWizardHandbook.TEXT_INSET_X - GuiWizardHandbook.PAGE_WIDTH : left + GuiWizardHandbook.TEXT_INSET_X; int y = top + GuiWizardHandbook.TEXT_INSET_Y + startLine * font.FONT_HEIGHT; - list.add(new GuiButtonHyperlink.Internal(0, x, y, font, entry.title, entry, 0, "")); + list.add(new GuiButtonHyperlink.Internal(0, x, y, font, entry.title, entry, 0, "", maxLineNumber-startLine, GuiWizardHandbook.isRightPage(startPage))); startLine++; @@ -156,21 +168,22 @@ class Contents { // Returning this is kind of trivial at the moment but if we ever wanted to add a header or something, // it would be more useful. - return entries.size(); + return visibleEntries.size(); } /** * Parses the given JSON object and constructs a new {@code Contents} from it, setting all the relevant fields * and references. * + * @param parent The parent section for this contents. * @param json A JSON object representing the contents to be constructed. This must contain at least an "id" * string. * @return The resulting {@code Contents} object. * @throws JsonSyntaxException if at any point the JSON object is found to be invalid. */ - static Contents fromJson(JsonObject json){ + static Contents fromJson(Section parent, JsonObject json){ - Contents contents = new Contents(JsonUtils.getString(json, "id")); + Contents contents = new Contents(JsonUtils.getString(json, "id"), parent); contents.hyperlinks = JsonUtils.getBoolean(json, "hyperlinks", true); contents.pageNumbers = JsonUtils.getBoolean(json, "page_numbers", true); diff --git a/src/main/java/electroblob/wizardry/client/gui/handbook/CraftingRecipe.java b/src/main/java/electroblob/wizardry/client/gui/handbook/CraftingRecipe.java index ecaf5105..a7b32212 100644 --- a/src/main/java/electroblob/wizardry/client/gui/handbook/CraftingRecipe.java +++ b/src/main/java/electroblob/wizardry/client/gui/handbook/CraftingRecipe.java @@ -1,43 +1,38 @@ package electroblob.wizardry.client.gui.handbook; +import com.google.common.collect.Streams; import com.google.gson.JsonElement; import com.google.gson.JsonObject; import com.google.gson.JsonSyntaxException; import electroblob.wizardry.client.DrawingUtils; -import electroblob.wizardry.spell.Mine; import net.minecraft.client.Minecraft; import net.minecraft.client.gui.FontRenderer; -import net.minecraft.client.gui.GuiScreen; -import net.minecraft.client.gui.recipebook.GuiRecipeBook; import net.minecraft.client.renderer.GlStateManager; import net.minecraft.client.renderer.RenderHelper; import net.minecraft.client.renderer.RenderItem; -import net.minecraft.item.Item; import net.minecraft.item.ItemStack; import net.minecraft.item.crafting.CraftingManager; import net.minecraft.item.crafting.IRecipe; import net.minecraft.item.crafting.Ingredient; -import net.minecraft.stats.RecipeBook; import net.minecraft.util.JsonUtils; -import net.minecraft.util.NonNullList; import net.minecraft.util.ResourceLocation; -import java.util.HashSet; -import java.util.Map; -import java.util.Set; +import java.util.*; class CraftingRecipe { - static final int WIDTH = 111, HEIGHT = 56; + static final int BORDER = 7; + static final int TEXTURE_INSET_X = 40, TEXTURE_INSET_Y = 190; + static final int WIDTH = 121, HEIGHT = 66; // Final fields are mandatory, the rest are optional - private final ResourceLocation location; + private final ResourceLocation[] locations; // Derived fields, not specifically defined in JSON - private IRecipe recipe; + private List recipes; private final Set instances = new HashSet<>(); - private CraftingRecipe(ResourceLocation location){ - this.location = location; + private CraftingRecipe(ResourceLocation[] locations){ + this.locations = locations; } /** @@ -60,9 +55,14 @@ class CraftingRecipe { * the recipes aren't necessarily loaded at that point. */ void load(){ - this.recipe = CraftingManager.getRecipe(location); + recipes = new ArrayList<>(locations.length); - if(recipe == null) throw new JsonSyntaxException("No such recipe: " + location); + for(ResourceLocation location : locations){ + + IRecipe recipe = CraftingManager.getRecipe(location); + if(recipe == null) throw new JsonSyntaxException("No such recipe: " + location); + recipes.add(recipe); + } } /** @@ -75,9 +75,12 @@ class CraftingRecipe { * @param top The y coordinate of the top of the GUI. */ void draw(FontRenderer font, RenderItem itemRenderer, int doublePage, int left, int top){ + + int index = (int)(Minecraft.getSystemTime() % Integer.MAX_VALUE)/2000; + for(int[] instance : instances){ if(GuiWizardHandbook.singleToDoublePage(instance[0]) == doublePage){ - renderCraftingRecipe(font, itemRenderer, left + instance[1], top + instance[2], this.recipe); + renderCraftingRecipe(font, itemRenderer, left + instance[1], top + instance[2], recipes.get(index % recipes.size())); } } } @@ -92,9 +95,12 @@ class CraftingRecipe { * @param top The y coordinate of the top of the GUI. */ void drawTooltips(GuiWizardHandbook gui, FontRenderer font, RenderItem itemRenderer, int doublePage, int left, int top, int mouseX, int mouseY){ + + int index = (int)(Minecraft.getSystemTime() % Integer.MAX_VALUE)/2000; + for(int[] instance : instances){ if(GuiWizardHandbook.singleToDoublePage(instance[0]) == doublePage){ - renderCraftingTooltips(gui, itemRenderer, left + instance[1], top + instance[2], mouseX, mouseY, this.recipe); + renderCraftingTooltips(gui, itemRenderer, left + instance[1], top + instance[2], mouseX, mouseY, recipes.get(index % recipes.size())); } } } @@ -103,15 +109,16 @@ class CraftingRecipe { * Parses the given JSON object and constructs a new {@code Image} from it, setting all the relevant fields * and references. * - * @param json A JSON object representing the image to be constructed. This must contain at least a "location" + * @param json A JSON object representing the image to be constructed. This must contain at least a "locations" * string. * @return The resulting {@code Image} object. * @throws JsonSyntaxException if at any point the JSON object is found to be invalid. */ static CraftingRecipe fromJson(JsonObject json){ - ResourceLocation location = new ResourceLocation(JsonUtils.getString(json, "location")); - return new CraftingRecipe(location); + ResourceLocation[] locations = Streams.stream(JsonUtils.getJsonArray(json, "locations")) + .map(je -> new ResourceLocation(je.getAsString())).toArray(ResourceLocation[]::new); + return new CraftingRecipe(locations); } static void populate(Map map, JsonObject json){ @@ -135,17 +142,15 @@ class CraftingRecipe { GlStateManager.color(1, 1, 1, 1); Minecraft.getMinecraft().renderEngine.bindTexture(GuiWizardHandbook.texture); - DrawingUtils.drawTexturedRect(x - 2, y - 2, 60, 190, WIDTH, HEIGHT, 512, 256); + DrawingUtils.drawTexturedRect(x, y, TEXTURE_INSET_X, TEXTURE_INSET_Y, WIDTH, HEIGHT, GuiWizardHandbook.TEXTURE_WIDTH, GuiWizardHandbook.TEXTURE_HEIGHT); GlStateManager.pushMatrix(); RenderHelper.enableGUIStandardItemLighting(); GlStateManager.disableLighting(); GlStateManager.enableRescaleNormal(); GlStateManager.enableColorMaterial(); - GlStateManager.enableLighting(); itemRenderer.zLevel = 100.0F; - // TODO: There may be a better way of doing this int index = (int)(Minecraft.getSystemTime() % Integer.MAX_VALUE)/2000; int i = 0; @@ -155,8 +160,8 @@ class CraftingRecipe { if(ingredient != Ingredient.EMPTY){ ItemStack stack = ingredient.getMatchingStacks()[index % ingredient.getMatchingStacks().length]; if(!stack.isEmpty()){ - itemRenderer.renderItemAndEffectIntoGUI(stack, x + 18 * (i%3), y + 18 * (i/3)); - itemRenderer.renderItemOverlays(font, stack, x + 18 * (i%3), y + 18 * (i/3)); + itemRenderer.renderItemAndEffectIntoGUI(stack, x + BORDER + 18 * (i%3), y + BORDER + 18 * (i/3)); + itemRenderer.renderItemOverlays(font, stack, x + BORDER + 18 * (i%3), y + BORDER + 18 * (i/3)); } } @@ -164,16 +169,15 @@ class CraftingRecipe { } if(!result.isEmpty()){ - itemRenderer.renderItemAndEffectIntoGUI(result, x + 86, y + 18); - itemRenderer.renderItemOverlays(font, result, x + 86, y + 18); + itemRenderer.renderItemAndEffectIntoGUI(result, x + BORDER + 86, y + BORDER + 18); + itemRenderer.renderItemOverlays(font, result, x + BORDER + 86, y + BORDER + 18); } GlStateManager.popMatrix(); - GlStateManager.enableLighting(); GlStateManager.enableDepth(); GlStateManager.disableColorMaterial(); itemRenderer.zLevel = 0.0F; - //RenderHelper.enableStandardItemLighting(); + RenderHelper.disableStandardItemLighting(); } @@ -187,9 +191,7 @@ class CraftingRecipe { GlStateManager.enableRescaleNormal(); GlStateManager.enableColorMaterial(); itemRenderer.zLevel = 0.0F; - GlStateManager.disableLighting(); - // TODO: There may be a better way of doing this int index = (int)(Minecraft.getSystemTime() % Integer.MAX_VALUE)/2000; int i = 0; @@ -198,7 +200,7 @@ class CraftingRecipe { if(ingredient != Ingredient.EMPTY){ ItemStack stack = ingredient.getMatchingStacks()[index % ingredient.getMatchingStacks().length]; - if(!stack.isEmpty() && isPointInRegion(x + 18 * (i%3), y + 18 * (i/3), 16, 16, mouseX, mouseY)){ + if(!stack.isEmpty() && isPointInRegion(x + BORDER + 18 * (i%3), y + BORDER + 18 * (i/3), 16, 16, mouseX, mouseY)){ gui.renderToolTip(stack, mouseX, mouseY); } } @@ -206,15 +208,14 @@ class CraftingRecipe { i++; } - if(!result.isEmpty() && isPointInRegion(x + 86, y + 18, 16, 16, mouseX, mouseY)){ + if(!result.isEmpty() && isPointInRegion(x + BORDER + 86, y + BORDER + 18, 16, 16, mouseX, mouseY)){ gui.renderToolTip(result, mouseX, mouseY); } GlStateManager.popMatrix(); - GlStateManager.enableLighting(); GlStateManager.enableDepth(); GlStateManager.disableColorMaterial(); - RenderHelper.enableStandardItemLighting(); + RenderHelper.disableStandardItemLighting(); } diff --git a/src/main/java/electroblob/wizardry/client/gui/handbook/GuiButtonHyperlink.java b/src/main/java/electroblob/wizardry/client/gui/handbook/GuiButtonHyperlink.java index 7aaa5bf4..d5a48d64 100644 --- a/src/main/java/electroblob/wizardry/client/gui/handbook/GuiButtonHyperlink.java +++ b/src/main/java/electroblob/wizardry/client/gui/handbook/GuiButtonHyperlink.java @@ -1,12 +1,14 @@ package electroblob.wizardry.client.gui.handbook; import com.google.gson.JsonSyntaxException; +import electroblob.wizardry.client.DrawingUtils; import electroblob.wizardry.registry.WizardrySounds; import net.minecraft.client.Minecraft; import net.minecraft.client.audio.PositionedSoundRecord; import net.minecraft.client.audio.SoundHandler; import net.minecraft.client.gui.FontRenderer; import net.minecraft.client.gui.GuiButton; +import net.minecraft.util.math.MathHelper; import net.minecraft.util.text.ITextComponent; import net.minecraft.util.text.TextComponentString; import net.minecraft.util.text.TextFormatting; @@ -19,10 +21,14 @@ public abstract class GuiButtonHyperlink extends GuiButton { public static final String URL_REGEX = "^((https?|ftp)://|(www|ftp)\\.)?[a-z0-9-]+(\\.[a-z0-9-]+)+([/?].*)?$"; + /** Pulse period of links to new sections, in milliseconds. */ + private static final float PULSATION_PERIOD = 1500; + final int indent; final List lines; + final int linesLeft; - GuiButtonHyperlink(int id, int x, int y, FontRenderer font, String text, int indent, String suffix){ + GuiButtonHyperlink(int id, int x, int y, FontRenderer font, String text, int indent, String suffix, int linesLeft, boolean rightPage){ super(id, x, y, font.getStringWidth(text), font.FONT_HEIGHT, text); @@ -36,6 +42,7 @@ public abstract class GuiButtonHyperlink extends GuiButton { } this.indent = indent; // Assigned here in case it was corrected above + this.linesLeft = linesLeft; String line1 = font.listFormattedStringToWidth(linkWithSuffix, GuiWizardHandbook.PAGE_WIDTH - indent).get(0); // Without trim(), there will be at least 1 leading space due to the custom wrapping @@ -59,6 +66,11 @@ public abstract class GuiButtonHyperlink extends GuiButton { } } } + + // Remove any lines that overflowed onto the next double-page + if(rightPage){ + while(lines.size() > linesLeft) lines.remove(lines.size() - 1); + } } public boolean isHovered(net.minecraft.client.gui.FontRenderer font, int mouseX, int mouseY){ @@ -72,6 +84,11 @@ public abstract class GuiButtonHyperlink extends GuiButton { int t = y + font.FONT_HEIGHT * i; + if(i > linesLeft){ + l = l + GuiWizardHandbook.GUI_WIDTH - 2 * GuiWizardHandbook.TEXT_INSET_X - GuiWizardHandbook.PAGE_WIDTH; + t -= GuiWizardHandbook.PAGE_HEIGHT - (GuiWizardHandbook.PAGE_HEIGHT % font.FONT_HEIGHT); + } + if(mouseX >= l && mouseY >= t && mouseX < l + font.getStringWidth(line) && mouseY < t + font.FONT_HEIGHT){ return true; } @@ -93,7 +110,6 @@ public abstract class GuiButtonHyperlink extends GuiButton { if(this.visible){ this.hovered = isHovered(minecraft.fontRenderer, mouseX, mouseY); - int colour = hovered ? GuiWizardHandbook.colours.get("highlight") : GuiWizardHandbook.colours.get("hyperlink"); int i = 0; @@ -104,13 +120,22 @@ public abstract class GuiButtonHyperlink extends GuiButton { int t = y + minecraft.fontRenderer.FONT_HEIGHT * i; - minecraft.fontRenderer.drawString(line, l, t, colour); + if(i > linesLeft){ + l = l + GuiWizardHandbook.GUI_WIDTH - 2 * GuiWizardHandbook.TEXT_INSET_X - GuiWizardHandbook.PAGE_WIDTH; + t -= GuiWizardHandbook.PAGE_HEIGHT - (GuiWizardHandbook.PAGE_HEIGHT % minecraft.fontRenderer.FONT_HEIGHT); + } + + minecraft.fontRenderer.drawString(line, l, t, getColour()); i++; } } } + protected int getColour(){ + return hovered ? GuiWizardHandbook.colours.get("highlight") : GuiWizardHandbook.colours.get("hyperlink"); + } + /** * Creates a new hyperlink button from the given arguments, automatically differentiating between URLs and sections. * @param x The x position of the button @@ -124,7 +149,7 @@ public abstract class GuiButtonHyperlink extends GuiButton { * @throws IllegalArgumentException if the given argument array is empty or contains more than 2 arguments * @throws JsonSyntaxException if the specified link target is not a URL or a valid section ID */ - public static GuiButtonHyperlink create(int x, int y, FontRenderer font, List upToLink, String[] arguments, String suffix){ + public static GuiButtonHyperlink create(int x, int y, FontRenderer font, List upToLink, String[] arguments, String suffix, int linesLeft, boolean rightPage){ if(arguments.length == 0 || arguments.length > 2) throw new IllegalArgumentException("Incorrect array length!"); @@ -133,7 +158,7 @@ public abstract class GuiButtonHyperlink extends GuiButton { if(arguments[0].matches(URL_REGEX)){ button = new GuiButtonHyperlink.External(0, x, y, font, arguments[arguments.length - 1], arguments[0], - font.getStringWidth(upToLink.get(upToLink.size() - 1)), suffix); + font.getStringWidth(upToLink.get(upToLink.size() - 1)), suffix, linesLeft, rightPage); }else{ @@ -142,7 +167,7 @@ public abstract class GuiButtonHyperlink extends GuiButton { if(target == null) throw new JsonSyntaxException("Hyperlink points to nonexistent section id " + arguments[0]); button = new GuiButtonHyperlink.Internal(0, x, y, font, arguments[arguments.length - 1], - target, font.getStringWidth(upToLink.get(upToLink.size() - 1)), suffix); + target, font.getStringWidth(upToLink.get(upToLink.size() - 1)), suffix, linesLeft, rightPage); } return button; @@ -152,26 +177,49 @@ public abstract class GuiButtonHyperlink extends GuiButton { final Section target; - Internal(int id, int x, int y, FontRenderer font, String text, Section target, int indent, String suffix){ - super(id, x, y, font, text, indent, suffix); + Internal(int id, int x, int y, FontRenderer font, String text, Section target, int indent, String suffix, int linesLeft, boolean rightPage){ + super(id, x, y, font, text, indent, suffix, linesLeft, rightPage); this.target = target; } + @Override + public boolean mousePressed(Minecraft minecraft, int mouseX, int mouseY){ + if(!target.isUnlocked()) return false; + return super.mousePressed(minecraft, mouseX, mouseY); + } + @Override public void playPressSound(SoundHandler soundHandler){ soundHandler.playSound(PositionedSoundRecord.getMasterRecord(WizardrySounds.MISC_PAGE_TURN, 1)); } + @Override + protected int getColour(){ + + if(!target.isUnlocked()) return GuiWizardHandbook.colours.get("text"); + + if(!hovered && target.isNew() && !Minecraft.getMinecraft().player.isCreative()){ + + int c = GuiWizardHandbook.colours.get("new_section"); + int d = GuiWizardHandbook.colours.get("hyperlink"); + float f = (MathHelper.sin((Minecraft.getSystemTime() % PULSATION_PERIOD) / PULSATION_PERIOD * 2 * (float)Math.PI) + 1) / 2f; + + return DrawingUtils.mix(c, d, f); + } + + return super.getColour(); + } + } static class External extends GuiButtonHyperlink { final ITextComponent link; - External(int id, int x, int y, FontRenderer font, String text, String url, int indent, String suffix){ - super(id, x, y, font, text, indent, suffix); + External(int id, int x, int y, FontRenderer font, String text, String url, int indent, String suffix, int linesLeft, boolean rightPage){ + super(id, x, y, font, text, indent, suffix, linesLeft, rightPage); this.link = new TextComponentString(text); - link.getStyle().setClickEvent(new ClickEvent(ClickEvent.Action.OPEN_URL, url)); + link.getStyle().setClickEvent(new ClickEvent(ClickEvent.Action.OPEN_URL, url)).setColor(TextFormatting.DARK_BLUE); } } diff --git a/src/main/java/electroblob/wizardry/client/gui/handbook/GuiButtonTurnPage.java b/src/main/java/electroblob/wizardry/client/gui/handbook/GuiButtonTurnPage.java index a05ed041..662e71a1 100644 --- a/src/main/java/electroblob/wizardry/client/gui/handbook/GuiButtonTurnPage.java +++ b/src/main/java/electroblob/wizardry/client/gui/handbook/GuiButtonTurnPage.java @@ -9,10 +9,8 @@ import net.minecraft.client.audio.SoundHandler; import net.minecraft.client.gui.GuiButton; import net.minecraft.client.renderer.GlStateManager; import net.minecraft.util.ResourceLocation; -import net.minecraftforge.fml.relauncher.Side; -import net.minecraftforge.fml.relauncher.SideOnly; -@SideOnly(Side.CLIENT) +//@SideOnly(Side.CLIENT) class GuiButtonTurnPage extends GuiButton { static final int WIDTH = 20; diff --git a/src/main/java/electroblob/wizardry/client/gui/handbook/GuiWizardHandbook.java b/src/main/java/electroblob/wizardry/client/gui/handbook/GuiWizardHandbook.java index 2c21a59f..dcb54387 100644 --- a/src/main/java/electroblob/wizardry/client/gui/handbook/GuiWizardHandbook.java +++ b/src/main/java/electroblob/wizardry/client/gui/handbook/GuiWizardHandbook.java @@ -3,6 +3,7 @@ package electroblob.wizardry.client.gui.handbook; import com.google.gson.Gson; import com.google.gson.JsonElement; import com.google.gson.JsonObject; +import com.google.gson.JsonSyntaxException; import electroblob.wizardry.Wizardry; import electroblob.wizardry.client.ClientProxy; import electroblob.wizardry.client.DrawingUtils; @@ -11,34 +12,28 @@ import electroblob.wizardry.client.gui.handbook.GuiButtonTurnPage.Type; import electroblob.wizardry.constants.Constants; import electroblob.wizardry.constants.Element; import electroblob.wizardry.constants.Tier; +import electroblob.wizardry.packet.PacketRequestAdvancementSync; +import electroblob.wizardry.packet.WizardryPacketHandler; import electroblob.wizardry.registry.WizardrySounds; import net.minecraft.client.Minecraft; import net.minecraft.client.audio.PositionedSoundRecord; import net.minecraft.client.audio.SoundHandler; import net.minecraft.client.gui.GuiButton; import net.minecraft.client.gui.GuiScreen; -import net.minecraft.client.multiplayer.ClientAdvancementManager; import net.minecraft.client.renderer.GlStateManager; import net.minecraft.client.resources.IResource; import net.minecraft.client.resources.IResourceManager; import net.minecraft.item.ItemStack; import net.minecraft.util.JsonUtils; -import net.minecraft.util.NonNullList; import net.minecraft.util.ResourceLocation; -import net.minecraftforge.event.entity.player.AdvancementEvent; -import net.minecraftforge.fml.common.Mod; -import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; -import net.minecraftforge.fml.relauncher.ReflectionHelper; -import org.apache.commons.lang3.tuple.Pair; import org.lwjgl.input.Keyboard; import java.awt.*; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; -import java.lang.reflect.Field; -import java.util.*; import java.util.List; +import java.util.*; /** * GUI class for the wizard's handbook. Like any GUI class, this is instantiated each time the book is opened. As of @@ -54,7 +49,6 @@ import java.util.List; * @see Image * @see CraftingRecipe */ -@Mod.EventBusSubscriber public class GuiWizardHandbook extends GuiScreen { private static final ResourceLocation DEFAULT = new ResourceLocation(Wizardry.MODID, "texts/handbook_en_us.json"); @@ -71,6 +65,7 @@ public class GuiWizardHandbook extends GuiScreen { static final String IMAGE_TAG = "image"; static final String RECIPE_TAG = "recipe"; + static final String RULER_TAG = "ruler"; static final Map FORMAT_TAGS = new HashMap<>(); @@ -79,6 +74,8 @@ public class GuiWizardHandbook extends GuiScreen { /** The dimensions of the rendered GUI area. */ static final int GUI_WIDTH = 288, GUI_HEIGHT = 180; + /** The dimensions of the GUI texture itself. */ + static final int TEXTURE_WIDTH = 512, TEXTURE_HEIGHT = 256; /** The dimensions of the area of a single page in which text can be drawn. */ static final int PAGE_WIDTH = 120, PAGE_HEIGHT = 140; /** The distance of the text from the top outside corner of each page. */ @@ -107,12 +104,12 @@ public class GuiWizardHandbook extends GuiScreen { * The double-page number where the bookmark is currently set, relative to the section stored in * {@link GuiWizardHandbook#bookmarkSection}. Static because it persists when the book is closed. */ - private static int bookmarkPage = 1; + private static int bookmarkPage = 0; /** - * A reference to the section in which the bookmark is currently set. Static because it persists when the book is - * closed. Storing a section means the bookmark doesn't change location when new sections are unlocked. + * The key corresponding to the section in which the bookmark is currently set. Static because it persists when the + * book is closed. Storing a section means the bookmark doesn't change location when new sections are unlocked. */ - private static Section bookmarkSection; + private static String bookmarkSection; // Buttons private GuiButton bookmark, next, previous, nextSection, previousSection, menu; @@ -164,19 +161,6 @@ public class GuiWizardHandbook extends GuiScreen { */ static final Map recipes = new HashMap<>(); - static String rulerText = "--------------------"; // Assigned here as a fallback - - private static final List>>> RECIPES = new ArrayList<>(); - - // Reflection - - static final Field ADVANCEMENT_TO_PROGRESS; - - static { - // TODO: Obf field name - ADVANCEMENT_TO_PROGRESS = ReflectionHelper.findField(ClientAdvancementManager.class, "advancementToProgress"); - } - /** * Adds a format tag to the handbook. All occurrences of the given tag string preceded by a # will be replaced with * the result of the given value string on GUI load. The value string, therefore, can be anything that should be @@ -193,9 +177,9 @@ public class GuiWizardHandbook extends GuiScreen { addFormatTag("next_spell_key", ClientProxy.NEXT_SPELL.getDisplayName()); addFormatTag("previous_spell_key", ClientProxy.PREVIOUS_SPELL.getDisplayName()); - addFormatTag("mana_per_crystal_minus_30", "" + (Constants.MANA_PER_CRYSTAL - 30)); + addFormatTag("example_charging_loss", "" + (Constants.MANA_PER_CRYSTAL - 30)); addFormatTag("mana_per_crystal", "" + Constants.MANA_PER_CRYSTAL); - addFormatTag("novice_max_charge", "" + Tier.BASIC.maxCharge); + addFormatTag("novice_max_charge", "" + Tier.NOVICE.maxCharge); addFormatTag("apprentice_max_charge", "" + Tier.APPRENTICE.maxCharge); addFormatTag("advanced_max_charge", "" + Tier.ADVANCED.maxCharge); addFormatTag("master_max_charge", "" + Tier.MASTER.maxCharge); @@ -264,12 +248,14 @@ public class GuiWizardHandbook extends GuiScreen { Minecraft.getMinecraft().renderEngine.bindTexture(texture); + GlStateManager.color(1, 1, 1, 1); + // Main background - DrawingUtils.drawTexturedRect(left, top, 0, 0, GUI_WIDTH, GUI_HEIGHT, 512, 256); + DrawingUtils.drawTexturedRect(left, top, 0, 0, GUI_WIDTH, GUI_HEIGHT, TEXTURE_WIDTH, TEXTURE_HEIGHT); // First page background if(currentPage == 0){ - DrawingUtils.drawTexturedRect(left, top, 368, 0, GUI_WIDTH / 2, GUI_HEIGHT, 512, 256); + DrawingUtils.drawTexturedRect(left, top, 368, 0, GUI_WIDTH / 2, GUI_HEIGHT, TEXTURE_WIDTH, TEXTURE_HEIGHT); previous.visible = false; previousSection.visible = false; // Not worth testing if we're in the first section every frame menu.visible = false; @@ -281,7 +267,7 @@ public class GuiWizardHandbook extends GuiScreen { // Last page background if(currentPage == singleToDoublePage(pageCount)){ - DrawingUtils.drawTexturedFlippedRect(left + GUI_WIDTH / 2, top, 368, 0, GUI_WIDTH / 2, GUI_HEIGHT, 512, 256, true, false); + DrawingUtils.drawTexturedFlippedRect(left + GUI_WIDTH / 2, top, 368, 0, GUI_WIDTH / 2, GUI_HEIGHT, TEXTURE_WIDTH, TEXTURE_HEIGHT, true, false); next.visible = false; nextSection.visible = false; }else{ @@ -302,9 +288,10 @@ public class GuiWizardHandbook extends GuiScreen { } // Main content + contentsList.values().forEach(c -> { if(c.section.isUnlocked()) c.draw(fontRenderer, currentPage, left, top); } ); + sections.values().forEach(s -> { if(s.isUnlocked()) s.draw(fontRenderer, currentPage, left, top); } ); + // These only get populated if the sections are unlocked so no checks are necessary images.values().forEach(i -> i.draw(fontRenderer, currentPage, left, top)); - contentsList.values().forEach(c -> c.draw(fontRenderer, currentPage, left, top)); - sections.values().forEach(s -> s.draw(fontRenderer, currentPage, left, top)); recipes.values().forEach(r -> r.draw(fontRenderer, itemRender, currentPage, left, top)); // Buttons @@ -314,14 +301,15 @@ public class GuiWizardHandbook extends GuiScreen { GlStateManager.color(1, 1, 1, 1); Minecraft.getMinecraft().renderEngine.bindTexture(texture); - if(currentPage == singleToDoublePage(bookmarkSection.startPage) + bookmarkPage){ + if(currentPage == singleToDoublePage(sections.get(bookmarkSection).startPage) + bookmarkPage){ + // If the current page is the bookmarked page, the (invisible) bookmark button is disabled bookmark.visible = false; - DrawingUtils.drawTexturedRect(left + 138, top, 299, 0, 11, 191, 512, 256); + DrawingUtils.drawTexturedRect(left + 138, top, 299, 0, 11, 191, TEXTURE_WIDTH, TEXTURE_HEIGHT); }else{ bookmark.visible = true; - bookmark.x = left + (currentPage > singleToDoublePage(bookmarkSection.startPage) + bookmarkPage ? 130 : 147); + bookmark.x = left + (currentPage > singleToDoublePage(sections.get(bookmarkSection).startPage) + bookmarkPage ? 130 : 147); DrawingUtils.drawTexturedRect(bookmark.x, top, - bookmark.isMouseOver() ? 310 : 288, 0, 11, 191, 512, 256); + bookmark.isMouseOver() ? 310 : 288, 0, 11, 191, TEXTURE_WIDTH, TEXTURE_HEIGHT); } // Recipe tooltips @@ -426,8 +414,6 @@ public class GuiWizardHandbook extends GuiScreen { JsonElement je = gson.fromJson(reader, JsonElement.class); JsonObject json = je.getAsJsonObject(); - rulerText = JsonUtils.getString(json, "ruler_text"); - JsonUtils.getJsonObject(json, "colours").entrySet().forEach(e -> colours.put(e.getKey(), Color.decode(e.getValue().getAsString()).getRGB())); @@ -443,10 +429,12 @@ public class GuiWizardHandbook extends GuiScreen { return; } - // Attempts to find a suitable place to put the bookmark to start with - bookmarkSection = sections.get("introduction"); - if(bookmarkSection == null) bookmarkSection = sectionList.get(0); + bookmarkSection = JsonUtils.getString(json, "bookmark_start_section"); + if(!sections.containsKey(bookmarkSection)) throw new JsonSyntaxException("Section with id " + bookmarkSection + " is undefined"); } + + // The first resource load on startup is done before the packet handler is loaded + if(WizardryPacketHandler.net != null) WizardryPacketHandler.net.sendToServer(new PacketRequestAdvancementSync.Message()); } /** @@ -460,6 +448,8 @@ public class GuiWizardHandbook extends GuiScreen { */ private static IResource getHandbookResource(IResourceManager manager){ + // TODO: Implement resource pack stacking to allow addon mods and texture packs to add/overwrite content + IResource handbookFile = null; try{ @@ -507,12 +497,15 @@ public class GuiWizardHandbook extends GuiScreen { if(currentSection != null){ - int index = sectionList.indexOf(currentSection); + List
    visibleSections = new ArrayList<>(sectionList); + visibleSections.removeIf(s -> !s.isUnlocked()); - if(button == nextSection && index + 1 < sections.size()){ - currentPage = singleToDoublePage(sectionList.get(index + 1).startPage); + int index = visibleSections.indexOf(currentSection); + + if(button == nextSection && index + 1 < visibleSections.size()){ + currentPage = singleToDoublePage(visibleSections.get(index + 1).startPage); }else if(index > 0){ - currentPage = singleToDoublePage(sectionList.get(index - 1).startPage); + currentPage = singleToDoublePage(visibleSections.get(index - 1).startPage); } } @@ -520,7 +513,7 @@ public class GuiWizardHandbook extends GuiScreen { currentPage = singleToDoublePage(sections.get("main_contents").startPage); }else if(button == bookmark && bookmarkSection != null){ - currentPage = singleToDoublePage(bookmarkSection.startPage) + bookmarkPage; + currentPage = singleToDoublePage(sections.get(bookmarkSection).startPage) + bookmarkPage; }else{ if(button instanceof GuiButtonHyperlink.Internal){ @@ -540,12 +533,12 @@ public class GuiWizardHandbook extends GuiScreen { this.selectedButton = bookmark; - for(Section section : sections.values()){ + for(String key : sections.keySet()){ // The bookmark is assumed to bookmark the left-hand page - if(section.containsPage(doubleToSinglePage(bookmarkPage, false))) bookmarkSection = section; + if(sections.get(key).containsPage(doubleToSinglePage(currentPage, false))) bookmarkSection = key; } - bookmarkPage = currentPage - singleToDoublePage(bookmarkSection.startPage); + bookmarkPage = currentPage - singleToDoublePage(sections.get(bookmarkSection).startPage); } }else{ super.mouseClicked(mouseX, mouseY, mouseButton); @@ -558,9 +551,14 @@ public class GuiWizardHandbook extends GuiScreen { super.renderToolTip(stack, x, y); } - @SubscribeEvent - public static void onAdvancementEvent(AdvancementEvent event){ - sections.values().forEach(s -> s.onAdvancement(event.getEntityPlayer(), event.getAdvancement())); + @Override + public boolean doesGuiPauseGame(){ + return Wizardry.settings.booksPauseGame; + } + + + public static void updateUnlockStatus(boolean showToasts, ResourceLocation... completedAdvancements){ + sections.values().forEach(s -> s.updateUnlockStatus(showToasts, completedAdvancements)); } } \ No newline at end of file diff --git a/src/main/java/electroblob/wizardry/client/gui/handbook/HandbookToast.java b/src/main/java/electroblob/wizardry/client/gui/handbook/HandbookToast.java new file mode 100644 index 00000000..2db6e666 --- /dev/null +++ b/src/main/java/electroblob/wizardry/client/gui/handbook/HandbookToast.java @@ -0,0 +1,54 @@ +package electroblob.wizardry.client.gui.handbook; + +import electroblob.wizardry.registry.WizardryItems; +import net.minecraft.client.gui.toasts.GuiToast; +import net.minecraft.client.gui.toasts.IToast; +import net.minecraft.client.renderer.GlStateManager; +import net.minecraft.client.renderer.RenderHelper; +import net.minecraft.client.resources.I18n; +import net.minecraft.item.ItemStack; +import net.minecraft.util.math.MathHelper; + +import java.util.List; + +//@SideOnly(Side.CLIENT) +public class HandbookToast implements IToast { + + private final Section section; + + public HandbookToast(Section section){ + this.section = section; + } + + public IToast.Visibility draw(GuiToast toastGui, long delta){ + + toastGui.getMinecraft().getTextureManager().bindTexture(TEXTURE_TOASTS); + + GlStateManager.color(1.0F, 1.0F, 1.0F); + toastGui.drawTexturedModalRect(0, 0, 0, 32, 160, 32); + + boolean firstPart = delta < 1500L; + + int a = firstPart ? MathHelper.floor(MathHelper.clamp((float)(1500L - delta) / 300.0F, 0.0F, 1.0F) * 255.0F) << 24 | 67108864 + : MathHelper.floor(MathHelper.clamp((float)(delta - 1500L) / 300.0F, 0.0F, 1.0F) * 252.0F) << 24 | 67108864; + + String s = firstPart ? I18n.format("handbook.toast.title") : section.title; + + int c = firstPart ? -11534256 : -16777216; + + List list = toastGui.getMinecraft().fontRenderer.listFormattedStringToWidth(s, 125); + + int h = 16 - list.size() * toastGui.getMinecraft().fontRenderer.FONT_HEIGHT / 2; + + for(String line : list){ + toastGui.getMinecraft().fontRenderer.drawString(line, 30, h, c | a); + h += toastGui.getMinecraft().fontRenderer.FONT_HEIGHT; + } + + RenderHelper.enableGUIStandardItemLighting(); + toastGui.getMinecraft().getRenderItem().renderItemAndEffectIntoGUI(null, new ItemStack(WizardryItems.wizard_handbook), 8, 8); + + return delta >= 5000L ? IToast.Visibility.HIDE : IToast.Visibility.SHOW; + } + +} \ No newline at end of file diff --git a/src/main/java/electroblob/wizardry/client/gui/handbook/Image.java b/src/main/java/electroblob/wizardry/client/gui/handbook/Image.java index cb0d391e..732bb10b 100644 --- a/src/main/java/electroblob/wizardry/client/gui/handbook/Image.java +++ b/src/main/java/electroblob/wizardry/client/gui/handbook/Image.java @@ -9,6 +9,7 @@ import net.minecraft.client.gui.FontRenderer; import net.minecraft.client.renderer.GlStateManager; import net.minecraft.util.JsonUtils; import net.minecraft.util.ResourceLocation; +import net.minecraft.util.math.MathHelper; import java.util.HashSet; import java.util.Map; @@ -22,11 +23,15 @@ class Image { private int textureWidth, textureHeight; private int u = 0, v = 0; private String caption = ""; + private boolean border = true; // Derived fields, not specifically defined in JSON private final Set instances = new HashSet<>(); private static final int CAPTION_OFFSET = 4; + private static final int TEXTURE_INSET_X = 180; + private static final int BORDER = 1; + private Image(ResourceLocation location, int width, int height){ this.location = location; this.width = width; @@ -68,6 +73,7 @@ class Image { * @param top The y coordinate of the top of the GUI. */ void draw(FontRenderer font, int doublePage, int left, int top){ + // Images for(int[] instance : instances){ if(GuiWizardHandbook.singleToDoublePage(instance[0]) == doublePage){ Minecraft.getMinecraft().renderEngine.bindTexture(location); @@ -77,6 +83,29 @@ class Image { top + instance[2] + height + CAPTION_OFFSET, GuiWizardHandbook.colours.get("caption")); } } + + if(border){ + // Borders - do this after all the images are drawn so we only have to bind the handbook texture again once + Minecraft.getMinecraft().renderEngine.bindTexture(GuiWizardHandbook.texture); + GlStateManager.color(1, 1, 1, 1); + for(int[] instance : instances){ + if(GuiWizardHandbook.singleToDoublePage(instance[0]) == doublePage){ + // Math.ceil accounts for odd-numbered image dimensions + DrawingUtils.drawTexturedFlippedRect(left + instance[1] - BORDER, top + instance[2] - BORDER, + TEXTURE_INSET_X, GuiWizardHandbook.GUI_HEIGHT, width / 2 + BORDER, height / 2 + BORDER, + GuiWizardHandbook.TEXTURE_WIDTH, GuiWizardHandbook.TEXTURE_HEIGHT, false, false); + DrawingUtils.drawTexturedFlippedRect(left + instance[1] + width / 2, top + instance[2] - BORDER, + TEXTURE_INSET_X, GuiWizardHandbook.GUI_HEIGHT, MathHelper.ceil(width / 2f) + BORDER, height / 2 + BORDER, + GuiWizardHandbook.TEXTURE_WIDTH, GuiWizardHandbook.TEXTURE_HEIGHT, true, false); + DrawingUtils.drawTexturedFlippedRect(left + instance[1] - BORDER, top + instance[2] + height / 2, + TEXTURE_INSET_X, GuiWizardHandbook.GUI_HEIGHT, width / 2 + BORDER, MathHelper.ceil(height / 2f) + BORDER, + GuiWizardHandbook.TEXTURE_WIDTH, GuiWizardHandbook.TEXTURE_HEIGHT, false, true); + DrawingUtils.drawTexturedFlippedRect(left + instance[1] + width / 2, top + instance[2] + height / 2, + TEXTURE_INSET_X, GuiWizardHandbook.GUI_HEIGHT, MathHelper.ceil(width / 2f) + BORDER, MathHelper.ceil(height / 2f) + BORDER, + GuiWizardHandbook.TEXTURE_WIDTH, GuiWizardHandbook.TEXTURE_HEIGHT, true, true); + } + } + } } /** @@ -98,7 +127,7 @@ class Image { image.textureWidth = JsonUtils.getInt(json, "texture_width", image.width); image.textureHeight = JsonUtils.getInt(json, "texture_height", image.height); image.caption = JsonUtils.getString(json, "caption", ""); - + image.border = JsonUtils.getBoolean(json, "border", true); return image; } diff --git a/src/main/java/electroblob/wizardry/client/gui/handbook/Section.java b/src/main/java/electroblob/wizardry/client/gui/handbook/Section.java index 29f5fc0e..c057d5e5 100644 --- a/src/main/java/electroblob/wizardry/client/gui/handbook/Section.java +++ b/src/main/java/electroblob/wizardry/client/gui/handbook/Section.java @@ -7,13 +7,12 @@ import com.google.gson.JsonSyntaxException; import electroblob.wizardry.Wizardry; import electroblob.wizardry.client.DrawingUtils; import electroblob.wizardry.util.WizardryUtilities; -import net.minecraft.advancements.Advancement; -import net.minecraft.advancements.AdvancementProgress; import net.minecraft.client.Minecraft; import net.minecraft.client.gui.FontRenderer; import net.minecraft.client.gui.GuiButton; -import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.client.renderer.GlStateManager; import net.minecraft.util.JsonUtils; +import net.minecraft.util.ResourceLocation; import org.apache.commons.lang3.StringUtils; import java.util.*; @@ -23,7 +22,7 @@ import java.util.*; * everything within the section itself, including JSON parsing, unlock triggers and drawing the actual rawText. * Sections may now also be nested and have other elements within them, such as images and a table of contents, a * behaviour which is also handled within this class. - *

    + *

    * The formatting of the book is now done 'dynamically' - that is, the exact positions and page numbers of * sections, images and so on are determined on GUI load and depend on which of the previous sections have been * unlocked, amongst other factors. This means that all of the unlocked sections must be formatted in order on GUI @@ -32,15 +31,15 @@ import java.util.*; * @author Electroblob * @since Wizardry 4.2 */ -// Because these are now generated on resource pack reload (not on handbook open, as before), this class must now -// be static +// Because these are now generated on resource pack reload (not on handbook open, as before), this class can no longer +// be a non-static inner class class Section { // Final fields are mandatory (none here though), the rest are optional String title; private String[] rawText; private Contents contents; - private Advancement[] triggers; + private ResourceLocation[] triggers; private Map subsections; private boolean centreX, centreY; @@ -54,6 +53,9 @@ class Section { */ private final List> pages; + private boolean unlocked = false; + private boolean isNew = false; + private Section(){ this.buttons = new ArrayList<>(); this.pages = new ArrayList<>(); @@ -65,10 +67,10 @@ class Section { } /** - * Returns true if the given page is within this section, false if not. + * Returns true if the given page is within this section, false if not (or if the section is locked). */ boolean containsPage(int page){ - return startPage <= page && startPage + pages.size() > page; + return this.isUnlocked() && startPage <= page && startPage + pages.size() > page; } /** @@ -77,32 +79,24 @@ class Section { */ boolean isUnlocked(){ + if(Minecraft.getMinecraft().player.isCreative()) return true; if(!Wizardry.settings.handbookProgression) return true; // Always unlocked if handbook progression is off + if(triggers == null) return true; // If no triggers were defined, the section is unlocked from the start // A section is automatically unlocked if one of its subsections is unlocked for(Section subsection : subsections.values()){ if(subsection.isUnlocked()) return true; } - if(triggers == null) return true; // If no triggers were defined, the section is unlocked from the start + return unlocked; + } - for(Advancement trigger : triggers){ - - try{ - - // TESTME: Is this properly synced or do we need to do that as well? - Map advancements = (Map)GuiWizardHandbook.ADVANCEMENT_TO_PROGRESS.get(Minecraft.getMinecraft().player.connection.getAdvancementManager()); - - if(advancements.get(trigger).isDone()){ - return true; - } - - }catch(IllegalAccessException e){ - e.printStackTrace(); - } - } - - return false; + /** + * Returns true if this section has been unlocked and not read yet. Also returns true if any subsections are new. + */ + boolean isNew(){ + if(!Wizardry.settings.handbookProgression) return false; + return isNew || this.subsections.values().stream().anyMatch(Section::isNew); } /** @@ -143,12 +137,19 @@ class Section { for(String line : lines){ - int lx = centreX ? x + GuiWizardHandbook.PAGE_WIDTH / 2 - font.getStringWidth(line) / 2 : x; - - font.drawString(line, lx, y, DrawingUtils.BLACK, false); + if(line.startsWith(GuiWizardHandbook.FORMAT_MARKER + GuiWizardHandbook.RULER_TAG)){ + GlStateManager.color(1, 1, 1, 1); + Minecraft.getMinecraft().renderEngine.bindTexture(GuiWizardHandbook.texture); + DrawingUtils.drawTexturedRect(x-1, y-1, 0, GuiWizardHandbook.GUI_HEIGHT, GuiWizardHandbook.PAGE_WIDTH + 2, 9, GuiWizardHandbook.TEXTURE_WIDTH, GuiWizardHandbook.TEXTURE_HEIGHT); + }else{ + int lx = centreX ? x + GuiWizardHandbook.PAGE_WIDTH / 2 - font.getStringWidth(line) / 2 : x; + font.drawString(line, lx, y, DrawingUtils.BLACK, false); + } y += font.FONT_HEIGHT; } + + isNew = false; // Now a page has been drawn, the player must have seen it so it's not new any more } } } @@ -180,7 +181,7 @@ class Section { // Adds the header if present if(!this.title.isEmpty()){ lines.add(this.title); - lines.add(GuiWizardHandbook.rulerText); + lines.add(GuiWizardHandbook.FORMAT_MARKER + GuiWizardHandbook.RULER_TAG); } // Adds space for the contents if it exists @@ -212,7 +213,7 @@ class Section { + StringUtils.abbreviate(raw, 50)); Image image = GuiWizardHandbook.images.get(arguments[1]); - if(image == null) throw new JsonSyntaxException("Image with id " + arguments[1] + "is undefined"); + if(image == null) throw new JsonSyntaxException("Image with id " + arguments[1] + " is undefined"); // Starts a new page if the image will not fit on the current one if((lines.size() % maxLineNumber) * font.FONT_HEIGHT + image.getHeight(font) > GuiWizardHandbook.PAGE_HEIGHT){ @@ -248,27 +249,35 @@ class Section { + StringUtils.abbreviate(raw, 50)); CraftingRecipe recipe = GuiWizardHandbook.recipes.get(arguments[1]); - if(recipe == null) throw new JsonSyntaxException("Recipe with id " + arguments[1] + "is undefined"); + if(recipe == null) throw new JsonSyntaxException("Recipe with id " + arguments[1] + " is undefined"); // Starts a new page if the recipe will not fit on the current one if((lines.size() % maxLineNumber) * font.FONT_HEIGHT + CraftingRecipe.HEIGHT > GuiWizardHandbook.PAGE_HEIGHT){ - // Remaining number of lines on the page - lines.addAll(Collections.nCopies(maxLineNumber - (lines.size() % maxLineNumber), "")); + // Remaining number of lines on the page, plus the first blank one on the new page + lines.addAll(Collections.nCopies(maxLineNumber - (lines.size() % maxLineNumber), " ")); } int page = startPage + (lines.size() / maxLineNumber); + if(lines.size() % maxLineNumber == 0) lines.add(" "); + int startLine = lines.size() % maxLineNumber - 1; + recipe.addInstance(page, GuiWizardHandbook.PAGE_WIDTH / 2 - CraftingRecipe.WIDTH / 2 + (GuiWizardHandbook.isRightPage(page) ? GuiWizardHandbook.GUI_WIDTH - GuiWizardHandbook.TEXT_INSET_X - GuiWizardHandbook.PAGE_WIDTH : GuiWizardHandbook.TEXT_INSET_X), - GuiWizardHandbook.TEXT_INSET_Y + (lines.size() % maxLineNumber) * font.FONT_HEIGHT); + GuiWizardHandbook.TEXT_INSET_Y + startLine * font.FONT_HEIGHT); // Height of the recipe in lines, rounded up // Uses a single space instead of an empty string so that the page trimming doesn't remove them - lines.addAll(Collections.nCopies(CraftingRecipe.HEIGHT / font.FONT_HEIGHT, " ")); + lines.addAll(Collections.nCopies(CraftingRecipe.HEIGHT / font.FONT_HEIGHT - 1, " ")); // This time we're not adding an extra space because it's not really needed }else{ // All other paragraphs + // Formatting + for(Map.Entry entry : GuiWizardHandbook.FORMAT_TAGS.entrySet()){ + paragraph = paragraph.replace(GuiWizardHandbook.FORMAT_MARKER + entry.getKey(), entry.getValue()); + } + // Hyperlinks int linkStart; @@ -284,15 +293,17 @@ class Section { String linkRaw = paragraph.substring(linkStart, linkEnd + 1); String[] arguments = paragraph.substring(linkStart + 1, linkEnd).split("\\s", 2); - String suffix = paragraph.substring(linkEnd).split("\\s", 2)[0]; + String suffix = paragraph.substring(linkEnd).split("\\s", 2)[0].substring(1); // substring(1) to remove the @ // The index of the single page currently being formatted, relative to the section int pageRelative = (lines.size() + upToLink.size() - 1) / maxLineNumber; // The overall index of the single page currently being formatted int page = startPage + pageRelative; + // The line number on this page + int lineNumber = (lines.size() + upToLink.size() - 1) % maxLineNumber; int x = GuiWizardHandbook.isRightPage(page) ? left + GuiWizardHandbook.GUI_WIDTH - GuiWizardHandbook.TEXT_INSET_X - GuiWizardHandbook.PAGE_WIDTH : left + GuiWizardHandbook.TEXT_INSET_X; - int y = top + GuiWizardHandbook.TEXT_INSET_Y + (((lines.size() + upToLink.size() - 1) % maxLineNumber)) * font.FONT_HEIGHT; + int y = top + GuiWizardHandbook.TEXT_INSET_Y + lineNumber * font.FONT_HEIGHT; // Adds any missing sub-lists while(this.buttons.size() <= pageRelative){ @@ -300,18 +311,13 @@ class Section { } // The button id only does what you use it for, so we're just not using it at all. - this.buttons.get(pageRelative).add(GuiButtonHyperlink.create(x, y, font, upToLink, arguments, suffix)); + this.buttons.get(pageRelative).add(GuiButtonHyperlink.create(x, y, font, upToLink, arguments, suffix, maxLineNumber - lineNumber - 1, GuiWizardHandbook.isRightPage(page))); // The link button should exactly overlay the display rawText in the main string // If the link has no display rawText specified, it displays the unformatted target string paragraph = paragraph.replace(linkRaw, arguments[arguments.length - 1]); } - // Formatting - for(Map.Entry entry : GuiWizardHandbook.FORMAT_TAGS.entrySet()){ - paragraph = paragraph.replace(GuiWizardHandbook.FORMAT_MARKER + entry.getKey(), entry.getValue()); - } - lines.addAll(font.listFormattedStringToWidth(paragraph, GuiWizardHandbook.PAGE_WIDTH)); } @@ -373,18 +379,22 @@ class Section { } if(JsonUtils.hasField(json, "contents")){ - section.contents = Contents.fromJson(JsonUtils.getJsonObject(json, "contents")); + section.contents = Contents.fromJson(section, JsonUtils.getJsonObject(json, "contents")); GuiWizardHandbook.contentsList.put(section.contents.id, section.contents); } if(JsonUtils.hasField(json, "text")){ - // TESTME: Does this always preserve order? section.rawText = Streams.stream(JsonUtils.getJsonArray(json, "text")) .map(e -> JsonUtils.getString(e, "element of array rawText")) .toArray(String[]::new); } - // TODO: Triggers + if(JsonUtils.hasField(json, "triggers")){ + section.triggers = Streams.stream(JsonUtils.getJsonArray(json, "triggers")) + .map(e -> new ResourceLocation(JsonUtils.getString(e, "element of array triggers"))) + .toArray(ResourceLocation[]::new); + // TODO: Can we validate this and throw a JSON exception if no such advancement exists? + } if(JsonUtils.hasField(json, "centre")){ JsonObject centre = JsonUtils.getJsonObject(json,"centre"); @@ -416,14 +426,26 @@ class Section { } } - public void onAdvancement(EntityPlayer player, Advancement advancement){ - Minecraft minecraft = Minecraft.getMinecraft(); - //System.out.println(title); - if(triggers != null && Arrays.asList(triggers).contains(advancement) && player == minecraft.player){ - //minecraft.getToastGui().drawToast(IToast); + /** + * Called on login and advancement completion to update this section's unlock status and display toast + * notifications if applicable. + */ + public void updateUnlockStatus(boolean showToasts, ResourceLocation... completedAdvancements){ - // Debug - //System.out.println(title); + if(triggers == null) return; + + List completed = new ArrayList<>(Arrays.asList(completedAdvancements)); + completed.retainAll(Arrays.asList(triggers)); + + // Only shows the toast when the section was locked before and is now unlocked + if(!this.unlocked && !completed.isEmpty() && showToasts && Wizardry.settings.handbookProgression){ + // Mmmmm toast... + Minecraft minecraft = Minecraft.getMinecraft(); + minecraft.getToastGui().add(new HandbookToast(this)); + this.isNew = true; } + + // Currently, this will not take subsections into account + this.unlocked = !completed.isEmpty(); } } diff --git a/src/main/java/electroblob/wizardry/client/model/BakedModelGlowingOverlay.java b/src/main/java/electroblob/wizardry/client/model/BakedModelGlowingOverlay.java new file mode 100644 index 00000000..c3324830 --- /dev/null +++ b/src/main/java/electroblob/wizardry/client/model/BakedModelGlowingOverlay.java @@ -0,0 +1,234 @@ +package electroblob.wizardry.client.model; + +import net.minecraft.block.state.IBlockState; +import net.minecraft.client.Minecraft; +import net.minecraft.client.renderer.block.model.BakedQuad; +import net.minecraft.client.renderer.block.model.IBakedModel; +import net.minecraft.client.renderer.block.model.ItemCameraTransforms; +import net.minecraft.client.renderer.block.model.ItemOverrideList; +import net.minecraft.client.renderer.texture.TextureAtlasSprite; +import net.minecraft.client.renderer.vertex.DefaultVertexFormats; +import net.minecraft.client.renderer.vertex.VertexFormat; +import net.minecraft.util.EnumFacing; +import net.minecraftforge.client.model.pipeline.UnpackedBakedQuad; +import net.minecraftforge.client.model.pipeline.VertexLighterFlat; +import net.minecraftforge.common.ForgeModContainer; +import net.minecraftforge.fml.client.FMLClientHandler; +import org.apache.commons.lang3.tuple.Pair; + +import javax.annotation.Nullable; +import javax.vecmath.Matrix4f; +import java.util.ArrayList; +import java.util.List; + +/** + * Custom baked model that stores a list of texture names and sets the lighting to full brightness for any quads + * with one of those textures. Most of this code was copied and adapted from refined storage, which is licensed under + * the MIT license. https://github.com/raoulvdberge/refinedstorage
    + *
    + * N.B. This doesn't cover item models, and all of the code/model solutions to this that I have tried haven't worked. + * However, I noticed that the shade tag seems to work perfectly for items, so instead I've simply duplicated the block + * models into the item models folder and add {@code "shade":false} where appropriate. (If it works, it works, right?) + * + * @author Electroblob + * @author raoulvdberge + */ +public class BakedModelGlowingOverlay implements IBakedModel { + + // Something something something cache, says Forge + // This breaks randomised block models (because it's cached, duh...) but simply including the rand parameter will + // completely defeat the point of the cache so I need some way of storing the randomised model variants... hmmm... + // See WeightedBakedModel for more on randomisation (it's pretty similar to my 1.7 implementation from years ago) + +// private class CacheKey { +// +// private IBakedModel base; +// private String suffix; +// private IBlockState state; +// private EnumFacing side; +// +// public CacheKey(IBakedModel base, String suffix, IBlockState state, EnumFacing side){ +// this.base = base; +// this.suffix = suffix; +// this.state = state; +// this.side = side; +// } +// +// @Override +// public boolean equals(Object o){ +// +// if(this == o) return true; +// if(o == null || getClass() != o.getClass()) return false; +// +// CacheKey cacheKey = (CacheKey)o; +// +// if(cacheKey.side != side) return false; +// if(!state.equals(cacheKey.state)) return false; +// +// return true; +// } +// +// @Override +// public int hashCode() { +// return state.hashCode() + (31 * (side != null ? side.hashCode() : 0)); +// } +// } +// +// private static final LoadingCache> CACHE = CacheBuilder.newBuilder().build(new CacheLoader>() { +// @Override +// public List load(CacheKey key) { +// return transformQuads(key.base.getQuads(key.state, key.side, 0), key.suffix); +// } +// }); + + private final IBakedModel delegate; + private String suffix; + + public BakedModelGlowingOverlay(IBakedModel delegate, String suffix){ + this.delegate = delegate; + this.suffix = suffix; + } + + @Override + public List getQuads(@Nullable IBlockState state, @Nullable EnumFacing side, long rand){ + if(state == null) return delegate.getQuads(state, side, rand); + return transformQuads(delegate.getQuads(state, side, rand), suffix); + //return CACHE.getUnchecked(new CacheKey(delegate, suffix, state instanceof IExtendedBlockState ? ((IExtendedBlockState) state).getClean() : state, side)); + } + + // I would write these myself but I'd end up with almost the exact same thing anyway + // They replace the quads from the original (delegate) model with full-brightness quads if their texture has the given suffix + + private static List transformQuads(List oldQuads, String suffix){ + + List quads = new ArrayList<>(oldQuads); + + for(int i = 0; i < quads.size(); ++i){ + BakedQuad quad = quads.get(i); + + if(quad.getSprite().getIconName().endsWith(suffix)){ + quads.set(i, transformQuad(quad, 0.007F)); // What's the significance of 0.007? + } + } + + return quads; + } + + private static BakedQuad transformQuad(BakedQuad quad, float light){ + + if(isLightMapDisabled()){ + return quad; + } + + VertexFormat newFormat = getFormatWithLightMap(quad.getFormat()); + + UnpackedBakedQuad.Builder builder = new UnpackedBakedQuad.Builder(newFormat); + + VertexLighterFlat trans = new VertexLighterFlat(Minecraft.getMinecraft().getBlockColors()) { + @Override + protected void updateLightmap(float[] normal, float[] lightmap, float x, float y, float z){ + lightmap[0] = light; + lightmap[1] = light; + } + + @Override + public void setQuadTint(int tint){ + // NO OP + } + }; + + trans.setParent(builder); + + quad.pipe(trans); + + builder.setQuadTint(quad.getTintIndex()); + builder.setQuadOrientation(quad.getFace()); + builder.setTexture(quad.getSprite()); + builder.setApplyDiffuseLighting(false); + + return builder.build(); + } + + @Override + public boolean isAmbientOcclusion(){ + return delegate.isAmbientOcclusion(); + } + + @Override + public boolean isGui3d(){ + return delegate.isGui3d(); + } + + @Override + public boolean isBuiltInRenderer(){ + return delegate.isBuiltInRenderer(); + } + + @Override + public TextureAtlasSprite getParticleTexture(){ + return delegate.getParticleTexture(); + } + + @Override + public ItemCameraTransforms getItemCameraTransforms(){ + return delegate.getItemCameraTransforms(); + } + + @Override + public ItemOverrideList getOverrides(){ + return delegate.getOverrides();//BakedModelItemOverride.instance; + } + + @Override + public boolean isAmbientOcclusion(IBlockState state){ + return delegate.isAmbientOcclusion(state); + } + + @Override + public Pair handlePerspective(ItemCameraTransforms.TransformType cameraTransformType){ + return delegate.handlePerspective(cameraTransformType); + } + + // Utilities + + private static boolean isLightMapDisabled(){ + return FMLClientHandler.instance().hasOptifine() || !ForgeModContainer.forgeLightPipelineEnabled; + } + + private static final VertexFormat ITEM_FORMAT_WITH_LIGHTMAP = new VertexFormat(DefaultVertexFormats.ITEM).addElement(DefaultVertexFormats.TEX_2S); + + private static VertexFormat getFormatWithLightMap(VertexFormat format){ + + if(isLightMapDisabled()){ + return format; + } + + if(format == DefaultVertexFormats.BLOCK){ + return DefaultVertexFormats.BLOCK; + }else if(format == DefaultVertexFormats.ITEM){ + return ITEM_FORMAT_WITH_LIGHTMAP; + }else if(!format.hasUvOffset(1)){ + VertexFormat result = new VertexFormat(format); + result.addElement(DefaultVertexFormats.TEX_2S); + return result; + } + + return format; + } + + // Bit of a weird way of doing things if you ask me, but as far as I can tell it's how you're supposed to do it +// public static final class BakedModelItemOverride extends ItemOverrideList { +// +// // This class doesn't contain any data of its own so it can be a singleton +// public static final BakedModelItemOverride instance = new BakedModelItemOverride(); +// +// private BakedModelItemOverride(){ +// super(ImmutableList.of()); // We're not using the list functionality +// } +// +// @Override +// public IBakedModel handleItemState(IBakedModel originalModel, ItemStack stack, @Nullable World world, @Nullable EntityLivingBase entity){ +// return new BakedModelGlowingOverlay(originalModel, "overlay"); // Bish bash bosh +// } +// } +} diff --git a/src/main/java/electroblob/wizardry/client/model/ModelIceGiant.java b/src/main/java/electroblob/wizardry/client/model/ModelIceGiant.java index 798cfcb4..592f0208 100644 --- a/src/main/java/electroblob/wizardry/client/model/ModelIceGiant.java +++ b/src/main/java/electroblob/wizardry/client/model/ModelIceGiant.java @@ -1,18 +1,16 @@ package electroblob.wizardry.client.model; -import javax.vecmath.Matrix4f; -import javax.vecmath.Vector3f; - import electroblob.wizardry.entity.living.EntityIceGiant; import net.minecraft.client.model.ModelBase; import net.minecraft.client.model.ModelRenderer; import net.minecraft.entity.Entity; import net.minecraft.entity.EntityLivingBase; import net.minecraft.util.math.MathHelper; -import net.minecraftforge.fml.relauncher.Side; -import net.minecraftforge.fml.relauncher.SideOnly; -@SideOnly(Side.CLIENT) +import javax.vecmath.Matrix4f; +import javax.vecmath.Vector3f; + +//@SideOnly(Side.CLIENT) public class ModelIceGiant extends ModelBase { /** The head model for the iron golem. */ public ModelRenderer iceGiantHead; diff --git a/src/main/java/electroblob/wizardry/client/model/ModelWizard.java b/src/main/java/electroblob/wizardry/client/model/ModelWizard.java index 0204c86a..8e7a469d 100644 --- a/src/main/java/electroblob/wizardry/client/model/ModelWizard.java +++ b/src/main/java/electroblob/wizardry/client/model/ModelWizard.java @@ -97,9 +97,9 @@ public class ModelWizard extends ModelBiped { setRotation(Shape13, 0F, 0F, 0F); // Makes head bits move with head - // bipedHead.addChild(Shape5); + // bipedHead.addChild(hatSegment4); bipedHead.addChild(beard); - // bipedHead.addChild(Shape7); + // bipedHead.addChild(hatSegment6); // bipedHead.addChild(Shape8); // bipedHead.addChild(Shape9); // bipedHead.addChild(Shape10); @@ -116,8 +116,8 @@ public class ModelWizard extends ModelBiped { /* public void render(Entity entity, float f, float f1, float f2, float f3, float f4, float f5) { * super.render(entity, f, f1, f2, f3, f4, f5); setRotationAngles(f, f1, f2, f3, f4, f5, entity); * bipedRightLeg.render(f5); bipedLeftLeg.render(f5); bipedBody.render(f5); bipedLeftArm.render(f5); - * bipedRightArm.render(f5); bipedHead.render(f5); Shape5.render(f5); Shape8.render(f5); Shape9.render(f5); - * Shape10.render(f5); Shape7.render(f5); Shape11.render(f5); Shape12.render(f5); Shape6.render(f5); + * bipedRightArm.render(f5); bipedHead.render(f5); hatSegment4.render(f5); Shape8.render(f5); Shape9.render(f5); + * Shape10.render(f5); hatSegment6.render(f5); Shape11.render(f5); Shape12.render(f5); hatSegment5.render(f5); * Shape13.render(f5); } */ private void setRotation(ModelRenderer model, float x, float y, float z){ model.rotateAngleX = x; diff --git a/src/main/java/electroblob/wizardry/client/model/ModelWizardArmour.java b/src/main/java/electroblob/wizardry/client/model/ModelWizardArmour.java index 20429a71..2bebd9c0 100644 --- a/src/main/java/electroblob/wizardry/client/model/ModelWizardArmour.java +++ b/src/main/java/electroblob/wizardry/client/model/ModelWizardArmour.java @@ -1,99 +1,110 @@ package electroblob.wizardry.client.model; +import electroblob.wizardry.block.BlockStatue; import net.minecraft.client.model.ModelRenderer; import net.minecraft.entity.Entity; public class ModelWizardArmour extends ModelArmourFixer { - ModelRenderer Shape1; - ModelRenderer Shape2; - ModelRenderer Shape3; - ModelRenderer Shape4; - ModelRenderer Shape5; - ModelRenderer Shape6; - ModelRenderer Shape7; + + ModelRenderer hatBrim; + ModelRenderer hatSegment1; + ModelRenderer hatSegment2; + ModelRenderer hatSegment3; + ModelRenderer hatSegment4; + ModelRenderer hatSegment5; + ModelRenderer hatSegment6; ModelRenderer robe; - public ModelWizardArmour(float scale){ + public ModelWizardArmour(float delta){ - super(scale, 0, 64, 64); + super(delta, 0, 64, 64); // This is necessary to stop the head from scaling. this.bipedHead = new ModelRenderer(this, 0, 0); - this.bipedHead.addBox(-4.0F, -8.0F, -4.0F, 8, 8, 8, 0.1f); + // The hat layer has an offset of 0.5, so 0.6 is about the smallest we can get away with + this.bipedHead.addBox(-4.0F, -8.0F, -4.0F, 8, 8, 8, 0.6f); this.bipedHead.setRotationPoint(0.0F, 0.0F + 0, 0.0F); - Shape1 = new ModelRenderer(this, -16, 32); - Shape1.addBox(-8F, -7F, -8F, 16, 0, 16); - Shape1.setRotationPoint(0F, 0F, 0F); - Shape1.setTextureSize(64, 64); - Shape1.mirror = true; - setRotation(Shape1, 0F, 0F, 0F); + hatBrim = new ModelRenderer(this, 0, 47); + // Making the height 1 stops the top and bottom z-fighting when the hat is enchanted + hatBrim.addBox(-8F, -6.85F, -8F, 16, 1, 16, 0.6f); + hatBrim.setRotationPoint(0F, 0F, 0F); + hatBrim.setTextureSize(64, 64); + hatBrim.mirror = true; + setRotation(hatBrim, 0F, 0F, 0F); - Shape2 = new ModelRenderer(this, 0, 48); - Shape2.addBox(0F, 0F, 0F, 6, 2, 6); - Shape2.setRotationPoint(-3F, -10F, -3F); - Shape2.setTextureSize(64, 64); - Shape2.mirror = true; - setRotation(Shape2, -0.1396263F, 0F, 0F); + hatSegment1 = new ModelRenderer(this, 0, 32); + hatSegment1.addBox(0F, 0F, 0F, 6, 2, 6, 0.2f); + hatSegment1.setRotationPoint(-3F, -10.6F, -3F); + hatSegment1.setTextureSize(64, 64); + hatSegment1.mirror = true; + setRotation(hatSegment1, -0.1396263F, 0F, 0F); - Shape3 = new ModelRenderer(this, 0, 56); - Shape3.addBox(0F, 0F, 0F, 5, 2, 5); - Shape3.setRotationPoint(-2.5F, -11.53333F, -2F); - Shape3.setTextureSize(64, 64); - Shape3.mirror = true; - setRotation(Shape3, -0.2443461F, 0F, 0F); + hatSegment2 = new ModelRenderer(this, 0, 40); + hatSegment2.addBox(0F, 0F, 0F, 5, 2, 5, 0.1f); + hatSegment2.setRotationPoint(-2.5F, -12.13333F, -2F); + hatSegment2.setTextureSize(64, 64); + hatSegment2.mirror = true; + setRotation(hatSegment2, -0.2443461F, 0F, 0F); - Shape4 = new ModelRenderer(this, 24, 48); - Shape4.addBox(0F, 0F, 0F, 4, 2, 4); - Shape4.setRotationPoint(-2F, -13F, -1F); - Shape4.setTextureSize(64, 64); - Shape4.mirror = true; - setRotation(Shape4, -0.4014257F, 0F, 0F); + hatSegment3 = new ModelRenderer(this, 24, 32); + hatSegment3.addBox(0F, 0F, 0F, 4, 2, 4); + hatSegment3.setRotationPoint(-2F, -13.6F, -1F); + hatSegment3.setTextureSize(64, 64); + hatSegment3.mirror = true; + setRotation(hatSegment3, -0.4014257F, 0F, 0F); - Shape5 = new ModelRenderer(this, 24, 54); - Shape5.addBox(0F, 0F, 0F, 3, 2, 3); - Shape5.setRotationPoint(-1.5F, -14F, 0F); - Shape5.setTextureSize(64, 64); - Shape5.mirror = true; - setRotation(Shape5, -0.5759587F, 0F, 0F); + hatSegment4 = new ModelRenderer(this, 24, 38); + hatSegment4.addBox(0F, 0F, 0F, 3, 2, 3); + hatSegment4.setRotationPoint(-1.5F, -14.6F, 0F); + hatSegment4.setTextureSize(64, 64); + hatSegment4.mirror = true; + setRotation(hatSegment4, -0.5759587F, 0F, 0F); - Shape6 = new ModelRenderer(this, 20, 59); - Shape6.addBox(0F, 0F, 0F, 2, 2, 2); - Shape6.setRotationPoint(-1F, -14F, 0F); - Shape6.setTextureSize(64, 64); - Shape6.mirror = true; - setRotation(Shape6, 0.3316126F, 0F, 0F); + hatSegment5 = new ModelRenderer(this, 20, 43); + hatSegment5.addBox(0F, 0F, 0F, 2, 2, 2); + hatSegment5.setRotationPoint(-1F, -14.6F, 0F); + hatSegment5.setTextureSize(64, 64); + hatSegment5.mirror = true; + setRotation(hatSegment5, 0.3316126F, 0F, 0F); - Shape7 = new ModelRenderer(this, 28, 59); - Shape7.addBox(0F, 0F, 0F, 1, 1, 3); - Shape7.setRotationPoint(-0.5F, -14.5F, 2F); - Shape7.setTextureSize(64, 64); - Shape7.mirror = true; - setRotation(Shape7, -0.5585054F, 0F, 0F); + hatSegment6 = new ModelRenderer(this, 28, 43); + hatSegment6.addBox(0F, 0F, 0F, 1, 1, 3); + hatSegment6.setRotationPoint(-0.5F, -15.1F, 2F); + hatSegment6.setTextureSize(64, 64); + hatSegment6.mirror = true; + setRotation(hatSegment6, -0.5585054F, 0F, 0F); - // The robe is now the body - bipedBody = new ModelRenderer(this, 40, 42); - bipedBody.addBox(-4F, 0F, -2F, 8, 18, 4, scale); + bipedBody = new ModelRenderer(this, 16, 16); + bipedBody.addBox(-4F, 0F, -2F, 8, 11, 4, delta); bipedBody.setRotationPoint(0F, 0F, 0F); bipedBody.setTextureSize(64, 64); bipedBody.mirror = true; setRotation(bipedBody, 0F, 0F, 0F); + robe = new ModelRenderer(this, 40, 32); + robe.addBox(-4F, 0F, -2F, 8, 7, 4, delta); + robe.setRotationPoint(0F, 12, 0F); // 12.5 accounts for the expansion of each box + robe.setTextureSize(64, 64); + robe.mirror = true; + setRotation(robe, 0F, 0F, 0F); + // Makes the hat rotate with the head. - bipedHead.addChild(Shape1); - bipedHead.addChild(Shape2); - bipedHead.addChild(Shape3); - bipedHead.addChild(Shape4); - bipedHead.addChild(Shape5); - bipedHead.addChild(Shape6); - bipedHead.addChild(Shape7); - // Makes the robe move with the body - // bipedBody.addChild(robe); + bipedHead.addChild(hatBrim); + bipedHead.addChild(hatSegment1); + bipedHead.addChild(hatSegment2); + bipedHead.addChild(hatSegment3); + bipedHead.addChild(hatSegment4); + bipedHead.addChild(hatSegment5); + bipedHead.addChild(hatSegment6); } public void render(Entity entity, float f, float f1, float f2, float f3, float f4, float f5){ + if(entity.isInvisible() && !entity.getEntityData().getBoolean(BlockStatue.PETRIFIED_NBT_KEY) + && !entity.getEntityData().getBoolean(BlockStatue.FROZEN_NBT_KEY)) return; super.render(entity, f, f1, f2, f3, f4, f5); setRotationAngles(f, f1, f2, f3, f4, f5, entity); + this.robe.render(f5); } private void setRotation(ModelRenderer model, float x, float y, float z){ @@ -104,6 +115,20 @@ public class ModelWizardArmour extends ModelArmourFixer { public void setRotationAngles(float f, float f1, float f2, float f3, float f4, float f5, Entity entity){ super.setRotationAngles(f, f1, f2, f3, f4, f5, entity); + this.robe.showModel = this.bipedBody.showModel; + if(this.isSneak){ + //this.robe.rotationPointY = 10.5f; + this.robe.rotationPointZ = 4; + }else{ + //this.robe.rotationPointY = 12.5f; + this.robe.rotationPointZ = 0; + } + + // The bottom part of the robe takes the y rotation from the rest of the robe but the x/z rotation + // from the average of the two legs + this.robe.rotateAngleX = (this.bipedLeftLeg.rotateAngleX + this.bipedRightLeg.rotateAngleX) / 2f; + this.robe.rotateAngleY = this.bipedBody.rotateAngleY; + this.robe.rotateAngleZ = (this.bipedLeftLeg.rotateAngleZ + this.bipedRightLeg.rotateAngleZ) / 2f; } } diff --git a/src/main/java/electroblob/wizardry/client/model/WizardryItemModels.java b/src/main/java/electroblob/wizardry/client/model/WizardryItemModels.java deleted file mode 100644 index f9d101c8..00000000 --- a/src/main/java/electroblob/wizardry/client/model/WizardryItemModels.java +++ /dev/null @@ -1,197 +0,0 @@ -package electroblob.wizardry.client.model; - -import electroblob.wizardry.registry.WizardryBlocks; -import electroblob.wizardry.registry.WizardryItems; -import net.minecraft.client.renderer.block.model.ModelResourceLocation; -import net.minecraft.item.Item; -import net.minecraft.item.ItemStack; -import net.minecraft.util.NonNullList; -import net.minecraftforge.client.event.ModelRegistryEvent; -import net.minecraftforge.client.model.ModelLoader; -import net.minecraftforge.fml.common.Mod; -import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; -import net.minecraftforge.fml.relauncher.Side; -import net.minecraftforge.fml.relauncher.SideOnly; -import net.minecraftforge.oredict.OreDictionary; - -/** - * Class responsible for registering all of wizardry's item (and itemblock) models. - * - * @author Electroblob - * @since Wizardry 2.1 - */ -@SideOnly(Side.CLIENT) -@Mod.EventBusSubscriber(Side.CLIENT) -public final class WizardryItemModels { - - @SubscribeEvent - public static void register(ModelRegistryEvent event){ - - // ItemBlocks - - registerItemModel(Item.getItemFromBlock(WizardryBlocks.arcane_workbench)); - registerItemModel(Item.getItemFromBlock(WizardryBlocks.crystal_ore)); - registerItemModel(Item.getItemFromBlock(WizardryBlocks.crystal_flower)); - registerItemModel(Item.getItemFromBlock(WizardryBlocks.transportation_stone)); - registerItemModel(Item.getItemFromBlock(WizardryBlocks.crystal_block)); - - // Items - - registerItemModel(WizardryItems.magic_crystal); - - registerItemModel(WizardryItems.magic_wand); - registerItemModel(WizardryItems.apprentice_wand); - registerItemModel(WizardryItems.advanced_wand); - registerItemModel(WizardryItems.master_wand); - - registerItemModel(WizardryItems.spell_book); - // Wildcard registered for wizard trades. - registerItemModel(WizardryItems.spell_book, OreDictionary.WILDCARD_VALUE, "normal"); - registerItemModel(WizardryItems.arcane_tome); - registerItemModel(WizardryItems.wizard_handbook); - - registerItemModel(WizardryItems.basic_fire_wand); - registerItemModel(WizardryItems.basic_ice_wand); - registerItemModel(WizardryItems.basic_lightning_wand); - registerItemModel(WizardryItems.basic_necromancy_wand); - registerItemModel(WizardryItems.basic_earth_wand); - registerItemModel(WizardryItems.basic_sorcery_wand); - registerItemModel(WizardryItems.basic_healing_wand); - - registerItemModel(WizardryItems.apprentice_fire_wand); - registerItemModel(WizardryItems.apprentice_ice_wand); - registerItemModel(WizardryItems.apprentice_lightning_wand); - registerItemModel(WizardryItems.apprentice_necromancy_wand); - registerItemModel(WizardryItems.apprentice_earth_wand); - registerItemModel(WizardryItems.apprentice_sorcery_wand); - registerItemModel(WizardryItems.apprentice_healing_wand); - - registerItemModel(WizardryItems.advanced_fire_wand); - registerItemModel(WizardryItems.advanced_ice_wand); - registerItemModel(WizardryItems.advanced_lightning_wand); - registerItemModel(WizardryItems.advanced_necromancy_wand); - registerItemModel(WizardryItems.advanced_earth_wand); - registerItemModel(WizardryItems.advanced_sorcery_wand); - registerItemModel(WizardryItems.advanced_healing_wand); - - registerItemModel(WizardryItems.master_fire_wand); - registerItemModel(WizardryItems.master_ice_wand); - registerItemModel(WizardryItems.master_lightning_wand); - registerItemModel(WizardryItems.master_necromancy_wand); - registerItemModel(WizardryItems.master_earth_wand); - registerItemModel(WizardryItems.master_sorcery_wand); - registerItemModel(WizardryItems.master_healing_wand); - - registerItemModel(WizardryItems.spectral_sword); - registerItemModel(WizardryItems.spectral_pickaxe); - registerItemModel(WizardryItems.spectral_bow); - - registerItemModel(WizardryItems.mana_flask); - - registerItemModel(WizardryItems.storage_upgrade); - registerItemModel(WizardryItems.siphon_upgrade); - registerItemModel(WizardryItems.condenser_upgrade); - registerItemModel(WizardryItems.range_upgrade); - registerItemModel(WizardryItems.duration_upgrade); - registerItemModel(WizardryItems.cooldown_upgrade); - registerItemModel(WizardryItems.blast_upgrade); - registerItemModel(WizardryItems.attunement_upgrade); - - registerItemModel(WizardryItems.flaming_axe); - registerItemModel(WizardryItems.frost_axe); - - registerItemModel(WizardryItems.firebomb); - registerItemModel(WizardryItems.poison_bomb); - - registerItemModel(WizardryItems.blank_scroll); - registerItemModel(WizardryItems.scroll); - - registerItemModel(WizardryItems.armour_upgrade); - - registerItemModel(WizardryItems.magic_silk); - - registerItemModel(WizardryItems.wizard_hat); - registerItemModel(WizardryItems.wizard_robe); - registerItemModel(WizardryItems.wizard_leggings); - registerItemModel(WizardryItems.wizard_boots); - - registerItemModel(WizardryItems.wizard_hat_fire); - registerItemModel(WizardryItems.wizard_robe_fire); - registerItemModel(WizardryItems.wizard_leggings_fire); - registerItemModel(WizardryItems.wizard_boots_fire); - - registerItemModel(WizardryItems.wizard_hat_ice); - registerItemModel(WizardryItems.wizard_robe_ice); - registerItemModel(WizardryItems.wizard_leggings_ice); - registerItemModel(WizardryItems.wizard_boots_ice); - - registerItemModel(WizardryItems.wizard_hat_lightning); - registerItemModel(WizardryItems.wizard_robe_lightning); - registerItemModel(WizardryItems.wizard_leggings_lightning); - registerItemModel(WizardryItems.wizard_boots_lightning); - - registerItemModel(WizardryItems.wizard_hat_necromancy); - registerItemModel(WizardryItems.wizard_robe_necromancy); - registerItemModel(WizardryItems.wizard_leggings_necromancy); - registerItemModel(WizardryItems.wizard_boots_necromancy); - - registerItemModel(WizardryItems.wizard_hat_earth); - registerItemModel(WizardryItems.wizard_robe_earth); - registerItemModel(WizardryItems.wizard_leggings_earth); - registerItemModel(WizardryItems.wizard_boots_earth); - - registerItemModel(WizardryItems.wizard_hat_sorcery); - registerItemModel(WizardryItems.wizard_robe_sorcery); - registerItemModel(WizardryItems.wizard_leggings_sorcery); - registerItemModel(WizardryItems.wizard_boots_sorcery); - - registerItemModel(WizardryItems.wizard_hat_healing); - registerItemModel(WizardryItems.wizard_robe_healing); - registerItemModel(WizardryItems.wizard_leggings_healing); - registerItemModel(WizardryItems.wizard_boots_healing); - - registerItemModel(WizardryItems.spectral_helmet); - registerItemModel(WizardryItems.spectral_chestplate); - registerItemModel(WizardryItems.spectral_leggings); - registerItemModel(WizardryItems.spectral_boots); - - registerItemModel(WizardryItems.smoke_bomb); - - registerItemModel(WizardryItems.identification_scroll); - } - - // Moved from the proxies - - /** - * Registers an item model, using the item's registry name as the model name (this convention makes it easier to - * keep track of everything). Variant defaults to "normal". Registers the model for metadata 0 automatically, plus - * all the other metadata values that the item can take, as defined in - * {@link Item#getSubItems(Item, net.minecraft.creativetab.CreativeTabs, java.util.List)}. The creative tab supplied - * to the aforementioned method will be whichever one the item is in. - */ - private static void registerItemModel(Item item){ - - if(item.getHasSubtypes()){ - NonNullList items = NonNullList.create(); - item.getSubItems(item.getCreativeTab(), items); // Client-only method, but we're client-side so this is OK. - for(ItemStack stack : items){ - ModelLoader.setCustomModelResourceLocation(item, stack.getMetadata(), - new ModelResourceLocation(item.getRegistryName(), "inventory")); - } - } - // Changing the last parameter from null to "inventory" fixed the item/block model weirdness. No idea why! - ModelLoader.setCustomModelResourceLocation(item, 0, - new ModelResourceLocation(item.getRegistryName(), "inventory")); - } - - /** - * Registers an item model for the given metadata, using the item's registry name as the model name (this convention - * makes it easier to keep track of everything). This is intended for registering additional metadata values which - * aren't displayed in the creative menu, for example the wildcard spell book used in wizard trades. - */ - private static void registerItemModel(Item item, int metadata, String variant){ - ModelLoader.setCustomModelResourceLocation(item, metadata, - new ModelResourceLocation(item.getRegistryName(), variant)); - } - -} diff --git a/src/main/java/electroblob/wizardry/client/model/WizardryModels.java b/src/main/java/electroblob/wizardry/client/model/WizardryModels.java new file mode 100644 index 00000000..a6f2529e --- /dev/null +++ b/src/main/java/electroblob/wizardry/client/model/WizardryModels.java @@ -0,0 +1,343 @@ +package electroblob.wizardry.client.model; + +import electroblob.wizardry.Wizardry; +import electroblob.wizardry.block.BlockCrystal; +import electroblob.wizardry.block.BlockPedestal; +import electroblob.wizardry.block.BlockRunestone; +import electroblob.wizardry.item.IMultiTexturedItem; +import electroblob.wizardry.item.ItemBlockMultiTexturedElemental; +import electroblob.wizardry.item.ItemCrystal; +import electroblob.wizardry.registry.WizardryBlocks; +import electroblob.wizardry.registry.WizardryItems; +import net.minecraft.client.renderer.block.model.IBakedModel; +import net.minecraft.client.renderer.block.model.ModelResourceLocation; +import net.minecraft.client.renderer.block.statemap.StateMap; +import net.minecraft.creativetab.CreativeTabs; +import net.minecraft.item.Item; +import net.minecraft.item.ItemStack; +import net.minecraft.util.NonNullList; +import net.minecraftforge.client.event.ModelBakeEvent; +import net.minecraftforge.client.event.ModelRegistryEvent; +import net.minecraftforge.client.model.ModelLoader; +import net.minecraftforge.fml.common.Mod; +import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; +import net.minecraftforge.fml.relauncher.Side; +import net.minecraftforge.oredict.OreDictionary; + +/** + * Class responsible for registering all of wizardry's item and block models. + * + * @author Electroblob + * @since Wizardry 2.1 + */ +//@SideOnly(Side.CLIENT) +@Mod.EventBusSubscriber(Side.CLIENT) +public final class WizardryModels { + + private WizardryModels(){} // No instances! + + @SubscribeEvent + public static void register(ModelRegistryEvent event){ + + // ItemBlocks + + registerItemModel(Item.getItemFromBlock(WizardryBlocks.arcane_workbench)); + registerItemModel(Item.getItemFromBlock(WizardryBlocks.crystal_ore)); + registerItemModel(Item.getItemFromBlock(WizardryBlocks.crystal_flower)); + registerItemModel(Item.getItemFromBlock(WizardryBlocks.transportation_stone)); + + ModelLoader.setCustomStateMapper(WizardryBlocks.crystal_block, new StateMap.Builder() + .withName(BlockCrystal.ELEMENT).withSuffix("_crystal_block").build()); + // Yay unchecked casting! But we know it's always ok here, and it makes everything much neater. + ItemBlockMultiTexturedElemental crystalBlockItem = (ItemBlockMultiTexturedElemental)Item.getItemFromBlock(WizardryBlocks.crystal_block); + registerMultiTexturedModel(crystalBlockItem); + + ModelLoader.setCustomStateMapper(WizardryBlocks.runestone, new StateMap.Builder() + .withName(BlockRunestone.ELEMENT).withSuffix("_runestone").build()); + ItemBlockMultiTexturedElemental runestoneItem = (ItemBlockMultiTexturedElemental)Item.getItemFromBlock(WizardryBlocks.runestone); + registerMultiTexturedModel(runestoneItem); + + ModelLoader.setCustomStateMapper(WizardryBlocks.runestone_pedestal, new StateMap.Builder() + .withName(BlockPedestal.ELEMENT).ignore(BlockPedestal.NATURAL).withSuffix("_runestone_pedestal").build()); // Don't care about NATURAL property + ItemBlockMultiTexturedElemental pedestalItem = (ItemBlockMultiTexturedElemental)Item.getItemFromBlock(WizardryBlocks.runestone_pedestal); + registerMultiTexturedModel(pedestalItem); + + // Items + + registerMultiTexturedModel((ItemCrystal)WizardryItems.magic_crystal); + + registerItemModel(WizardryItems.magic_wand); + registerItemModel(WizardryItems.apprentice_wand); + registerItemModel(WizardryItems.advanced_wand); + registerItemModel(WizardryItems.master_wand); + + registerItemModel(WizardryItems.spell_book); + // Wildcard registered for wizard trades. + registerItemModel(WizardryItems.spell_book, OreDictionary.WILDCARD_VALUE, "normal"); + registerItemModel(WizardryItems.arcane_tome); + registerItemModel(WizardryItems.wizard_handbook); + + registerItemModel(WizardryItems.novice_fire_wand); + registerItemModel(WizardryItems.novice_ice_wand); + registerItemModel(WizardryItems.novice_lightning_wand); + registerItemModel(WizardryItems.novice_necromancy_wand); + registerItemModel(WizardryItems.novice_earth_wand); + registerItemModel(WizardryItems.novice_sorcery_wand); + registerItemModel(WizardryItems.novice_healing_wand); + + registerItemModel(WizardryItems.apprentice_fire_wand); + registerItemModel(WizardryItems.apprentice_ice_wand); + registerItemModel(WizardryItems.apprentice_lightning_wand); + registerItemModel(WizardryItems.apprentice_necromancy_wand); + registerItemModel(WizardryItems.apprentice_earth_wand); + registerItemModel(WizardryItems.apprentice_sorcery_wand); + registerItemModel(WizardryItems.apprentice_healing_wand); + + registerItemModel(WizardryItems.advanced_fire_wand); + registerItemModel(WizardryItems.advanced_ice_wand); + registerItemModel(WizardryItems.advanced_lightning_wand); + registerItemModel(WizardryItems.advanced_necromancy_wand); + registerItemModel(WizardryItems.advanced_earth_wand); + registerItemModel(WizardryItems.advanced_sorcery_wand); + registerItemModel(WizardryItems.advanced_healing_wand); + + registerItemModel(WizardryItems.master_fire_wand); + registerItemModel(WizardryItems.master_ice_wand); + registerItemModel(WizardryItems.master_lightning_wand); + registerItemModel(WizardryItems.master_necromancy_wand); + registerItemModel(WizardryItems.master_earth_wand); + registerItemModel(WizardryItems.master_sorcery_wand); + registerItemModel(WizardryItems.master_healing_wand); + + registerItemModel(WizardryItems.spectral_sword); + registerItemModel(WizardryItems.spectral_pickaxe); + registerItemModel(WizardryItems.spectral_bow); + + registerItemModel(WizardryItems.small_mana_flask); + registerItemModel(WizardryItems.medium_mana_flask); + registerItemModel(WizardryItems.large_mana_flask); + + registerItemModel(WizardryItems.crystal_shard); + registerItemModel(WizardryItems.grand_crystal); + + registerItemModel(WizardryItems.astral_diamond); + + registerItemModel(WizardryItems.purifying_elixir); + + registerItemModel(WizardryItems.storage_upgrade); + registerItemModel(WizardryItems.siphon_upgrade); + registerItemModel(WizardryItems.condenser_upgrade); + registerItemModel(WizardryItems.range_upgrade); + registerItemModel(WizardryItems.duration_upgrade); + registerItemModel(WizardryItems.cooldown_upgrade); + registerItemModel(WizardryItems.blast_upgrade); + registerItemModel(WizardryItems.attunement_upgrade); + registerItemModel(WizardryItems.melee_upgrade); + + registerItemModel(WizardryItems.flaming_axe); + registerItemModel(WizardryItems.frost_axe); + + registerItemModel(WizardryItems.firebomb); + registerItemModel(WizardryItems.poison_bomb); + registerItemModel(WizardryItems.smoke_bomb); + registerItemModel(WizardryItems.spark_bomb); + + registerItemModel(WizardryItems.blank_scroll); + registerItemModel(WizardryItems.scroll); + registerItemModel(WizardryItems.identification_scroll); + + registerItemModel(WizardryItems.armour_upgrade); + + registerItemModel(WizardryItems.magic_silk); + + registerItemModel(WizardryItems.wizard_hat); + registerItemModel(WizardryItems.wizard_robe); + registerItemModel(WizardryItems.wizard_leggings); + registerItemModel(WizardryItems.wizard_boots); + + registerItemModel(WizardryItems.wizard_hat_fire); + registerItemModel(WizardryItems.wizard_robe_fire); + registerItemModel(WizardryItems.wizard_leggings_fire); + registerItemModel(WizardryItems.wizard_boots_fire); + + registerItemModel(WizardryItems.wizard_hat_ice); + registerItemModel(WizardryItems.wizard_robe_ice); + registerItemModel(WizardryItems.wizard_leggings_ice); + registerItemModel(WizardryItems.wizard_boots_ice); + + registerItemModel(WizardryItems.wizard_hat_lightning); + registerItemModel(WizardryItems.wizard_robe_lightning); + registerItemModel(WizardryItems.wizard_leggings_lightning); + registerItemModel(WizardryItems.wizard_boots_lightning); + + registerItemModel(WizardryItems.wizard_hat_necromancy); + registerItemModel(WizardryItems.wizard_robe_necromancy); + registerItemModel(WizardryItems.wizard_leggings_necromancy); + registerItemModel(WizardryItems.wizard_boots_necromancy); + + registerItemModel(WizardryItems.wizard_hat_earth); + registerItemModel(WizardryItems.wizard_robe_earth); + registerItemModel(WizardryItems.wizard_leggings_earth); + registerItemModel(WizardryItems.wizard_boots_earth); + + registerItemModel(WizardryItems.wizard_hat_sorcery); + registerItemModel(WizardryItems.wizard_robe_sorcery); + registerItemModel(WizardryItems.wizard_leggings_sorcery); + registerItemModel(WizardryItems.wizard_boots_sorcery); + + registerItemModel(WizardryItems.wizard_hat_healing); + registerItemModel(WizardryItems.wizard_robe_healing); + registerItemModel(WizardryItems.wizard_leggings_healing); + registerItemModel(WizardryItems.wizard_boots_healing); + + registerItemModel(WizardryItems.spectral_helmet); + registerItemModel(WizardryItems.spectral_chestplate); + registerItemModel(WizardryItems.spectral_leggings); + registerItemModel(WizardryItems.spectral_boots); + + registerItemModel(WizardryItems.lightning_hammer); + + registerItemModel(WizardryItems.ring_condensing); + registerItemModel(WizardryItems.ring_siphoning); + registerItemModel(WizardryItems.ring_battlemage); + registerItemModel(WizardryItems.ring_combustion); + registerItemModel(WizardryItems.ring_fire_melee); + registerItemModel(WizardryItems.ring_fire_biome); + registerItemModel(WizardryItems.ring_disintegration); + registerItemModel(WizardryItems.ring_ice_melee); + registerItemModel(WizardryItems.ring_ice_biome); + registerItemModel(WizardryItems.ring_arcane_frost); + registerItemModel(WizardryItems.ring_shattering); + registerItemModel(WizardryItems.ring_lightning_melee); + registerItemModel(WizardryItems.ring_storm); + registerItemModel(WizardryItems.ring_seeking); + registerItemModel(WizardryItems.ring_hammer); + registerItemModel(WizardryItems.ring_soulbinding); + registerItemModel(WizardryItems.ring_leeching); + registerItemModel(WizardryItems.ring_necromancy_melee); + registerItemModel(WizardryItems.ring_mind_control); + registerItemModel(WizardryItems.ring_poison); + registerItemModel(WizardryItems.ring_earth_melee); + registerItemModel(WizardryItems.ring_earth_biome); + registerItemModel(WizardryItems.ring_full_moon); + registerItemModel(WizardryItems.ring_extraction); + registerItemModel(WizardryItems.ring_mana_return); + registerItemModel(WizardryItems.ring_blockwrangler); + registerItemModel(WizardryItems.ring_conjurer); + registerItemModel(WizardryItems.ring_defender); + registerItemModel(WizardryItems.ring_paladin); + registerItemModel(WizardryItems.ring_interdiction); + + registerItemModel(WizardryItems.amulet_arcane_defence); + registerItemModel(WizardryItems.amulet_warding); + registerItemModel(WizardryItems.amulet_wisdom); + registerItemModel(WizardryItems.amulet_fire_protection); + registerItemModel(WizardryItems.amulet_fire_cloaking); + registerItemModel(WizardryItems.amulet_ice_immunity); + registerItemModel(WizardryItems.amulet_ice_protection); + registerItemModel(WizardryItems.amulet_potential); + registerItemModel(WizardryItems.amulet_channeling); + registerItemModel(WizardryItems.amulet_lich); + registerItemModel(WizardryItems.amulet_wither_immunity); + registerItemModel(WizardryItems.amulet_glide); + registerItemModel(WizardryItems.amulet_banishing); + registerItemModel(WizardryItems.amulet_anchoring); + registerItemModel(WizardryItems.amulet_recovery); + registerItemModel(WizardryItems.amulet_transience); + registerItemModel(WizardryItems.amulet_resurrection); + registerItemModel(WizardryItems.amulet_auto_shield); + + registerItemModel(WizardryItems.charm_haggler); + registerItemModel(WizardryItems.charm_experience_tome); + registerItemModel(WizardryItems.charm_auto_smelt); + registerItemModel(WizardryItems.charm_lava_walking); + registerItemModel(WizardryItems.charm_storm); + registerItemModel(WizardryItems.charm_minion_health); + registerItemModel(WizardryItems.charm_minion_variants); + registerItemModel(WizardryItems.charm_flight); + registerItemModel(WizardryItems.charm_growth); + registerItemModel(WizardryItems.charm_abseiling); + registerItemModel(WizardryItems.charm_silk_touch); + registerItemModel(WizardryItems.charm_stop_time); + registerItemModel(WizardryItems.charm_light); + registerItemModel(WizardryItems.charm_transportation); + registerItemModel(WizardryItems.charm_feeding); + + } + + @SubscribeEvent + public static void bake(ModelBakeEvent event){ + // MMMmmmm I love the smell of freshly-baked models... + // This stuff is the boilerplate for making runestone overlay render with full brightness + // See https://www.minecraftforge.net/forum/topic/66005-how-do-i-make-a-tileentityspecialrenderer-solved-with-ibakedmodel/ + // As usual the Forge documentation is just a description of each class and not an explanation of how to use them + // I had to work out where this goes from the refined storage repo linked in the above thread, which is mixed in + // with a more extensive registration system (which is super neat, but it's overkill for our purposes) + // https://github.com/raoulvdberge/refinedstorage/blob/13d6e7f2b92f41b5009187aa2cbde50dbc72082f/src/main/java/com/raoulvdberge/refinedstorage/proxy/ProxyClient.java#L59 + + for(ModelResourceLocation location : event.getModelRegistry().getKeys()){ + + if(location.getNamespace().equals(Wizardry.MODID)){ + + if(location.getPath().contains("runestone") || location.getPath().contains("runestone_pedestal")){ + IBakedModel original = event.getModelRegistry().getObject(location); + event.getModelRegistry().putObject(location, new BakedModelGlowingOverlay(original, "overlay")); + } + } + } + } + + // Moved from the proxies + + /** + * Registers an item model, using the item's registry name as the model name (this convention makes it easier to + * keep track of everything). Variant defaults to "normal". Registers the model for metadata 0 automatically, plus + * all the other metadata values that the item can take, as defined in + * {@link Item#getSubItems(CreativeTabs, NonNullList)}. The creative tab supplied + * to the aforementioned method will be whichever one the item is in. + */ + private static void registerItemModel(Item item){ + + if(item.getHasSubtypes()){ + NonNullList items = NonNullList.create(); + item.getSubItems(item.getCreativeTab(), items); // Client-only method, but we're client-side so this is OK. + for(ItemStack stack : items){ + ModelLoader.setCustomModelResourceLocation(item, stack.getMetadata(), + new ModelResourceLocation(item.getRegistryName(), "inventory")); + } + } + // Changing the last parameter from null to "inventory" fixed the item/block model weirdness. No idea why! + ModelLoader.setCustomModelResourceLocation(item, 0, + new ModelResourceLocation(item.getRegistryName(), "inventory")); + } + + /** + * Registers an item model, using the itemstack-sensitive {@link IMultiTexturedItem#getModelName(ItemStack)} as the + * model name. This allows items to change their texture based on metadata/NBT. Variant defaults to "normal". Registers the + * model for metadata 0 automatically, plus all the other metadata values that the item can take, as defined in + * {@link Item#getSubItems(CreativeTabs, NonNullList)}. The creative tab supplied + * to the aforementioned method will be whichever one the item is in. + */ + private static void registerMultiTexturedModel(T item){ + + if(item.getHasSubtypes()){ + NonNullList items = NonNullList.create(); + item.getSubItems(item.getCreativeTab(), items); + for(ItemStack stack : items){ + ModelLoader.setCustomModelResourceLocation(item, stack.getMetadata(), + new ModelResourceLocation(item.getModelName(stack), "inventory")); + } + } + } + + /** + * Registers an item model for the given metadata, using the item's registry name as the model name (this convention + * makes it easier to keep track of everything). This is intended for registering additional metadata values which + * aren't displayed in the creative menu, for example the wildcard spell book used in wizard trades. + */ + private static void registerItemModel(Item item, int metadata, String variant){ + ModelLoader.setCustomModelResourceLocation(item, metadata, + new ModelResourceLocation(item.getRegistryName(), variant)); + } + +} diff --git a/src/main/java/electroblob/wizardry/client/particle/ParticleBeam.java b/src/main/java/electroblob/wizardry/client/particle/ParticleBeam.java index 63548e0b..3e6d3a3f 100644 --- a/src/main/java/electroblob/wizardry/client/particle/ParticleBeam.java +++ b/src/main/java/electroblob/wizardry/client/particle/ParticleBeam.java @@ -1,13 +1,12 @@ package electroblob.wizardry.client.particle; -import org.lwjgl.opengl.GL11; - import net.minecraft.client.renderer.BufferBuilder; import net.minecraft.client.renderer.GlStateManager; import net.minecraft.client.renderer.OpenGlHelper; import net.minecraft.client.renderer.Tessellator; import net.minecraft.client.renderer.vertex.DefaultVertexFormats; import net.minecraft.world.World; +import org.lwjgl.opengl.GL11; public class ParticleBeam extends ParticleTargeted { @@ -17,10 +16,15 @@ public class ParticleBeam extends ParticleTargeted { public ParticleBeam(World world, double x, double y, double z){ super(world, x, y, z); // Does not have a texture! this.setRBGColorF(1, 1, 1); - this.setMaxAge(1); + this.setMaxAge(0); this.particleScale = 1; } - + + @Override + public boolean shouldDisableDepth(){ + return true; + } + @Override public int getFXLayer(){ return 3; @@ -31,7 +35,7 @@ public class ParticleBeam extends ParticleTargeted { float scale = this.particleScale; - if(this.particleMaxAge > 1){ + if(this.particleMaxAge > 0){ float ageFraction = (particleAge + partialTicks - 1)/particleMaxAge; // Squaring this makes it look smoother than a linear shrinking effect scale = this.particleScale * (1 - ageFraction*ageFraction); diff --git a/src/main/java/electroblob/wizardry/client/particle/ParticleBuff.java b/src/main/java/electroblob/wizardry/client/particle/ParticleBuff.java index 9e9a46d0..a7a8a752 100644 --- a/src/main/java/electroblob/wizardry/client/particle/ParticleBuff.java +++ b/src/main/java/electroblob/wizardry/client/particle/ParticleBuff.java @@ -1,26 +1,18 @@ package electroblob.wizardry.client.particle; -import org.lwjgl.opengl.GL11; - import electroblob.wizardry.Wizardry; import net.minecraft.client.Minecraft; -import net.minecraft.client.particle.Particle; -import net.minecraft.client.renderer.BufferBuilder; -import net.minecraft.client.renderer.GlStateManager; +import net.minecraft.client.renderer.*; import net.minecraft.client.renderer.GlStateManager.DestFactor; import net.minecraft.client.renderer.GlStateManager.SourceFactor; -import net.minecraft.client.renderer.OpenGlHelper; -import net.minecraft.client.renderer.RenderHelper; -import net.minecraft.client.renderer.Tessellator; import net.minecraft.client.renderer.vertex.DefaultVertexFormats; import net.minecraft.entity.Entity; import net.minecraft.util.ResourceLocation; import net.minecraft.util.math.MathHelper; import net.minecraft.world.World; -import net.minecraftforge.fml.relauncher.Side; -import net.minecraftforge.fml.relauncher.SideOnly; +import org.lwjgl.opengl.GL11; -@SideOnly(Side.CLIENT) +//@SideOnly(Side.CLIENT) public class ParticleBuff extends ParticleWizardry { private static final ResourceLocation TEXTURE = new ResourceLocation(Wizardry.MODID, "textures/particle/buff.png"); @@ -28,13 +20,19 @@ public class ParticleBuff extends ParticleWizardry { public ParticleBuff(World world, double x, double y, double z){ super(world, x, y, z); - this.setVelocity(0, 0.27, 0); // Approximately what it was before - this.mirror = world.rand.nextBoolean(); + this.setVelocity(0, 0.162, 0); // Approximately what it was before + this.mirror = random.nextBoolean(); this.setMaxAge(15); this.setGravity(false); this.canCollide = false; } - + + @Override + public boolean shouldDisableDepth(){ + return true; + } + + @Override public void onUpdate(){ super.onUpdate(); @@ -59,14 +57,13 @@ public class ParticleBuff extends ParticleWizardry { @Override public void renderParticle(BufferBuilder buffer, Entity viewer, float partialTicks, float rotationX, float rotationZ, float rotationYZ, float rotationXY, float rotationXZ){ + + // Copied from ParticleWizardry, needs to be here since we're not calling super + updateEntityLinking(partialTicks); GlStateManager.pushMatrix(); GlStateManager.pushAttrib(); - float scale = 0.6f; - GlStateManager.scale(scale, scale, scale); - if(mirror) GlStateManager.scale(-1, 1, 1); - GlStateManager.enableBlend(); GlStateManager.disableAlpha(); GlStateManager.disableCull(); @@ -94,31 +91,29 @@ public class ParticleBuff extends ParticleWizardry { buffer.begin(GL11.GL_TRIANGLE_STRIP, DefaultVertexFormats.POSITION_TEX_COLOR); - // I'm pretty sure these were always static. - Particle.interpPosX = viewer.lastTickPosX + (viewer.posX - viewer.lastTickPosX) * (double)partialTicks; - Particle.interpPosY = viewer.lastTickPosY + (viewer.posY - viewer.lastTickPosY) * (double)partialTicks; - Particle.interpPosZ = viewer.lastTickPosZ + (viewer.posZ - viewer.lastTickPosZ) * (double)partialTicks; - float x = (float)(this.prevPosX + (this.posX - this.prevPosX) * (double)partialTicks - interpPosX); float y = (float)(this.prevPosY + (this.posY - this.prevPosY) * (double)partialTicks - interpPosY); float z = (float)(this.prevPosZ + (this.posZ - this.prevPosZ) * (double)partialTicks - interpPosZ); - + // Increases from 0 to 1 in steps of 0.125 evenly throughout the particle's lifetime float f = 0.875f - 0.125f * MathHelper.floor((float)this.particleAge/(float)this.particleMaxAge * 8 - 0.000001f); float g = f + 0.125f; float hrepeat = 1; - float yScale = 0.7f; + float scale = 0.6f; + float yScale = 0.7f * scale; + float dx = mirror ? -scale : scale; + float dz = scale; - buffer.pos(x-1, y-yScale, z-1).tex(0, g).color(particleRed, particleGreen, particleBlue, particleAlpha).endVertex(); - buffer.pos(x-1, y+yScale, z-1).tex(0, f).color(particleRed, particleGreen, particleBlue, particleAlpha).endVertex(); - buffer.pos(x+1, y-yScale, z-1).tex(0.25*hrepeat, g).color(particleRed, particleGreen, particleBlue, particleAlpha).endVertex(); - buffer.pos(x+1, y+yScale, z-1).tex(0.25*hrepeat, f).color(particleRed, particleGreen, particleBlue, particleAlpha).endVertex(); - buffer.pos(x+1, y-yScale, z+1).tex(0.5*hrepeat, g).color(particleRed, particleGreen, particleBlue, particleAlpha).endVertex(); - buffer.pos(x+1, y+yScale, z+1).tex(0.5*hrepeat, f).color(particleRed, particleGreen, particleBlue, particleAlpha).endVertex(); - buffer.pos(x-1, y-yScale, z+1).tex(0.75*hrepeat, g).color(particleRed, particleGreen, particleBlue, particleAlpha).endVertex(); - buffer.pos(x-1, y+yScale, z+1).tex(0.75*hrepeat, f).color(particleRed, particleGreen, particleBlue, particleAlpha).endVertex(); - buffer.pos(x-1, y-yScale, z-1).tex(hrepeat, g).color(particleRed, particleGreen, particleBlue, particleAlpha).endVertex(); - buffer.pos(x-1, y+yScale, z-1).tex(hrepeat, f).color(particleRed, particleGreen, particleBlue, particleAlpha).endVertex(); + buffer.pos(x-dx, y-yScale, z-dz).tex(0, g).color(particleRed, particleGreen, particleBlue, particleAlpha).endVertex(); + buffer.pos(x-dx, y+yScale, z-dz).tex(0, f).color(particleRed, particleGreen, particleBlue, particleAlpha).endVertex(); + buffer.pos(x+dx, y-yScale, z-dz).tex(0.25*hrepeat, g).color(particleRed, particleGreen, particleBlue, particleAlpha).endVertex(); + buffer.pos(x+dx, y+yScale, z-dz).tex(0.25*hrepeat, f).color(particleRed, particleGreen, particleBlue, particleAlpha).endVertex(); + buffer.pos(x+dx, y-yScale, z+dz).tex(0.5*hrepeat, g).color(particleRed, particleGreen, particleBlue, particleAlpha).endVertex(); + buffer.pos(x+dx, y+yScale, z+dz).tex(0.5*hrepeat, f).color(particleRed, particleGreen, particleBlue, particleAlpha).endVertex(); + buffer.pos(x-dx, y-yScale, z+dz).tex(0.75*hrepeat, g).color(particleRed, particleGreen, particleBlue, particleAlpha).endVertex(); + buffer.pos(x-dx, y+yScale, z+dz).tex(0.75*hrepeat, f).color(particleRed, particleGreen, particleBlue, particleAlpha).endVertex(); + buffer.pos(x-dx, y-yScale, z-dz).tex(hrepeat, g).color(particleRed, particleGreen, particleBlue, particleAlpha).endVertex(); + buffer.pos(x-dx, y+yScale, z-dz).tex(hrepeat, f).color(particleRed, particleGreen, particleBlue, particleAlpha).endVertex(); Tessellator.getInstance().draw(); diff --git a/src/main/java/electroblob/wizardry/client/particle/ParticleDarkMagic.java b/src/main/java/electroblob/wizardry/client/particle/ParticleDarkMagic.java index b4bc8710..7558bf89 100644 --- a/src/main/java/electroblob/wizardry/client/particle/ParticleDarkMagic.java +++ b/src/main/java/electroblob/wizardry/client/particle/ParticleDarkMagic.java @@ -3,10 +3,8 @@ package electroblob.wizardry.client.particle; import net.minecraft.client.renderer.BufferBuilder; import net.minecraft.entity.Entity; import net.minecraft.world.World; -import net.minecraftforge.fml.relauncher.Side; -import net.minecraftforge.fml.relauncher.SideOnly; -@SideOnly(Side.CLIENT) +//@SideOnly(Side.CLIENT) public class ParticleDarkMagic extends ParticleWizardry { /** Base spell texture index */ diff --git a/src/main/java/electroblob/wizardry/client/particle/ParticleDust.java b/src/main/java/electroblob/wizardry/client/particle/ParticleDust.java index 3a7f70fd..cd925b81 100644 --- a/src/main/java/electroblob/wizardry/client/particle/ParticleDust.java +++ b/src/main/java/electroblob/wizardry/client/particle/ParticleDust.java @@ -1,10 +1,8 @@ package electroblob.wizardry.client.particle; import net.minecraft.world.World; -import net.minecraftforge.fml.relauncher.Side; -import net.minecraftforge.fml.relauncher.SideOnly; -@SideOnly(Side.CLIENT) +//@SideOnly(Side.CLIENT) public class ParticleDust extends ParticleWizardry { public ParticleDust(World world, double x, double y, double z){ @@ -24,7 +22,7 @@ public class ParticleDust extends ParticleWizardry { this.prevPosX = this.posX; this.prevPosY = this.posY; this.prevPosZ = this.posZ; - // this.moveEntity(this.motionX, this.motionY, this.motionZ); + this.move(this.motionX, this.motionY, this.motionZ); if(this.particleMaxAge-- <= 0){ this.setExpired(); diff --git a/src/main/java/electroblob/wizardry/client/particle/ParticleFlash.java b/src/main/java/electroblob/wizardry/client/particle/ParticleFlash.java index a24cd16b..f85bc90c 100644 --- a/src/main/java/electroblob/wizardry/client/particle/ParticleFlash.java +++ b/src/main/java/electroblob/wizardry/client/particle/ParticleFlash.java @@ -19,10 +19,15 @@ public class ParticleFlash extends ParticleWizardry { this.particleScale = 0.6f; // 7.1f is the value used in fireworks this.particleMaxAge = 6; } - + @Override - public void renderParticle(BufferBuilder buffer, Entity entityIn, float partialTicks, float rotationX, float rotationZ, float rotationYZ, float rotationXY, float rotationXZ){ - float f4 = particleScale * MathHelper.sin(((float)this.particleAge + partialTicks - 1.0F)/particleMaxAge * (float)Math.PI); + public boolean shouldDisableDepth(){ + return true; // Well this fixes everything... let's hope it doesn't cause any side-effects! + } + + @Override + public void drawParticle(BufferBuilder buffer, Entity entityIn, float partialTicks, float rotationX, float rotationZ, float rotationYZ, float rotationXY, float rotationXZ){ + float f4 = particleScale * MathHelper.sin(((float)this.particleAge + partialTicks - 1.0F)/particleMaxAge * (float)Math.PI); this.setAlphaF(0.6F - ((float)this.particleAge + partialTicks - 1.0F)/particleMaxAge * 0.5F); float f5 = (float)(this.prevPosX + (this.posX - this.prevPosX) * (double)partialTicks - interpPosX); float f6 = (float)(this.prevPosY + (this.posY - this.prevPosY) * (double)partialTicks - interpPosY); @@ -34,7 +39,7 @@ public class ParticleFlash extends ParticleWizardry { buffer.pos((double)(f5 - rotationX * f4 + rotationXY * f4), (double)(f6 + rotationZ * f4), (double)(f7 - rotationYZ * f4 + rotationXZ * f4)).tex(0.5D, 0.125D).color(this.particleRed, this.particleGreen, this.particleBlue, this.particleAlpha).lightmap(j, k).endVertex(); buffer.pos((double)(f5 + rotationX * f4 + rotationXY * f4), (double)(f6 + rotationZ * f4), (double)(f7 + rotationYZ * f4 + rotationXZ * f4)).tex(0.25D, 0.125D).color(this.particleRed, this.particleGreen, this.particleBlue, this.particleAlpha).lightmap(j, k).endVertex(); buffer.pos((double)(f5 + rotationX * f4 - rotationXY * f4), (double)(f6 - rotationZ * f4), (double)(f7 + rotationYZ * f4 - rotationXZ * f4)).tex(0.25D, 0.375D).color(this.particleRed, this.particleGreen, this.particleBlue, this.particleAlpha).lightmap(j, k).endVertex(); - } + } @Override public int getBrightnessForRender(float partialTicks){ diff --git a/src/main/java/electroblob/wizardry/client/particle/ParticleIce.java b/src/main/java/electroblob/wizardry/client/particle/ParticleIce.java index bc530448..22a86d18 100644 --- a/src/main/java/electroblob/wizardry/client/particle/ParticleIce.java +++ b/src/main/java/electroblob/wizardry/client/particle/ParticleIce.java @@ -6,9 +6,8 @@ import net.minecraftforge.client.event.TextureStitchEvent; import net.minecraftforge.fml.common.Mod; import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; import net.minecraftforge.fml.relauncher.Side; -import net.minecraftforge.fml.relauncher.SideOnly; -@SideOnly(Side.CLIENT) +//@SideOnly(Side.CLIENT) @Mod.EventBusSubscriber(Side.CLIENT) public class ParticleIce extends ParticleWizardry { diff --git a/src/main/java/electroblob/wizardry/client/particle/ParticleLeaf.java b/src/main/java/electroblob/wizardry/client/particle/ParticleLeaf.java index 327ac57a..07f7c9fb 100644 --- a/src/main/java/electroblob/wizardry/client/particle/ParticleLeaf.java +++ b/src/main/java/electroblob/wizardry/client/particle/ParticleLeaf.java @@ -6,9 +6,8 @@ import net.minecraftforge.client.event.TextureStitchEvent; import net.minecraftforge.fml.common.Mod; import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; import net.minecraftforge.fml.relauncher.Side; -import net.minecraftforge.fml.relauncher.SideOnly; -@SideOnly(Side.CLIENT) +//@SideOnly(Side.CLIENT) @Mod.EventBusSubscriber(Side.CLIENT) public class ParticleLeaf extends ParticleWizardry { @@ -24,7 +23,7 @@ public class ParticleLeaf extends ParticleWizardry { this.particleGravity = 0; this.canCollide = true; // Produces a variety of browns and greens - this.setRBGColorF(0.1f + 0.3f * world.rand.nextFloat(), 0.5f + 0.3f * world.rand.nextFloat(), 0.1f); + this.setRBGColorF(0.1f + 0.3f * random.nextFloat(), 0.5f + 0.3f * random.nextFloat(), 0.1f); } @Override diff --git a/src/main/java/electroblob/wizardry/client/particle/ParticleLightning.java b/src/main/java/electroblob/wizardry/client/particle/ParticleLightning.java index 80f43088..fc73ff92 100644 --- a/src/main/java/electroblob/wizardry/client/particle/ParticleLightning.java +++ b/src/main/java/electroblob/wizardry/client/particle/ParticleLightning.java @@ -1,15 +1,12 @@ package electroblob.wizardry.client.particle; -import java.util.Random; - -import org.lwjgl.opengl.GL11; - import net.minecraft.client.renderer.BufferBuilder; import net.minecraft.client.renderer.GlStateManager; import net.minecraft.client.renderer.OpenGlHelper; import net.minecraft.client.renderer.Tessellator; import net.minecraft.client.renderer.vertex.DefaultVertexFormats; import net.minecraft.world.World; +import org.lwjgl.opengl.GL11; public class ParticleLightning extends ParticleTargeted { @@ -28,10 +25,6 @@ public class ParticleLightning extends ParticleTargeted { /** Number of ticks to wait before the arc changes shape again. */ private static final int UPDATE_PERIOD = 1; - /** A random long value used by the renderer as a seed to generate its vertices from, ensuring they remain the same - * across multiple frames. Not synced. */ - public final long seed; - public ParticleLightning(World world, double x, double y, double z){ super(world, x, y, z); // Does not have a texture! seed = this.rand.nextLong(); @@ -39,7 +32,12 @@ public class ParticleLightning extends ParticleTargeted { this.setMaxAge(3); this.particleScale = 1; } - + + @Override + public boolean shouldDisableDepth(){ + return true; + } + @Override public int getFXLayer(){ return 3; @@ -67,7 +65,7 @@ public class ParticleLightning extends ParticleTargeted { // Creates a random from the arc's seed field + the number of ticks it has existed/the update period. // By using a seed, we can ensure the vertex positions and forks are identical a) for each layer, even // though they are rendered sequentially, and b) across many frames (and ticks, if updateTime > 1). - Random random = new Random(this.seed + this.particleAge/UPDATE_PERIOD); + random.setSeed(this.seed + this.particleAge/UPDATE_PERIOD); // numberOfSegments-1 because the last segment is handled separately. for(int i=0; i this.particleMaxAge/2){ - this.setAlphaF(1 - ((float)this.particleAge - (float)(this.particleMaxAge/2)) / (float)this.particleMaxAge); + this.setAlphaF(1 - ((float)this.particleAge - this.particleMaxAge/2f) / (this.particleMaxAge/2f)); } EnumFacing facing = EnumFacing.fromAngle(yaw); diff --git a/src/main/java/electroblob/wizardry/client/particle/ParticleSnow.java b/src/main/java/electroblob/wizardry/client/particle/ParticleSnow.java index e5de49f9..b34b3bab 100644 --- a/src/main/java/electroblob/wizardry/client/particle/ParticleSnow.java +++ b/src/main/java/electroblob/wizardry/client/particle/ParticleSnow.java @@ -6,9 +6,8 @@ import net.minecraftforge.client.event.TextureStitchEvent; import net.minecraftforge.fml.common.Mod; import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; import net.minecraftforge.fml.relauncher.Side; -import net.minecraftforge.fml.relauncher.SideOnly; -@SideOnly(Side.CLIENT) +//@SideOnly(Side.CLIENT) @Mod.EventBusSubscriber(Side.CLIENT) public class ParticleSnow extends ParticleWizardry { @@ -24,7 +23,7 @@ public class ParticleSnow extends ParticleWizardry { this.canCollide = true; this.setMaxAge(40 + rand.nextInt(10)); // Produces a variety of light blues and whites - this.setRBGColorF(0.9f + 0.1f * world.rand.nextFloat(), 0.95f + 0.05f * world.rand.nextFloat(), 1); + this.setRBGColorF(0.9f + 0.1f * random.nextFloat(), 0.95f + 0.05f * random.nextFloat(), 1); } @SubscribeEvent diff --git a/src/main/java/electroblob/wizardry/client/particle/ParticleSpark.java b/src/main/java/electroblob/wizardry/client/particle/ParticleSpark.java index 5d879ad0..7617d450 100644 --- a/src/main/java/electroblob/wizardry/client/particle/ParticleSpark.java +++ b/src/main/java/electroblob/wizardry/client/particle/ParticleSpark.java @@ -6,9 +6,8 @@ import net.minecraftforge.client.event.TextureStitchEvent; import net.minecraftforge.fml.common.Mod; import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; import net.minecraftforge.fml.relauncher.Side; -import net.minecraftforge.fml.relauncher.SideOnly; -@SideOnly(Side.CLIENT) +//@SideOnly(Side.CLIENT) @Mod.EventBusSubscriber(Side.CLIENT) public class ParticleSpark extends ParticleWizardry { @@ -25,14 +24,18 @@ public class ParticleSpark extends ParticleWizardry { this.canCollide = false; this.setMaxAge(3); // Lifetime defaults to 3 (and is very unlikely to be changed) } - + + @Override + public boolean shouldDisableDepth(){ + return true; + } + // May no longer be necessary, ParticleManager seems to enable blending now // @Override // public void applyGLStateChanges(){ // GlStateManager.enableBlend(); // GlStateManager.blendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA); -// // TESTME: Are these two actually necessary? // GlStateManager.disableLighting(); // OpenGlHelper.setLightmapTextureCoords(OpenGlHelper.lightmapTexUnit, 240, 240); // } diff --git a/src/main/java/electroblob/wizardry/client/particle/ParticleSparkle.java b/src/main/java/electroblob/wizardry/client/particle/ParticleSparkle.java index 4aa64a35..812678a2 100644 --- a/src/main/java/electroblob/wizardry/client/particle/ParticleSparkle.java +++ b/src/main/java/electroblob/wizardry/client/particle/ParticleSparkle.java @@ -6,9 +6,8 @@ import net.minecraftforge.client.event.TextureStitchEvent; import net.minecraftforge.fml.common.Mod; import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; import net.minecraftforge.fml.relauncher.Side; -import net.minecraftforge.fml.relauncher.SideOnly; -@SideOnly(Side.CLIENT) +//@SideOnly(Side.CLIENT) @Mod.EventBusSubscriber(Side.CLIENT) public class ParticleSparkle extends ParticleWizardry { diff --git a/src/main/java/electroblob/wizardry/client/particle/ParticleSphere.java b/src/main/java/electroblob/wizardry/client/particle/ParticleSphere.java new file mode 100644 index 00000000..89eaf5a7 --- /dev/null +++ b/src/main/java/electroblob/wizardry/client/particle/ParticleSphere.java @@ -0,0 +1,131 @@ +package electroblob.wizardry.client.particle; + +import net.minecraft.client.renderer.BufferBuilder; +import net.minecraft.client.renderer.GlStateManager; +import net.minecraft.client.renderer.OpenGlHelper; +import net.minecraft.client.renderer.Tessellator; +import net.minecraft.client.renderer.vertex.DefaultVertexFormats; +import net.minecraft.entity.Entity; +import net.minecraft.util.math.MathHelper; +import net.minecraft.world.World; +import org.lwjgl.opengl.GL11; + +public class ParticleSphere extends ParticleWizardry { + + public ParticleSphere(World world, double x, double y, double z){ + super(world, x, y, z); + this.setRBGColorF(1, 1, 1); + this.particleMaxAge = 5; + this.particleAlpha = 0.8f; + } + + @Override + public boolean shouldDisableDepth(){ + return true; + } + + @Override + public int getFXLayer(){ + return 3; + } + + @Override + public void onUpdate(){ + + super.onUpdate(); + + } + + @Override + public void renderParticle(BufferBuilder buffer, Entity viewer, float partialTicks, float rotationX, float rotationZ, float rotationYZ, + float rotationXY, float rotationXZ){ + + // Copied from ParticleWizardry, needs to be here since we're not calling super + updateEntityLinking(partialTicks); + + float x = (float)(this.prevPosX + (this.posX - this.prevPosX) * (double)partialTicks); + float y = (float)(this.prevPosY + (this.posY - this.prevPosY) * (double)partialTicks); + float z = (float)(this.prevPosZ + (this.posZ - this.prevPosZ) * (double)partialTicks); + + GlStateManager.pushMatrix(); + GlStateManager.translate(x - interpPosX, y - interpPosY, z - interpPosZ); + + GlStateManager.disableLighting(); + GlStateManager.enableBlend(); + GlStateManager.enableCull(); + GlStateManager.disableTexture2D(); + GlStateManager.blendFunc(GlStateManager.SourceFactor.SRC_ALPHA, GlStateManager.DestFactor.ONE); + OpenGlHelper.setLightmapTextureCoords(OpenGlHelper.lightmapTexUnit, 240f, 240f); + + float latStep = (float)Math.PI/20; + float longStep = (float)Math.PI/20; + + float sphereRadius = this.particleScale * (this.particleAge + partialTicks - 1) / this.particleMaxAge; + float alpha = this.particleAlpha * (1 - (this.particleAge + partialTicks - 1) / this.particleMaxAge); + + drawSphere(Tessellator.getInstance(), buffer, sphereRadius, latStep, longStep, true, particleRed, particleGreen, particleBlue, alpha); + drawSphere(Tessellator.getInstance(), buffer, sphereRadius, latStep, longStep, false, particleRed, particleGreen, particleBlue, alpha); + + GlStateManager.enableTexture2D(); + GlStateManager.enableLighting(); + GlStateManager.disableCull(); + GlStateManager.disableBlend(); + + GlStateManager.popMatrix(); + + } + + @Override + public int getBrightnessForRender(float partialTicks){ + return 15728880; + } + + /** + * Draws a sphere (using lat/long triangles) with the given parameters. + * @param radius The radius of the sphere. + * @param latStep The latitude step; smaller is smoother but increases performance cost. + * @param longStep The longitude step; smaller is smoother but increases performance cost. + * @param inside Whether to draw the outside or the inside of the sphere. + * @param r The red component of the sphere colour. + * @param g The green component of the sphere colour. + * @param b The blue component of the sphere colour. + * @param a The alpha component of the sphere colour. + */ + private static void drawSphere(Tessellator tessellator, BufferBuilder buffer, float radius, float latStep, float longStep, boolean inside, float r, float g, float b, float a){ + + buffer.begin(GL11.GL_TRIANGLE_STRIP, DefaultVertexFormats.POSITION_COLOR); + + boolean goingUp = inside; + + buffer.pos(0, goingUp ? -radius : radius, 0).color(r, g, b, a).endVertex(); // Start at the north pole + + for(float longitude = -(float)Math.PI; longitude <= (float)Math.PI; longitude += longStep){ + + // Leave the poles out since they only have a single point per stack instead of two + for(float theta = (float)Math.PI/2 - latStep; theta >= -(float)Math.PI/2 + latStep; theta -= latStep){ + + float latitude = goingUp ? -theta : theta; + + float hRadius = radius * MathHelper.cos(latitude); + float vy = radius * MathHelper.sin(latitude); + float vx = hRadius * MathHelper.sin(longitude); + float vz = hRadius * MathHelper.cos(longitude); + + buffer.pos(vx, vy, vz).color(r, g, b, a).endVertex(); + + vx = hRadius * MathHelper.sin(longitude + longStep); + vz = hRadius * MathHelper.cos(longitude + longStep); + + buffer.pos(vx, vy, vz).color(r, g, b, a).endVertex(); + } + + // The next pole + buffer.pos(0, goingUp ? radius : -radius, 0).color(r, g, b, a).endVertex(); + + goingUp = !goingUp; + } + + tessellator.draw(); + } + +} diff --git a/src/main/java/electroblob/wizardry/client/particle/ParticleSummon.java b/src/main/java/electroblob/wizardry/client/particle/ParticleSummon.java new file mode 100644 index 00000000..55daba3e --- /dev/null +++ b/src/main/java/electroblob/wizardry/client/particle/ParticleSummon.java @@ -0,0 +1,132 @@ +package electroblob.wizardry.client.particle; + +import electroblob.wizardry.Wizardry; +import net.minecraft.client.Minecraft; +import net.minecraft.client.renderer.*; +import net.minecraft.client.renderer.GlStateManager.DestFactor; +import net.minecraft.client.renderer.GlStateManager.SourceFactor; +import net.minecraft.client.renderer.vertex.DefaultVertexFormats; +import net.minecraft.entity.Entity; +import net.minecraft.util.ResourceLocation; +import net.minecraft.util.math.MathHelper; +import net.minecraft.world.World; +import org.lwjgl.opengl.GL11; + +//@SideOnly(Side.CLIENT) +public class ParticleSummon extends ParticleWizardry { + + private static final ResourceLocation TEXTURE = new ResourceLocation(Wizardry.MODID, "textures/particle/summon.png"); + private final boolean mirror; + + public ParticleSummon(World world, double x, double y, double z){ + super(world, x, y, z); + this.mirror = random.nextBoolean(); + this.setMaxAge(10); + this.setGravity(false); + this.canCollide = false; + } + +// @Override +// public void onUpdate(){ +// super.onUpdate(); +// if(this.particleAge > this.particleMaxAge/2) this.particleAlpha = 2f - 2f*(float)this.particleAge/(float)this.particleMaxAge; +// } + + /* There are 4 layers of particles, specified as 0-3 by the method below. - Layer 0 causes the normal particles.png + * to be bound to the render engine for normal particles. - Layer 1 causes the block textures to be bound to the + * render engine for digging fx and falling fx. - Layer 2 causes the item textures to be bound to the render engine + * for tool breaking fx, snowballpoofs, slime particles, etc. - Layer 3 is not used in vanilla minecraft and was + * presumably added by forge for exactly this reason. This means no texture is bound by vanilla minecraft, meaning + * you are free to do as you wish without possibly overwriting vanilla particles. Mod particles won't be overwritten + * anyway since they bind their own textures. It is of course important to bind the texture every time you render a + * custom particle, but I don't see how you could do it any other way, since you don't have access to + * EffectRenderer. */ + @Override + public int getFXLayer(){ + // This can only be 0-3 or it will cause an ArrayIndexOutOfBoundsException in EffectRenderer. + return 3; + } + + @Override + public void renderParticle(BufferBuilder buffer, Entity viewer, float partialTicks, float rotationX, float rotationZ, + float rotationYZ, float rotationXY, float rotationXZ){ + + // Copied from ParticleWizardry, needs to be here since we're not calling super + updateEntityLinking(partialTicks); + + GlStateManager.pushMatrix(); + GlStateManager.pushAttrib(); + + float scale = 0.6f; + GlStateManager.scale(scale, scale, scale); + if(mirror) GlStateManager.scale(-1, 1, 1); + + GlStateManager.enableBlend(); + GlStateManager.disableAlpha(); + GlStateManager.disableCull(); + GlStateManager.disableLighting(); + GlStateManager.blendFunc(SourceFactor.SRC_ALPHA, DestFactor.ONE); + // Makes the particle colour add to the colour of the texture pixels, rather than the default multiplying + GlStateManager.glTexEnvi(GL11.GL_TEXTURE_ENV, GL11.GL_TEXTURE_ENV_MODE, GL11.GL_ADD); + + OpenGlHelper.setLightmapTextureCoords(OpenGlHelper.lightmapTexUnit, 240f, 240f); + + GlStateManager.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_WRAP_S, GL11.GL_REPEAT); + GlStateManager.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_WRAP_T, GL11.GL_REPEAT); + + // Does the texture translation wrapping thing (the cool stuff) +// GlStateManager.matrixMode(GL11.GL_TEXTURE); +// GlStateManager.loadIdentity(); +// +// GlStateManager.translate((this.particleAge + partialTicks)/(float)this.particleMaxAge * -2, 0, 0); +// +// GlStateManager.matrixMode(GL11.GL_MODELVIEW); + + RenderHelper.disableStandardItemLighting(); + + Minecraft.getMinecraft().getTextureManager().bindTexture(TEXTURE); + + buffer.begin(GL11.GL_TRIANGLE_STRIP, DefaultVertexFormats.POSITION_TEX_COLOR); + + float x = (float)(this.prevPosX + (this.posX - this.prevPosX) * (double)partialTicks - interpPosX); + float y = (float)(this.prevPosY + (this.posY - this.prevPosY) * (double)partialTicks - interpPosY); + float z = (float)(this.prevPosZ + (this.posZ - this.prevPosZ) * (double)partialTicks - interpPosZ); + + // Increases from 0 to 1 in steps of 0.125 evenly throughout the particle's lifetime + float f = 0.125f * MathHelper.floor((float)this.particleAge/(float)this.particleMaxAge * 8 - 0.000001f); + float g = f + 0.125f; + float hrepeat = 1; + float yScale = 3f; + + this.setRBGColorF(1, 1, 1); + + buffer.pos(x-1, y, z-1).tex(0, g).color(particleRed, particleGreen, particleBlue, particleAlpha).endVertex(); + buffer.pos(x-1, y+yScale, z-1).tex(0, f).color(particleRed, particleGreen, particleBlue, particleAlpha).endVertex(); + buffer.pos(x+1, y, z-1).tex(0.25*hrepeat, g).color(particleRed, particleGreen, particleBlue, particleAlpha).endVertex(); + buffer.pos(x+1, y+yScale, z-1).tex(0.25*hrepeat, f).color(particleRed, particleGreen, particleBlue, particleAlpha).endVertex(); + buffer.pos(x+1, y, z+1).tex(0.5*hrepeat, g).color(particleRed, particleGreen, particleBlue, particleAlpha).endVertex(); + buffer.pos(x+1, y+yScale, z+1).tex(0.5*hrepeat, f).color(particleRed, particleGreen, particleBlue, particleAlpha).endVertex(); + buffer.pos(x-1, y, z+1).tex(0.75*hrepeat, g).color(particleRed, particleGreen, particleBlue, particleAlpha).endVertex(); + buffer.pos(x-1, y+yScale, z+1).tex(0.75*hrepeat, f).color(particleRed, particleGreen, particleBlue, particleAlpha).endVertex(); + buffer.pos(x-1, y, z-1).tex(hrepeat, g).color(particleRed, particleGreen, particleBlue, particleAlpha).endVertex(); + buffer.pos(x-1, y+yScale, z-1).tex(hrepeat, f).color(particleRed, particleGreen, particleBlue, particleAlpha).endVertex(); + + Tessellator.getInstance().draw(); + + // Undoes the texture transformations +// GlStateManager.matrixMode(GL11.GL_TEXTURE); +// GlStateManager.loadIdentity(); +// GlStateManager.matrixMode(GL11.GL_MODELVIEW); + + GlStateManager.disableBlend(); + GlStateManager.enableAlpha(); + GlStateManager.enableCull(); + GlStateManager.enableLighting(); + // Reverses the colour addition change from before + GlStateManager.glTexEnvi(GL11.GL_TEXTURE_ENV, GL11.GL_TEXTURE_ENV_MODE, GL11.GL_MODULATE); + + GlStateManager.popAttrib(); + GlStateManager.popMatrix(); + + } +} diff --git a/src/main/java/electroblob/wizardry/client/particle/ParticleTargeted.java b/src/main/java/electroblob/wizardry/client/particle/ParticleTargeted.java index 80ce3e59..cd89d0af 100644 --- a/src/main/java/electroblob/wizardry/client/particle/ParticleTargeted.java +++ b/src/main/java/electroblob/wizardry/client/particle/ParticleTargeted.java @@ -1,23 +1,28 @@ package electroblob.wizardry.client.particle; -import javax.annotation.Nullable; - -import org.lwjgl.opengl.GL11; - import electroblob.wizardry.Wizardry; import net.minecraft.client.renderer.BufferBuilder; import net.minecraft.client.renderer.GlStateManager; import net.minecraft.client.renderer.Tessellator; import net.minecraft.entity.Entity; import net.minecraft.util.ResourceLocation; +import net.minecraft.util.math.Vec3d; import net.minecraft.world.World; +import org.lwjgl.opengl.GL11; + +import javax.annotation.Nullable; /** Superclass for particles with a second target entity or target position. */ public abstract class ParticleTargeted extends ParticleWizardry { - + protected double targetX; protected double targetY; protected double targetZ; + protected double targetVelX; + protected double targetVelY; + protected double targetVelZ; + + protected double length; /** The target this particle is linked to. The particle will stretch to touch this entity. */ @Nullable @@ -33,43 +38,83 @@ public abstract class ParticleTargeted extends ParticleWizardry { this.targetY = y; this.targetZ = z; } + + @Override + public void setTargetVelocity(double vx, double vy, double vz){ + this.targetVelX = vx; + this.targetVelY = vy; + this.targetVelZ = vz; + } @Override public void setTargetEntity(Entity target){ this.target = target; } - + + @Override + public void setLength(double length){ + this.length = length; + } + + @Override + public void onUpdate(){ + + super.onUpdate(); + + if(!Double.isNaN(targetVelX) && !Double.isNaN(targetVelY) && !Double.isNaN(targetVelZ)){ + this.targetX += this.targetVelX; + this.targetY += this.targetVelY; + this.targetZ += this.targetVelZ; + } + } + @Override public void renderParticle(BufferBuilder buffer, Entity viewer, float partialTicks, float rotationX, float rotationZ, float rotationYZ, float rotationXY, float rotationXZ){ - + + // Copied from ParticleWizardry, needs to be here since we're not calling super + updateEntityLinking(partialTicks); + + float x = (float)(this.prevPosX + (this.posX - this.prevPosX) * (double)partialTicks); + float y = (float)(this.prevPosY + (this.posY - this.prevPosY) * (double)partialTicks); + float z = (float)(this.prevPosZ + (this.posZ - this.prevPosZ) * (double)partialTicks); + if(this.target != null){ - this.targetX = this.target.posX; - this.targetY = this.target.getEntityBoundingBox().minY + target.height/2; - this.targetZ = this.target.posZ; + + this.targetX = this.target.prevPosX + (this.target.posX - this.target.prevPosX) * partialTicks; + double correction = this.target.getEntityBoundingBox().minY - this.target.posY; + this.targetY = this.target.prevPosY + (this.target.posY - this.target.prevPosY) * partialTicks + + target.height/2 + correction; + this.targetZ = this.target.prevPosZ + (this.target.posZ - this.target.prevPosZ) * partialTicks; + + }else if(this.entity != null && this.length > 0){ + + Vec3d look = entity.getLook(partialTicks).scale(length); + this.targetX = x + look.x; + this.targetY = y + look.y; + this.targetZ = z + look.z; } if(Double.isNaN(targetX) || Double.isNaN(targetY) || Double.isNaN(targetZ)){ Wizardry.logger.warn("Attempted to render a targeted particle, but neither its target entity nor target" - + "position was set!"); + + "position was set, and it either had no length assigned or was not linked to an entity!"); return; } - // I'm pretty sure these were always static. - interpPosX = viewer.lastTickPosX + (viewer.posX - viewer.lastTickPosX) * (double)partialTicks; - interpPosY = viewer.lastTickPosY + (viewer.posY - viewer.lastTickPosY) * (double)partialTicks; - interpPosZ = viewer.lastTickPosZ + (viewer.posZ - viewer.lastTickPosZ) * (double)partialTicks; - - float x = (float)(this.prevPosX + (this.posX - this.prevPosX) * (double)partialTicks - interpPosX); - float y = (float)(this.prevPosY + (this.posY - this.prevPosY) * (double)partialTicks - interpPosY); - float z = (float)(this.prevPosZ + (this.posZ - this.prevPosZ) * (double)partialTicks - interpPosZ); - GlStateManager.pushMatrix(); - GlStateManager.translate(x, y, z); + GlStateManager.translate(x - interpPosX, y - interpPosY, z - interpPosZ); - double dx = this.targetX - this.posX; - double dy = this.targetY - this.posY; - double dz = this.targetZ - this.posZ; + double dx = this.targetX - x; + double dy = this.targetY - y; + double dz = this.targetZ - z; + + // No need for previous tick target positions and all that stuff since this is the only place they're used + // and interpolating like this works just as well + if(!Double.isNaN(targetVelX) && !Double.isNaN(targetVelY) && !Double.isNaN(targetVelZ)){ + dx += partialTicks * this.targetVelX; + dy += partialTicks * this.targetVelY; + dz += partialTicks * this.targetVelZ; + } // The distance from origin to endpoint double length = Math.sqrt(dx*dx+dy*dy+dz*dz); @@ -87,12 +132,12 @@ public abstract class ParticleTargeted extends ParticleWizardry { GlStateManager.popMatrix(); } - + /** Called from {@link ParticleTargeted#renderParticle(BufferBuilder, Entity, float, float, float, float, float, float)}, * once the appropriate calculations and transformations have been applied, to actually render the particle. Subclasses * override this instead of overriding {@code renderParticle} directly, and inside render the particle along * the z-axis, starting at (0, 0, 0) - it will be translated and rotated automatically. - *

    + *

    * N.B. Other than transformations, no GL state changes are applied; these should be done within this method. * * @param tessellator A reference to the tessellator, for convenience. diff --git a/src/main/java/electroblob/wizardry/client/particle/ParticleTornado.java b/src/main/java/electroblob/wizardry/client/particle/ParticleTornado.java index 8887e503..8dab58fa 100644 --- a/src/main/java/electroblob/wizardry/client/particle/ParticleTornado.java +++ b/src/main/java/electroblob/wizardry/client/particle/ParticleTornado.java @@ -3,14 +3,13 @@ package electroblob.wizardry.client.particle; import net.minecraft.block.state.IBlockState; import net.minecraft.client.particle.ParticleDigging; import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.MathHelper; import net.minecraft.world.World; -import net.minecraftforge.fml.relauncher.Side; -import net.minecraftforge.fml.relauncher.SideOnly; -@SideOnly(Side.CLIENT) +//@SideOnly(Side.CLIENT) public class ParticleTornado extends ParticleDigging { - private double angle; + private float angle; private double radius; private double speed; /** Velocity of the tornado itself; in other words the velocity of the point the particle circles around. */ @@ -20,9 +19,9 @@ public class ParticleTornado extends ParticleDigging { public ParticleTornado(World world, int maxAge, double originX, double originZ, double radius, double yPos, double velX, double velZ, IBlockState block){ super(world, 0, 0, 0, 0, 0, 0, block); - this.angle = this.rand.nextDouble() * Math.PI * 2; - double x = originX - Math.cos(angle) * radius; - double z = originZ + radius * Math.sin(angle); + float angle = this.rand.nextFloat() * (float)Math.PI * 2; + double x = originX - MathHelper.cos(angle) * radius; + double z = originZ + radius * MathHelper.sin(angle); this.radius = radius; this.setPosition(x, yPos, z); this.prevPosX = x; @@ -66,8 +65,8 @@ public class ParticleTornado extends ParticleDigging { // v = r times omega; therefore the normalised velocity vector needs to be r times the angle increment / 2 pi. this.angle += omega; - this.motionZ = radius * omega * Math.cos(angle); - this.motionX = radius * omega * Math.sin(angle); + this.motionZ = radius * omega * MathHelper.cos(angle); + this.motionX = radius * omega * MathHelper.sin(angle); this.move(motionX + velX, 0, motionZ + velZ); if(this.particleAge > this.particleMaxAge / 2){ diff --git a/src/main/java/electroblob/wizardry/client/particle/ParticleVine.java b/src/main/java/electroblob/wizardry/client/particle/ParticleVine.java new file mode 100644 index 00000000..79c9d872 --- /dev/null +++ b/src/main/java/electroblob/wizardry/client/particle/ParticleVine.java @@ -0,0 +1,154 @@ +package electroblob.wizardry.client.particle; + +import electroblob.wizardry.Wizardry; +import net.minecraft.client.Minecraft; +import net.minecraft.client.renderer.BufferBuilder; +import net.minecraft.client.renderer.GlStateManager; +import net.minecraft.client.renderer.OpenGlHelper; +import net.minecraft.client.renderer.Tessellator; +import net.minecraft.client.renderer.texture.TextureAtlasSprite; +import net.minecraft.client.renderer.vertex.DefaultVertexFormats; +import net.minecraft.entity.Entity; +import net.minecraft.util.ResourceLocation; +import net.minecraft.util.math.MathHelper; +import net.minecraft.world.World; +import net.minecraftforge.client.event.TextureStitchEvent; +import net.minecraftforge.fml.common.Mod; +import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; +import net.minecraftforge.fml.relauncher.Side; +import org.lwjgl.opengl.GL11; + +//@SideOnly(Side.CLIENT) +@Mod.EventBusSubscriber(Side.CLIENT) +public class ParticleVine extends ParticleTargeted { + + /** Half the width of the vine. */ + private static final float THICKNESS = 0.02f; + private static final float LEAF_SPACING = 0.5f; + private static final float SEGMENT_LENGTH = 1; + + private static final ResourceLocation STEM_TEXTURE = new ResourceLocation(Wizardry.MODID, "particle/vine"); + private static final ResourceLocation[] LEAF_TEXTURES = generateTextures("vine_leaf", 5); + + public ParticleVine(World world, double x, double y, double z){ + super(world, x, y, z, STEM_TEXTURE); + //this.setRBGColorF(1, 1, 1); + this.setMaxAge(0); + this.particleScale = 1; + this.setRBGColorF(0.2f, 0.65f, 0f); + } + + @Override + public void renderParticle(BufferBuilder buffer, Entity viewer, float partialTicks, float rotationX, float rotationZ, float rotationYZ, float rotationXY, float rotationXZ){ + // When using FX layer 1 the BufferBuilder is already drawing... but in the wrong mode :/ + Tessellator.getInstance().draw(); + super.renderParticle(buffer, viewer, partialTicks, rotationX, rotationZ, rotationYZ, rotationXY, rotationXZ); + buffer.begin(GL11.GL_QUADS, DefaultVertexFormats.PARTICLE_POSITION_TEX_COLOR_LMAP); + } + + @Override + protected void draw(Tessellator tessellator, double length, float partialTicks){ + + random.setSeed(seed); // Reset the random so we get the same sequence of numbers each frame + + float scale = this.particleScale; + + BufferBuilder buffer = tessellator.getBuffer(); + + GlStateManager.disableLighting(); + OpenGlHelper.setLightmapTextureCoords(OpenGlHelper.lightmapTexUnit, 240f, 240f); + + // Hmmmm we can't get the texture to tile using OpenGL texture space because it's on a sprite sheet... + // Solution: Draw loads of boxes. Simple! + // (Since there aren't going to be that many of these particles around we could have not used sprite sheets + // and done the OpenGL texture space thing, but this is kinda easier) + // Everything is drawn back-to-front so it looks like the vine is growing from the origin, not the endpoint + int i = 0; + while(i + SEGMENT_LENGTH < length){ + drawShearedBox(tessellator, 0, 0, length-i, 0, 0, length-i-SEGMENT_LENGTH, THICKNESS * scale, + particleRed, particleGreen, particleBlue, particleAlpha); + i += SEGMENT_LENGTH; + } + + drawShearedBox(tessellator, 0, 0, length-i, 0, 0, 0, THICKNESS * scale, + particleRed, particleGreen, particleBlue, particleAlpha); + + for(double l=length; l>0; l-=LEAF_SPACING){ + + GlStateManager.pushMatrix(); + + GlStateManager.rotate(random.nextInt(4) * 90, 0, 0, 1); + + buffer.begin(GL11.GL_QUADS, DefaultVertexFormats.POSITION_TEX_COLOR); + + TextureAtlasSprite leaf = Minecraft.getMinecraft().getTextureMapBlocks().getAtlasSprite( + LEAF_TEXTURES[random.nextInt(LEAF_TEXTURES.length)].toString()); + + float w = 16 * THICKNESS * scale; + float u1 = leaf.getMinU(); + float u2 = leaf.getMaxU(); + float v1 = leaf.getMinV(); + float v2 = leaf.getMaxV(); + + float colourVariation = 0.3f; + + float r = MathHelper.clamp(particleRed + (random.nextFloat() - 0.5f) * colourVariation, 0, 1); + float g = MathHelper.clamp(particleGreen + (random.nextFloat() - 0.5f) * colourVariation, 0, 1); + float b = MathHelper.clamp(particleBlue + (random.nextFloat() - 0.5f) * colourVariation, 0, 1); + + buffer.pos(0, 0, l).tex(u1, v1).color(r, g, b, particleAlpha).endVertex(); + buffer.pos(w, 0, l).tex(u2, v1).color(r, g, b, particleAlpha).endVertex(); + buffer.pos(w, w, l).tex(u2, v2).color(r, g, b, particleAlpha).endVertex(); + buffer.pos(0, w, l).tex(u1, v2).color(r, g, b, particleAlpha).endVertex(); + + tessellator.draw(); + + GlStateManager.popMatrix(); + } + + // Makes the rain go weird + //GlStateManager.enableLighting(); + } + + /** Draws a single box for one segment of the arc, from the point (x1, y1, z1) to the point (x2, y2, z2), with given width and colour. */ + private void drawShearedBox(Tessellator tessellator, double x1, double y1, double z1, double x2, double y2, double z2, float width, float r, float g, float b, float a){ + + float u1 = particleTexture.getMinU(); + float u2 = u1 + (particleTexture.getMaxU() - u1) * (float)(z1-z2)/SEGMENT_LENGTH; + float v1 = particleTexture.getMinV(); + float dv = particleTexture.getMaxV() - v1; + // width * 8 gives the total 'circumference' of the box + float v2 = v1 + dv * 0.0625f; + float v3 = v1 + dv * 0.125f; + float v4 = v1 + dv * 0.1875f; + float v5 = v1 + dv * 0.25f; + + BufferBuilder buffer = tessellator.getBuffer(); + + buffer.begin(GL11.GL_TRIANGLE_STRIP, DefaultVertexFormats.POSITION_TEX_COLOR); + + buffer.pos(x1-width, y1-width, z1).tex(u1, v1).color(r, g, b, a).endVertex(); + buffer.pos(x2-width, y2-width, z2).tex(u2, v1).color(r, g, b, a).endVertex(); + buffer.pos(x1-width, y1+width, z1).tex(u1, v2).color(r, g, b, a).endVertex(); + buffer.pos(x2-width, y2+width, z2).tex(u2, v2).color(r, g, b, a).endVertex(); + buffer.pos(x1+width, y1+width, z1).tex(u1, v3).color(r, g, b, a).endVertex(); + buffer.pos(x2+width, y2+width, z2).tex(u2, v3).color(r, g, b, a).endVertex(); + buffer.pos(x1+width, y1-width, z1).tex(u1, v4).color(r, g, b, a).endVertex(); + buffer.pos(x2+width, y2-width, z2).tex(u2, v4).color(r, g, b, a).endVertex(); + buffer.pos(x1-width, y1-width, z1).tex(u1, v5).color(r, g, b, a).endVertex(); + buffer.pos(x2-width, y2-width, z2).tex(u2, v5).color(r, g, b, a).endVertex(); + + tessellator.draw(); + } + + @SubscribeEvent + public static void onTextureStitchEvent(TextureStitchEvent.Pre event){ + + event.getMap().registerSprite(STEM_TEXTURE); + + for(ResourceLocation texture : LEAF_TEXTURES){ + event.getMap().registerSprite(texture); + } + } + +} diff --git a/src/main/java/electroblob/wizardry/client/particle/ParticleWizardry.java b/src/main/java/electroblob/wizardry/client/particle/ParticleWizardry.java index 62f96e7f..1172bb34 100644 --- a/src/main/java/electroblob/wizardry/client/particle/ParticleWizardry.java +++ b/src/main/java/electroblob/wizardry/client/particle/ParticleWizardry.java @@ -1,35 +1,41 @@ package electroblob.wizardry.client.particle; -import java.util.Arrays; -import java.util.stream.Collectors; - -import javax.annotation.Nullable; - import electroblob.wizardry.Wizardry; +import electroblob.wizardry.client.ClientProxy; +import electroblob.wizardry.entity.ICustomHitbox; +import electroblob.wizardry.util.WizardryUtilities; import net.minecraft.client.Minecraft; import net.minecraft.client.particle.Particle; import net.minecraft.client.renderer.BufferBuilder; import net.minecraft.client.renderer.texture.TextureAtlasSprite; import net.minecraft.entity.Entity; import net.minecraft.util.ResourceLocation; +import net.minecraft.util.math.AxisAlignedBB; import net.minecraft.util.math.MathHelper; +import net.minecraft.util.math.Vec3d; import net.minecraft.world.World; import net.minecraftforge.client.event.TextureStitchEvent; import net.minecraftforge.fml.relauncher.Side; import net.minecraftforge.fml.relauncher.SideOnly; +import javax.annotation.Nullable; +import java.util.Arrays; +import java.util.List; +import java.util.Random; +import java.util.stream.Collectors; + /** * Abstract superclass for all of wizardry's particles. This replaces {@code ParticleCustomTexture} (the functionality of * which is no longer necessary since wizardry now uses {@code TextureAtlasSprite}s to do the rendering), and fits into * {@code ParticleBuilder} by exposing all the necessary variables through getters, allowing them to be set on the fly * rather than needing to be passed into the constructor. - *

    + *

    * The new system is as follows: - *

    + *

    * - All particle classes have a single constructor which takes a world and a position only.
    * - Each particle class defines any relevant default values in its constructor, including velocity.
    * - The particle builder then overwrites any other values that were set during building. - *

    + *

    * This beauty of this system is that there are never any redundant parameters when spawning particles, since you can set * as many or as few parameters as necessary - and in addition, common defaults don't need setting at all. For example, * snow particles nearly always fall at the same speed, which can now be defined in the particle class and no longer @@ -39,12 +45,24 @@ import net.minecraftforge.fml.relauncher.SideOnly; * @since Wizardry 4.2.0 * @see electroblob.wizardry.util.ParticleBuilder ParticleBuilder */ -@SideOnly(Side.CLIENT) +//@SideOnly(Side.CLIENT) public abstract class ParticleWizardry extends Particle { /** Implementation of animated particles using the TextureAtlasSprite system. Why vanilla doesn't support this I * don't know, considering it too has animated particles. */ protected final TextureAtlasSprite[] sprites; + + /** A long value used by the renderer as a random number seed, ensuring anything that is randomised remains the + * same across multiple frames. For example, lightning particles use this to keep their shape across ticks. + * This value can also be set during particle creation, allowing users to keep randomised properties the same + * even across multiple particles. If unspecified, the seed is chosen at random. */ + protected long seed; + /** This particle's random number generator. All particles should use this in preference to any other random + * instance (like random), even if it isn't actually necessary to keep properties across frames. Note that + * if you do need to generate the same sequence of random numbers each frame, you must call + * {@code random.setSeed(seed)} from the {@link ParticleWizardry#renderParticle(BufferBuilder, Entity, float, float, float, float, float, float)} + * method - this is not done automatically. */ + protected Random random = new Random(); // If we're not using a seed, this defaults to any old seed /** True if the particle is shaded, false if the particle always renders at full brightness. Defaults to false. */ protected boolean shaded = false; @@ -64,12 +82,12 @@ public abstract class ParticleWizardry extends Particle { /** The entity this particle is linked to. The particle will move with this entity. */ @Nullable protected Entity entity = null; - /** Coordinates of this particle relative to the linked entity. If the linked entity is null, these are not used. */ + /** Coordinates of this particle relative to the linked entity. If the linked entity is null, these are used as + * the absolute coordinates of the centre of rotation for particles with spin. If the particle has neither a + * linked entity nor spin, these are not used. */ protected double relativeX, relativeY, relativeZ; - /** Velocity of this particle relative to the linked entity. The relative x and z velocities are also used when - * the particle has spin to move the centre of rotation. If the linked entity is null and the particle is not - * spinning, these are not used and will be {@code NaN}. */ - protected double relativeMotionX = Double.NaN, relativeMotionY = Double.NaN, relativeMotionZ = Double.NaN; + /** Velocity of this particle relative to the linked entity. If the linked entity is null, these are not used. */ + protected double relativeMotionX, relativeMotionY, relativeMotionZ; // Note that roll (equivalent to rotating the texture) is effectively handled by particleAngle - although that is // actually the rotation speed and not the angle itself. /** The yaw angle this particle is facing, or {@code NaN} if this particle always faces the viewer (default behaviour). */ @@ -77,6 +95,14 @@ public abstract class ParticleWizardry extends Particle { /** The pitch angle this particle is facing, or {@code NaN} if this particle always faces the viewer (default behaviour). */ protected float pitch = Float.NaN; + /** The fraction of the impact velocity that should be the maximum spread speed added on impact. */ + private static final double SPREAD_FACTOR = 0.2; + /** Lateral velocity is reduced by this factor on impact, before adding random spread velocity. */ + private static final double IMPACT_FRICTION = 0.2; + + /** Previous-tick velocity, used in collision detection. */ + private double prevVelX, prevVelY, prevVelZ; + /** * Creates a new particle in the given world at the given position. All other parameters are set via the various * setter methods ({@link electroblob.wizardry.util.ParticleBuilder ParticleBuilder} deals with all of that anyway). @@ -108,7 +134,6 @@ public abstract class ParticleWizardry extends Particle { this.setParticleTexture(sprites[0]); }else{ - sprites = new TextureAtlasSprite[0]; } } @@ -117,6 +142,15 @@ public abstract class ParticleWizardry extends Particle { // Setters for parameters that affect all particles - these are implemented in this class (although they may be // reimplemented in subclasses) + + /** Sets the seed for this particle's randomly generated values and resets {@link ParticleWizardry#random} to use + * that seed. Implementations will differ between particle types; for example, ParticleLightning has an update + * period which changes the seed every few ticks, whereas ParticleVine simply retains the same seed for its entire + * lifetime. */ + public void setSeed(long seed){ + this.seed = seed; + this.random = new Random(seed); + } /** Sets whether the particle should render at full brightness or not. True if the particle is shaded, false if * the particle always renders at full brightness. Defaults to false.*/ @@ -154,13 +188,10 @@ public abstract class ParticleWizardry extends Particle { public void setSpin(double radius, double speed){ this.radius = radius; this.speed = speed * 2 * Math.PI; // Converts rotations per tick into radians per tick for the trig functions - this.angle = this.rand.nextFloat() * (float)Math.PI * 2; // Random start angle TODO: Perhaps this should be specified? + this.angle = this.rand.nextFloat() * (float)Math.PI * 2; // Random start angle // Need to set the start position or the circle won't be centred on the correct position - this.relativeX = radius * -MathHelper.cos(angle); - this.relativeZ = radius * MathHelper.sin(angle); - this.setPosition(posX + relativeX, posY, posZ + relativeZ); - this.prevPosX = posX; - this.prevPosZ = posZ; + this.posX = relativeX - radius * MathHelper.cos(angle); + this.posZ = relativeZ + radius * MathHelper.sin(angle); // Set these to the correct values this.relativeMotionX = motionX; this.relativeMotionY = motionY; @@ -180,6 +211,7 @@ public abstract class ParticleWizardry extends Particle { this.prevPosX = this.posX; this.prevPosY = this.posY; this.prevPosZ = this.posZ; + // Set these to the correct values this.relativeMotionX = motionX; this.relativeMotionY = motionY; this.relativeMotionZ = motionZ; @@ -218,7 +250,7 @@ public abstract class ParticleWizardry extends Particle { /** * Sets the direction this particle faces. This will cause the particle to render facing the given direction. - * @param yaw The yaw angle of this particle in degrees, where 0 is [TODO south?]. + * @param yaw The yaw angle of this particle in degrees, where 0 is south. * @param pitch The pitch angle of this particle in degrees, where 0 is horizontal. */ public void setFacing(float yaw, float pitch){ @@ -239,6 +271,18 @@ public abstract class ParticleWizardry extends Particle { public void setTargetPosition(double x, double y, double z){ // Does nothing for normal particles since normal particles always render at a single point } + + /** + * Sets the target point velocity for this particle. This will cause the position it stretches to touch to move + * at the given velocity. Has no effect unless {@link ParticleWizardry#setTargetVelocity(double, double, double)} + * is also used. + * @param vx The x velocity of the target point. + * @param vy The y velocity of the target point. + * @param vz The z velocity of the target point. + */ + public void setTargetVelocity(double vx, double vy, double vz){ + // Does nothing for normal particles since normal particles always render at a single point + } /** * Links this particle to the given target. This will cause it to stretch to touch the target, if supported. @@ -247,6 +291,15 @@ public abstract class ParticleWizardry extends Particle { public void setTargetEntity(Entity target){ // Does nothing for normal particles since normal particles always render at a single point } + + /** + * Sets the length of this particle. This will cause it to stretch to touch a point this distance along its + * linked entity's line of sight. + * @param length The length to set. + */ + public void setLength(double length){ + // Does nothing for normal particles since normal particles always render at a single point + } // ============================================== Method Overrides ============================================== @@ -278,15 +331,16 @@ public abstract class ParticleWizardry extends Particle { * @param lookYZ Equal to {@code -lookZ} times the sine of {@code viewer.rotationPitch}. Will be 0 when facing directly horizontal. * When facing directly up, will be equal to {@code -lookZ}. When facing directly down, will be equal to {@code lookZ}. */ + // Fun fact: unlike entities, particles don't seem to bother checking the camera frustum... @Override public void renderParticle(BufferBuilder buffer, Entity viewer, float partialTicks, float lookZ, float lookY, float lookX, float lookXY, float lookYZ){ + + updateEntityLinking(partialTicks); if(Float.isNaN(this.yaw) || Float.isNaN(this.pitch)){ - // Normal behaviour (rotates to face the viewer) - super.renderParticle(buffer, viewer, partialTicks, lookZ, lookY, lookX, lookXY, lookYZ); - + drawParticle(buffer, viewer, partialTicks, lookZ, lookY, lookX, lookXY, lookYZ); }else{ // Specific rotation @@ -302,7 +356,25 @@ public abstract class ParticleWizardry extends Particle { float rotationYZ = -rotationZ * MathHelper.sin(pitch * degToRadFactor); float rotationXY = rotationX * MathHelper.sin(pitch * degToRadFactor); - super.renderParticle(buffer, viewer, partialTicks, rotationX, rotationY, rotationZ, rotationYZ, rotationXY); + drawParticle(buffer, viewer, partialTicks, rotationX, rotationY, rotationZ, rotationYZ, rotationXY); + } + } + + /** + * Delegate function for {@link ParticleWizardry#renderParticle(BufferBuilder, Entity, float, float, float, float, float, float)}; + * does the actual rendering. Subclasses should override this method instead of renderParticle. By default, this + * method simply calls super.renderParticle. + */ + protected void drawParticle(BufferBuilder buffer, Entity viewer, float partialTicks, float rotationX, float rotationY, float rotationZ, float rotationYZ, float rotationXY){ + super.renderParticle(buffer, viewer, partialTicks, rotationX, rotationY, rotationZ, rotationYZ, rotationXY); + } + + protected void updateEntityLinking(float partialTicks){ + if(this.entity != null){ + // This is kind of cheating but we know it's always a constant velocity so it works fine + prevPosX = posX + entity.prevPosX - entity.posX - relativeMotionX * (1-partialTicks); + prevPosY = posY + entity.prevPosY - entity.posY - relativeMotionY * (1-partialTicks); + prevPosZ = posZ + entity.prevPosZ - entity.posZ - relativeMotionZ * (1-partialTicks); } } @@ -310,38 +382,43 @@ public abstract class ParticleWizardry extends Particle { public void onUpdate(){ super.onUpdate(); - - // If any of these values is NaN, the particle has neither an entity nor a spin - if(!Double.isNaN(relativeMotionX) && !Double.isNaN(relativeMotionY) && !Double.isNaN(relativeMotionZ)){ - - // This allows velocity changes from entity linking and spin to stack - double vx = relativeMotionX; - double vy = relativeMotionY; - double vz = relativeMotionZ; + + if(this.canCollide && this.onGround){ + // I reject your friction and substitute my own! + this.motionX /= 0.699999988079071D; + this.motionZ /= 0.699999988079071D; + } + + if(entity != null || radius > 0){ + + double x = relativeX; + double y = relativeY; + double z = relativeZ; // Entity linking if(this.entity != null){ - - if(this.entity.isDead) this.setExpired(); - - this.setPosition(this.entity.posX + relativeX, this.entity.getEntityBoundingBox().minY + relativeY, - this.entity.posZ + relativeZ); - // Velocity is set so that the renderer will interpolate correctly between ticks - vx += this.entity.motionX; - vy += this.entity.motionY; - vz += this.entity.motionZ; + if(this.entity.isDead){ + this.setExpired(); + }else{ + x += this.entity.posX; + y += this.entity.posY; + z += this.entity.posZ; + } } // Spin if(radius > 0){ angle += speed; - vx += radius * speed * MathHelper.sin(angle); - vz += radius * speed * MathHelper.cos(angle); + // If the particle has spin, x/z relative position is used as centre and coords are changed each tick + x += radius * -MathHelper.cos(angle); + z += radius * MathHelper.sin(angle); } - - this.relativeX += vx; - this.relativeY += vy; - this.relativeZ += vz; + + this.setPosition(x, y, z); + + this.relativeX += relativeMotionX; + this.relativeY += relativeMotionY; + this.relativeZ += relativeMotionZ; } // Colour fading @@ -357,8 +434,96 @@ public abstract class ParticleWizardry extends Particle { // (which would probably otherwise happen if particleAge == particleMaxAge) this.setParticleTexture(sprites[Math.min((int)(ageFraction * sprites.length), sprites.length - 1)]); } + + // Collision spreading + if(canCollide){ + + if(this.motionX == 0 && this.prevVelX != 0){ // If the particle just collided in x + // Reduce lateral velocity so the added spread speed actually has an effect + this.motionY *= IMPACT_FRICTION; + this.motionZ *= IMPACT_FRICTION; + // Add random velocity in y and z proportional to the impact velocity + this.motionY += (rand.nextDouble()*2 - 1) * this.prevVelX * SPREAD_FACTOR; + this.motionZ += (rand.nextDouble()*2 - 1) * this.prevVelX * SPREAD_FACTOR; + } + + if(this.motionY == 0 && this.prevVelY != 0){ // If the particle just collided in y + // Reduce lateral velocity so the added spread speed actually has an effect + this.motionX *= IMPACT_FRICTION; + this.motionZ *= IMPACT_FRICTION; + // Add random velocity in x and z proportional to the impact velocity + this.motionX += (rand.nextDouble()*2 - 1) * this.prevVelY * SPREAD_FACTOR; + this.motionZ += (rand.nextDouble()*2 - 1) * this.prevVelY * SPREAD_FACTOR; + } + + if(this.motionZ == 0 && this.prevVelZ != 0){ // If the particle just collided in z + // Reduce lateral velocity so the added spread speed actually has an effect + this.motionX *= IMPACT_FRICTION; + this.motionY *= IMPACT_FRICTION; + // Add random velocity in x and y proportional to the impact velocity + this.motionX += (rand.nextDouble()*2 - 1) * this.prevVelZ * SPREAD_FACTOR; + this.motionY += (rand.nextDouble()*2 - 1) * this.prevVelZ * SPREAD_FACTOR; + } + + double searchRadius = 20; + + List nearbyEntities = WizardryUtilities.getEntitiesWithinRadius(searchRadius, this.posX, + this.posY, this.posZ, world, Entity.class); + + nearbyEntities.removeIf(e -> !(e instanceof ICustomHitbox && ((ICustomHitbox)e).contains(new Vec3d(this.posX, this.posY, this.posZ)))); + + if(nearbyEntities.size() > 0) this.setExpired(); + + } + + this.prevVelX = motionX; + this.prevVelY = motionY; + this.prevVelZ = motionZ; } - + + // Overridden and copied to fix the collision behaviour + @Override + public void move(double x, double y, double z){ + + double origY = y; + double origX = x; + double origZ = z; + + if(this.canCollide){ + + List list = this.world.getCollisionBoxes(null, this.getBoundingBox().expand(x, y, z)); + + for(AxisAlignedBB axisalignedbb : list){ + y = axisalignedbb.calculateYOffset(this.getBoundingBox(), y); + } + + this.setBoundingBox(this.getBoundingBox().offset(0.0D, y, 0.0D)); + + for(AxisAlignedBB axisalignedbb1 : list){ + x = axisalignedbb1.calculateXOffset(this.getBoundingBox(), x); + } + + this.setBoundingBox(this.getBoundingBox().offset(x, 0.0D, 0.0D)); + + for(AxisAlignedBB axisalignedbb2 : list){ + z = axisalignedbb2.calculateZOffset(this.getBoundingBox(), z); + } + + this.setBoundingBox(this.getBoundingBox().offset(0.0D, 0.0D, z)); + + }else{ + this.setBoundingBox(this.getBoundingBox().offset(x, y, z)); + } + + this.resetPositionToBB(); + this.onGround = origY != y && origY < 0.0D; + + if(origX != x) this.motionX = 0.0D; + if(origY != y) this.motionY = 0.0D; // Why doesn't Particle do this for y? + if(origZ != z) this.motionZ = 0.0D; + } + + // =============================================== Helper Methods =============================================== /** Static helper method that generates an array of n ResourceLocations using the particle file naming convention, @@ -390,6 +555,21 @@ public abstract class ParticleWizardry extends Particle { return textures; } + /** + * Associates the given {@link ResourceLocation} with the given {@link IWizardryParticleFactory}, allowing it to + * be used in the {@link electroblob.wizardry.util.ParticleBuilder ParticleBuilder}. This is a similar concept to + * registering entity renderers, in that it associates the client-only bit with its common-code counterpart - but + * of course, particles are client-side only so a simple identifier is all that is necessary. As with entity + * renderers, this method may only be called from the client side, probably a client proxy. + * @param name The {@link ResourceLocation} to use for the particle. This effectively replaces the particle type + * enum from previous versions. Keep a reference to this somewhere in common code for use later. + * @param factory A {@link IWizardryParticleFactory} that produces your particle. A constructor reference is usually + * sufficient. + */ + public static void registerParticle(ResourceLocation name, IWizardryParticleFactory factory){ + ClientProxy.addParticleFactory(name, factory); + } + /** Simple particle factory interface which takes a world and a position and returns a particle. Used (via method * references) in the client proxy to link particle enum types to actual particle classes. */ @SideOnly(Side.CLIENT) diff --git a/src/main/java/electroblob/wizardry/client/renderer/LayerFrost.java b/src/main/java/electroblob/wizardry/client/renderer/LayerFrost.java new file mode 100644 index 00000000..ae8536dd --- /dev/null +++ b/src/main/java/electroblob/wizardry/client/renderer/LayerFrost.java @@ -0,0 +1,153 @@ +package electroblob.wizardry.client.renderer; + +import electroblob.wizardry.Wizardry; +import electroblob.wizardry.block.BlockStatue; +import electroblob.wizardry.registry.WizardryPotions; +import net.minecraft.client.Minecraft; +import net.minecraft.client.model.ModelBase; +import net.minecraft.client.model.ModelBiped; +import net.minecraft.client.model.ModelPlayer; +import net.minecraft.client.renderer.GlStateManager; +import net.minecraft.client.renderer.GlStateManager.DestFactor; +import net.minecraft.client.renderer.GlStateManager.SourceFactor; +import net.minecraft.client.renderer.OpenGlHelper; +import net.minecraft.client.renderer.entity.Render; +import net.minecraft.client.renderer.entity.RenderLivingBase; +import net.minecraft.client.renderer.entity.RenderPlayer; +import net.minecraft.client.renderer.entity.layers.LayerRenderer; +import net.minecraft.entity.Entity; +import net.minecraft.entity.EntityLivingBase; +import net.minecraft.util.ResourceLocation; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.MathHelper; +import org.lwjgl.opengl.GL11; + +/** + * Layer used to render the frost texture on a creature with the frostbite effect. Handles dynamic tiling of the texture. + * + * @author Electroblob + * @since Wizardry 1.2 + */ +public class LayerFrost implements LayerRenderer { + + protected ModelBase model; + private final RenderLivingBase renderer; + + private static final ResourceLocation texture = new ResourceLocation(Wizardry.MODID, "textures/entity/frost_overlay.png"); + + public static void initialiseLayers(){ + + for(Render renderer : Minecraft.getMinecraft().getRenderManager().entityRenderMap.values()){ + // Because the zombie classes are now split properly, their renderers play nicely like everything else. + if(renderer instanceof RenderLivingBase){ + // Adds a frost layer to all the living entity renderers in the game. Whether it is actually rendered + // is decided in doRenderLayer below on a per-entity basis. + ((RenderLivingBase)renderer).addLayer(new LayerFrost((RenderLivingBase)renderer)); + } + } + + for(RenderPlayer renderer : Minecraft.getMinecraft().getRenderManager().getSkinMap().values()){ + renderer.addLayer(new LayerFrost(renderer)); + } + } + + public LayerFrost(RenderLivingBase renderer){ + this.renderer = renderer; + this.model = renderer.getMainModel(); + } + + @Override + public void doRenderLayer(EntityLivingBase entity, float limbSwing, float limbSwingAmount, float partialTicks, + float ageInTicks, float netHeadYaw, float headPitch, float scale){ + + if(entity.isPotionActive(WizardryPotions.frost) || entity.getEntityData().getBoolean(BlockStatue.FROZEN_NBT_KEY)){ + + GlStateManager.enableLighting(); + int i = this.getBlockBrightnessForEntity(entity, partialTicks); + + int j = i % 65536; + int k = i / 65536; + OpenGlHelper.setLightmapTextureCoords(OpenGlHelper.lightmapTexUnit, (float)j / 1.0F, (float)k / 1.0F); + + // Frost texture + GlStateManager.enableBlend(); + GlStateManager.blendFunc(SourceFactor.SRC_ALPHA, DestFactor.ONE_MINUS_SRC_ALPHA); + this.renderer.bindTexture(texture); + this.renderEntityModel(entity, limbSwing, limbSwingAmount, partialTicks, ageInTicks, netHeadYaw, + headPitch, scale); + GlStateManager.disableBlend(); + + } + } + + private int getBlockBrightnessForEntity(Entity entity, float partialTicks){ + + BlockPos.MutableBlockPos pos = new BlockPos.MutableBlockPos(MathHelper.floor(entity.posX), 0, + MathHelper.floor(entity.posZ)); + + if(entity.world.isBlockLoaded(pos)){ + pos.setY(MathHelper.floor(entity.posY + (double)entity.getEyeHeight())); + return entity.world.getCombinedLight(pos, 0); + }else{ + return 0; + } + } + + private void renderEntityModel(EntityLivingBase entity, float limbSwing, float limbSwingAmount, float partialTicks, + float ageInTicks, float netHeadYaw, float headPitch, float scale){ + + GlStateManager.pushMatrix(); + // Enables tiling (Also used for guardian beam, beacon beam and ender crystal beam) + GlStateManager.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_WRAP_S, GL11.GL_REPEAT); + GlStateManager.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_WRAP_T, GL11.GL_REPEAT); + + GlStateManager.depthMask(true); // Some entities set depth mask to false (i.e. no sorting of faces by depth) + // In particular, LayerSpiderEyes sets it to false when the spider is invisible, for some reason. + + // Changes the scale at which the texture is applied to the model. See LayerCreeper for a similar example, + // but with translation instead of scaling. + // NOTE: You can do all sorts of fun stuff with this, just by applying transformations in the 2D texture space. + GlStateManager.matrixMode(GL11.GL_TEXTURE); + GlStateManager.loadIdentity(); + double scaleX = 1, scaleY = 1; + // It's more logical to use the model's texture size, but some classes don't bother setting it properly + // (e.g. ModelVillager), so to get the correct dimensions I'm getting them from the first box instead. + if(model.boxList != null && model.boxList.get(0) != null){ + scaleX = (double)model.boxList.get(0).textureWidth / 16d; + scaleY = (double)model.boxList.get(0).textureHeight / 16d; + }else{ // Fallback to model fields; should never be needed + scaleX = (double)model.textureWidth / 16d; + scaleY = (double)model.textureHeight / 16d; + } + GlStateManager.scale(scaleX, scaleY, 1); + GlStateManager.matrixMode(GL11.GL_MODELVIEW); + + // Hides the hat layer for bipeds + if(this.model instanceof ModelBiped) ((ModelBiped)this.model).bipedHeadwear.isHidden = true; + + if(this.model instanceof ModelPlayer){ + ((ModelPlayer)this.model).bipedBodyWear.isHidden = true; + ((ModelPlayer)this.model).bipedLeftArmwear.isHidden = true; + ((ModelPlayer)this.model).bipedRightArmwear.isHidden = true; + ((ModelPlayer)this.model).bipedLeftLegwear.isHidden = true; + ((ModelPlayer)this.model).bipedRightLegwear.isHidden = true; + } + + this.model.setLivingAnimations(entity, limbSwing, limbSwingAmount, partialTicks); + this.model.render(entity, limbSwing, limbSwingAmount, ageInTicks, netHeadYaw, headPitch, scale); + + if(this.model instanceof ModelBiped) ((ModelBiped)this.model).bipedHeadwear.isHidden = false; + + // Undoes the texture scaling + GlStateManager.matrixMode(GL11.GL_TEXTURE); + GlStateManager.loadIdentity(); + GlStateManager.matrixMode(GL11.GL_MODELVIEW); + + GlStateManager.popMatrix(); + } + + @Override + public boolean shouldCombineTextures(){ + return false; + } +} \ No newline at end of file diff --git a/src/main/java/electroblob/wizardry/client/renderer/LayerStone.java b/src/main/java/electroblob/wizardry/client/renderer/LayerStone.java index 7978e26e..ed1d5669 100644 --- a/src/main/java/electroblob/wizardry/client/renderer/LayerStone.java +++ b/src/main/java/electroblob/wizardry/client/renderer/LayerStone.java @@ -1,9 +1,5 @@ package electroblob.wizardry.client.renderer; -import java.util.Map.Entry; - -import org.lwjgl.opengl.GL11; - import electroblob.wizardry.block.BlockStatue; import electroblob.wizardry.client.ClientProxy; import net.minecraft.client.Minecraft; @@ -21,6 +17,7 @@ import net.minecraft.entity.EntityLivingBase; import net.minecraft.util.ResourceLocation; import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.MathHelper; +import org.lwjgl.opengl.GL11; /** * Layer used to render the stone texture on a petrified creature. Handles dynamic tiling of the stone texture. @@ -36,16 +33,14 @@ public class LayerStone implements LayerRenderer { private static final ResourceLocation texture = new ResourceLocation("textures/blocks/stone.png"); public static void initialiseLayers(){ - for(Entry, Render> entry : Minecraft.getMinecraft() - .getRenderManager().entityRenderMap.entrySet()){ + + for(Render renderer : Minecraft.getMinecraft().getRenderManager().entityRenderMap.values()){ // Because the zombie classes are now split properly, their renderers play nicely like everything else. - if(entry.getValue() instanceof RenderLivingBase){ + if(renderer instanceof RenderLivingBase){ // Adds a stone layer to all the living entity renderers in the game. Whether it is actually rendered // is decided in doRenderLayer below on a per-entity basis. - ((RenderLivingBase)entry.getValue()).addLayer(new LayerStone((RenderLivingBase)entry.getValue())); + ((RenderLivingBase)renderer).addLayer(new LayerStone((RenderLivingBase)renderer)); } - // NOTE: May have to do some special stuff for players if they are to be added; see - // Minecraft.getMinecraft().getRenderManager().getSkinMap() } } @@ -55,12 +50,13 @@ public class LayerStone implements LayerRenderer { } // FIXME: Does not work with zombie pigmen, I have no idea why. + // I believe the issue is with the TESR actually, since LayerFrost works fine @Override public void doRenderLayer(EntityLivingBase entity, float limbSwing, float limbSwingAmount, float partialTicks, float ageInTicks, float netHeadYaw, float headPitch, float scale){ - if(entity.getEntityData().getBoolean(BlockStatue.NBT_KEY)){ + if(entity.getEntityData().getBoolean(BlockStatue.PETRIFIED_NBT_KEY)){ GlStateManager.enableLighting(); int i = this.getBlockBrightnessForEntity(entity, partialTicks); @@ -108,7 +104,6 @@ public class LayerStone implements LayerRenderer { GlStateManager.pushMatrix(); // Enables tiling (Also used for guardian beam, beacon beam and ender crystal beam) - // TODO: Backport this improvement GlStateManager.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_WRAP_S, GL11.GL_REPEAT); GlStateManager.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_WRAP_T, GL11.GL_REPEAT); diff --git a/src/main/java/electroblob/wizardry/client/renderer/LayerStrayMinionClothing.java b/src/main/java/electroblob/wizardry/client/renderer/LayerStrayMinionClothing.java new file mode 100644 index 00000000..00496ecb --- /dev/null +++ b/src/main/java/electroblob/wizardry/client/renderer/LayerStrayMinionClothing.java @@ -0,0 +1,33 @@ +package electroblob.wizardry.client.renderer; + +import electroblob.wizardry.entity.living.EntityStrayMinion; +import net.minecraft.client.model.ModelSkeleton; +import net.minecraft.client.renderer.GlStateManager; +import net.minecraft.client.renderer.entity.RenderLivingBase; +import net.minecraft.client.renderer.entity.layers.LayerRenderer; +import net.minecraft.util.ResourceLocation; + +/** Had to copy this entire class just because of one unnecessarily specific type parameter. The type parameter has been + * changed to {@code EntityStrayMinion} and parameter types updated accordingly. Everything else is identical. */ +public class LayerStrayMinionClothing implements LayerRenderer { + + private static final ResourceLocation STRAY_CLOTHES_TEXTURES = new ResourceLocation("textures/entity/skeleton/stray_overlay.png"); + private final RenderLivingBase renderer; + private final ModelSkeleton layerModel = new ModelSkeleton(0.25F, true); + + public LayerStrayMinionClothing(RenderLivingBase renderer){ + this.renderer = renderer; + } + + public void doRenderLayer(EntityStrayMinion entity, float limbSwing, float limbSwingAmount, float partialTicks, float ageInTicks, float netHeadYaw, float headPitch, float scale){ + this.layerModel.setModelAttributes(this.renderer.getMainModel()); + this.layerModel.setLivingAnimations(entity, limbSwing, limbSwingAmount, partialTicks); + GlStateManager.color(1.0F, 1.0F, 1.0F, 1.0F); + this.renderer.bindTexture(STRAY_CLOTHES_TEXTURES); + this.layerModel.render(entity, limbSwing, limbSwingAmount, ageInTicks, netHeadYaw, headPitch, scale); + } + + public boolean shouldCombineTextures(){ + return true; + } +} \ No newline at end of file diff --git a/src/main/java/electroblob/wizardry/client/renderer/RenderArcaneLock.java b/src/main/java/electroblob/wizardry/client/renderer/RenderArcaneLock.java new file mode 100644 index 00000000..cb2058f8 --- /dev/null +++ b/src/main/java/electroblob/wizardry/client/renderer/RenderArcaneLock.java @@ -0,0 +1,89 @@ +package electroblob.wizardry.client.renderer; + +import electroblob.wizardry.Wizardry; +import electroblob.wizardry.spell.ArcaneLock; +import electroblob.wizardry.util.WizardryUtilities; +import net.minecraft.client.Minecraft; +import net.minecraft.client.renderer.BufferBuilder; +import net.minecraft.client.renderer.GlStateManager; +import net.minecraft.client.renderer.OpenGlHelper; +import net.minecraft.client.renderer.Tessellator; +import net.minecraft.client.renderer.vertex.DefaultVertexFormats; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.tileentity.TileEntity; +import net.minecraft.util.ResourceLocation; +import net.minecraft.util.math.Vec3d; +import net.minecraft.world.World; +import net.minecraftforge.client.event.RenderWorldLastEvent; +import net.minecraftforge.fml.common.Mod; +import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; +import net.minecraftforge.fml.relauncher.Side; +import org.lwjgl.opengl.GL11; + +@Mod.EventBusSubscriber(Side.CLIENT) +public class RenderArcaneLock { + + private static final ResourceLocation[] textures = new ResourceLocation[8]; + + static { + for(int i=0; i { @@ -30,19 +30,19 @@ public class RenderArcaneWorkbench extends TileEntitySpecialRenderer { @@ -81,21 +77,21 @@ public class RenderBlackHole extends Render { int sliceAngle = 20 + a; - double x1 = scale * Math.sin((blackhole.ticksExisted + 40 * j) * (Math.PI / 180)); - // double y1 = 0.7*Math.cos((blackhole.timer - 40*j)*(Math.PI/180))*j/10; - double z1 = scale * Math.cos((blackhole.ticksExisted + 40 * j) * (Math.PI / 180)); + double x1 = scale * MathHelper.sin((blackhole.ticksExisted + 40 * j) * ((float)Math.PI / 180f)); + // double y1 = 0.7*MathHelper.cos((blackhole.timer - 40*j)*(Math.PI/180))*j/10; + double z1 = scale * MathHelper.cos((blackhole.ticksExisted + 40 * j) * ((float)Math.PI / 180)); - double x2 = scale * Math.sin((blackhole.ticksExisted + 40 * j - sliceAngle) * (Math.PI / 180)); - // double y2 = 0.7*Math.sin((blackhole.timer - 40*j)*(Math.PI/180))*j/10; - double z2 = scale * Math.cos((blackhole.ticksExisted + 40 * j - sliceAngle) * (Math.PI / 180)); + double x2 = scale * MathHelper.sin((blackhole.ticksExisted + 40 * j - sliceAngle) * ((float)Math.PI / 180)); + // double y2 = 0.7*MathHelper.sin((blackhole.timer - 40*j)*(Math.PI/180))*j/10; + double z2 = scale * MathHelper.cos((blackhole.ticksExisted + 40 * j - sliceAngle) * ((float)Math.PI / 180)); - double absoluteX = x1 * Math.cos(31 * b); - double absoluteY = z1 * Math.sin(31 * a) + x1 * Math.cos(31 * a) * Math.sin(31 * b); - double absoluteZ = z1 * Math.cos(31 * a); + double absoluteX = x1 * MathHelper.cos(31 * b); + double absoluteY = z1 * MathHelper.sin(31 * a) + x1 * MathHelper.cos(31 * a) * MathHelper.sin(31 * b); + double absoluteZ = z1 * MathHelper.cos(31 * a); - double absoluteX2 = x2 * Math.cos(31 * b); - double absoluteY2 = z2 * Math.sin(31 * a) + x2 * Math.cos(31 * a) * Math.sin(31 * b); - double absoluteZ2 = z2 * Math.cos(31 * a); + double absoluteX2 = x2 * MathHelper.cos(31 * b); + double absoluteY2 = z2 * MathHelper.sin(31 * a) + x2 * MathHelper.cos(31 * a) * MathHelper.sin(31 * b); + double absoluteZ2 = z2 * MathHelper.cos(31 * a); /* buffer.begin(0, DefaultVertexFormats.POSITION_TEX); * * tessellator.setColorOpaque(255, 255, 255); GL11.glPointSize(5); diff --git a/src/main/java/electroblob/wizardry/client/renderer/RenderBubble.java b/src/main/java/electroblob/wizardry/client/renderer/RenderBubble.java index fa0cb695..2694f1e8 100644 --- a/src/main/java/electroblob/wizardry/client/renderer/RenderBubble.java +++ b/src/main/java/electroblob/wizardry/client/renderer/RenderBubble.java @@ -1,7 +1,5 @@ package electroblob.wizardry.client.renderer; -import org.lwjgl.opengl.GL11; - import electroblob.wizardry.Wizardry; import electroblob.wizardry.entity.construct.EntityBubble; import electroblob.wizardry.util.WizardryUtilities; @@ -14,6 +12,7 @@ import net.minecraft.client.renderer.entity.Render; import net.minecraft.client.renderer.entity.RenderManager; import net.minecraft.client.renderer.vertex.DefaultVertexFormats; import net.minecraft.util.ResourceLocation; +import org.lwjgl.opengl.GL11; public class RenderBubble extends Render { diff --git a/src/main/java/electroblob/wizardry/client/renderer/RenderContainmentField.java b/src/main/java/electroblob/wizardry/client/renderer/RenderContainmentField.java new file mode 100644 index 00000000..b52b83b0 --- /dev/null +++ b/src/main/java/electroblob/wizardry/client/renderer/RenderContainmentField.java @@ -0,0 +1,268 @@ +package electroblob.wizardry.client.renderer; + +import electroblob.wizardry.Wizardry; +import electroblob.wizardry.potion.PotionContainment; +import electroblob.wizardry.registry.WizardryPotions; +import electroblob.wizardry.util.WizardryUtilities; +import net.minecraft.client.Minecraft; +import net.minecraft.client.renderer.BufferBuilder; +import net.minecraft.client.renderer.GlStateManager; +import net.minecraft.client.renderer.OpenGlHelper; +import net.minecraft.client.renderer.Tessellator; +import net.minecraft.client.renderer.vertex.DefaultVertexFormats; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.nbt.NBTUtil; +import net.minecraft.util.ResourceLocation; +import net.minecraft.util.math.MathHelper; +import net.minecraft.util.math.Vec3d; +import net.minecraftforge.client.event.RenderWorldLastEvent; +import net.minecraftforge.fml.common.Mod; +import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; +import net.minecraftforge.fml.relauncher.Side; +import org.lwjgl.opengl.GL11; + +@Mod.EventBusSubscriber(Side.CLIENT) +public class RenderContainmentField { + + private static final ResourceLocation[] textures = new ResourceLocation[8]; + + private static final float ANIMATION_SPEED = 0.004f; + private static final float FADE_DISTANCE_SQUARED = 15; + + static { + for(int i=0; i { diff --git a/src/main/java/electroblob/wizardry/client/renderer/RenderDecoy.java b/src/main/java/electroblob/wizardry/client/renderer/RenderDecoy.java index 4c421adc..10acfa56 100644 --- a/src/main/java/electroblob/wizardry/client/renderer/RenderDecoy.java +++ b/src/main/java/electroblob/wizardry/client/renderer/RenderDecoy.java @@ -1,8 +1,5 @@ package electroblob.wizardry.client.renderer; -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; - import electroblob.wizardry.Wizardry; import electroblob.wizardry.entity.living.EntityDecoy; import net.minecraft.client.model.ModelBiped; @@ -12,10 +9,11 @@ import net.minecraft.client.renderer.entity.RenderManager; import net.minecraft.entity.Entity; import net.minecraft.util.ResourceLocation; import net.minecraftforge.fml.relauncher.ReflectionHelper; -import net.minecraftforge.fml.relauncher.Side; -import net.minecraftforge.fml.relauncher.SideOnly; -@SideOnly(Side.CLIENT) +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; + +//@SideOnly(Side.CLIENT) public class RenderDecoy extends RenderBiped { private static final ResourceLocation steveTextures = new ResourceLocation("textures/entity/steve.png"); diff --git a/src/main/java/electroblob/wizardry/client/renderer/RenderEvilWizard.java b/src/main/java/electroblob/wizardry/client/renderer/RenderEvilWizard.java index 2828261f..34299e1c 100644 --- a/src/main/java/electroblob/wizardry/client/renderer/RenderEvilWizard.java +++ b/src/main/java/electroblob/wizardry/client/renderer/RenderEvilWizard.java @@ -7,10 +7,8 @@ import net.minecraft.client.renderer.entity.RenderBiped; import net.minecraft.client.renderer.entity.RenderManager; import net.minecraft.client.renderer.entity.layers.LayerBipedArmor; import net.minecraft.util.ResourceLocation; -import net.minecraftforge.fml.relauncher.Side; -import net.minecraftforge.fml.relauncher.SideOnly; -@SideOnly(Side.CLIENT) +//@SideOnly(Side.CLIENT) public class RenderEvilWizard extends RenderBiped { static final ResourceLocation[] textures = new ResourceLocation[6]; diff --git a/src/main/java/electroblob/wizardry/client/renderer/RenderFireRing.java b/src/main/java/electroblob/wizardry/client/renderer/RenderFireRing.java index 8597bacf..9e01b89b 100644 --- a/src/main/java/electroblob/wizardry/client/renderer/RenderFireRing.java +++ b/src/main/java/electroblob/wizardry/client/renderer/RenderFireRing.java @@ -1,7 +1,5 @@ package electroblob.wizardry.client.renderer; -import org.lwjgl.opengl.GL11; - import electroblob.wizardry.entity.construct.EntityFireRing; import net.minecraft.client.Minecraft; import net.minecraft.client.renderer.BufferBuilder; @@ -15,6 +13,7 @@ import net.minecraft.client.renderer.texture.TextureMap; import net.minecraft.client.renderer.vertex.DefaultVertexFormats; import net.minecraft.init.Blocks; import net.minecraft.util.ResourceLocation; +import org.lwjgl.opengl.GL11; public class RenderFireRing extends Render { diff --git a/src/main/java/electroblob/wizardry/client/renderer/RenderForceArrow.java b/src/main/java/electroblob/wizardry/client/renderer/RenderForceArrow.java index a7632a8d..7f908e71 100644 --- a/src/main/java/electroblob/wizardry/client/renderer/RenderForceArrow.java +++ b/src/main/java/electroblob/wizardry/client/renderer/RenderForceArrow.java @@ -1,7 +1,5 @@ package electroblob.wizardry.client.renderer; -import org.lwjgl.opengl.GL11; - import electroblob.wizardry.Wizardry; import electroblob.wizardry.entity.projectile.EntityForceArrow; import net.minecraft.client.renderer.BufferBuilder; @@ -13,10 +11,9 @@ import net.minecraft.client.renderer.entity.RenderManager; import net.minecraft.client.renderer.vertex.DefaultVertexFormats; import net.minecraft.util.ResourceLocation; import net.minecraft.util.math.MathHelper; -import net.minecraftforge.fml.relauncher.Side; -import net.minecraftforge.fml.relauncher.SideOnly; +import org.lwjgl.opengl.GL11; -@SideOnly(Side.CLIENT) +//@SideOnly(Side.CLIENT) public class RenderForceArrow extends Render { private static final ResourceLocation arrowTextures = new ResourceLocation(Wizardry.MODID, diff --git a/src/main/java/electroblob/wizardry/client/renderer/RenderForcefield.java b/src/main/java/electroblob/wizardry/client/renderer/RenderForcefield.java new file mode 100644 index 00000000..660c1e1a --- /dev/null +++ b/src/main/java/electroblob/wizardry/client/renderer/RenderForcefield.java @@ -0,0 +1,124 @@ +package electroblob.wizardry.client.renderer; + +import electroblob.wizardry.entity.construct.EntityForcefield; +import net.minecraft.client.renderer.BufferBuilder; +import net.minecraft.client.renderer.GlStateManager; +import net.minecraft.client.renderer.OpenGlHelper; +import net.minecraft.client.renderer.Tessellator; +import net.minecraft.client.renderer.entity.Render; +import net.minecraft.client.renderer.entity.RenderManager; +import net.minecraft.client.renderer.vertex.DefaultVertexFormats; +import net.minecraft.util.ResourceLocation; +import net.minecraft.util.math.MathHelper; +import org.lwjgl.opengl.GL11; + +public class RenderForcefield extends Render { + + private static final float EXPANSION_TIME = 3; + + public RenderForcefield(RenderManager renderManager){ + super(renderManager); + } + + @Override + public void doRender(EntityForcefield entity, double x, double y, double z, float yaw, float partialTicks){ + + // For now we're just using a UV sphere + + GlStateManager.pushMatrix(); + + GlStateManager.disableLighting(); + GlStateManager.enableBlend(); + GlStateManager.disableTexture2D(); + GlStateManager.blendFunc(GlStateManager.SourceFactor.SRC_ALPHA, GlStateManager.DestFactor.ONE_MINUS_SRC_ALPHA); + OpenGlHelper.setLightmapTextureCoords(OpenGlHelper.lightmapTexUnit, 240f, 240f); + + GlStateManager.translate(x, y, z); + + float latStep = (float)Math.PI/20; + float longStep = (float)Math.PI/20; + + float pulse = MathHelper.sin((entity.ticksExisted + partialTicks)/10f); + + float r = 0.35f, g = 0.55f + 0.05f * pulse, b = 1; + + float radius = entity.getRadius(); + float a = 0.5f; + + if(entity.ticksExisted > entity.lifetime - EXPANSION_TIME){ + radius *= 1 + 0.2f * (entity.ticksExisted + partialTicks - (entity.lifetime - EXPANSION_TIME))/EXPANSION_TIME; + a *= Math.max(0, 1 - (entity.ticksExisted + partialTicks - (entity.lifetime - EXPANSION_TIME))/EXPANSION_TIME); + }else if(entity.ticksExisted < EXPANSION_TIME){ + radius *= 1 - (EXPANSION_TIME - entity.ticksExisted - partialTicks)/EXPANSION_TIME; + a *= 1 - (EXPANSION_TIME - entity.ticksExisted - partialTicks)/EXPANSION_TIME; + } + + // Draw the inside first + drawSphere(radius - 0.1f - 0.025f * pulse, latStep, longStep, true, r, g, b, a); + drawSphere(radius - 0.1f - 0.025f * pulse, latStep, longStep, false, 1, 1, 1, a); + drawSphere(radius, latStep, longStep, false, r, g, b, 0.7f * a); + + GlStateManager.enableTexture2D(); + GlStateManager.enableLighting(); + GlStateManager.disableBlend(); + + GlStateManager.popMatrix(); + } + + @Override + protected ResourceLocation getEntityTexture(EntityForcefield entity){ + return null; + } + + /** + * Draws a sphere (using lat/long triangles) with the given parameters. + * @param radius The radius of the sphere. + * @param latStep The latitude step; smaller is smoother but increases performance cost. + * @param longStep The longitude step; smaller is smoother but increases performance cost. + * @param inside Whether to draw the outside or the inside of the sphere. + * @param r The red component of the sphere colour. + * @param g The green component of the sphere colour. + * @param b The blue component of the sphere colour. + * @param a The alpha component of the sphere colour. + */ + private static void drawSphere(float radius, float latStep, float longStep, boolean inside, float r, float g, float b, float a){ + + Tessellator tessellator = Tessellator.getInstance(); + BufferBuilder buffer = tessellator.getBuffer(); + + buffer.begin(GL11.GL_TRIANGLE_STRIP, DefaultVertexFormats.POSITION_COLOR); + + boolean goingUp = inside; + + buffer.pos(0, goingUp ? -radius : radius, 0).color(r, g, b, a).endVertex(); // Start at the north pole + + for(float longitude = -(float)Math.PI; longitude <= (float)Math.PI; longitude += longStep){ + + // Leave the poles out since they only have a single point per stack instead of two + for(float theta = (float)Math.PI/2 - latStep; theta >= -(float)Math.PI/2 + latStep; theta -= latStep){ + + float latitude = goingUp ? -theta : theta; + + float hRadius = radius * MathHelper.cos(latitude); + float vy = radius * MathHelper.sin(latitude); + float vx = hRadius * MathHelper.sin(longitude); + float vz = hRadius * MathHelper.cos(longitude); + + buffer.pos(vx, vy, vz).color(r, g, b, a).endVertex(); + + vx = hRadius * MathHelper.sin(longitude + longStep); + vz = hRadius * MathHelper.cos(longitude + longStep); + + buffer.pos(vx, vy, vz).color(r, g, b, a).endVertex(); + } + + // The next pole + buffer.pos(0, goingUp ? radius : -radius, 0).color(r, g, b, a).endVertex(); + + goingUp = !goingUp; + } + + tessellator.draw(); + } + +} diff --git a/src/main/java/electroblob/wizardry/client/renderer/RenderHammer.java b/src/main/java/electroblob/wizardry/client/renderer/RenderHammer.java index 8f448603..3962e04b 100644 --- a/src/main/java/electroblob/wizardry/client/renderer/RenderHammer.java +++ b/src/main/java/electroblob/wizardry/client/renderer/RenderHammer.java @@ -19,11 +19,13 @@ public class RenderHammer extends Render { } @Override - public void doRender(EntityHammer entity, double x, double y, double z, float f, float f1){ + public void doRender(EntityHammer entity, double x, double y, double z, float yaw, float partialTicks){ GlStateManager.pushMatrix(); GlStateManager.translate(x, y + 1.5, z); GlStateManager.rotate(180, 0F, 0F, 1F); + GlStateManager.rotate(yaw, 0, 1, 0); + GlStateManager.rotate(entity.prevRotationPitch + (entity.rotationPitch - entity.prevRotationPitch) * partialTicks, 0, 0, 1); this.bindTexture(texture); diff --git a/src/main/java/electroblob/wizardry/client/renderer/RenderIceGiant.java b/src/main/java/electroblob/wizardry/client/renderer/RenderIceGiant.java index b78c6888..e20f22bf 100644 --- a/src/main/java/electroblob/wizardry/client/renderer/RenderIceGiant.java +++ b/src/main/java/electroblob/wizardry/client/renderer/RenderIceGiant.java @@ -7,10 +7,8 @@ import net.minecraft.client.renderer.GlStateManager; import net.minecraft.client.renderer.entity.RenderLiving; import net.minecraft.client.renderer.entity.RenderManager; import net.minecraft.util.ResourceLocation; -import net.minecraftforge.fml.relauncher.Side; -import net.minecraftforge.fml.relauncher.SideOnly; -@SideOnly(Side.CLIENT) +//@SideOnly(Side.CLIENT) public class RenderIceGiant extends RenderLiving { private static final ResourceLocation texture = new ResourceLocation(Wizardry.MODID, diff --git a/src/main/java/electroblob/wizardry/client/renderer/RenderIceSpike.java b/src/main/java/electroblob/wizardry/client/renderer/RenderIceSpike.java index 961b87f5..3a88d93b 100644 --- a/src/main/java/electroblob/wizardry/client/renderer/RenderIceSpike.java +++ b/src/main/java/electroblob/wizardry/client/renderer/RenderIceSpike.java @@ -1,7 +1,5 @@ package electroblob.wizardry.client.renderer; -import org.lwjgl.opengl.GL11; - import electroblob.wizardry.Wizardry; import electroblob.wizardry.entity.construct.EntityIceSpike; import net.minecraft.client.renderer.BufferBuilder; @@ -12,6 +10,7 @@ import net.minecraft.client.renderer.entity.Render; import net.minecraft.client.renderer.entity.RenderManager; import net.minecraft.client.renderer.vertex.DefaultVertexFormats; import net.minecraft.util.ResourceLocation; +import org.lwjgl.opengl.GL11; public class RenderIceSpike extends Render { @@ -23,13 +22,14 @@ public class RenderIceSpike extends Render { } @Override - public void doRender(EntityIceSpike entity, double x, double y, double z, float fa, float partialTickTime){ + public void doRender(EntityIceSpike entity, double x, double y, double z, float yaw, float partialTickTime){ GlStateManager.pushMatrix(); GlStateManager.translate((float)x, (float)y, (float)z); - // Apparently, disabling lighting... doesn't disable lighting. Or at least, you can still set the brightness - // with setLightmapTextureCoords. + GlStateManager.rotate(entity.rotationYaw - 90.0F, 0.0F, 1.0F, 0.0F); + GlStateManager.rotate(entity.rotationPitch - 90, 0.0F, 0.0F, 1.0F); + GlStateManager.disableLighting(); int j = entity.getBrightnessForRender(); diff --git a/src/main/java/electroblob/wizardry/client/renderer/RenderLightningDisc.java b/src/main/java/electroblob/wizardry/client/renderer/RenderLightningDisc.java index 77af69d3..96fe6110 100644 --- a/src/main/java/electroblob/wizardry/client/renderer/RenderLightningDisc.java +++ b/src/main/java/electroblob/wizardry/client/renderer/RenderLightningDisc.java @@ -1,7 +1,5 @@ package electroblob.wizardry.client.renderer; -import org.lwjgl.opengl.GL11; - import electroblob.wizardry.entity.projectile.EntityLightningDisc; import net.minecraft.client.renderer.BufferBuilder; import net.minecraft.client.renderer.GlStateManager; @@ -11,6 +9,7 @@ import net.minecraft.client.renderer.entity.Render; import net.minecraft.client.renderer.entity.RenderManager; import net.minecraft.client.renderer.vertex.DefaultVertexFormats; import net.minecraft.util.ResourceLocation; +import org.lwjgl.opengl.GL11; public class RenderLightningDisc extends Render { diff --git a/src/main/java/electroblob/wizardry/client/renderer/RenderMagicArrow.java b/src/main/java/electroblob/wizardry/client/renderer/RenderMagicArrow.java index 9dfb0527..b0db9b36 100644 --- a/src/main/java/electroblob/wizardry/client/renderer/RenderMagicArrow.java +++ b/src/main/java/electroblob/wizardry/client/renderer/RenderMagicArrow.java @@ -1,7 +1,5 @@ package electroblob.wizardry.client.renderer; -import org.lwjgl.opengl.GL11; - import electroblob.wizardry.entity.projectile.EntityMagicArrow; import net.minecraft.client.renderer.BufferBuilder; import net.minecraft.client.renderer.GlStateManager; @@ -12,10 +10,9 @@ import net.minecraft.client.renderer.entity.RenderManager; import net.minecraft.client.renderer.vertex.DefaultVertexFormats; import net.minecraft.util.ResourceLocation; import net.minecraft.util.math.MathHelper; -import net.minecraftforge.fml.relauncher.Side; -import net.minecraftforge.fml.relauncher.SideOnly; +import org.lwjgl.opengl.GL11; -@SideOnly(Side.CLIENT) +//@SideOnly(Side.CLIENT) public class RenderMagicArrow extends Render { private final ResourceLocation texture; diff --git a/src/main/java/electroblob/wizardry/client/renderer/RenderMagicLight.java b/src/main/java/electroblob/wizardry/client/renderer/RenderMagicLight.java index 198e02f7..a0e2a2ce 100644 --- a/src/main/java/electroblob/wizardry/client/renderer/RenderMagicLight.java +++ b/src/main/java/electroblob/wizardry/client/renderer/RenderMagicLight.java @@ -1,18 +1,14 @@ package electroblob.wizardry.client.renderer; -import org.lwjgl.opengl.GL11; - import electroblob.wizardry.Wizardry; import electroblob.wizardry.tileentity.TileEntityMagicLight; import net.minecraft.client.Minecraft; -import net.minecraft.client.renderer.BufferBuilder; -import net.minecraft.client.renderer.GlStateManager; -import net.minecraft.client.renderer.OpenGlHelper; -import net.minecraft.client.renderer.RenderHelper; -import net.minecraft.client.renderer.Tessellator; +import net.minecraft.client.renderer.*; import net.minecraft.client.renderer.tileentity.TileEntitySpecialRenderer; import net.minecraft.client.renderer.vertex.DefaultVertexFormats; import net.minecraft.util.ResourceLocation; +import net.minecraft.util.math.MathHelper; +import org.lwjgl.opengl.GL11; public class RenderMagicLight extends TileEntitySpecialRenderer { @@ -40,10 +36,9 @@ public class RenderMagicLight extends TileEntitySpecialRenderer tileentity.maxTimer - 10 && tileentity.timer <= tileentity.maxTimer){ - GlStateManager.scale((float)(tileentity.maxTimer - tileentity.timer) / 10, - (float)(tileentity.maxTimer - tileentity.timer) / 10, - (float)(tileentity.maxTimer - tileentity.timer) / 10); + if(tileentity.maxTimer > 0 && tileentity.timer > tileentity.maxTimer - 10){ + float scale = Math.max(0, (float)(tileentity.maxTimer - tileentity.timer) / 10); + GlStateManager.scale(scale, scale, scale); } // Renders the aura effect @@ -105,13 +100,13 @@ public class RenderMagicLight extends TileEntitySpecialRenderer { private static final ResourceLocation texture = new ResourceLocation(Wizardry.MODID, "textures/entity/phoenix.png"); diff --git a/src/main/java/electroblob/wizardry/client/renderer/RenderPossessingPlayer.java b/src/main/java/electroblob/wizardry/client/renderer/RenderPossessingPlayer.java new file mode 100644 index 00000000..0820a178 --- /dev/null +++ b/src/main/java/electroblob/wizardry/client/renderer/RenderPossessingPlayer.java @@ -0,0 +1,41 @@ +package electroblob.wizardry.client.renderer; + +import electroblob.wizardry.spell.Possession; +import net.minecraft.client.renderer.entity.Render; +import net.minecraft.entity.EntityLiving; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraftforge.client.event.RenderPlayerEvent; +import net.minecraftforge.fml.common.Mod; +import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; +import net.minecraftforge.fml.relauncher.Side; + +@Mod.EventBusSubscriber(Side.CLIENT) +public class RenderPossessingPlayer { + + @SubscribeEvent + @SuppressWarnings("unchecked") // Can't check it due to type erasure + public static void onRenderPlayerPreEvent(RenderPlayerEvent.Pre event){ + + EntityPlayer player = event.getEntityPlayer(); + EntityLiving possessee = Possession.getPossessee(player); + + if(possessee != null){ + // I reject your renderer and substitute my own! + Render renderer = (Render)event.getRenderer().getRenderManager().entityRenderMap.get(possessee.getClass()); + float yaw = player.prevRotationYaw + (player.rotationYaw - player.prevRotationYaw) * event.getPartialRenderTick(); + possessee.swingProgress = player.swingProgress; + possessee.prevSwingProgress = player.prevSwingProgress; + possessee.renderYawOffset = player.renderYawOffset; + possessee.prevRenderYawOffset = player.prevRenderYawOffset; + possessee.rotationYawHead = player.rotationYawHead; + possessee.prevRotationYawHead = player.prevRotationYawHead; + possessee.rotationPitch = player.rotationPitch; + possessee.prevRotationPitch = player.prevRotationPitch; + possessee.limbSwing = player.limbSwing; + possessee.limbSwingAmount = player.limbSwingAmount; + possessee.prevLimbSwingAmount = player.prevLimbSwingAmount; + renderer.doRender(possessee, event.getX(), event.getY(), event.getZ(), yaw, event.getPartialRenderTick()); + event.setCanceled(true); + } + } +} diff --git a/src/main/java/electroblob/wizardry/client/renderer/RenderProjectile.java b/src/main/java/electroblob/wizardry/client/renderer/RenderProjectile.java index 387257b4..f5ece03f 100644 --- a/src/main/java/electroblob/wizardry/client/renderer/RenderProjectile.java +++ b/src/main/java/electroblob/wizardry/client/renderer/RenderProjectile.java @@ -1,7 +1,5 @@ package electroblob.wizardry.client.renderer; -import org.lwjgl.opengl.GL11; - import electroblob.wizardry.entity.projectile.EntityMagicProjectile; import net.minecraft.client.Minecraft; import net.minecraft.client.renderer.BufferBuilder; @@ -12,10 +10,9 @@ import net.minecraft.client.renderer.entity.Render; import net.minecraft.client.renderer.entity.RenderManager; import net.minecraft.client.renderer.vertex.DefaultVertexFormats; import net.minecraft.util.ResourceLocation; -import net.minecraftforge.fml.relauncher.Side; -import net.minecraftforge.fml.relauncher.SideOnly; +import org.lwjgl.opengl.GL11; -@SideOnly(Side.CLIENT) +//@SideOnly(Side.CLIENT) public class RenderProjectile extends Render { private float scale; diff --git a/src/main/java/electroblob/wizardry/client/renderer/RenderShadowWard.java b/src/main/java/electroblob/wizardry/client/renderer/RenderShadowWard.java new file mode 100644 index 00000000..a0cf181f --- /dev/null +++ b/src/main/java/electroblob/wizardry/client/renderer/RenderShadowWard.java @@ -0,0 +1,148 @@ +package electroblob.wizardry.client.renderer; + +import electroblob.wizardry.Wizardry; +import electroblob.wizardry.registry.Spells; +import electroblob.wizardry.util.WizardryUtilities; +import net.minecraft.client.Minecraft; +import net.minecraft.client.renderer.BufferBuilder; +import net.minecraft.client.renderer.GlStateManager; +import net.minecraft.client.renderer.OpenGlHelper; +import net.minecraft.client.renderer.Tessellator; +import net.minecraft.client.renderer.vertex.DefaultVertexFormats; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.util.ResourceLocation; +import net.minecraft.util.math.Vec3d; +import net.minecraftforge.client.event.RenderPlayerEvent; +import net.minecraftforge.client.event.RenderWorldLastEvent; +import net.minecraftforge.fml.common.Mod; +import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; +import net.minecraftforge.fml.relauncher.Side; +import org.lwjgl.opengl.GL11; + +@Mod.EventBusSubscriber(Side.CLIENT) +public class RenderShadowWard { + + private static final ResourceLocation TEXTURE = new ResourceLocation(Wizardry.MODID, "textures/entity/shadow_ward.png"); + + // First person + @SubscribeEvent + public static void onRenderWorldLastEvent(RenderWorldLastEvent event){ + // Only render in first person + if(Minecraft.getMinecraft().gameSettings.thirdPersonView == 0){ + + EntityPlayer player = Minecraft.getMinecraft().player; + + if(WizardryUtilities.isCasting(player, Spells.shadow_ward)){ + + GlStateManager.pushMatrix(); + + GlStateManager.enableBlend(); + GlStateManager.blendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA); + //GlStateManager.shadeModel(GL11.GL_SMOOTH); + GlStateManager.disableLighting(); + //GlStateManager.disableAlpha(); + OpenGlHelper.setLightmapTextureCoords(OpenGlHelper.lightmapTexUnit, 240f, 240f); + + GlStateManager.translate(0, 1.2, 0); + GlStateManager.rotate(-player.rotationYaw, 0, 1, 0); + GlStateManager.rotate(player.rotationPitch, 1, 0, 0); + + Minecraft.getMinecraft().renderEngine.bindTexture(TEXTURE); + + GlStateManager.pushMatrix(); + + GlStateManager.translate(0, 0, 1.2); + GlStateManager.rotate(player.world.getTotalWorldTime() * -2, 0, 0, 1); + GlStateManager.scale(1.1, 1.1, 1.1); + + Tessellator tessellator = Tessellator.getInstance(); + BufferBuilder buffer = tessellator.getBuffer(); + + buffer.begin(GL11.GL_QUADS, DefaultVertexFormats.POSITION_TEX); + + buffer.pos(-0.5, 0.5, -0.5).tex(0, 0).endVertex(); + buffer.pos(0.5, 0.5, -0.5).tex(1, 0).endVertex(); + buffer.pos(0.5, -0.5, -0.5).tex(1, 1).endVertex(); + buffer.pos(-0.5, -0.5, -0.5).tex(0, 1).endVertex(); + + tessellator.draw(); + + buffer.begin(GL11.GL_QUADS, DefaultVertexFormats.POSITION_TEX); + + buffer.pos(-0.5, 0.5, -0.5).tex(0, 0).endVertex(); + buffer.pos(-0.5, -0.5, -0.5).tex(0, 1).endVertex(); + buffer.pos(0.5, -0.5, -0.5).tex(1, 1).endVertex(); + buffer.pos(0.5, 0.5, -0.5).tex(1, 0).endVertex(); + + tessellator.draw(); + + GlStateManager.popMatrix(); + + //GlStateManager.shadeModel(GL11.GL_FLAT); + GlStateManager.enableLighting(); + GlStateManager.disableBlend(); + + GlStateManager.popMatrix(); + + } + } + } + + // Third person + @SubscribeEvent + public static void onRenderPlayerEvent(RenderPlayerEvent.Post event){ + + EntityPlayer player = event.getEntityPlayer(); + + if(WizardryUtilities.isCasting(player, Spells.shadow_ward)){ + + GlStateManager.pushMatrix(); + + GlStateManager.enableBlend(); + GlStateManager.blendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA); + GlStateManager.disableLighting(); + OpenGlHelper.setLightmapTextureCoords(OpenGlHelper.lightmapTexUnit, 240f, 240f); + + Vec3d delta = player.getPositionEyes(event.getPartialRenderTick()) + .subtract(Minecraft.getMinecraft().player.getPositionEyes(event.getPartialRenderTick())); + GlStateManager.translate(delta.x, delta.y, delta.z); + + GlStateManager.rotate(180, 0, 1, 0); + GlStateManager.rotate(-player.renderYawOffset, 0, 1, 0); + + Minecraft.getMinecraft().renderEngine.bindTexture(TEXTURE); + + Tessellator tessellator = Tessellator.getInstance(); + BufferBuilder buffer = tessellator.getBuffer(); + + GlStateManager.translate(0, 1.2, 0); + GlStateManager.rotate(player.world.getTotalWorldTime() * -2, 0, 0, 1); + GlStateManager.scale(1.1, 1.1, 1.1); + + buffer.begin(GL11.GL_QUADS, DefaultVertexFormats.POSITION_TEX); + + buffer.pos(-0.5, 0.5, -0.5).tex(0, 0).endVertex(); + buffer.pos(0.5, 0.5, -0.5).tex(1, 0).endVertex(); + buffer.pos(0.5, -0.5, -0.5).tex(1, 1).endVertex(); + buffer.pos(-0.5, -0.5, -0.5).tex(0, 1).endVertex(); + + tessellator.draw(); + + buffer.begin(GL11.GL_QUADS, DefaultVertexFormats.POSITION_TEX); + + buffer.pos(-0.5, 0.5, -0.5).tex(0, 0).endVertex(); + buffer.pos(-0.5, -0.5, -0.5).tex(0, 1).endVertex(); + buffer.pos(0.5, -0.5, -0.5).tex(1, 1).endVertex(); + buffer.pos(0.5, 0.5, -0.5).tex(1, 0).endVertex(); + + tessellator.draw(); + + GlStateManager.enableLighting(); + GlStateManager.disableBlend(); + + GlStateManager.popMatrix(); + + } + } + +} diff --git a/src/main/java/electroblob/wizardry/client/renderer/RenderShield.java b/src/main/java/electroblob/wizardry/client/renderer/RenderShield.java new file mode 100644 index 00000000..6211d4f4 --- /dev/null +++ b/src/main/java/electroblob/wizardry/client/renderer/RenderShield.java @@ -0,0 +1,168 @@ +package electroblob.wizardry.client.renderer; + +import electroblob.wizardry.Wizardry; +import electroblob.wizardry.data.WizardData; +import electroblob.wizardry.registry.Spells; +import electroblob.wizardry.spell.Shield; +import electroblob.wizardry.util.WizardryUtilities; +import net.minecraft.client.Minecraft; +import net.minecraft.client.renderer.BufferBuilder; +import net.minecraft.client.renderer.GlStateManager; +import net.minecraft.client.renderer.OpenGlHelper; +import net.minecraft.client.renderer.Tessellator; +import net.minecraft.client.renderer.vertex.DefaultVertexFormats; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.util.ResourceLocation; +import net.minecraft.util.math.Vec3d; +import net.minecraftforge.client.event.RenderPlayerEvent; +import net.minecraftforge.client.event.RenderWorldLastEvent; +import net.minecraftforge.fml.common.Mod; +import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; +import net.minecraftforge.fml.relauncher.Side; +import org.lwjgl.opengl.GL11; + +@Mod.EventBusSubscriber(Side.CLIENT) +public class RenderShield { + + private static final ResourceLocation TEXTURE = new ResourceLocation(Wizardry.MODID, "textures/entity/shield.png"); + + // First person + @SubscribeEvent + public static void onRenderWorldLastEvent(RenderWorldLastEvent event){ + // Only render in first person + if(Minecraft.getMinecraft().gameSettings.thirdPersonView == 0){ + + EntityPlayer player = Minecraft.getMinecraft().player; + + if(WizardData.get(player).getVariable(Shield.SHIELD_KEY) != null && WizardryUtilities.isCasting(player, Spells.shield)){ + + GlStateManager.pushMatrix(); + + GlStateManager.disableCull(); + GlStateManager.enableBlend(); + GlStateManager.blendFunc(GL11.GL_ONE, GL11.GL_SRC_ALPHA); + GlStateManager.shadeModel(GL11.GL_SMOOTH); + GlStateManager.disableLighting(); + OpenGlHelper.setLightmapTextureCoords(OpenGlHelper.lightmapTexUnit, 240f, 240f); + + GlStateManager.translate(0, 1.4, 0); + + GlStateManager.rotate(-player.rotationYaw, 0, 1, 0); + GlStateManager.rotate(player.rotationPitch, 1, 0, 0); + + GlStateManager.translate(0, 0, 0.8); + + Tessellator tessellator = Tessellator.getInstance(); + + Minecraft.getMinecraft().renderEngine.bindTexture(TEXTURE); + + render(tessellator); + + GlStateManager.enableLighting(); + + GlStateManager.shadeModel(GL11.GL_FLAT); + GlStateManager.enableCull(); + GlStateManager.disableBlend(); + // RenderHelper.enableStandardItemLighting(); + + GlStateManager.popMatrix(); + } + } + } + + // Third person + @SubscribeEvent + public static void onRenderPlayerEvent(RenderPlayerEvent.Post event){ + + EntityPlayer player = event.getEntityPlayer(); + + if(WizardData.get(player).getVariable(Shield.SHIELD_KEY) != null && WizardryUtilities.isCasting(player, Spells.shield)){ + + GlStateManager.pushMatrix(); + + GlStateManager.disableCull(); + GlStateManager.enableBlend(); + // For some reason, the old blend function (GL11.GL_SRC_ALPHA, GL11.GL_SRC_ALPHA) caused the inner + // edges to appear black, so I have changed it to this, which looks very slightly different. + GlStateManager.blendFunc(GL11.GL_ONE, GL11.GL_SRC_ALPHA); + GlStateManager.shadeModel(GL11.GL_SMOOTH); + GlStateManager.disableLighting(); + OpenGlHelper.setLightmapTextureCoords(OpenGlHelper.lightmapTexUnit, 240f, 240f); + + Vec3d delta = player.getPositionEyes(event.getPartialRenderTick()) + .subtract(Minecraft.getMinecraft().player.getPositionEyes(event.getPartialRenderTick())); + GlStateManager.translate(delta.x, delta.y, delta.z); + + GlStateManager.translate(0, 1.3, 0); + + // GlStateManager.rotate(180, 0, 1, 0); + GlStateManager.rotate(-player.renderYawOffset, 0, 1, 0); + // GlStateManager.rotate(-player.rotationPitch, 1, 0, 0); + + GlStateManager.translate(0, 0, 0.8); + + Tessellator tessellator = Tessellator.getInstance(); + + Minecraft.getMinecraft().renderEngine.bindTexture(TEXTURE); + + render(tessellator); + + GlStateManager.enableLighting(); + + GlStateManager.shadeModel(GL11.GL_FLAT); + GlStateManager.enableCull(); + GlStateManager.disableBlend(); + // RenderHelper.enableStandardItemLighting(); + + GlStateManager.popMatrix(); + } + } + + private static void render(Tessellator tessellator){ + + BufferBuilder buffer = tessellator.getBuffer(); + + double widthOuter = 0.6d; + double heightOuter = 0.7d; + double widthInner = 0.3d; + double heightInner = 0.4d; + double depth = 0.2d; + + buffer.begin(GL11.GL_TRIANGLE_STRIP, DefaultVertexFormats.POSITION_TEX_COLOR); + + buffer.pos(-widthOuter, heightInner, -depth).tex(0, 0.2).color(0, 0, 0, 255).endVertex(); + buffer.pos(-widthInner, heightInner, 0).tex(0.2, 0.2).color(200, 200, 255, 255).endVertex(); + buffer.pos(-widthInner, heightOuter, -depth).tex(0.2, 0).color(0, 0, 0, 255).endVertex(); + buffer.pos(-widthInner, heightInner, 0).tex(0.2, 0.2).color(200, 200, 255, 255).endVertex(); + + buffer.pos(widthInner, heightOuter, -depth).tex(0.8, 0).color(0, 0, 0, 255).endVertex(); + buffer.pos(widthInner, heightInner, 0).tex(0.8, 0.2).color(200, 200, 255, 255).endVertex(); + buffer.pos(widthOuter, heightInner, -depth).tex(1, 0.2).color(0, 0, 0, 255).endVertex(); + buffer.pos(widthInner, heightInner, 0).tex(0.8, 0.2).color(200, 200, 255, 255).endVertex(); + + buffer.pos(widthOuter, -heightInner, -depth).tex(1, 0.8).color(0, 0, 0, 255).endVertex(); + buffer.pos(widthInner, -heightInner, 0).tex(0.8, 0.8).color(200, 200, 255, 255).endVertex(); + buffer.pos(widthInner, -heightOuter, -depth).tex(0.8, 1).color(0, 0, 0, 255).endVertex(); + buffer.pos(widthInner, -heightInner, 0).tex(0.8, 0.8).color(200, 200, 255, 255).endVertex(); + + buffer.pos(-widthInner, -heightOuter, -depth).tex(0.2, 1).color(0, 0, 0, 255).endVertex(); + buffer.pos(-widthInner, -heightInner, 0).tex(0.2, 0.8).color(200, 200, 255, 255).endVertex(); + buffer.pos(-widthOuter, -heightInner, -depth).tex(0, 0.8).color(0, 0, 0, 255).endVertex(); + buffer.pos(-widthInner, -heightInner, 0).tex(0.2, 0.8).color(200, 200, 255, 255).endVertex(); + + buffer.pos(-widthOuter, heightInner, -depth).tex(0, 0.2).color(0, 0, 0, 255).endVertex(); + buffer.pos(-widthInner, heightInner, 0).tex(0.2, 0.2).color(200, 200, 255, 255).endVertex(); + + tessellator.draw(); + + buffer.begin(GL11.GL_TRIANGLE_STRIP, DefaultVertexFormats.POSITION_TEX_COLOR); + + buffer.pos(-widthInner, heightInner, 0).tex(0.2, 0.2).color(200, 200, 255, 255).endVertex(); + buffer.pos(widthInner, heightInner, 0).tex(0.8, 0.2).color(200, 200, 255, 255).endVertex(); + buffer.pos(-widthInner, -heightInner, 0).tex(0.2, 0.8).color(200, 200, 255, 255).endVertex(); + buffer.pos(widthInner, -heightInner, 0).tex(0.8, 0.8).color(200, 200, 255, 255).endVertex(); + + tessellator.draw(); + } + +} diff --git a/src/main/java/electroblob/wizardry/client/renderer/RenderSigil.java b/src/main/java/electroblob/wizardry/client/renderer/RenderSigil.java index 739b44c1..5d43d31c 100644 --- a/src/main/java/electroblob/wizardry/client/renderer/RenderSigil.java +++ b/src/main/java/electroblob/wizardry/client/renderer/RenderSigil.java @@ -1,10 +1,8 @@ package electroblob.wizardry.client.renderer; -import org.lwjgl.opengl.GL11; - import electroblob.wizardry.entity.construct.EntityHealAura; import electroblob.wizardry.entity.construct.EntityMagicConstruct; -import electroblob.wizardry.util.WizardryUtilities; +import electroblob.wizardry.util.AllyDesignationSystem; import net.minecraft.client.Minecraft; import net.minecraft.client.renderer.BufferBuilder; import net.minecraft.client.renderer.GlStateManager; @@ -15,6 +13,7 @@ import net.minecraft.client.renderer.entity.RenderManager; import net.minecraft.client.renderer.vertex.DefaultVertexFormats; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.util.ResourceLocation; +import org.lwjgl.opengl.GL11; public class RenderSigil extends Render { @@ -34,8 +33,8 @@ public class RenderSigil extends Render { // Makes the sigil invisible to enemies of the player that created it if(this.invisibleToEnemies){ - - if(entity.getCaster() instanceof EntityPlayer && !WizardryUtilities + // Unfortunately we can't access the caster's allies if they're not online, it only works the other way round + if(entity.getCaster() instanceof EntityPlayer && !AllyDesignationSystem .isPlayerAlly((EntityPlayer)entity.getCaster(), Minecraft.getMinecraft().player)){ return; } diff --git a/src/main/java/electroblob/wizardry/client/renderer/RenderSpiritHorse.java b/src/main/java/electroblob/wizardry/client/renderer/RenderSpiritHorse.java index c3452e38..79cd0ab7 100644 --- a/src/main/java/electroblob/wizardry/client/renderer/RenderSpiritHorse.java +++ b/src/main/java/electroblob/wizardry/client/renderer/RenderSpiritHorse.java @@ -1,22 +1,23 @@ package electroblob.wizardry.client.renderer; -import org.lwjgl.opengl.GL11; - import electroblob.wizardry.Wizardry; +import electroblob.wizardry.entity.living.EntitySpiritHorse; import net.minecraft.client.renderer.GlStateManager; import net.minecraft.client.renderer.entity.RenderHorse; import net.minecraft.client.renderer.entity.RenderManager; import net.minecraft.entity.passive.EntityHorse; import net.minecraft.util.ResourceLocation; -import net.minecraftforge.fml.relauncher.Side; -import net.minecraftforge.fml.relauncher.SideOnly; +import org.lwjgl.opengl.GL11; -@SideOnly(Side.CLIENT) +//@SideOnly(Side.CLIENT) public class RenderSpiritHorse extends RenderHorse { private static final ResourceLocation texture = new ResourceLocation(Wizardry.MODID, "textures/entity/spirit_horse.png"); +// private static final int GHOST_COPIES = 3; +// private static final float DECONVERGENCE = 0.35f; + public RenderSpiritHorse(RenderManager renderManager){ super(renderManager); } @@ -27,10 +28,36 @@ public class RenderSpiritHorse extends RenderHorse { } @Override - protected void preRenderCallback(EntityHorse entitylivingbaseIn, float partialTickTime){ - super.preRenderCallback(entitylivingbaseIn, partialTickTime); + protected void preRenderCallback(EntityHorse horse, float partialTickTime){ + super.preRenderCallback(horse, partialTickTime); GlStateManager.enableBlend(); GlStateManager.blendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA); + if(horse instanceof EntitySpiritHorse){ // Always true + GlStateManager.color(1, 1, 1, ((EntitySpiritHorse)horse).getOpacity()); + } + } + + @Override + public void doRender(EntityHorse entity, double x, double y, double z, float entityYaw, float partialTicks){ + + super.doRender(entity, x, y, z, entityYaw, partialTicks); + +// double dx = (entity.posX - entity.prevPosX) * DECONVERGENCE; +// double dy = (entity.posY - entity.prevPosY) * DECONVERGENCE; +// double dz = (entity.posZ - entity.prevPosZ) * DECONVERGENCE; +// float dyaw = (entity.rotationYaw - entity.prevRotationYaw) * DECONVERGENCE; +// +// float opacity = 1; +// if(entity instanceof EntitySpiritHorse){ // Always true +// opacity = ((EntitySpiritHorse)entity).getOpacity(); +// } +// +// for(int i = 0; i < GHOST_COPIES; i++){ +// +// GlStateManager.color(1, 1, 1, opacity * (0.6f - (float)i/(GHOST_COPIES*2))); +// +// super.doRender(entity, x - dx * i, y - dy * i, z - dz * i, entityYaw - dyaw * i, partialTicks); +// } } } diff --git a/src/main/java/electroblob/wizardry/client/renderer/RenderSpiritWolf.java b/src/main/java/electroblob/wizardry/client/renderer/RenderSpiritWolf.java index a3f4fadc..0564f69b 100644 --- a/src/main/java/electroblob/wizardry/client/renderer/RenderSpiritWolf.java +++ b/src/main/java/electroblob/wizardry/client/renderer/RenderSpiritWolf.java @@ -1,22 +1,23 @@ package electroblob.wizardry.client.renderer; -import org.lwjgl.opengl.GL11; - import electroblob.wizardry.Wizardry; +import electroblob.wizardry.entity.living.EntitySpiritWolf; import net.minecraft.client.renderer.GlStateManager; import net.minecraft.client.renderer.entity.RenderManager; import net.minecraft.client.renderer.entity.RenderWolf; import net.minecraft.entity.passive.EntityWolf; import net.minecraft.util.ResourceLocation; -import net.minecraftforge.fml.relauncher.Side; -import net.minecraftforge.fml.relauncher.SideOnly; +import org.lwjgl.opengl.GL11; -@SideOnly(Side.CLIENT) +//@SideOnly(Side.CLIENT) public class RenderSpiritWolf extends RenderWolf { private static final ResourceLocation texture = new ResourceLocation(Wizardry.MODID, "textures/entity/spirit_wolf.png"); +// private static final int GHOST_COPIES = 3; +// private static final float DECONVERGENCE = 0.8f; + public RenderSpiritWolf(RenderManager renderManager){ super(renderManager); } @@ -31,5 +32,31 @@ public class RenderSpiritWolf extends RenderWolf { super.preRenderCallback(entity, partialTickTime); GlStateManager.enableBlend(); GlStateManager.blendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA); + if(entity instanceof EntitySpiritWolf){ // Always true + GlStateManager.color(1, 1, 1, ((EntitySpiritWolf)entity).getOpacity()); + } + } + + @Override + public void doRender(EntityWolf entity, double x, double y, double z, float entityYaw, float partialTicks){ + + super.doRender(entity, x, y, z, entityYaw, partialTicks); + +// double dx = (entity.posX - entity.prevPosX) * DECONVERGENCE; +// double dy = (entity.posY - entity.prevPosY) * DECONVERGENCE; +// double dz = (entity.posZ - entity.prevPosZ) * DECONVERGENCE; +// float dyaw = (entity.rotationYaw - entity.prevRotationYaw) * DECONVERGENCE; +// +// float opacity = 1; +// if(entity instanceof EntitySpiritWolf){ // Always true +// opacity = ((EntitySpiritWolf)entity).getOpacity(); +// } +// +// for(int i = 0; i < GHOST_COPIES; i++){ +// +// GlStateManager.color(1, 1, 1, opacity * (0.6f - (float)i/(GHOST_COPIES*2))); +// +// super.doRender(entity, x - dx * i, y - dy * i, z - dz * i, entityYaw - dyaw * i, partialTicks); +// } } } diff --git a/src/main/java/electroblob/wizardry/client/renderer/RenderStrayMinion.java b/src/main/java/electroblob/wizardry/client/renderer/RenderStrayMinion.java new file mode 100644 index 00000000..815d4979 --- /dev/null +++ b/src/main/java/electroblob/wizardry/client/renderer/RenderStrayMinion.java @@ -0,0 +1,24 @@ +package electroblob.wizardry.client.renderer; + +import net.minecraft.client.renderer.entity.RenderManager; +import net.minecraft.client.renderer.entity.RenderSkeleton; +import net.minecraft.entity.monster.AbstractSkeleton; +import net.minecraft.util.ResourceLocation; + +/** This class also had to be copied for the same reason as {@link LayerStrayMinionClothing}. */ +public class RenderStrayMinion extends RenderSkeleton { + + private static final ResourceLocation STRAY_SKELETON_TEXTURES = new ResourceLocation("textures/entity/skeleton/stray.png"); + + public RenderStrayMinion(RenderManager manager){ + super(manager); + this.addLayer(new LayerStrayMinionClothing(this)); // This is the only change + } + + /** + * Returns the location of an entity's texture. Doesn't seem to be called unless you call Render.bindEntityTexture. + */ + protected ResourceLocation getEntityTexture(AbstractSkeleton entity){ + return STRAY_SKELETON_TEXTURES; + } +} \ No newline at end of file diff --git a/src/main/java/electroblob/wizardry/client/renderer/RenderTransportationUI.java b/src/main/java/electroblob/wizardry/client/renderer/RenderTransportationUI.java new file mode 100644 index 00000000..599d168e --- /dev/null +++ b/src/main/java/electroblob/wizardry/client/renderer/RenderTransportationUI.java @@ -0,0 +1,177 @@ +package electroblob.wizardry.client.renderer; + +import electroblob.wizardry.Wizardry; +import electroblob.wizardry.data.WizardData; +import electroblob.wizardry.item.ISpellCastingItem; +import electroblob.wizardry.item.ItemArtefact; +import electroblob.wizardry.registry.Spells; +import electroblob.wizardry.registry.WizardryItems; +import electroblob.wizardry.spell.Transportation; +import electroblob.wizardry.util.Location; +import electroblob.wizardry.util.WizardryUtilities; +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.FontRenderer; +import net.minecraft.client.renderer.BufferBuilder; +import net.minecraft.client.renderer.GlStateManager; +import net.minecraft.client.renderer.OpenGlHelper; +import net.minecraft.client.renderer.Tessellator; +import net.minecraft.client.renderer.vertex.DefaultVertexFormats; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.item.ItemStack; +import net.minecraft.util.ResourceLocation; +import net.minecraft.util.math.Vec3d; +import net.minecraftforge.client.event.RenderWorldLastEvent; +import net.minecraftforge.fml.common.Mod; +import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; +import net.minecraftforge.fml.relauncher.Side; +import org.lwjgl.opengl.GL11; + +import java.util.List; + +@Mod.EventBusSubscriber(Side.CLIENT) +public class RenderTransportationUI { + + private static final ResourceLocation TEXTURE = new ResourceLocation(Wizardry.MODID, "textures/gui/transportation_marker.png"); + + // I can't get rid of the view bobbing with RenderWorldLastEvent, is there an alternative? + @SubscribeEvent + public static void onRenderWorldLastEvent(RenderWorldLastEvent event){ + + // Only render in first person + if(Minecraft.getMinecraft().gameSettings.thirdPersonView != 0) return; + + EntityPlayer player = Minecraft.getMinecraft().player; + + ItemStack stack = player.getHeldItemMainhand(); + if(!(stack.getItem() instanceof ISpellCastingItem)){ + stack = player.getHeldItemOffhand(); + if(!(stack.getItem() instanceof ISpellCastingItem)) return; + } + + if(((ISpellCastingItem)stack.getItem()).getCurrentSpell(stack) == Spells.transportation + && ItemArtefact.isArtefactActive(player, WizardryItems.charm_transportation)){ + + WizardData data = WizardData.get(player); + if(data == null) return; + + List locations = data.getVariable(Transportation.LOCATIONS_KEY); + + if(locations == null) return; + + GlStateManager.pushMatrix(); + + Vec3d origin = player.getPositionEyes(event.getPartialTicks()); + GlStateManager.translate(0, origin.y - Minecraft.getMinecraft().getRenderManager().viewerPosY, 0); + + Tessellator tessellator = Tessellator.getInstance(); + BufferBuilder buffer = tessellator.getBuffer(); + + Location target = Transportation.getLocationAimedAt(player, locations, event.getPartialTicks()); + + for(Location location : locations){ + + if(location.dimension != player.dimension) continue; + + GlStateManager.pushMatrix(); + GlStateManager.enableBlend(); + GlStateManager.disableLighting(); + GlStateManager.disableDepth(); + OpenGlHelper.setLightmapTextureCoords(OpenGlHelper.lightmapTexUnit, 240, 240); + GlStateManager.blendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA); + GlStateManager.color(1, 1, 1, 1); + + Minecraft.getMinecraft().renderEngine.bindTexture(TEXTURE); + + buffer.begin(GL11.GL_QUADS, DefaultVertexFormats.POSITION_TEX_COLOR); + + Vec3d position = WizardryUtilities.getCentre(location.pos).subtract(origin); + double distance = position.length(); + // The icon lines up perfectly if you render it at actual distance, otherwise view bobbing messes things up + // However, if that's outside the render distance it won't render at all! To fudge our way around this + // problem, we're capping the distance to just below the render distance and adjusting the scale accordingly + double distanceCap = Minecraft.getMinecraft().gameSettings.renderDistanceChunks * 16 - 8; + double displayDist = distance > distanceCap ? distanceCap : distance; + double factor = displayDist/distance; + + GlStateManager.translate(position.x * factor, position.y * factor, position.z * factor); + + GlStateManager.rotate(-Minecraft.getMinecraft().getRenderManager().playerViewY, 0.0F, 1.0F, 0.0F); + GlStateManager.rotate(Minecraft.getMinecraft().getRenderManager().playerViewX, 1.0F, 0.0F, 0.0F); + + // Get the angle between the player's look vector and the direction of the stone circle + double angle = Transportation.getLookDeviationAngle(player, location.pos, event.getPartialTicks()); + double iconSize = Transportation.getIconSize(distance); + + // Now apply a fancy formula to make it enlarge with a nice smooth animation: + double proximityFactor = Math.max(0, Math.pow(1 - angle/iconSize * angle/iconSize, 3)); + iconSize *= 1 + 0.3 * proximityFactor; + iconSize *= displayDist; // Adjust the icon size for perspective + + float f = location == target ? 1 : 0.5f; // Makes it obvious which one is being aimed at + + buffer.pos(-iconSize, iconSize, 0).tex(0, 0).color(f, 1, f, f).endVertex(); + buffer.pos(iconSize, iconSize, 0).tex(1, 0).color(f, 1, f, f).endVertex(); + buffer.pos(iconSize, -iconSize, 0).tex(1, 1).color(f, 1, f, f).endVertex(); + buffer.pos(-iconSize, -iconSize, 0).tex(0, 1).color(f, 1, f, f).endVertex(); + + tessellator.draw(); + + GlStateManager.popMatrix(); + + if(location == target){ + String label = location.pos.getX() + ", " + location.pos.getY() + ", " + location.pos.getZ(); + drawLabel(Minecraft.getMinecraft().fontRenderer, label, (float)(position.x * factor), + (float)(position.y * factor + iconSize*1.5f), (float)(position.z * factor), (float)displayDist * 0.2f, 0, + Minecraft.getMinecraft().getRenderManager().playerViewY, Minecraft.getMinecraft().getRenderManager().playerViewX); + } + } + + GlStateManager.disableBlend(); + GlStateManager.enableTexture2D(); + GlStateManager.enableLighting(); + GlStateManager.enableDepth(); + GlStateManager.disableRescaleNormal(); + GlStateManager.popMatrix(); + } + } + + // Copied from EntityRenderer#drawNameplate and tweaked a bit + private static void drawLabel(FontRenderer fontRendererIn, String str, float x, float y, float z, float scale, int verticalShift, float viewerYaw, float viewerPitch){ + + GlStateManager.pushMatrix(); + GlStateManager.translate(x, y, z); + GlStateManager.glNormal3f(0.0F, 1.0F, 0.0F); + GlStateManager.rotate(-viewerYaw, 0.0F, 1.0F, 0.0F); + GlStateManager.rotate(viewerPitch, 1.0F, 0.0F, 0.0F); + GlStateManager.scale(-0.025F, -0.025F, 0.025F); + GlStateManager.scale(scale, scale, scale); + GlStateManager.disableLighting(); + GlStateManager.depthMask(false); + + GlStateManager.disableDepth(); + + GlStateManager.enableBlend(); + GlStateManager.tryBlendFuncSeparate(GlStateManager.SourceFactor.SRC_ALPHA, GlStateManager.DestFactor.ONE_MINUS_SRC_ALPHA, GlStateManager.SourceFactor.ONE, GlStateManager.DestFactor.ZERO); + int i = fontRendererIn.getStringWidth(str) / 2; + GlStateManager.disableTexture2D(); + Tessellator tessellator = Tessellator.getInstance(); + BufferBuilder bufferbuilder = tessellator.getBuffer(); + bufferbuilder.begin(7, DefaultVertexFormats.POSITION_COLOR); + bufferbuilder.pos((double)(-i - 1), (double)(-1 + verticalShift), 0.0D).color(0.0F, 0.0F, 0.0F, 0.25F).endVertex(); + bufferbuilder.pos((double)(-i - 1), (double)(8 + verticalShift), 0.0D).color(0.0F, 0.0F, 0.0F, 0.25F).endVertex(); + bufferbuilder.pos((double)(i + 1), (double)(8 + verticalShift), 0.0D).color(0.0F, 0.0F, 0.0F, 0.25F).endVertex(); + bufferbuilder.pos((double)(i + 1), (double)(-1 + verticalShift), 0.0D).color(0.0F, 0.0F, 0.0F, 0.25F).endVertex(); + tessellator.draw(); + GlStateManager.enableTexture2D(); + + fontRendererIn.drawString(str, -fontRendererIn.getStringWidth(str) / 2, verticalShift, 0x86ff65); + GlStateManager.enableDepth(); + + GlStateManager.depthMask(true); + fontRendererIn.drawString(str, -fontRendererIn.getStringWidth(str) / 2, verticalShift, 0x86ff65); + GlStateManager.enableLighting(); + GlStateManager.disableBlend(); + GlStateManager.color(1.0F, 1.0F, 1.0F, 1.0F); + GlStateManager.popMatrix(); + } +} diff --git a/src/main/java/electroblob/wizardry/client/renderer/RenderWings.java b/src/main/java/electroblob/wizardry/client/renderer/RenderWings.java new file mode 100644 index 00000000..5701d736 --- /dev/null +++ b/src/main/java/electroblob/wizardry/client/renderer/RenderWings.java @@ -0,0 +1,113 @@ +package electroblob.wizardry.client.renderer; + +import electroblob.wizardry.Wizardry; +import electroblob.wizardry.registry.Spells; +import electroblob.wizardry.util.WizardryUtilities; +import net.minecraft.client.Minecraft; +import net.minecraft.client.renderer.BufferBuilder; +import net.minecraft.client.renderer.GlStateManager; +import net.minecraft.client.renderer.OpenGlHelper; +import net.minecraft.client.renderer.Tessellator; +import net.minecraft.client.renderer.vertex.DefaultVertexFormats; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.util.ResourceLocation; +import net.minecraft.util.math.MathHelper; +import net.minecraft.util.math.Vec3d; +import net.minecraftforge.client.event.RenderPlayerEvent; +import net.minecraftforge.fml.common.Mod; +import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; +import net.minecraftforge.fml.relauncher.Side; +import org.lwjgl.opengl.GL11; + +@Mod.EventBusSubscriber(Side.CLIENT) +public class RenderWings { + + private static final ResourceLocation TEXTURE = new ResourceLocation(Wizardry.MODID, "textures/entity/wing.png"); + + // No first person in here because you can never see the wings on your back! + + // Third person + @SubscribeEvent + public static void onRenderPlayerEvent(RenderPlayerEvent.Post event){ + + EntityPlayer player = event.getEntityPlayer(); + + if(WizardryUtilities.isCasting(player, Spells.flight)){ + + GlStateManager.pushMatrix(); + + GlStateManager.enableBlend(); + GlStateManager.blendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA); + GlStateManager.disableLighting(); + OpenGlHelper.setLightmapTextureCoords(OpenGlHelper.lightmapTexUnit, 240f, 240f); + + Vec3d delta = player.getPositionEyes(event.getPartialRenderTick()) + .subtract(Minecraft.getMinecraft().player.getPositionEyes(event.getPartialRenderTick())); + GlStateManager.translate(delta.x, delta.y, delta.z); + + // GlStateManager.rotate(-entityplayer.rotationYawHead, 0, 1, 0); + GlStateManager.rotate(-player.renderYawOffset, 0, 1, 0); + // GlStateManager.rotate(180, 1, 0, 0); + + Minecraft.getMinecraft().renderEngine.bindTexture(TEXTURE); + Tessellator tessellator = Tessellator.getInstance(); + BufferBuilder buffer = tessellator.getBuffer(); + + GlStateManager.pushMatrix(); + + GlStateManager.translate(0.1, 0.4, -0.15); + GlStateManager.rotate(20 + 20 * MathHelper.sin((player.ticksExisted + event.getPartialRenderTick()) * 0.3f), 0, 1, 0); + + buffer.begin(GL11.GL_QUADS, DefaultVertexFormats.POSITION_TEX); + + buffer.pos(0, 2, 0).tex(0, 0).endVertex(); + buffer.pos(2, 2, 0).tex(1, 0).endVertex(); + buffer.pos(2, 0, 0).tex(1, 1).endVertex(); + buffer.pos(0, 0, 0).tex(0, 1).endVertex(); + + tessellator.draw(); + + buffer.begin(GL11.GL_QUADS, DefaultVertexFormats.POSITION_TEX); + + buffer.pos(0, 2, 0).tex(0, 0).endVertex(); + buffer.pos(0, 0, 0).tex(0, 1).endVertex(); + buffer.pos(2, 0, 0).tex(1, 1).endVertex(); + buffer.pos(2, 2, 0).tex(1, 0).endVertex(); + + tessellator.draw(); + + GlStateManager.popMatrix(); + + GlStateManager.pushMatrix(); + + GlStateManager.translate(-0.1, 0.4, -0.15); + GlStateManager.rotate(-200 - 20 * MathHelper.sin((player.ticksExisted + event.getPartialRenderTick()) * 0.3f), 0, 1, 0); + + buffer.begin(GL11.GL_QUADS, DefaultVertexFormats.POSITION_TEX); + + buffer.pos(0, 2, 0).tex(0, 0).endVertex(); + buffer.pos(2, 2, 0).tex(1, 0).endVertex(); + buffer.pos(2, 0, 0).tex(1, 1).endVertex(); + buffer.pos(0, 0, 0).tex(0, 1).endVertex(); + + tessellator.draw(); + + buffer.begin(GL11.GL_QUADS, DefaultVertexFormats.POSITION_TEX); + + buffer.pos(0, 2, 0).tex(0, 0).endVertex(); + buffer.pos(0, 0, 0).tex(0, 1).endVertex(); + buffer.pos(2, 0, 0).tex(1, 1).endVertex(); + buffer.pos(2, 2, 0).tex(1, 0).endVertex(); + + tessellator.draw(); + + GlStateManager.popMatrix(); + + GlStateManager.enableLighting(); + GlStateManager.disableBlend(); + + GlStateManager.popMatrix(); + } + } + +} diff --git a/src/main/java/electroblob/wizardry/client/renderer/RenderWizard.java b/src/main/java/electroblob/wizardry/client/renderer/RenderWizard.java index baa322ee..566bc5a7 100644 --- a/src/main/java/electroblob/wizardry/client/renderer/RenderWizard.java +++ b/src/main/java/electroblob/wizardry/client/renderer/RenderWizard.java @@ -7,10 +7,8 @@ import net.minecraft.client.renderer.entity.RenderBiped; import net.minecraft.client.renderer.entity.RenderManager; import net.minecraft.client.renderer.entity.layers.LayerBipedArmor; import net.minecraft.util.ResourceLocation; -import net.minecraftforge.fml.relauncher.Side; -import net.minecraftforge.fml.relauncher.SideOnly; -@SideOnly(Side.CLIENT) +//@SideOnly(Side.CLIENT) public class RenderWizard extends RenderBiped { static final ResourceLocation[] textures = new ResourceLocation[6]; diff --git a/src/main/java/electroblob/wizardry/client/renderer/RenderWraithMinion.java b/src/main/java/electroblob/wizardry/client/renderer/RenderWraithMinion.java index da691189..d8cfe382 100644 --- a/src/main/java/electroblob/wizardry/client/renderer/RenderWraithMinion.java +++ b/src/main/java/electroblob/wizardry/client/renderer/RenderWraithMinion.java @@ -5,10 +5,8 @@ import net.minecraft.client.model.ModelBlaze; import net.minecraft.client.renderer.entity.RenderLiving; import net.minecraft.client.renderer.entity.RenderManager; import net.minecraft.util.ResourceLocation; -import net.minecraftforge.fml.relauncher.Side; -import net.minecraftforge.fml.relauncher.SideOnly; -@SideOnly(Side.CLIENT) +//@SideOnly(Side.CLIENT) public class RenderWraithMinion extends RenderLiving { private ResourceLocation texture = new ResourceLocation("textures/entity/blaze.png"); diff --git a/src/main/java/electroblob/wizardry/command/CommandCastSpell.java b/src/main/java/electroblob/wizardry/command/CommandCastSpell.java index 7dbbde14..c71e9e29 100644 --- a/src/main/java/electroblob/wizardry/command/CommandCastSpell.java +++ b/src/main/java/electroblob/wizardry/command/CommandCastSpell.java @@ -1,36 +1,41 @@ package electroblob.wizardry.command; -import java.util.List; - -import electroblob.wizardry.WizardData; import electroblob.wizardry.Wizardry; +import electroblob.wizardry.data.WizardData; import electroblob.wizardry.event.SpellCastEvent; import electroblob.wizardry.event.SpellCastEvent.Source; import electroblob.wizardry.packet.PacketCastSpell; +import electroblob.wizardry.packet.PacketCastSpellAtPos; import electroblob.wizardry.packet.WizardryPacketHandler; import electroblob.wizardry.spell.Spell; import electroblob.wizardry.util.SpellModifiers; -import net.minecraft.command.CommandBase; -import net.minecraft.command.CommandException; -import net.minecraft.command.ICommandSender; -import net.minecraft.command.NumberInvalidException; -import net.minecraft.command.PlayerNotFoundException; -import net.minecraft.command.WrongUsageException; -import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.command.*; import net.minecraft.entity.player.EntityPlayerMP; import net.minecraft.nbt.JsonToNBT; import net.minecraft.nbt.NBTException; import net.minecraft.server.MinecraftServer; +import net.minecraft.util.EnumFacing; import net.minecraft.util.EnumHand; import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.Vec3d; import net.minecraft.util.text.ITextComponent; import net.minecraft.util.text.TextComponentTranslation; import net.minecraft.util.text.TextFormatting; +import net.minecraft.world.World; import net.minecraftforge.common.MinecraftForge; import net.minecraftforge.fml.common.network.simpleimpl.IMessage; +import java.util.List; + public class CommandCastSpell extends CommandBase { + /** The default number of ticks for which /cast will cast a continuous spell, if duration is not specified. */ + public static final int DEFAULT_CASTING_DURATION = 100; + /** The minimum number of seconds for which /cast may cast a continuous spell. */ + public static final int MIN_CASTING_DURATION = 0; + /** The maximum number of seconds for which /cast may cast a continuous spell. */ + public static final int MAX_CASTING_DURATION = 1000000; + @Override public String getName(){ return Wizardry.settings.castCommandName; @@ -74,6 +79,8 @@ public class CommandCastSpell extends CommandBase { int i = 0; EntityPlayerMP caster = null; + Vec3d origin = null; + EnumFacing direction = null; try{ caster = getCommandSenderAsPlayer(sender); @@ -85,12 +92,24 @@ public class CommandCastSpell extends CommandBase { Spell spell = Spell.get(arguments[i++]); if(spell == null){ - throw new NumberInvalidException("commands." + Wizardry.MODID + ":cast.not_found", new Object[]{arguments[i - 1]}); + throw new NumberInvalidException("commands." + Wizardry.MODID + ":cast.not_found", arguments[i - 1]); } boolean castAsOtherPlayer = false; - if(i < arguments.length){ + if(i + 3 < arguments.length){ + + Vec3d vec3d = sender.getPositionVector(); + CoordinateArg x = parseCoordinate(vec3d.x, arguments[i++], true); + CoordinateArg y = parseCoordinate(vec3d.y, arguments[i++], 0, 256, false); + CoordinateArg z = parseCoordinate(vec3d.z, arguments[i++], true); + + origin = new Vec3d(x.getResult(), y.getResult(), z.getResult()); + + direction = EnumFacing.byName(arguments[i++]); + if(direction == null) throw new NumberInvalidException("commands." + Wizardry.MODID + ":cast.invalid_direction", arguments[i - 1]); + + }else if(i < arguments.length){ try{ // If the second argument is a player and is not the player that gave the command, the spell is cast // as the given player rather than the command sender, and there is a different chat readout. @@ -107,8 +126,31 @@ public class CommandCastSpell extends CommandBase { // If, after this point, the player is still null, the sender must be a command block or the console and the // player must not have been specified, meaning an exception should be thrown. - if(caster == null) - throw new PlayerNotFoundException("You must specify which player you wish to perform this action on."); + if(caster == null && origin == null) + throw new PlayerNotFoundException("commands." + Wizardry.MODID + ":cast.origin_not_specified"); + + int duration = DEFAULT_CASTING_DURATION; + int seconds = duration/20; + + if(spell.isContinuous){ + + if(i >= arguments.length) throw new CommandException("commands." + Wizardry.MODID + ":cast.duration_not_specified"); + + try{ + seconds = parseInt(arguments[i++]); + }catch(NumberInvalidException e){ + // If no duration was found, assume it was unspecified + i--; + } + + if(seconds < MIN_CASTING_DURATION){ + throw new NumberInvalidException("commands.generic.num.tooSmall", seconds, MIN_CASTING_DURATION); + }else if(seconds > MAX_CASTING_DURATION){ + throw new NumberInvalidException("commands.generic.num.tooBig", seconds, MAX_CASTING_DURATION); + } + + duration = seconds * 20; + } SpellModifiers modifiers = new SpellModifiers(); @@ -136,64 +178,124 @@ public class CommandCastSpell extends CommandBase { // ===== Spell casting ===== - // If anything stops the spell working at this point, nothing else happens. - if(MinecraftForge.EVENT_BUS.post(new SpellCastEvent.Pre(caster, spell, modifiers, Source.COMMAND))){ - displayFailMessage(sender, spell); - return; - } + if(origin != null){ // Positional - WizardData data = WizardData.get((EntityPlayer)caster); + World world = sender.getEntityWorld(); - if(spell.isContinuous){ + // If anything stops the spell working at this point, nothing else happens. + if(MinecraftForge.EVENT_BUS.post(new SpellCastEvent.Pre(Source.COMMAND, spell, world, + origin.x, origin.y, origin.z, direction, modifiers))){ + if(server.sendCommandFeedback()) displayFailMessage(sender, spell); + return; + } - // Events for continuous spell casting via commands are dealt with in WizardData. + if(spell.isContinuous){ - if(data != null){ - if(data.isCasting()){ - data.stopCastingContinuousSpell(); - }else{ + if(spell.cast(world, origin.x, origin.y, origin.z, direction, 0, duration, modifiers)){ - data.startCastingContinuousSpell(spell, modifiers); + MinecraftForge.EVENT_BUS.post(new SpellCastEvent.Post(Source.COMMAND, spell, world, origin.x, origin.y, origin.z, direction, modifiers)); - if(castAsOtherPlayer){ - sender.sendMessage( - new TextComponentTranslation("commands." + Wizardry.MODID + ":cast.success_remote_continuous", - spell.getNameForTranslationFormatted(), caster.getName())); - }else{ - sender.sendMessage(new TextComponentTranslation("commands." + Wizardry.MODID + ":cast.success_continuous", - spell.getNameForTranslationFormatted())); + SpellEmitter.add(spell, world, origin.x, origin.y, origin.z, direction, duration, modifiers); + IMessage msg = new PacketCastSpellAtPos.Message(origin, direction, spell, modifiers, duration); + WizardryPacketHandler.net.sendToDimension(msg, world.provider.getDimension()); + + if(server.sendCommandFeedback()){ + sender.sendMessage(new TextComponentTranslation("commands." + Wizardry.MODID + ":cast.success_position_continuous", + spell.getNameForTranslationFormatted(), origin.x, origin.y, origin.z, seconds)); } + + return; } + }else{ + + if(spell.cast(world, origin.x, origin.y, origin.z, direction, 0, -1, modifiers)){ + + MinecraftForge.EVENT_BUS.post(new SpellCastEvent.Post(Source.COMMAND, spell, world, origin.x, origin.y, origin.z, direction, modifiers)); + + if(spell.requiresPacket()){ + // Sends a packet to all players in dimension to tell them to spawn particles. + // Only sent if the spell succeeded, because if the spell failed, you wouldn't + // need to spawn any particles! + IMessage msg = new PacketCastSpellAtPos.Message(origin, direction, spell, modifiers); + WizardryPacketHandler.net.sendToDimension(msg, world.provider.getDimension()); + } + + if(server.sendCommandFeedback()){ + sender.sendMessage(new TextComponentTranslation("commands." + Wizardry.MODID + ":cast.success_position", + spell.getNameForTranslationFormatted(), origin.x, origin.y, origin.z)); + } + + return; + } + } + + }else{ // Player-based + + // If anything stops the spell working at this point, nothing else happens. + if(MinecraftForge.EVENT_BUS.post(new SpellCastEvent.Pre(Source.COMMAND, spell, caster, modifiers))){ + if(server.sendCommandFeedback()) displayFailMessage(sender, spell); return; } - }else{ + if(spell.isContinuous){ - if(spell.cast(caster.world, caster, EnumHand.MAIN_HAND, 0, modifiers)){ + WizardData data = WizardData.get(caster); - MinecraftForge.EVENT_BUS.post(new SpellCastEvent.Post(caster, spell, modifiers, Source.COMMAND)); + // Events/packets for continuous spell casting via commands are dealt with in WizardData. - if(spell.doesSpellRequirePacket()){ - // Sends a packet to all players in dimension to tell them to spawn particles. - // Only sent if the spell succeeded, because if the spell failed, you wouldn't - // need to spawn any particles! - IMessage msg = new PacketCastSpell.Message(caster.getEntityId(), null, spell.id(), modifiers); - WizardryPacketHandler.net.sendToDimension(msg, caster.world.provider.getDimension()); + if(data != null){ + if(data.isCasting()){ + data.stopCastingContinuousSpell(); // TODO: Where should this go now? + }else{ + + data.startCastingContinuousSpell(spell, modifiers, duration); + + if(server.sendCommandFeedback()){ + if(castAsOtherPlayer){ + sender.sendMessage( + new TextComponentTranslation("commands." + Wizardry.MODID + ":cast.success_remote_continuous", + spell.getNameForTranslationFormatted(), caster.getName(), seconds)); + }else{ + sender.sendMessage(new TextComponentTranslation("commands." + Wizardry.MODID + ":cast.success_continuous", + spell.getNameForTranslationFormatted(), seconds)); + } + } + } + + return; } - if(castAsOtherPlayer){ - sender.sendMessage(new TextComponentTranslation("commands." + Wizardry.MODID + ":cast.success_remote", - spell.getNameForTranslationFormatted(), caster.getName())); - }else{ - sender.sendMessage(new TextComponentTranslation("commands." + Wizardry.MODID + ":cast.success", - spell.getNameForTranslationFormatted())); + }else{ + + if(spell.cast(caster.world, caster, EnumHand.MAIN_HAND, 0, modifiers)){ + + MinecraftForge.EVENT_BUS.post(new SpellCastEvent.Post(Source.COMMAND, spell, caster, modifiers)); + + if(spell.requiresPacket()){ + // Sends a packet to all players in dimension to tell them to spawn particles. + // Only sent if the spell succeeded, because if the spell failed, you wouldn't + // need to spawn any particles! + IMessage msg = new PacketCastSpell.Message(caster.getEntityId(), null, spell, modifiers); + WizardryPacketHandler.net.sendToDimension(msg, caster.world.provider.getDimension()); + } + + if(server.sendCommandFeedback()){ + if(castAsOtherPlayer){ + sender.sendMessage(new TextComponentTranslation("commands." + Wizardry.MODID + ":cast.success_remote", + spell.getNameForTranslationFormatted(), caster.getName())); + }else{ + sender.sendMessage(new TextComponentTranslation("commands." + Wizardry.MODID + ":cast.success", + spell.getNameForTranslationFormatted())); + } + } + + return; } - return; } } - displayFailMessage(sender, spell); + if(server.sendCommandFeedback()) displayFailMessage(sender, spell); } } diff --git a/src/main/java/electroblob/wizardry/command/CommandDiscoverSpell.java b/src/main/java/electroblob/wizardry/command/CommandDiscoverSpell.java index d97e6470..84733924 100644 --- a/src/main/java/electroblob/wizardry/command/CommandDiscoverSpell.java +++ b/src/main/java/electroblob/wizardry/command/CommandDiscoverSpell.java @@ -1,24 +1,19 @@ package electroblob.wizardry.command; -import java.util.List; - -import electroblob.wizardry.WizardData; import electroblob.wizardry.Wizardry; +import electroblob.wizardry.data.WizardData; import electroblob.wizardry.event.DiscoverSpellEvent; import electroblob.wizardry.registry.Spells; import electroblob.wizardry.spell.Spell; -import net.minecraft.command.CommandBase; -import net.minecraft.command.CommandException; -import net.minecraft.command.ICommandSender; -import net.minecraft.command.NumberInvalidException; -import net.minecraft.command.PlayerNotFoundException; -import net.minecraft.command.WrongUsageException; +import net.minecraft.command.*; import net.minecraft.entity.player.EntityPlayerMP; import net.minecraft.server.MinecraftServer; import net.minecraft.util.math.BlockPos; import net.minecraft.util.text.TextComponentTranslation; import net.minecraftforge.common.MinecraftForge; +import java.util.List; + public class CommandDiscoverSpell extends CommandBase { @Override @@ -92,7 +87,7 @@ public class CommandDiscoverSpell extends CommandBase { if(spell == null){ throw new NumberInvalidException("commands." + Wizardry.MODID + ":discoverspell.not_found", - new Object[]{arguments[i - 1]}); + arguments[i - 1]); } } @@ -110,32 +105,32 @@ public class CommandDiscoverSpell extends CommandBase { if(player == null) throw new PlayerNotFoundException("You must specify which player you wish to perform this action on."); - WizardData properties = WizardData.get(player); + WizardData data = WizardData.get(player); - if(properties != null){ + if(data != null){ if(clear){ - properties.spellsDiscovered.clear(); - sender.sendMessage( + data.spellsDiscovered.clear(); + if(server.sendCommandFeedback()) sender.sendMessage( new TextComponentTranslation("commands." + Wizardry.MODID + ":discoverspell.clear", player.getName())); }else if(all){ - properties.spellsDiscovered.addAll(Spell.getSpells(Spell.allSpells)); - sender.sendMessage( + data.spellsDiscovered.addAll(Spell.getSpells(Spell.allSpells)); + if(server.sendCommandFeedback()) sender.sendMessage( new TextComponentTranslation("commands." + Wizardry.MODID + ":discoverspell.all", player.getName())); }else{ - if(properties.hasSpellBeenDiscovered(spell)){ - properties.spellsDiscovered.remove(spell); - sender.sendMessage(new TextComponentTranslation("commands." + Wizardry.MODID + ":discoverspell.removespell", + if(data.hasSpellBeenDiscovered(spell)){ + data.spellsDiscovered.remove(spell); + if(server.sendCommandFeedback()) sender.sendMessage(new TextComponentTranslation("commands." + Wizardry.MODID + ":discoverspell.removespell", spell.getNameForTranslationFormatted(), player.getName())); }else{ if(!MinecraftForge.EVENT_BUS .post(new DiscoverSpellEvent(player, spell, DiscoverSpellEvent.Source.COMMAND))){ - properties.discoverSpell(spell); - sender.sendMessage(new TextComponentTranslation("commands." + Wizardry.MODID + ":discoverspell.addspell", + data.discoverSpell(spell); + if(server.sendCommandFeedback()) sender.sendMessage(new TextComponentTranslation("commands." + Wizardry.MODID + ":discoverspell.addspell", spell.getNameForTranslationFormatted(), player.getName())); } } } - properties.sync(); + data.sync(); } } } diff --git a/src/main/java/electroblob/wizardry/command/CommandSetAlly.java b/src/main/java/electroblob/wizardry/command/CommandSetAlly.java index 2ca42dfa..2ffcc375 100644 --- a/src/main/java/electroblob/wizardry/command/CommandSetAlly.java +++ b/src/main/java/electroblob/wizardry/command/CommandSetAlly.java @@ -1,16 +1,9 @@ package electroblob.wizardry.command; -import java.util.List; - -import electroblob.wizardry.WizardData; import electroblob.wizardry.Wizardry; +import electroblob.wizardry.data.WizardData; import electroblob.wizardry.util.WizardryUtilities; -import net.minecraft.command.CommandBase; -import net.minecraft.command.CommandException; -import net.minecraft.command.ICommandSender; -import net.minecraft.command.NumberInvalidException; -import net.minecraft.command.PlayerNotFoundException; -import net.minecraft.command.WrongUsageException; +import net.minecraft.command.*; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.entity.player.EntityPlayerMP; import net.minecraft.server.MinecraftServer; @@ -18,6 +11,8 @@ import net.minecraft.util.math.BlockPos; import net.minecraft.util.text.TextComponentTranslation; import net.minecraft.util.text.TextFormatting; +import java.util.List; + public class CommandSetAlly extends CommandBase { @Override @@ -85,10 +80,12 @@ public class CommandSetAlly extends CommandBase { if(allyOf != sender && sender instanceof EntityPlayer && !WizardryUtilities.isPlayerOp((EntityPlayer)sender, server)){ // Displays a chat message if a non-op tries to modify another player's allies. - TextComponentTranslation TextComponentTranslation2 = new TextComponentTranslation( - "commands." + Wizardry.MODID + ":ally.permission"); - TextComponentTranslation2.getStyle().setColor(TextFormatting.RED); - allyOf.sendMessage(TextComponentTranslation2); + if(server.sendCommandFeedback()){ + TextComponentTranslation TextComponentTranslation2 = new TextComponentTranslation( + "commands." + Wizardry.MODID + ":ally.permission"); + TextComponentTranslation2.getStyle().setColor(TextFormatting.RED); + allyOf.sendMessage(TextComponentTranslation2); + } return; } @@ -102,15 +99,17 @@ public class CommandSetAlly extends CommandBase { if(allyOf == ally) throw new NumberInvalidException("commands." + Wizardry.MODID + ":ally.self"); - if(WizardData.get(allyOf) != null){ - String string = WizardData.get(allyOf).toggleAlly(ally) ? "add" : "remove"; - if(executeAsOtherPlayer){ - sender.sendMessage(new TextComponentTranslation("commands." + Wizardry.MODID + ":ally." + string + "ally", - ally.getName(), allyOf.getName())); - // In this case, the player whose allies have been modified is also notified. - allyOf.sendMessage(new TextComponentTranslation("item.wand." + string + "ally", ally.getName())); - }else{ - sender.sendMessage(new TextComponentTranslation("item.wand." + string + "ally", ally.getName())); + if(server.sendCommandFeedback()){ + if(WizardData.get(allyOf) != null){ + String string = WizardData.get(allyOf).toggleAlly(ally) ? "add" : "remove"; + if(executeAsOtherPlayer){ + sender.sendMessage(new TextComponentTranslation("commands." + Wizardry.MODID + ":ally." + string + "ally", + ally.getName(), allyOf.getName())); + // In this case, the player whose allies have been modified is also notified. + allyOf.sendMessage(new TextComponentTranslation("item.wand." + string + "ally", ally.getName())); + }else{ + sender.sendMessage(new TextComponentTranslation("item.wand." + string + "ally", ally.getName())); + } } } diff --git a/src/main/java/electroblob/wizardry/command/CommandViewAllies.java b/src/main/java/electroblob/wizardry/command/CommandViewAllies.java index 3bb82a2b..dde5e46d 100644 --- a/src/main/java/electroblob/wizardry/command/CommandViewAllies.java +++ b/src/main/java/electroblob/wizardry/command/CommandViewAllies.java @@ -1,12 +1,8 @@ package electroblob.wizardry.command; -import java.util.List; -import java.util.Set; - -import electroblob.wizardry.WizardData; import electroblob.wizardry.Wizardry; +import electroblob.wizardry.data.WizardData; import electroblob.wizardry.util.WizardryUtilities; -import net.minecraft.client.resources.I18n; import net.minecraft.command.CommandBase; import net.minecraft.command.CommandException; import net.minecraft.command.ICommandSender; @@ -18,6 +14,9 @@ import net.minecraft.util.math.BlockPos; import net.minecraft.util.text.TextComponentTranslation; import net.minecraft.util.text.TextFormatting; +import java.util.List; +import java.util.Set; + public class CommandViewAllies extends CommandBase { @Override @@ -75,10 +74,12 @@ public class CommandViewAllies extends CommandBase { if(player != sender && sender instanceof EntityPlayer && !WizardryUtilities.isPlayerOp((EntityPlayer)sender, server)){ // Displays a chat message if a non-op tries to view another player's allies. - TextComponentTranslation TextComponentTranslation2 = new TextComponentTranslation( - "commands." + Wizardry.MODID + ":allies.permission"); - TextComponentTranslation2.getStyle().setColor(TextFormatting.RED); - player.sendMessage(TextComponentTranslation2); + if(server.sendCommandFeedback()){ + TextComponentTranslation TextComponentTranslation2 = new TextComponentTranslation( + "commands." + Wizardry.MODID + ":allies.permission"); + TextComponentTranslation2.getStyle().setColor(TextFormatting.RED); + player.sendMessage(TextComponentTranslation2); + } return; } @@ -101,6 +102,7 @@ public class CommandViewAllies extends CommandBase { playerList = new TextComponentTranslation("commands." + Wizardry.MODID + ":allies.none"); } + // Ignore sendCommandFeedback here since that's the entire point of this command if(executeAsOtherPlayer){ sender.sendMessage( new TextComponentTranslation("commands." + Wizardry.MODID + ":allies.list_other", player.getName(), playerList)); diff --git a/src/main/java/electroblob/wizardry/command/SpellEmitter.java b/src/main/java/electroblob/wizardry/command/SpellEmitter.java new file mode 100644 index 00000000..7a09e6b0 --- /dev/null +++ b/src/main/java/electroblob/wizardry/command/SpellEmitter.java @@ -0,0 +1,177 @@ +package electroblob.wizardry.command; + +import electroblob.wizardry.Wizardry; +import electroblob.wizardry.data.SpellEmitterData; +import electroblob.wizardry.event.SpellCastEvent; +import electroblob.wizardry.spell.Spell; +import electroblob.wizardry.util.SpellModifiers; +import io.netty.buffer.ByteBuf; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.util.EnumFacing; +import net.minecraft.util.ITickable; +import net.minecraft.world.World; +import net.minecraftforge.common.MinecraftForge; + +/** + * A {@code SpellEmitter} represents a continuous spell being cast from a position via commands. + * + * @since Wizardry 4.2 + * @author Electroblob + */ +public class SpellEmitter implements ITickable { + + protected final Spell spell; + protected World world; + protected final double x, y, z; + protected final EnumFacing direction; + protected final int duration; + protected final SpellModifiers modifiers; + + protected int castingTick = 0; + protected boolean needsRemoving = false; + + protected SpellEmitter(Spell spell, World world, double x, double y, double z, EnumFacing direction, int duration, SpellModifiers modifiers){ + this.spell = spell; + this.world = world; + this.duration = duration; + this.x = x; + this.y = y; + this.z = z; + this.direction = direction; + this.modifiers = modifiers; + } + + /** Marks this spell emitter to be removed next tick. */ + protected void markForRemoval(){ + this.needsRemoving = true; + } + + /** Returns whether this spell emitter is marked for removal. */ + public boolean needsRemoving(){ + return needsRemoving; + } + + /** Returns the {@link SpellCastEvent.Source} that should be used for events fired by this spell emitter. */ + protected SpellCastEvent.Source getSource(){ + return SpellCastEvent.Source.COMMAND; + } + + /** Sets this spell emitter's world. This should only be used on the client side when the world has not yet been + * set, otherwise the world will not be changed and a warning will be printed to the console. */ + public void setWorld(World world){ + if(world.isRemote && this.world == null){ + this.world = world; + }else{ + Wizardry.logger.warn("Tried to change the world for a spell emitter, this shouldn't happen!"); + } + } + + @Override + public void update(){ + + if(castingTick < duration){ + + if(!MinecraftForge.EVENT_BUS.post(new SpellCastEvent.Tick(getSource(), spell, world, x, y, z, direction, modifiers, castingTick))){ + + if(spell.cast(world, x, y, z, direction, castingTick, duration, modifiers)){ + if(castingTick == 0) MinecraftForge.EVENT_BUS.post(new SpellCastEvent.Post(getSource(), spell, world, x, y, z, direction, modifiers)); + castingTick++; + return; + } + } + } + // If the time ran out or the spell failed, interrupt spell casting + MinecraftForge.EVENT_BUS.post(new SpellCastEvent.Finish(getSource(), spell, world, x, y, z, direction, modifiers, castingTick)); + spell.finishCasting(world, null, x, y, z, direction, duration, modifiers); + markForRemoval(); + } + + /** Writes this {@code SpellEmitter} to the given ByteBuf. */ + public void write(ByteBuf buf){ + buf.writeInt(spell.networkID()); + buf.writeDouble(x); + buf.writeDouble(y); + buf.writeDouble(z); + buf.writeInt(direction.getIndex()); + // This is sent through as the duration, meaning castingTick always starts at zero client-side, which is + // important for sounds to work correctly. As a consequence, the client's castingTick will be different to the + // server value if the player changes dimension or re-logs. However, since this is pretty uncommon anyway I + // think it's an ok compromise. + buf.writeInt(duration - castingTick); + modifiers.write(buf); + } + + /** Reads a {@code SpellEmitter} from the given ByteBuf and returns it. */ + public static SpellEmitter read(ByteBuf buf){ + + Spell spell = Spell.byNetworkID(buf.readInt()); + double x = buf.readDouble(); + double y = buf.readDouble(); + double z = buf.readDouble(); + EnumFacing direction = EnumFacing.byIndex(buf.readInt()); + int duration = buf.readInt(); + SpellModifiers modifiers = new SpellModifiers(); + modifiers.read(buf); + + return new SpellEmitter(spell, null, x, y, z, direction, duration, modifiers); + } + + // INBTSerializable is annoying, it doesn't allow you to have final fields + + /** Returns a new {@link NBTTagCompound} representing this {@code SpellEmitter}. */ + public NBTTagCompound toNBT(){ + + NBTTagCompound nbt = new NBTTagCompound(); + + nbt.setInteger("spell", spell.metadata()); + nbt.setDouble("x", x); + nbt.setDouble("y", y); + nbt.setDouble("z", z); + nbt.setInteger("direction", direction.getIndex()); + nbt.setInteger("duration", duration); + nbt.setTag("modifiers", modifiers.toNBT()); + nbt.setInteger("castingTick", castingTick); + + return nbt; + } + + /** Creates a new {@code SpellEmitter} from the given {@link NBTTagCompound} and returns it. */ + public static SpellEmitter fromNBT(World world, NBTTagCompound nbt){ + + Spell spell = Spell.byMetadata(nbt.getInteger("spell")); + double x = nbt.getDouble("x"); + double y = nbt.getDouble("y"); + double z = nbt.getDouble("z"); + EnumFacing direction = EnumFacing.byIndex(nbt.getInteger("direction")); + int duration = nbt.getInteger("duration"); + SpellModifiers modifiers = SpellModifiers.fromNBT(nbt.getCompoundTag("modifiers")); + int castingTick = nbt.getInteger("castingTick"); + + SpellEmitter emitter = new SpellEmitter(spell, world, x, y, z, direction, duration, modifiers); + emitter.castingTick = castingTick; + return emitter; + } + + /** + * Creates a new {@code SpellEmitter} and adds it to the list of active emitters in {@link SpellEmitterData}. + * This method does not perform any syncing. + * + * @param spell The spell to be cast + * @param world The world in which to cast the spell + * @param x The x-coordinate of the spell origin + * @param y The y-coordinate of the spell origin + * @param z The z-coordinate of the spell origin + * @param direction The direction to cast the spell in + * @param duration The number of ticks to cast the spell for + * @param modifiers The {@link SpellModifiers} for the spell + */ + public static void add(Spell spell, World world, double x, double y, double z, EnumFacing direction, int duration, SpellModifiers modifiers){ + if(spell.isContinuous){ + if(duration <= 0) Wizardry.logger.warn("Adding a spell emitter with negative or zero duration!"); + SpellEmitterData.get(world).add(new SpellEmitter(spell, world, x, y, z, direction, duration, modifiers)); + }else{ + Wizardry.logger.warn("Tried to add a non-continuous spell emitter for spell {}", spell.getRegistryName()); + } + } + +} diff --git a/src/main/java/electroblob/wizardry/constants/Constants.java b/src/main/java/electroblob/wizardry/constants/Constants.java index 28bba9a9..0316b4e3 100644 --- a/src/main/java/electroblob/wizardry/constants/Constants.java +++ b/src/main/java/electroblob/wizardry/constants/Constants.java @@ -5,23 +5,25 @@ import electroblob.wizardry.WizardryEventHandler; /** Stores various global constants used in Wizardry. */ public final class Constants { + /** The amount of mana a crystal shard is worth */ + // 100 doesn't divide nicely by 9 so we're calling this 10. I guess you lose a little bit by smashing a crystal. + public static final int MANA_PER_SHARD = 10; /** The amount of mana each magic crystal is worth */ public static final int MANA_PER_CRYSTAL = 100; - /** The amount of mana each mana flask can hold */ - public static final int MANA_PER_FLASK = 700; + /** The amount of mana a grand magic crystal is worth */ + public static final int GRAND_CRYSTAL_MANA = 400; /** The maximum number of one type of wand upgrade which can be applied to a wand. */ public static final int UPGRADE_STACK_LIMIT = 3; /** The fraction by which cooldowns are reduced for each level of cooldown upgrade. */ public static final float COOLDOWN_REDUCTION_PER_LEVEL = 0.15f; /** The fraction by which maximum charge is increased for each level of storage upgrade. */ public static final float STORAGE_INCREASE_PER_LEVEL = 0.15f; - /** The fraction by which damage is increased for each tier of matching wand. */ - public static final float DAMAGE_INCREASE_PER_TIER = 0.15f; - /** - * The fraction by which costs are reduced for each piece of matching armour. Note that changing this value will not - * affect continuous spells, since they are handled differently. - */ - public static final float COST_REDUCTION_PER_ARMOUR = 0.2f; + /** The fraction by which potency is increased for each tier of matching wand. */ + public static final float POTENCY_INCREASE_PER_TIER = 0.15f; + /** The fraction by which costs are reduced for each piece of matching armour. */ + public static final float COST_REDUCTION_PER_ARMOUR = 0.15f; + /** The extra fraction by which costs are reduced for a full set of elemental armour. */ + public static final float FULL_ARMOUR_SET_BONUS = 0.2f; /** The fraction by which spell duration is increased for each level of duration upgrade. */ public static final float DURATION_INCREASE_PER_LEVEL = 0.25f; /** The fraction by which spell range is increased for each level of range upgrade. */ @@ -32,7 +34,7 @@ public final class Constants { public static final double FROST_SLOWNESS_PER_LEVEL = 0.5; /** The fraction by which movement speed is reduced per level of decay effect. */ public static final double DECAY_SLOWNESS_PER_LEVEL = 0.2; - /** The fraction by which dig speed is reduced per level of frost effect. */ + /** The fraction by which dig speed is reduced per level of frostbite effect. */ public static final float FROST_FATIGUE_PER_LEVEL = 0.45f; /** The number of ticks between each mana increase for wands with the condenser upgrade. */ public static final int CONDENSER_TICK_INTERVAL = 50; @@ -40,11 +42,13 @@ public final class Constants { * The amount of mana given for a kill for each level of siphon upgrade. A random amount from 0 to this number - 1 * is also added. See {@link WizardryEventHandler#onLivingDeathEvent} for more details. */ - public static final int SIPHON_MANA_PER_LEVEL = 3; + public static final int SIPHON_MANA_PER_LEVEL = 5; /** * The number of ticks between the spawning of patches of decay when an entity has the decay effect. Note that decay * won't spawn again if something is already standing in it. */ public static final int DECAY_SPREAD_INTERVAL = 8; + /** The fraction by which potency is increased per level of the empowerment effect. */ + public static final float EMPOWERMENT_POTENCY_PER_LEVEL = 0.25f; } diff --git a/src/main/java/electroblob/wizardry/constants/Element.java b/src/main/java/electroblob/wizardry/constants/Element.java index dd357774..7b433693 100644 --- a/src/main/java/electroblob/wizardry/constants/Element.java +++ b/src/main/java/electroblob/wizardry/constants/Element.java @@ -1,7 +1,7 @@ package electroblob.wizardry.constants; import electroblob.wizardry.Wizardry; -import net.minecraft.client.resources.I18n; +import net.minecraft.util.IStringSerializable; import net.minecraft.util.ResourceLocation; import net.minecraft.util.text.ITextComponent; import net.minecraft.util.text.Style; @@ -10,19 +10,18 @@ import net.minecraft.util.text.TextFormatting; import net.minecraftforge.fml.relauncher.Side; import net.minecraftforge.fml.relauncher.SideOnly; -public enum Element { +public enum Element implements IStringSerializable { - /** - * The 'default' element, with {@link electroblob.wizardry.spell.MagicMissile MagicMissile} being its only spell. - */ - MAGIC(new Style().setColor(TextFormatting.GRAY), "simple", Wizardry.MODID), - FIRE(new Style().setColor(TextFormatting.DARK_RED), "fire", Wizardry.MODID), - ICE(new Style().setColor(TextFormatting.AQUA), "ice", Wizardry.MODID), - LIGHTNING(new Style().setColor(TextFormatting.DARK_AQUA), "lightning", Wizardry.MODID), - NECROMANCY(new Style().setColor(TextFormatting.DARK_PURPLE), "necromancy", Wizardry.MODID), - EARTH(new Style().setColor(TextFormatting.DARK_GREEN), "earth", Wizardry.MODID), - SORCERY(new Style().setColor(TextFormatting.GREEN), "sorcery", Wizardry.MODID), - HEALING(new Style().setColor(TextFormatting.YELLOW), "healing", Wizardry.MODID); + /** The 'default' element, with {@link electroblob.wizardry.registry.Spells#magic_missile magic missile} being its + * only spell. */ + MAGIC(new Style().setColor(TextFormatting.GRAY), "magic"), + FIRE(new Style().setColor(TextFormatting.DARK_RED), "fire"), + ICE(new Style().setColor(TextFormatting.AQUA), "ice"), + LIGHTNING(new Style().setColor(TextFormatting.DARK_AQUA), "lightning"), + NECROMANCY(new Style().setColor(TextFormatting.DARK_PURPLE), "necromancy"), + EARTH(new Style().setColor(TextFormatting.DARK_GREEN), "earth"), + SORCERY(new Style().setColor(TextFormatting.GREEN), "sorcery"), + HEALING(new Style().setColor(TextFormatting.YELLOW), "healing"); /** Display colour for this element */ private final Style colour; @@ -31,16 +30,31 @@ public enum Element { /** The {@link ResourceLocation} for this element's 8x8 icon (displayed in the arcane workbench GUI) */ private final ResourceLocation icon; - private Element(Style colour, String name, String modid){ + Element(Style colour, String name){ + this(colour, name, Wizardry.MODID); + } + + Element(Style colour, String name, String modid){ this.colour = colour; this.unlocalisedName = name; this.icon = new ResourceLocation(modid, "textures/gui/element_icon_" + unlocalisedName + ".png"); } + /** Returns the element with the given name, or throws an {@link java.lang.IllegalArgumentException} if no such + * element exists. */ + public static Element fromName(String name){ + + for(Element element : values()){ + if(element.unlocalisedName.equals(name)) return element; + } + + throw new IllegalArgumentException("No such element with unlocalised name: " + name); + } + /** Returns the translated display name of this element, without formatting. */ @SideOnly(Side.CLIENT) public String getDisplayName(){ - return I18n.format("element." + getUnlocalisedName()); + return net.minecraft.client.resources.I18n.format("element." + getName()); } /** Returns the {@link Style} object representing the colour of this element. */ @@ -55,11 +69,12 @@ public enum Element { /** Returns the translated display name for wizards of this element, shown in the trading GUI. */ public ITextComponent getWizardName(){ - return new TextComponentTranslation("element." + getUnlocalisedName() + ".wizard"); + return new TextComponentTranslation("element." + getName() + ".wizard"); } - /** Returns this element's unlocalised name. */ - public String getUnlocalisedName(){ + /** Returns this element's unlocalised name. Also used as the serialised string in block properties. */ + @Override + public String getName(){ return unlocalisedName; } diff --git a/src/main/java/electroblob/wizardry/constants/SpellType.java b/src/main/java/electroblob/wizardry/constants/SpellType.java index e1791940..afefec7f 100644 --- a/src/main/java/electroblob/wizardry/constants/SpellType.java +++ b/src/main/java/electroblob/wizardry/constants/SpellType.java @@ -1,6 +1,5 @@ package electroblob.wizardry.constants; -import net.minecraft.client.resources.I18n; import net.minecraftforge.fml.relauncher.Side; import net.minecraftforge.fml.relauncher.SideOnly; @@ -21,8 +20,23 @@ public enum SpellType { this.unlocalisedName = name; } + /** Returns the spell type with the given name, or throws an {@link java.lang.IllegalArgumentException} if no such + * spell type exists. */ + public static SpellType fromName(String name){ + + for(SpellType type : values()){ + if(type.unlocalisedName.equals(name)) return type; + } + + throw new IllegalArgumentException("No such spell type with unlocalised name: " + name); + } + + public String getUnlocalisedName(){ + return unlocalisedName; + } + @SideOnly(Side.CLIENT) public String getDisplayName(){ - return I18n.format("spelltype." + unlocalisedName); + return net.minecraft.client.resources.I18n.format("spelltype." + unlocalisedName); } } \ No newline at end of file diff --git a/src/main/java/electroblob/wizardry/constants/Tier.java b/src/main/java/electroblob/wizardry/constants/Tier.java index 2cadd2a0..5cf6bdd0 100644 --- a/src/main/java/electroblob/wizardry/constants/Tier.java +++ b/src/main/java/electroblob/wizardry/constants/Tier.java @@ -1,19 +1,20 @@ package electroblob.wizardry.constants; -import java.util.Random; - -import net.minecraft.client.resources.I18n; +import net.minecraft.util.text.ITextComponent; import net.minecraft.util.text.Style; +import net.minecraft.util.text.TextComponentTranslation; import net.minecraft.util.text.TextFormatting; import net.minecraftforge.fml.relauncher.Side; import net.minecraftforge.fml.relauncher.SideOnly; +import java.util.Random; + public enum Tier { - BASIC(700, 3, 12, new Style().setColor(TextFormatting.WHITE), "basic"), - APPRENTICE(1000, 5, 5, new Style().setColor(TextFormatting.AQUA), "apprentice"), - ADVANCED(1500, 7, 2, new Style().setColor(TextFormatting.DARK_BLUE), "advanced"), - MASTER(2500, 9, 1, new Style().setColor(TextFormatting.DARK_PURPLE), "master"); + NOVICE(700, 3, 12, 0, new Style().setColor(TextFormatting.WHITE), "novice"), + APPRENTICE(1000, 5, 5, 6000, new Style().setColor(TextFormatting.AQUA), "apprentice"), + ADVANCED(1500, 7, 2, 9000, new Style().setColor(TextFormatting.DARK_BLUE), "advanced"), + MASTER(2500, 9, 1, 15000, new Style().setColor(TextFormatting.DARK_PURPLE), "master"); /** Maximum mana a wand of this tier can store. */ public final int maxCharge; @@ -23,29 +24,59 @@ public enum Tier { public final int upgradeLimit; /** The weight given to this tier in the standard weighting. */ public final int weight; + /** The progression required for a wand to be upgraded to this tier. */ + public final int progression; /** The colour of text associated with this tier. */ // Changed to a Style object for consistency. private final Style colour; private final String unlocalisedName; - private Tier(int maxCharge, int upgradeLimit, int weight, Style colour, String name){ + Tier(int maxCharge, int upgradeLimit, int weight, int progression, Style colour, String name){ this.maxCharge = maxCharge; this.level = ordinal(); this.upgradeLimit = upgradeLimit; this.weight = weight; + this.progression = progression; this.colour = colour; this.unlocalisedName = name; } + /** Returns the tier with the given name, or throws an {@link java.lang.IllegalArgumentException} if no such + * tier exists. */ + public static Tier fromName(String name){ + + for(Tier tier : values()){ + if(tier.unlocalisedName.equals(name)) return tier; + } + + throw new IllegalArgumentException("No such tier with unlocalised name: " + name); + } + @SideOnly(Side.CLIENT) public String getDisplayName(){ - return I18n.format("tier." + unlocalisedName); + return net.minecraft.client.resources.I18n.format("tier." + unlocalisedName); + } + + /** + * Returns a {@code TextComponentTranslation} which will be translated to the display name of the tier, without + * formatting (i.e. not coloured). + */ + public TextComponentTranslation getNameForTranslation(){ + return new TextComponentTranslation("tier." + unlocalisedName); } @SideOnly(Side.CLIENT) public String getDisplayNameWithFormatting(){ - return this.getFormattingCode() + I18n.format("tier." + unlocalisedName); + return this.getFormattingCode() + net.minecraft.client.resources.I18n.format("tier." + unlocalisedName); + } + + /** + * Returns a {@code TextComponentTranslation} which will be translated to the display name of the tier, with + * formatting (i.e. coloured). + */ + public ITextComponent getNameForTranslationFormatted(){ + return new TextComponentTranslation("tier." + unlocalisedName).setStyle(this.colour); } public String getUnlocalisedName(){ diff --git a/src/main/java/electroblob/wizardry/data/BlockCastingData.java b/src/main/java/electroblob/wizardry/data/BlockCastingData.java new file mode 100644 index 00000000..a02d2de7 --- /dev/null +++ b/src/main/java/electroblob/wizardry/data/BlockCastingData.java @@ -0,0 +1,183 @@ +package electroblob.wizardry.data; + +import electroblob.wizardry.Wizardry; +import electroblob.wizardry.event.SpellCastEvent; +import electroblob.wizardry.packet.PacketDispenserCastSpell; +import electroblob.wizardry.packet.WizardryPacketHandler; +import electroblob.wizardry.registry.Spells; +import electroblob.wizardry.spell.None; +import electroblob.wizardry.spell.Spell; +import electroblob.wizardry.util.SpellModifiers; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.tileentity.TileEntity; +import net.minecraft.util.EnumFacing; +import net.minecraftforge.common.MinecraftForge; +import net.minecraftforge.common.util.INBTSerializable; +import net.minecraftforge.fml.common.network.simpleimpl.IMessage; + +/** + * Base class for {@link DispenserCastingData}. Originally this was written because command blocks had a similar system, + * but that was later removed in favour of spell emitters - however, this class has been kept so that others can use it + * for different spellcasting blocks if they wish. + * + * @since Wizardry 4.2 + * @author Electroblob + */ +public abstract class BlockCastingData implements INBTSerializable { + + /** The tile entity this BlockCastingData instance belongs to. */ + protected final T tileEntity; + + /** The continuous spell this tile entity is currently casting, or the {@link None} spell if it is not casting. */ + protected Spell spell; + /** The coordinates of the current continuous spell's origin. */ + protected double x, y, z; + /** The time for which this tile entity has been casting a continuous spell. Increments by 1 each tick. */ + protected int castingTick; + /** SpellModifiers object for the current continuous spell. */ + protected SpellModifiers modifiers; + + public BlockCastingData(T tileEntity){ + this.tileEntity = tileEntity; + this.spell = Spells.none; + this.modifiers = new SpellModifiers(); + this.castingTick = 0; + } + + /** Returns whether this tile entity is currently casting a continuous spell. */ + public boolean isCasting(){ + return this.spell != null && this.spell != Spells.none; + } + + /** Returns the continuous spell this tile entity is currently casting, or the {@link None} spell if it isn't + * casting anything. */ + public Spell currentlyCasting(){ + return spell; + } + + /** Starts casting the given continuous spell from this tile entity. */ + protected void startCasting(Spell spell, double x, double y, double z, SpellModifiers modifiers){ + + if(!spell.isContinuous){ + Wizardry.logger.warn("Tried to start casting a continuous spell from a tile entity, but the given spell was not continuous!"); + return; + } + + this.spell = spell; + this.x = x; + this.y = y; + this.z = z; + this.castingTick = 0; + this.modifiers = modifiers; + } + + /** Stops casting the current spell. */ + protected void stopCasting(){ + this.spell = Spells.none; + this.castingTick = 0; + this.modifiers.reset(); + } + + /** Stops casting the current spell and sends a packet to clients to update them. If called client-side, this just + * delegates to {@link BlockCastingData#stopCasting()}. */ + protected void stopCastingAndNotify(){ + + stopCasting(); + + if(!tileEntity.getWorld().isRemote){ + IMessage msg = new PacketDispenserCastSpell.Message(x, y, z, getDirection(), tileEntity.getPos(), spell, 0, modifiers); + WizardryPacketHandler.net.sendToDimension(msg, tileEntity.getWorld().provider.getDimension()); + } + } + + /** Called once per tick to update the block casting data. This is not called automatically, subclasses must + * do so using their own tick event handlers. */ + protected void update(){ + + if(this.tileEntity.isInvalid()){ + return; + } + + if(this.isCasting() && this.spell.isContinuous){ + + // If the dispenser has stopped receiving power, the spell stops immediately. + if(!shouldContinueCasting()){ + this.stopCasting(); // This seems to work fine on both sides, so no point sending a packet + return; + } + + EnumFacing direction = getDirection(); + + if(MinecraftForge.EVENT_BUS.post(new SpellCastEvent.Tick(getSource(), spell, tileEntity.getWorld(), + x, y, z, direction, modifiers, castingTick))){ + // When the event is canceled client-side, this will stop the spell on the client only, as specified in + // the javadoc for SpellCastEvent.Tick. + this.stopCastingAndNotify(); + return; + } + + this.spell.cast(tileEntity.getWorld(), x, y, z, direction, castingTick, -1, modifiers); + + castingTick++; + + }else{ + this.castingTick = 0; + } + } + + /** Returns the direction to cast the current spell in. */ + protected abstract EnumFacing getDirection(); + + /** Returns the source of spells cast from this block. */ + protected abstract SpellCastEvent.Source getSource(); + + /** Called each tick during continuous spell casting to determine if the spell should continue or stop. */ + protected abstract boolean shouldContinueCasting(); + + @Override + public NBTTagCompound serializeNBT(){ + + NBTTagCompound nbt = new NBTTagCompound(); + + nbt.setInteger("spell", spell.metadata()); + nbt.setInteger("castingTick", castingTick); + nbt.setTag("modifiers", modifiers.toNBT()); + + return nbt; + } + + @Override + public void deserializeNBT(NBTTagCompound nbt){ + + if(nbt != null){ + + this.spell = Spell.byMetadata(nbt.getInteger("spell")); + this.castingTick = nbt.getInteger("castingTick"); + this.modifiers = SpellModifiers.fromNBT(nbt.getCompoundTag("modifiers")); + } + } + + // The two methods below broke EVERYTHING, somehow they made the server think it was the client... + +// // Only fired server-side +// @SubscribeEvent +// public static void onWorldTickEvent(TickEvent.WorldTickEvent event){ +// +// if(!event.world.isRemote && event.phase == TickEvent.Phase.END){ +// // This will fire once for each dimension, but since we want dispenser-casting to work in all dimensions, +// // this is correct (the loaded tile entity list will of course be different in each case. +// this.update(); +// } +// } +// +// // Only called client-side +// @SubscribeEvent +// public static void onClientTickEvent(TickEvent.ClientTickEvent event){ +// World world = net.minecraft.client.Minecraft.getMinecraft().world; +// if(event.phase == TickEvent.Phase.END && !net.minecraft.client.Minecraft.getMinecraft().isGamePaused() +// && world != null){ +// this.update(); +// } +// } + +} diff --git a/src/main/java/electroblob/wizardry/data/DispenserCastingData.java b/src/main/java/electroblob/wizardry/data/DispenserCastingData.java new file mode 100644 index 00000000..28d0fe56 --- /dev/null +++ b/src/main/java/electroblob/wizardry/data/DispenserCastingData.java @@ -0,0 +1,219 @@ +package electroblob.wizardry.data; + +import electroblob.wizardry.Wizardry; +import electroblob.wizardry.event.SpellCastEvent.Source; +import electroblob.wizardry.item.ItemScroll; +import electroblob.wizardry.registry.Spells; +import electroblob.wizardry.spell.Spell; +import electroblob.wizardry.util.SpellModifiers; +import net.minecraft.block.BlockDispenser; +import net.minecraft.item.ItemStack; +import net.minecraft.nbt.NBTBase; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.tileentity.TileEntity; +import net.minecraft.tileentity.TileEntityDispenser; +import net.minecraft.util.EnumFacing; +import net.minecraft.util.ResourceLocation; +import net.minecraftforge.common.capabilities.Capability; +import net.minecraftforge.common.capabilities.Capability.IStorage; +import net.minecraftforge.common.capabilities.CapabilityInject; +import net.minecraftforge.common.capabilities.CapabilityManager; +import net.minecraftforge.common.capabilities.ICapabilitySerializable; +import net.minecraftforge.event.AttachCapabilitiesEvent; +import net.minecraftforge.fml.common.Mod; +import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; +import net.minecraftforge.fml.common.gameevent.TickEvent; + +import java.util.ArrayList; +import java.util.List; + +/** + * Internal capability for attaching data to dispensers. The sole purpose of this class is to keep track of continuous + * spell casting for dispensers. + *

    + * Forge seems to have separate classes to hold the Capability<...> instance ('key') and methods for getting the + * capability, but in my opinion there are already too many classes to deal with, so I'm not adding any more than are + * necessary, meaning those constants and values are kept here instead. + * + * @since Wizardry 4.2 + * @author Electroblob + */ +@Mod.EventBusSubscriber +public class DispenserCastingData extends BlockCastingData { + + /** Static instance of what I like to refer to as the capability key. Private because, well, it's internal! */ + // This annotation does some crazy Forge magic behind the scenes and assigns this field a value. + @CapabilityInject(DispenserCastingData.class) + private static final Capability DISPENSER_CASTING_CAPABILITY = null; + + /** The time for which this dispenser will continue casting a continuous spell. When castingTick exceeds this value, + * the dispenser will either stop casting or, if it contains more of the same type of scroll, continue casting and + * increase this value by the duration that the spell should be cast for. */ + private int duration; + + public DispenserCastingData(){ + this(null); // Nullary constructor for the registration method factory parameter + } + + public DispenserCastingData(TileEntityDispenser dispenser){ + super(dispenser); + } + + /** Starts casting the given continuous spell from this dispenser. */ + public void startCasting(Spell spell, double x, double y, double z, int duration, SpellModifiers modifiers){ + startCasting(spell, x, y, z, modifiers); + this.castingTick = 1; // 1 because we already cast it once in BehaviourSpellDispense + this.duration = duration; + } + + @Override + public void stopCasting(){ + super.stopCasting(); + } + + @Override + protected Source getSource(){ + return Source.DISPENSER; + } + + @Override + protected EnumFacing getDirection(){ + return tileEntity.getWorld().getBlockState(tileEntity.getPos()).getValue(BlockDispenser.FACING); + } + + @Override + protected boolean shouldContinueCasting(){ + return tileEntity.getWorld().isBlockPowered(tileEntity.getPos()); + } + + @Override + public void update(){ + + super.update(); + + // Check whether enough scrolls are left + if(this.isCasting() && this.spell.isContinuous){ + + if(castingTick > duration && !tileEntity.getWorld().isRemote){ + + if(findNewScroll()){ + duration += ItemScroll.CASTING_TIME; // Best way to do it for now. + }else{ + this.stopCastingAndNotify(); + } + } + } + } + + /** Searches through the dispenser's inventory for a new stack of scrolls of the same spell that is currently being + * cast and returns true if at least one such stack is found. Also consumes one scroll if a stack is found; if more + * than one applicable stack is found then one will be chosen at random. */ + private boolean findNewScroll(){ + + if(spell == Spells.none) return false; + + List slots = new ArrayList(); + + for(int i = 0; i < tileEntity.getSizeInventory(); i++){ + ItemStack stack = tileEntity.getStackInSlot(i); + if(stack.getItem() instanceof ItemScroll && stack.getMetadata() == spell.metadata()) slots.add(i); + } + + if(slots.isEmpty()) return false; // If no stack was found that matched the current spell + + tileEntity.decrStackSize(slots.get(tileEntity.getWorld().rand.nextInt(slots.size())), 1); // Consumes 1 scroll + return true; + } + + /** Returns the DispenserCastingData instance for the specified dispenser. */ + public static DispenserCastingData get(TileEntityDispenser dispenser){ + return dispenser.getCapability(DISPENSER_CASTING_CAPABILITY, null); + } + + /** Called from preInit in the main mod class to register the DispenserCastingData capability. */ + public static void register(){ + + CapabilityManager.INSTANCE.register(DispenserCastingData.class, new IStorage(){ + + @Override + public NBTBase writeNBT(Capability capability, DispenserCastingData instance, EnumFacing side){ + return null; + } + + @Override + public void readNBT(Capability capability, DispenserCastingData instance, EnumFacing side, NBTBase nbt){} + + }, DispenserCastingData::new); + } + + // Event handlers + + @SubscribeEvent + // The type parameter here has to be SoundLoopSpellDispenser, not TileEntityDispenser, or the event won't get fired. + public static void onCapabilityLoad(AttachCapabilitiesEvent event){ + + if(event.getObject() instanceof TileEntityDispenser) + event.addCapability(new ResourceLocation(Wizardry.MODID, "casting_data"), + new DispenserCastingData.Provider((TileEntityDispenser)event.getObject())); + } + + // Only fired server-side + @SubscribeEvent + public static void onWorldTickEvent(TickEvent.WorldTickEvent event){ + + if(event.phase == TickEvent.Phase.END){ + + // This will fire once for each dimension, but since we want dispenser-casting to work in all dimensions, + // this is correct (the loaded tile entity list will of course be different in each case. + + for(TileEntity tileentity : event.world.loadedTileEntityList){ + if(tileentity instanceof TileEntityDispenser){ + if(DispenserCastingData.get((TileEntityDispenser)tileentity) != null){ + DispenserCastingData.get((TileEntityDispenser)tileentity).update(); + } + } + } + } + } + + /** + * This is a nested class for a few reasons: firstly, it makes sense because instances of this and + * DispenserCastingData go hand-in-hand; secondly, it's too short to be worth a separate file; and thirdly (and most + * importantly) it allows me to access DISPENSER_CASTING_CAPABILITY while keeping it private. + */ + public static class Provider implements ICapabilitySerializable { + + private final DispenserCastingData data; + + public Provider(TileEntityDispenser dispenser){ + data = new DispenserCastingData(dispenser); + } + + @Override + public boolean hasCapability(Capability capability, EnumFacing facing){ + return capability == DISPENSER_CASTING_CAPABILITY; + } + + @Override + public T getCapability(Capability capability, EnumFacing facing){ + + if(capability == DISPENSER_CASTING_CAPABILITY){ + return DISPENSER_CASTING_CAPABILITY.cast(data); + } + + return null; + } + + @Override + public NBTTagCompound serializeNBT(){ + return data.serializeNBT(); + } + + @Override + public void deserializeNBT(NBTTagCompound nbt){ + data.deserializeNBT(nbt); + } + + } + +} diff --git a/src/main/java/electroblob/wizardry/data/IStoredVariable.java b/src/main/java/electroblob/wizardry/data/IStoredVariable.java new file mode 100644 index 00000000..f6594f57 --- /dev/null +++ b/src/main/java/electroblob/wizardry/data/IStoredVariable.java @@ -0,0 +1,256 @@ +package electroblob.wizardry.data; + +import io.netty.buffer.ByteBuf; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.item.ItemStack; +import net.minecraft.nbt.*; +import net.minecraft.util.math.BlockPos; +import net.minecraftforge.fml.common.network.ByteBufUtils; + +import java.util.UUID; +import java.util.function.BiFunction; +import java.util.function.Function; + +/** + * Extension of {@link IVariable} which adds NBT read/write methods. Instances of this interface must be + * registered on load using {@link WizardData#registerStoredVariables(IStoredVariable...)} in order for NBT storage + * to work. A good place to do this is in spell constructors, if that's where the variable is being used. + *

    + * This interface is provided for complex cases that require custom NBT handling of some kind. In most cases, + * {@link StoredVariable} should be sufficient. + *

    + * @param The type of variable stored. + */ +public interface IStoredVariable extends IVariable { + + /** Writes the value to the given NBT tag. */ + void write(NBTTagCompound nbt, T value); + + /** Reads the value from the given NBT tag. */ + T read(NBTTagCompound nbt); + + /** + * General-purpose implementation of {@link IStoredVariable}. In most cases, this should be sufficient. This class + * also contains a number of static methods for common implementations (primitives, {@code String}, {@code UUID}, + * {@code BlockPos} and {@code ItemStack}). + *

    + * @param The type of variable stored. + * @param The type of NBT tag the variable will be stored as. + */ + class StoredVariable implements IStoredVariable { + + private final String key; + private final Persistence persistence; + + private final Function serialiser; + private final Function deserialiser; + + private boolean synced; + + private BiFunction ticker; + + /** + * Creates a new {@code StoredVariable} with the given key and serialisation behaviour. + * @param key The string key used to write the value to NBT (should be unique). This serves no other purpose. + * @param serialiser A function used to write the value to NBT. + * @param deserialiser A function used to read the value from NBT. + */ + public StoredVariable(String key, Function serialiser, Function deserialiser, Persistence persistence){ + this.key = key; + this.serialiser = serialiser; + this.deserialiser = deserialiser; + this.persistence = persistence; + this.ticker = (p, t) -> t; // Initialise this with a do-nothing function, can be overwritten later + } + + /** + * Replaces this variable's update method with the given update function. Beware of auto-unboxing of + * primitive types! For lambda expressions, check the second parameter isn't null before operating on it. + * For method references, do not reference a method that takes a primitive type. Otherwise, this will cause + * a (difficult to debug) {@link NullPointerException} if the key was not stored. + * @param ticker A {@link BiFunction} specifying the actions to be performed on this variable each tick. The + * {@code BiFunction} returns the new value for this variable. + * @return This {@code StoredVariable} object, allowing this method to be chained onto object creation. + */ + public StoredVariable withTicker(BiFunction ticker){ + this.ticker = ticker; + return this; + } + + /** + * Adds synchronisation to this variable, meaning it will be sent to clients whenever {@link WizardData#sync()} + * is called (this always happens on player login, but other than that you'll need to do it yourself). + * @return This {@code StoredVariable} object, allowing this method to be chained onto object creation. + */ + public StoredVariable setSynced(){ + this.synced = true; + return this; + } + + @Override + public void write(NBTTagCompound nbt, T value){ + if(value != null) nbt.setTag(key, serialiser.apply(value)); + } + + @Override + @SuppressWarnings("unchecked") // Can't check it due to type erasure + public T read(NBTTagCompound nbt){ + // A system allowing any kind of variable to be stored on the fly cannot be made without casting somewhere. + // However, doing it like this means we only cast once, below, and proper regulation of access means we + // can effectively guarantee the cast is safe. + return nbt.hasKey(key) ? deserialiser.apply((E)nbt.getTag(key)) : null; // Still gotta check it ain't null + } + + @Override + public T update(EntityPlayer player, T value){ + return ticker.apply(player, value); + } + + @Override + public boolean isPersistent(boolean respawn){ + return respawn ? persistence.persistsOnRespawn() : persistence.persistsOnDimensionChange(); + } + + @Override + public boolean isSynced(){ + return synced; + } + + @Override + public void write(ByteBuf buf, T value){ + if(!synced) return; + NBTTagCompound nbt = new NBTTagCompound(); + write(nbt, value); + ByteBufUtils.writeTag(buf, nbt); // Sure, it's not super-efficient, but it's by far the simplest way! + } + + @Override + public T read(ByteBuf buf){ + if(!synced) return null; // Better to check in here because this method should only read if it needs to + NBTTagCompound nbt = ByteBufUtils.readTag(buf); + if(nbt == null) return null; + return read(nbt); + } + + // Standard implementations to shorten common usages a bit + + /** Creates a new {@code StoredVariable} for a byte value with the given key. */ + public static StoredVariable ofByte(String key, Persistence persistence){ + return new StoredVariable<>(key, NBTTagByte::new, NBTTagByte::getByte, persistence); + } + + /** Creates a new {@code StoredVariable} for a boolean value with the given key. As per Minecraft's usual + * NBT conventions, the boolean value is stored as an {@link NBTTagByte} (1 = true, 0 = false). */ + public static StoredVariable ofBoolean(String key, Persistence persistence){ + return new StoredVariable<>(key, b -> new NBTTagByte((byte)(b?1:0)), t -> t.getByte() == 1, persistence); + } + + /** Creates a new {@code StoredVariable} for an integer value with the given key. */ + public static StoredVariable ofInt(String key, Persistence persistence){ + return new StoredVariable<>(key, NBTTagInt::new, NBTTagInt::getInt, persistence); + } + + // I'm not going to do byte and long arrays here, if you really need them it's pretty obvious how to do it + + /** Creates a new {@code StoredVariable} for an integer array value with the given key. */ + public static StoredVariable ofIntArray(String key, Persistence persistence){ + return new StoredVariable<>(key, NBTTagIntArray::new, NBTTagIntArray::getIntArray, persistence); + } + + /** Creates a new {@code StoredVariable} for a float value with the given key. */ + public static StoredVariable ofFloat(String key, Persistence persistence){ + return new StoredVariable<>(key, NBTTagFloat::new, NBTTagFloat::getFloat, persistence); + } + + /** Creates a new {@code StoredVariable} for a double value with the given key. */ + public static StoredVariable ofDouble(String key, Persistence persistence){ + return new StoredVariable<>(key, NBTTagDouble::new, NBTTagDouble::getDouble, persistence); + } + + /** Creates a new {@code StoredVariable} for a short value with the given key. */ + public static StoredVariable ofShort(String key, Persistence persistence){ + return new StoredVariable<>(key, NBTTagShort::new, NBTTagShort::getShort, persistence); + } + + /** Creates a new {@code StoredVariable} for a long value with the given key. */ + public static StoredVariable ofLong(String key, Persistence persistence){ + return new StoredVariable<>(key, NBTTagLong::new, NBTTagLong::getLong, persistence); + } + + /** Creates a new {@code StoredVariable} for a {@link String} value with the given key. */ + public static StoredVariable ofString(String key, Persistence persistence){ + return new StoredVariable<>(key, NBTTagString::new, NBTTagString::getString, persistence); + } + + /** Creates a new {@code StoredVariable} for a {@link BlockPos} value with the given key. */ + public static StoredVariable ofBlockPos(String key, Persistence persistence){ + return new StoredVariable<>(key, NBTUtil::createPosTag, NBTUtil::getPosFromTag, persistence); + } + + /** Creates a new {@code StoredVariable} for a {@link UUID} value with the given key. */ + public static StoredVariable ofUUID(String key, Persistence persistence){ + return new StoredVariable<>(key, NBTUtil::createUUIDTag, NBTUtil::getUUIDFromTag, persistence); + } + + /** Creates a new {@code StoredVariable} for an {@link ItemStack} value with the given key. */ + public static StoredVariable ofItemStack(String key, Persistence persistence){ + return new StoredVariable<>(key, ItemStack::serializeNBT, ItemStack::new, persistence); + } + + /** Creates a new {@code StoredVariable} for an {@link NBTTagCompound} value with the given key. */ + public static StoredVariable ofNBT(String key, Persistence persistence){ + return new StoredVariable<>(key, t -> t, t -> t, persistence); // No conversion required! + } + + // Neither of these work just ignore them + +// /** Creates a new {@code StoredVariable} for an {@link NBTTagCompound} value with the given key which stores the +// * given {@code IVariable} for an entity. Entities cannot be stored directly as an {@code IStoredVariable} +// * because they require a world instance on construction. */ +// @SuppressWarnings("unchecked") // Can't check it due to type erasure +// public static StoredVariable ofNBTForEntity(String key, Persistence persistence, IVariable toStore){ +// return ofNBT(key, persistence).withTicker((p, t) -> { +// if(WizardData.get(p) != null){ +// try{ +// T e = (T)EntityList.createEntityByIDFromName(new ResourceLocation(t.getString("entityType")), p.world); +// e.readFromNBT(t); +// WizardData.get(p).setVariable(toStore, e); +// }catch(ClassCastException e){ +// Wizardry.logger.error("Error reading entity from NBT: entity not of expected type", e); +// } +// } +// return t; +// }); +// } + +// /** Creates a new {@code StoredVariable} for an {@link Entity} value with the given key. The returned +// * {@code StoredVariable} has a ticker which extracts the entity from the given; this functionality will need to be +// * replicated in any replacement ticker function. */ +// @SuppressWarnings("unchecked") // Can't check it due to type erasure +// public static StoredVariable ofEntity(String key, Persistence persistence, IVariable storage){ +// // Well this is horrible +// return new IStoredVariable.StoredVariable<>(key, +// (T e) -> { +// NBTTagCompound nbt = new NBTTagCompound(); +// nbt.setString("entityType", EntityList.getKey(e).toString()); +// e.writeToNBT(nbt); +// return nbt; +// }, +// t -> null, persistence) +// .withTicker((p, e) -> { +// if(e == null){ +// try{ +// NBTTagCompound nbt = WizardData.get(p).getVariable(storage); +// if(nbt == null) return null; +// e = (T)EntityList.createEntityByIDFromName(new ResourceLocation(nbt.getString("entityType")), p.world); +// e.readFromNBT(nbt); +// return e; +// }catch(ClassCastException x){ +// Wizardry.logger.error("Error reading stored variable from NBT: entity not of expected type", x); +// } +// } +// return null; +// }); +// } + } +} diff --git a/src/main/java/electroblob/wizardry/data/IVariable.java b/src/main/java/electroblob/wizardry/data/IVariable.java new file mode 100644 index 00000000..3388be93 --- /dev/null +++ b/src/main/java/electroblob/wizardry/data/IVariable.java @@ -0,0 +1,118 @@ +package electroblob.wizardry.data; + +import io.netty.buffer.ByteBuf; +import net.minecraft.entity.player.EntityPlayer; + +import java.util.function.BiFunction; + +/** + * Instances of this interface act as keys which allow spellData of any type to be stored in {@link WizardData} at + * runtime. This means spells (or anything else, for that matter) may define their own storedVariables to be stored + * with the player and handle those storedVariables themselves. This prevents {@code WizardData} from being cluttered + * with spell-specific fields and allows addon mods to leverage {@code WizardData} for their own spells or other data, + * rather than defining their own capability. This system is somewhat similar to {@code DataManager}. + *

    + * Instances should be created once and stored statically (or pseudo-statically) in some sensible location, such + * as a spell class. They can then be used as keys to access the values themselves via {@link WizardData}. + * Encapsulation can also be achieved by simply restricting access to the keys. + *

    + * @param The type of variable stored. + */ +public interface IVariable { + + // To reiterate, instances of this interface are KEYS. They are both accessors for the data and define how + // it is stored and handled, but they DO NOT CONTAIN THE ACTUAL DATA. + // Only one instance exists for each thing to be stored, and is shared across instances of WizardData. + + /** Convenience method that allows this variable to define tick behaviour. This is particularly useful for + * trivial operations such as decrementing a value, for which a dedicated event handling method would be + * unnecessarily verbose. */ + T update(EntityPlayer player, T value); + + /** + * Returns whether this variable persists when data is copied. + * @param respawn True if the player died and is respawning, false if they are just travelling between dimensions. + * @return True if the variable should be copied over, false if not. + */ + boolean isPersistent(boolean respawn); + + /** + * Returns whether this variable requires syncing with clients. + * @return True if the variable should be synced with clients, false if not. + */ + boolean isSynced(); + + /** + * Writes this variable's value to the given {@link ByteBuf}. + */ + void write(ByteBuf buf, T value); + + /** + * Reads this variable's value from the given {@link ByteBuf}. + */ + T read(ByteBuf buf); + + /** If you're storing a lot of data, you can optionally implement this method to define a condition which, if + * satisfied, will result in the data being removed from storage, reducing unnecessary syncing and saving. This + * is particularly relevant if the value is synced as it reduces packet size. */ + default boolean canPurge(EntityPlayer player, T value){ + return false; + } + + /** + * General-purpose implementation of {@link IVariable} for non-stored variables. These may still, however, persist + * across player respawn/dimension change. + *

    + * @param The type of variable stored. + */ + class Variable implements IVariable { + + private final Persistence persistence; + + private BiFunction ticker; + + public Variable(Persistence persistence){ + this.persistence = persistence; + this.ticker = (p, t) -> t; + } + + /** + * Replaces this variable's update method with the given update function. Beware of auto-unboxing of + * primitive types! For lambda expressions, check the second parameter isn't null before operating on it. + * For method references, do not reference a method that takes a primitive type. Otherwise, this will cause + * a (difficult to debug) {@link NullPointerException} if the key was not stored. + * @param ticker A {@link BiFunction} specifying the actions to be performed on this variable each tick. The + * {@code BiFunction} returns the new value for this variable. + * @return This {@code Variable} object, allowing this method to be chained onto object creation. + */ + public Variable withTicker(BiFunction ticker){ + this.ticker = ticker; + return this; + } + + @Override + public T update(EntityPlayer player, T value){ + return ticker.apply(player, value); + } + + @Override + public boolean isPersistent(boolean respawn){ + return respawn ? persistence.persistsOnRespawn() : persistence.persistsOnDimensionChange(); + } + + @Override + public boolean isSynced(){ + return false;// Not implemented for now, maybe we will one day + } + + @Override + public void write(ByteBuf buf, T value){ + // NYI + } + + @Override + public T read(ByteBuf buf){ + return null; // NYI + } + } +} diff --git a/src/main/java/electroblob/wizardry/data/Persistence.java b/src/main/java/electroblob/wizardry/data/Persistence.java new file mode 100644 index 00000000..8babc457 --- /dev/null +++ b/src/main/java/electroblob/wizardry/data/Persistence.java @@ -0,0 +1,25 @@ +package electroblob.wizardry.data; + +/** Enum which defines the circumstances in which an {@link IVariable} persists, i.e. whether its value is carried over. */ +public enum Persistence { + + NEVER(false, false), + DIMENSION_CHANGE(false, true), + RESPAWN(true, false), + ALWAYS(true, true); + + private boolean persistsOnRespawn, persistsOnDimensionChange; + + Persistence(boolean persistsOnRespawn, boolean persistsOnDimensionChange){ + this.persistsOnRespawn = persistsOnRespawn; + this.persistsOnDimensionChange = persistsOnDimensionChange; + } + + public boolean persistsOnRespawn(){ + return persistsOnRespawn; + } + + public boolean persistsOnDimensionChange(){ + return persistsOnDimensionChange; + } +} diff --git a/src/main/java/electroblob/wizardry/data/SpellEmitterData.java b/src/main/java/electroblob/wizardry/data/SpellEmitterData.java new file mode 100644 index 00000000..a3178303 --- /dev/null +++ b/src/main/java/electroblob/wizardry/data/SpellEmitterData.java @@ -0,0 +1,128 @@ +package electroblob.wizardry.data; + +import electroblob.wizardry.Wizardry; +import electroblob.wizardry.command.SpellEmitter; +import electroblob.wizardry.packet.PacketEmitterData; +import electroblob.wizardry.packet.WizardryPacketHandler; +import electroblob.wizardry.spell.Spell; +import electroblob.wizardry.util.NBTExtras; +import electroblob.wizardry.util.SpellModifiers; +import net.minecraft.entity.player.EntityPlayerMP; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.nbt.NBTTagList; +import net.minecraft.util.EnumFacing; +import net.minecraft.world.World; +import net.minecraft.world.storage.WorldSavedData; +import net.minecraftforge.common.util.Constants; +import net.minecraftforge.event.world.WorldEvent; +import net.minecraftforge.fml.common.Mod; +import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; +import net.minecraftforge.fml.common.gameevent.PlayerEvent; +import net.minecraftforge.fml.common.gameevent.TickEvent; + +import java.util.ArrayList; +import java.util.List; + +/** + * Class responsible for storing and keeping track of {@link SpellEmitter}s. Each world has its own instance of + * {@code SpellEmitterData} which can be retrieved using {@link SpellEmitterData#get(World)}.
    + *
    + * To add a new {@code SpellEmitter}, use {@link SpellEmitter#add(Spell, World, double, double, double, EnumFacing, int, SpellModifiers)}. + * + * @since Wizardry 4.2 + * @author Electroblob + */ +@Mod.EventBusSubscriber +public class SpellEmitterData extends WorldSavedData { + + public static final String NAME = Wizardry.MODID + "_spell_emitters"; + + private final List emitters = new ArrayList<>(); + + private NBTTagList emitterTags = null; + + // Required constructors + public SpellEmitterData(){ + this(NAME); + } + + public SpellEmitterData(String name){ + super(name); + } + + /** Returns the spell emitter data for this world, or creates a new instance if it doesn't exist yet. */ + public static SpellEmitterData get(World world){ + + SpellEmitterData instance = (SpellEmitterData)world.getPerWorldStorage().getOrLoadData(SpellEmitterData.class, NAME); + + if(instance == null){ + instance = new SpellEmitterData(); + world.getPerWorldStorage().setData(NAME, instance); + }else if(instance.emitters.isEmpty() && instance.emitterTags != null){ + instance.loadEmitters(world); + } + + return instance; + } + + /** Sends the active spell emitters for this world to the specified player's client. */ + public void sync(EntityPlayerMP player){ + PacketEmitterData.Message msg = new PacketEmitterData.Message(emitters); + WizardryPacketHandler.net.sendTo(msg, player); + Wizardry.logger.info("Synchronising spell emitters for " + player.getName()); + } + + /** Adds the given {@link SpellEmitter} to the list of emitters for this {@code SpellEmitterData}. */ + public void add(SpellEmitter emitter){ + emitters.add(emitter); + markDirty(); + } + + @Override + public void readFromNBT(NBTTagCompound nbt){ + emitterTags = nbt.getTagList("emitters", Constants.NBT.TAG_COMPOUND); + } + + private void loadEmitters(World world){ + emitters.clear(); + emitters.addAll(NBTExtras.NBTToList(emitterTags, (NBTTagCompound t) -> SpellEmitter.fromNBT(world, t))); + emitterTags = null; // Now we know it's loaded + } + + @Override + public NBTTagCompound writeToNBT(NBTTagCompound compound){ + compound.setTag("emitters", NBTExtras.listToNBT(emitters, SpellEmitter::toNBT)); + return compound; + } + + public static void update(World world){ + SpellEmitterData data = SpellEmitterData.get(world); + if(!data.emitters.isEmpty()){ + data.emitters.forEach(SpellEmitter::update); + data.emitters.removeIf(SpellEmitter::needsRemoving); + data.markDirty(); // Mark dirty if there are changes to be saved + } + } + + @SubscribeEvent + public static void tick(TickEvent.WorldTickEvent event){ + if(!event.world.isRemote && event.phase == TickEvent.Phase.END){ + update(event.world); + } + } + + @SubscribeEvent + public static void onWorldLoadEvent(WorldEvent.Load event){ + // Called to initialise the spell emitter data when a world loads, if it isn't already. + SpellEmitterData.get(event.getWorld()); + } + + @SubscribeEvent + public static void onPlayerChangedDimensionEvent(PlayerEvent.PlayerChangedDimensionEvent event){ + // Needs to be done here as well as PlayerLoggedInEvent because SpellEmitterData is dimension-specific + if(event.player instanceof EntityPlayerMP){ + SpellEmitterData.get(event.player.world).sync((EntityPlayerMP)event.player); + } + } + +} diff --git a/src/main/java/electroblob/wizardry/SpellGlyphData.java b/src/main/java/electroblob/wizardry/data/SpellGlyphData.java similarity index 85% rename from src/main/java/electroblob/wizardry/SpellGlyphData.java rename to src/main/java/electroblob/wizardry/data/SpellGlyphData.java index 58f0635a..03fc3f89 100644 --- a/src/main/java/electroblob/wizardry/SpellGlyphData.java +++ b/src/main/java/electroblob/wizardry/data/SpellGlyphData.java @@ -1,13 +1,6 @@ -package electroblob.wizardry; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Random; - -import org.apache.commons.lang3.RandomStringUtils; +package electroblob.wizardry.data; +import electroblob.wizardry.Wizardry; import electroblob.wizardry.packet.PacketGlyphData; import electroblob.wizardry.packet.WizardryPacketHandler; import electroblob.wizardry.spell.Spell; @@ -20,6 +13,9 @@ import net.minecraftforge.common.util.Constants.NBT; import net.minecraftforge.event.world.WorldEvent; import net.minecraftforge.fml.common.Mod; import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; +import org.apache.commons.lang3.RandomStringUtils; + +import java.util.*; /** * Class responsible for generating and storing the randomised spell names and descriptions for each world, which are @@ -32,8 +28,8 @@ public class SpellGlyphData extends WorldSavedData { public static final String NAME = Wizardry.MODID + "_glyphData"; - public Map randomNames = new HashMap(Spell.getTotalSpellCount()); - public Map randomDescriptions = new HashMap(Spell.getTotalSpellCount()); + public Map randomNames = new HashMap<>(Spell.getTotalSpellCount()); + public Map randomDescriptions = new HashMap<>(Spell.getTotalSpellCount()); // Required constructors public SpellGlyphData(){ @@ -110,12 +106,16 @@ public class SpellGlyphData extends WorldSavedData { /** Sends the random spell names for this world to the specified player's client. */ public void sync(EntityPlayerMP player){ - List names = new ArrayList(); - List descriptions = new ArrayList(); + List names = new ArrayList<>(); + List descriptions = new ArrayList<>(); - for(Spell spell : Spell.getSpells(Spell.allSpells)){ + int id = 0; + + while(id < Spell.getTotalSpellCount()){ + Spell spell = Spell.byNetworkID(id + 1); // +1 because the None spell is not included names.add(this.randomNames.get(spell)); descriptions.add(this.randomDescriptions.get(spell)); + id++; } PacketGlyphData.Message msg = new PacketGlyphData.Message(names, descriptions); @@ -144,15 +144,15 @@ public class SpellGlyphData extends WorldSavedData { @Override public void readFromNBT(NBTTagCompound nbt){ - this.randomNames = new HashMap(); - this.randomDescriptions = new HashMap(); + this.randomNames = new HashMap<>(); + this.randomDescriptions = new HashMap<>(); NBTTagList tagList = nbt.getTagList("spellGlyphData", NBT.TAG_COMPOUND); for(int i = 0; i < tagList.tagCount(); i++){ NBTTagCompound tag = tagList.getCompoundTagAt(i); - randomNames.put(Spell.get(tag.getInteger("spell")), tag.getString("name")); - randomDescriptions.put(Spell.get(tag.getInteger("spell")), tag.getString("description")); + randomNames.put(Spell.byMetadata(tag.getInteger("spell")), tag.getString("name")); + randomDescriptions.put(Spell.byMetadata(tag.getInteger("spell")), tag.getString("description")); } } @@ -165,7 +165,7 @@ public class SpellGlyphData extends WorldSavedData { // Much like the enchantments tag for items, this stores a list of spell-id-to-name tag pairs // The description is now also included; there's no point in making a second compound tag! NBTTagCompound tag = new NBTTagCompound(); - tag.setInteger("spell", spell.id()); + tag.setInteger("spell", spell.metadata()); tag.setString("name", this.randomNames.get(spell)); tag.setString("description", this.randomDescriptions.get(spell)); tagList.appendTag(tag); @@ -180,7 +180,6 @@ public class SpellGlyphData extends WorldSavedData { public static void onWorldLoadEvent(WorldEvent.Load event){ if(!event.getWorld().isRemote && event.getWorld().provider.getDimension() == 0){ // Called to initialise the spell glyph data when a world loads, if it isn't already. - // NOTE: Do we actually need this, or can we just let it initialise the first time it is needed? (see below) SpellGlyphData.get(event.getWorld()); } } diff --git a/src/main/java/electroblob/wizardry/WizardData.java b/src/main/java/electroblob/wizardry/data/WizardData.java similarity index 51% rename from src/main/java/electroblob/wizardry/WizardData.java rename to src/main/java/electroblob/wizardry/data/WizardData.java index fd27d9c0..433e3855 100644 --- a/src/main/java/electroblob/wizardry/WizardData.java +++ b/src/main/java/electroblob/wizardry/data/WizardData.java @@ -1,53 +1,35 @@ -package electroblob.wizardry; +package electroblob.wizardry.data; -import java.lang.ref.WeakReference; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Iterator; -import java.util.Map; -import java.util.Map.Entry; -import java.util.Set; -import java.util.UUID; - -import electroblob.wizardry.constants.Element; +import com.google.common.collect.EvictingQueue; +import electroblob.wizardry.Wizardry; import electroblob.wizardry.enchantment.Imbuement; -import electroblob.wizardry.entity.EntityShield; import electroblob.wizardry.entity.living.ISummonedCreature; import electroblob.wizardry.event.SpellCastEvent; import electroblob.wizardry.event.SpellCastEvent.Source; -import electroblob.wizardry.integration.DamageSafetyChecker; import electroblob.wizardry.packet.PacketCastContinuousSpell; import electroblob.wizardry.packet.PacketPlayerSync; -import electroblob.wizardry.packet.PacketTransportation; import electroblob.wizardry.packet.WizardryPacketHandler; import electroblob.wizardry.registry.Spells; -import electroblob.wizardry.registry.WizardryAdvancementTriggers; import electroblob.wizardry.spell.None; import electroblob.wizardry.spell.Spell; -import electroblob.wizardry.util.MagicDamage; -import electroblob.wizardry.util.MagicDamage.DamageType; +import electroblob.wizardry.util.NBTExtras; import electroblob.wizardry.util.SpellModifiers; -import electroblob.wizardry.util.WizardryUtilities; import net.minecraft.enchantment.Enchantment; -import net.minecraft.enchantment.EnchantmentHelper; import net.minecraft.entity.Entity; -import net.minecraft.entity.EntityLivingBase; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.entity.player.EntityPlayerMP; import net.minecraft.init.Items; -import net.minecraft.init.MobEffects; -import net.minecraft.init.SoundEvents; import net.minecraft.item.ItemEnchantedBook; import net.minecraft.item.ItemStack; import net.minecraft.nbt.*; -import net.minecraft.potion.PotionEffect; import net.minecraft.util.EnumFacing; import net.minecraft.util.EnumHand; import net.minecraft.util.ResourceLocation; -import net.minecraft.util.math.BlockPos; import net.minecraftforge.common.MinecraftForge; import net.minecraftforge.common.capabilities.Capability; +import net.minecraftforge.common.capabilities.Capability.IStorage; import net.minecraftforge.common.capabilities.CapabilityInject; +import net.minecraftforge.common.capabilities.CapabilityManager; import net.minecraftforge.common.capabilities.ICapabilitySerializable; import net.minecraftforge.common.util.Constants.NBT; import net.minecraftforge.common.util.INBTSerializable; @@ -59,11 +41,16 @@ import net.minecraftforge.fml.common.Mod; import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; import net.minecraftforge.fml.common.network.simpleimpl.IMessage; +import javax.annotation.Nullable; +import java.lang.ref.WeakReference; +import java.util.*; +import java.util.stream.Collectors; + /** * Capability-based replacement for the old ExtendedPlayer class from 1.7.10. This has been reworked to leave minimum * external changes (for my own sanity, mainly!). Turns out the only major difference between an internal capability and * an IEEP is a couple of redundant classes and a different way of registering it. - *

    + *

    * Forge seems to have separate classes to hold the Capability<...> instance ('key') and methods for getting the * capability, but in my opinion there are already too many classes to deal with, so I'm not adding any more than are * necessary, meaning those constants and values are kept here instead. @@ -80,86 +67,172 @@ public class WizardData implements INBTSerializable { @CapabilityInject(WizardData.class) private static final Capability WIZARD_DATA_CAPABILITY = null; + /** Internal storage of registered variable keys. This only contains the stored keys. */ + private static final Set storedVariables = new HashSet<>(); + + /** The maximum number of recent spells to track. */ + public static final int MAX_RECENT_SPELLS = 10; + /** The player this WizardData instance belongs to. */ private final EntityPlayer player; - // This one is still necessary, because I can't override the equip animation for items that aren't from Wizardry. - private Map imbuementDurations; + /** An instance of {@link Random} which is guaranteed to produce the same number sequence client and server + * side provided that it is always called from common code. This can be useful in reducing the number of + * packets sent in certain situations.
    + *
    + * This is achieved by setting the seed to a new random value each time {@link WizardData#sync()} is called and + * sending this to the client so it can also set its seed to that value. */ + public final Random synchronisedRandom; - public boolean hasSpiritWolf; - public boolean hasSpiritHorse; + /** Whether this player is currently casting a continuous spell via commands. Not saved over world reload and reset + * on player death. */ + private Spell castCommandSpell; + /** The time for which this player has been casting a continuous spell via commands. Increments by 1 each tick. Not + * saved over world reload and reset on player death. */ + private int castCommandTick; + /** SpellModifiers object for the current continuous spell cast via commands. Not saved over world reload and reset + * on player death. */ + private SpellModifiers castCommandModifiers; + /** The number of ticks this player's current continuous spell lasts for, or null if there is none. Not saved over + * world reload and reset on player death. */ + private int castCommandDuration; - /** - * Whether this player is currently casting a continuous spell via commands. Not saved over world reload and reset - * on player death. - */ - private Spell currentlyCasting; - /** - * The time for which this player has been casting a continuous spell via commands. Increments by 1 each tick. Not - * saved over world reload and reset on player death. - */ - private int castingTick; - /** - * SpellModifiers object for the current continuous spell cast via commands. Not saved over world reload and reset - * on player death. - */ - private SpellModifiers spellModifiers; - /** Coordinates for the saved transportation stone circle location. Will be null if no location is saved. */ - private BlockPos stoneCircleLocation; - /** Dimension id which the saved stone circle is in. */ - private int stoneCircleDimension; - /** Time left until the player teleports under the effect of transportation */ - private int tpCountdown; - - /** Coordinates for the saved clairvoyance location. Will be null if no location is saved. */ - private BlockPos clairvoyanceLocation; - /** Dimension id which the saved clairvoyance point is in. */ - private int clairvoyanceDimension; - - public EntityShield shield; + /** SpellModifiers object for the current continuous spell cast via items. Not saved over world reload and reset + * on player death. N.B. Since a player can only use one item at a time, this can be reused for any item that + * casts spells, it's not just for wands.*/ + public SpellModifiers itemCastingModifiers; public WeakReference selectedMinion; - /** - * Set of this player's discovered spells. Do not write to this list directly, use - * {@link WizardData#discoverSpell(Spell)} instead. - */ + /** Set of this player's discovered spells. Do not write to this list directly, use + * {@link WizardData#discoverSpell(Spell)} instead. */ public Set spellsDiscovered; private Set allies; - /** - * List of usernames of this player's allies. May not be accurate 100% of the time. This is here so that a player + /** List of usernames of this player's allies. May not be accurate 100% of the time. This is here so that a player * can view the usernames of their allies even when those allies are not online. Do not use this for any other - * purpose than displaying the names! - */ + * purpose than displaying the names! */ public Set allyNames; - private Set soulboundCreatures; - + /** Internal storage of custom (spell-specific) data. Note that a {@code Map} cannot specify that its values are of + * the same type as the type parameter of its keys, so to ensure this condition always holds, the map must only + * be modified via {@link WizardData#setVariable(IVariable, Object)}, which (as a method) is able to enforce it. */ + private final Map spellData; + + private Queue recentSpells; + + // This one is still necessary, because I can't override the equip animation for items that aren't from Wizardry. + // Leaving this for now because merging it into the spell data system will be more tricky + private Map imbuementDurations; + + /** Stores this player's y velocity from the previous tick; used for the velocity-based fall damage replacement. */ + public double prevMotionY; + public WizardData(){ this(null); // Nullary constructor for the registration method factory parameter } public WizardData(EntityPlayer player){ this.player = player; - this.imbuementDurations = new HashMap(); - this.spellsDiscovered = new HashSet(); + this.synchronisedRandom = new Random(); + this.imbuementDurations = new HashMap<>(); + this.spellsDiscovered = new HashSet<>(); // All players can recognise magic missile. This is not done using discoverSpell because that seems to cause - // a crash on load occasionally (probably something to do with achievements being initalised) + // a crash on load occasionally (probably something to do with achievements being initialised) this.spellsDiscovered.add(Spells.magic_missile); - this.hasSpiritWolf = false; - this.hasSpiritHorse = false; - this.currentlyCasting = Spells.none; - this.spellModifiers = new SpellModifiers(); - this.castingTick = 0; - this.stoneCircleDimension = 0; - this.clairvoyanceDimension = 0; - this.setTpCountdown(0); - this.allies = new HashSet(); - this.allyNames = new HashSet(); - this.soulboundCreatures = new HashSet(); + this.recentSpells = EvictingQueue.create(MAX_RECENT_SPELLS); // Only keeps a reference to the last 10 spells cast + this.castCommandSpell = Spells.none; + this.castCommandModifiers = new SpellModifiers(); + this.castCommandTick = 0; + this.itemCastingModifiers = new SpellModifiers(); + this.allies = new HashSet<>(); + this.allyNames = new HashSet<>(); + this.spellData = new HashMap<>(); } + /** Called from preInit in the main mod class to register the WizardData capability. */ + public static void register(){ + + // Yes - by the looks of it, having an interface is completely unnecessary in this case. + CapabilityManager.INSTANCE.register(WizardData.class, new IStorage(){ + // These methods are only called by Capability.writeNBT() or Capability.readNBT(), which in turn are + // NEVER CALLED. Unless I'm missing some reflective invocation, that means this entire class serves only + // to allow capabilities to be saved and loaded manually. What that would be useful for I don't know. + // (If an API forces most users to write redundant code for no reason, it's not user friendly, is it?) + // ... well, that's my rant for today! + @Override + public NBTBase writeNBT(Capability capability, WizardData instance, EnumFacing side){ + return null; + } + + @Override + public void readNBT(Capability capability, WizardData instance, EnumFacing side, NBTBase nbt){} + + }, WizardData::new); + } + + /** Returns the WizardData instance for the specified player. */ + public static WizardData get(EntityPlayer player){ + return player.getCapability(WIZARD_DATA_CAPABILITY, null); + } + + // ============================================= Variable Storage ============================================= + + // This is my answer to having spells define their own player variables. It's not the prettiest system ever, but + // I think the ability to add arbitrary data to this class and have it save itself to NBT automatically is pretty + // powerful. If it doesn't need saving, this can even be done on the fly - no registration necessary. + + // The reason we have interfaces here is to allow custom implementations of the NBT read/write methods, for + // example, reading/writing multiple keys without having to wrap them in an NBTTagCompound. + + /** Registers the given {@link IStoredVariable} objects as keys that will be stored to NBT for each {@code WizardData} + * instance. */ + public static void registerStoredVariables(IStoredVariable... variables){ + storedVariables.addAll(Arrays.asList(variables)); + } + + /** Returns a set containing the registered {@link IStoredVariable} objects for which {@link IVariable#isSynced()} + * returns true. Used internally for packet reading. */ + public static Set getSyncedVariables(){ + return storedVariables.stream().filter(IVariable::isSynced).collect(Collectors.toSet()); + } + + /** + * Stores the given value under the given key in this {@code WizardData} object. + * @param variable The key under which the value is to be stored. See {@link IVariable} for more details. + * @param value The value to be stored. + * @param The type of the value to be stored. Note that the given variable (key) may be of a supertype of the + * stored value itself; however, when the value is retrieved its type will match that of the key. In + * other words, if an {@code Integer} is stored under a {@code IVariable}, a {@code Number} will + * be returned when the value is retrieved. + */ + // This use of type parameters guarantees that spellData may only be stored (and therefore may only be accessed) + // using a compatible key. For instance, the following code will not compile: + // Number i = 1; + // setVariable(StoredVariable.ofInt("key", Persistence.ALWAYS), i); + public void setVariable(IVariable variable, T value){ + this.spellData.put(variable, value); + } + + /** + * Returns the value stored under the given key in this {@code WizardData} object, or null if the key was not + * stored. + * @param variable The key whose associated value is to be returned. + * @param The type of the returned value. + * @return The value associated with the given key, or null no such key was stored. Beware of auto-unboxing + * of primitive types! Directly assigning the result to a primitive type, as in {@code int i = getVariable(...)}, + * will cause a {@link NullPointerException} if the key was not stored. + */ + @SuppressWarnings("unchecked") // The spellData map is fully encapsulated so we can be sure that the cast is safe + @Nullable + public T getVariable(IVariable variable){ + return (T)spellData.get(variable); + } + + // ============================================== Miscellaneous ============================================== + + // Spell discovery + public boolean hasSpellBeenDiscovered(Spell spell){ return spellsDiscovered.contains(spell) || spell instanceof None; } @@ -175,66 +248,34 @@ public class WizardData implements INBTSerializable { public boolean discoverSpell(Spell spell){ if(spellsDiscovered == null){ - spellsDiscovered = new HashSet(); + spellsDiscovered = new HashSet<>(); } // The 'none' spell cannot be discovered if(spell instanceof None) return false; // Tries to add the spell to the list of discovered spells, and returns false if it was already present - if(!spellsDiscovered.add(spell)) return false; - // If the spell had not already been discovered, achievements can be triggered and the method returns true - if(spellsDiscovered.containsAll(Spell.getSpells(Spell::isEnabled))){ - WizardryAdvancementTriggers.all_spells.triggerFor(this.player); - } - - for(Element element : Element.values()){ - if(element != Element.MAGIC - && spellsDiscovered.containsAll(Spell.getSpells(new Spell.TierElementFilter(null, element)))){ - WizardryAdvancementTriggers.element_master.triggerFor(this.player); - } - } - - return true; + return spellsDiscovered.add(spell); } - /** Sets the player's saved transportation stone location and dimension. */ - public void setStoneCircleLocation(BlockPos pos, int dimensionID){ - this.stoneCircleLocation = pos; - this.stoneCircleDimension = dimensionID; + // Recent spell tracking + + /** + * Adds the given spell to this player's recently-cast spells. Spells can (and will) be added multiple times, and + * will be automatically removed when enough spells are added after them. + * @param spell The spell to be tracked. + */ + public void trackRecentSpell(Spell spell){ + this.recentSpells.add(spell); } - /** Returns the coordinates of the associated player's saved transportation stone circle. */ - public BlockPos getStoneCircleLocation(){ - return stoneCircleLocation; + /** + * Returns the number of times the given spell is tracked in this player's recently-cast spells. + * @param spell The spell to count casts for. + */ + public int countRecentCasts(Spell spell){ + return (int)this.recentSpells.stream().filter(s -> s == spell).count(); // We know this can't be more than 10 } - /** Returns the dimension ID of the associated player's saved transportation stone circle. */ - public int getStoneCircleDimension(){ - return stoneCircleDimension; - } - - public int getTpCountdown(){ - return tpCountdown; - } - - public void setTpCountdown(int tpCountdown){ - this.tpCountdown = tpCountdown; - } - - /** Sets the player's saved clairvoyance location. */ - public void setClairvoyancePoint(BlockPos pos, int dimensionID){ - this.clairvoyanceLocation = pos; - this.clairvoyanceDimension = dimensionID; - } - - /** Returns the coordinates for the saved clairvoyance location. Will be null if no location is saved. */ - public BlockPos getClairvoyanceLocation(){ - return clairvoyanceLocation; - } - - /** Returns the dimension ID for the saved clairvoyance location. Will be null if no location is saved. */ - public int getClairvoyanceDimension(){ - return clairvoyanceDimension; - } + // Imbuements /** * Overwrites the imbuement duration associated with the given imubement for this player, or creates it if there was @@ -282,7 +323,7 @@ public class WizardData implements INBTSerializable { NBTTagList enchantmentList = stack.getItem() == Items.ENCHANTED_BOOK ? ItemEnchantedBook.getEnchantments(stack) : stack.getEnchantmentTagList(); - Iterator iterator =enchantmentList.iterator(); + Iterator iterator = enchantmentList.iterator(); // For each of the item's enchantments while(iterator.hasNext()){ NBTTagCompound enchantmentTag = (NBTTagCompound) iterator.next(); @@ -296,9 +337,8 @@ public class WizardData implements INBTSerializable { this.imbuementDurations.put((Imbuement)enchantment, duration - 1); // Adds this imbuement to the set of imbuements that need to be kept activeImbuements.add((Imbuement)enchantment); - // Otherwise: }else{ - // Removes the enchantment from the item + // Otherwise, removes the enchantment from the item iterator.remove(); } } @@ -309,6 +349,8 @@ public class WizardData implements INBTSerializable { this.imbuementDurations.keySet().retainAll(activeImbuements); } + // Ally designation system + /** * Adds the given player to the list of allies belonging to the associated player, or removes the player if they are * already in the list of allies. Returns true if the player was added, false if they were removed. @@ -331,48 +373,26 @@ public class WizardData implements INBTSerializable { return this.allies.contains(player.getUniqueID()) || this.player.isOnSameTeam(player); } - /** Adds the given entity to this player's list of soulbound creatures, and returns whether it succeeded. */ - public boolean soulbind(EntityLivingBase target){ - return this.soulboundCreatures.add(target.getUniqueID()); + /** Returns whether the player with the given UUID is in this player's list of allies. The player to whom the given + * UUID belongs need not be logged in. This method is intended for use by owned entities so that their owner's + * allies don't accidentally damage them, even when the owner is offline. */ + public boolean isPlayerAlly(UUID playerUUID){ + // Scoreboard teams use usernames, but since we keep a cache of those... + return this.allies.contains(playerUUID) || (this.player.getTeam() != null && this.player.getTeam().getMembershipCollection() != null + && this.player.getTeam().getMembershipCollection().stream().anyMatch(allyNames::contains)); } - /** Returns whether the given entity has been soulbound to this player. */ - public boolean isCreatureSoulbound(EntityPlayer target){ - return this.soulboundCreatures.contains(target.getUniqueID()); - } - - /** - * Damages all creatures soulbound to this player by the given amount, and removes from the list any that no longer - * exist. - */ - public void damageAllSoulboundCreatures(float damage, String originalSourceName){ - - for(Iterator iterator = this.soulboundCreatures.iterator(); iterator.hasNext();){ - - Entity entity = WizardryUtilities.getEntityByUUID(this.player.world, iterator.next()); - - if(entity == null) iterator.remove(); - - if(entity instanceof EntityLivingBase){ - // Retaliatory effect - if(DamageSafetyChecker.attackEntitySafely(entity, MagicDamage.causeDirectMagicDamage(this.player, - DamageType.MAGIC, true), damage, originalSourceName)){ - // Sound only plays if the damage succeeds - player.playSound(SoundEvents.ENTITY_WITHER_HURT, 1.0F, player.world.rand.nextFloat() * 0.2F + 1.0F); - } - } - } - } + // Command continuous spell casting /** Starts casting the given spell with the given modifiers. */ - public void startCastingContinuousSpell(Spell spell, SpellModifiers modifiers){ + public void startCastingContinuousSpell(Spell spell, SpellModifiers modifiers, int duration){ - this.currentlyCasting = spell; - this.spellModifiers = modifiers; + this.castCommandSpell = spell; + this.castCommandModifiers = modifiers; + this.castCommandDuration = duration; if(!this.player.world.isRemote){ - PacketCastContinuousSpell.Message message = new PacketCastContinuousSpell.Message(this.player.getEntityId(), - spell.id(), this.spellModifiers); + PacketCastContinuousSpell.Message message = new PacketCastContinuousSpell.Message(this.player, spell, modifiers, duration); WizardryPacketHandler.net.sendToDimension(message, this.player.world.provider.getDimension()); } } @@ -380,46 +400,48 @@ public class WizardData implements INBTSerializable { /** Stops casting the current spell. */ public void stopCastingContinuousSpell(){ - this.currentlyCasting = Spells.none; - this.castingTick = 0; - this.spellModifiers.reset(); + this.castCommandSpell = Spells.none; + this.castCommandTick = 0; + this.castCommandModifiers.reset(); if(!this.player.world.isRemote){ - PacketCastContinuousSpell.Message message = new PacketCastContinuousSpell.Message(this.player.getEntityId(), - Spells.none.id(), this.spellModifiers); + PacketCastContinuousSpell.Message message = new PacketCastContinuousSpell.Message(this.player, Spells.none, this.castCommandModifiers, this.castCommandDuration); WizardryPacketHandler.net.sendToDimension(message, this.player.world.provider.getDimension()); } } - /** Casts the current continuous spell, fires relevant events and updates the castingTick field. */ + /** Casts the current continuous spell, fires relevant events and updates the castCommandTick field. */ public void updateContinuousSpellCasting(){ - if(this.currentlyCasting != null && this.currentlyCasting.isContinuous){ + if(this.castCommandSpell != null && this.castCommandSpell.isContinuous){ - if(MinecraftForge.EVENT_BUS.post( - new SpellCastEvent.Tick(player, currentlyCasting, spellModifiers, Source.COMMAND, castingTick))){ + if(castCommandTick >= castCommandDuration){ this.stopCastingContinuousSpell(); return; } - if(this.currentlyCasting.cast(player.world, player, EnumHand.MAIN_HAND, castingTick, this.spellModifiers) - && this.castingTick == 0){ - // On the first tick casting a continuous spell via commands, SpellCastEvent.Post is fired. - MinecraftForge.EVENT_BUS - .post(new SpellCastEvent.Post(player, currentlyCasting, spellModifiers, Source.COMMAND)); + if(MinecraftForge.EVENT_BUS.post(new SpellCastEvent.Tick(Source.COMMAND, castCommandSpell, player, castCommandModifiers, castCommandTick))){ + this.stopCastingContinuousSpell(); + return; } - castingTick++; + if(this.castCommandSpell.cast(player.world, player, EnumHand.MAIN_HAND, castCommandTick, this.castCommandModifiers) + && this.castCommandTick == 0){ + // On the first tick casting a continuous spell via commands, SpellCastEvent.Post is fired. + MinecraftForge.EVENT_BUS.post(new SpellCastEvent.Post(Source.COMMAND, castCommandSpell, player, castCommandModifiers)); + } + + castCommandTick++; }else{ - // Why is this here? Surely castingTick will always be 0 if currentlyCasting is null? - this.castingTick = 0; + // Why is this here? Surely castCommandTick will always be 0 if castCommandSpell is null? + this.castCommandTick = 0; } } /** Returns whether this player is currently casting a continuous spell via commands. */ public boolean isCasting(){ - return this.currentlyCasting != null && this.currentlyCasting != Spells.none; + return this.castCommandSpell != null && this.castCommandSpell != Spells.none; } /** @@ -427,69 +449,50 @@ public class WizardData implements INBTSerializable { * casting anything. */ public Spell currentlyCasting(){ - return currentlyCasting; + return castCommandSpell; } + // ============================================== Data Handling ============================================== + /** Called each time the associated player is updated. */ + @SuppressWarnings("unchecked") // Again, we know it must be ok private void update(){ if(this.selectedMinion != null && this.selectedMinion.get() == null) this.selectedMinion = null; - // This new system removes a lot of repetitive event handler code and inflexible variables which had duplicate + prevMotionY = player.motionY; + + // This new system removes a lot of repetitive event handler code and inflexible spellData which had duplicate // functions, just for different enchantments. updateImbuedItems(); - - if(!player.world.isRemote){ - if(getTpCountdown() == 1){ - player.setPositionAndUpdate(this.stoneCircleLocation.getX() + 0.5, this.stoneCircleLocation.getY(), - this.stoneCircleLocation.getZ() + 0.5); - player.addPotionEffect(new PotionEffect(MobEffects.BLINDNESS, 50, 0)); - IMessage msg = new PacketTransportation.Message(player.getEntityId()); - WizardryPacketHandler.net.sendToDimension(msg, player.world.provider.getDimension()); - } - - if(getTpCountdown() > 0){ - setTpCountdown(getTpCountdown() - 1); - } - } - updateContinuousSpellCasting(); - } - /** - * Returns the WizardData instance for the specified player. - */ - public static final WizardData get(EntityPlayer player){ - return player.getCapability(WIZARD_DATA_CAPABILITY, null); + this.spellData.forEach((k, v) -> this.spellData.put(k, k.update(player, v))); + this.spellData.keySet().removeIf(k -> k.canPurge(player, this.spellData.get(k))); } /** * Called from the event handler each time the associated player entity is cloned, i.e. on respawn or when - * travelling to a different dimension. Used to copy over any variables that should persist over player death. This - * is the inverse of the old onPlayerDeath method, which reset the variables that shouldn't persist. + * travelling to a different dimension. Used to copy over any spellData that should persist over player death. This + * is the inverse of the old onPlayerDeath method, which reset the spellData that shouldn't persist. * - * @param data The old WizardData whose variables are to be copied over. + * @param data The old WizardData whose spellData are to be copied over. * @param respawn True if the player died and is respawning, false if they are just travelling between dimensions. */ public void copyFrom(WizardData data, boolean respawn){ - // TODO: What happens with spirit wolf and spirit horse? - this.hasSpiritHorse = data.hasSpiritHorse; - this.hasSpiritWolf = data.hasSpiritWolf; + this.allies = data.allies; this.allyNames = data.allyNames; - this.clairvoyanceDimension = data.clairvoyanceDimension; - this.clairvoyanceLocation = data.clairvoyanceLocation; this.selectedMinion = data.selectedMinion; - // Curse of soulbinding is lifted when the caster dies, but not when they switch dimensions. - if(!respawn) this.soulboundCreatures = data.soulboundCreatures; this.spellsDiscovered = data.spellsDiscovered; - this.stoneCircleDimension = data.stoneCircleDimension; - this.stoneCircleLocation = data.stoneCircleLocation; + this.recentSpells = data.recentSpells; + + for(IVariable variable : data.spellData.keySet()){ + if(variable.isPersistent(respawn)) this.spellData.put(variable, data.spellData.get(variable)); + } // Imbuements are lost on death so their durations do not persist. // Command spell casting is reset on death so the associated variables do not persist. - // tpCountdown is reset both when the player dies and when they switch dimensions. - } /** Sends a packet to this player's client to synchronise necessary information. Only called server side. */ @@ -498,45 +501,39 @@ public class WizardData implements INBTSerializable { int id = -1; if(this.selectedMinion != null && this.selectedMinion.get() instanceof Entity) id = ((Entity)this.selectedMinion.get()).getEntityId(); - IMessage msg = new PacketPlayerSync.Message(this.spellsDiscovered, id); + long seed = player.world.rand.nextLong(); + this.synchronisedRandom.setSeed(seed); + IMessage msg = new PacketPlayerSync.Message(seed, this.spellsDiscovered, id, this.spellData); WizardryPacketHandler.net.sendTo(msg, (EntityPlayerMP)this.player); } } @Override + @SuppressWarnings("unchecked") public NBTTagCompound serializeNBT(){ NBTTagCompound properties = new NBTTagCompound(); - properties.setTag("imbuements", WizardryUtilities.mapToNBT(this.imbuementDurations, + properties.setTag("imbuements", NBTExtras.mapToNBT(this.imbuementDurations, imbuement -> new NBTTagInt(Enchantment.getEnchantmentID((Enchantment)imbuement)), NBTTagInt::new)); - properties.setBoolean("hasSpiritWolf", this.hasSpiritWolf); - properties.setBoolean("hasSpiritHorse", this.hasSpiritHorse); - - if(this.stoneCircleLocation != null) - properties.setLong("stoneCircleLocation", this.stoneCircleLocation.toLong()); - properties.setInteger("stoneCircleDimension", this.stoneCircleDimension); - properties.setInteger("tpCountdown", this.tpCountdown); - - if(this.clairvoyanceLocation != null) - properties.setLong("clairvoyanceLocation", this.clairvoyanceLocation.toLong()); - properties.setInteger("clairvoyanceDimension", this.getClairvoyanceDimension()); - // Mmmmmm Java 8.... - properties.setTag("allies", WizardryUtilities.listToNBT(this.allies, WizardryUtilities::UUIDtoTagCompound)); - properties.setTag("allyNames", WizardryUtilities.listToNBT(this.allyNames, NBTTagString::new)); - properties.setTag("soulboundCreatures", WizardryUtilities.listToNBT(this.soulboundCreatures, WizardryUtilities::UUIDtoTagCompound)); + properties.setTag("allies", NBTExtras.listToNBT(this.allies, NBTUtil::createUUIDTag)); + properties.setTag("allyNames", NBTExtras.listToNBT(this.allyNames, NBTTagString::new)); // Might be worth converting this over to WizardryUtilities.listToNBT. int[] spells = new int[this.spellsDiscovered.size()]; int i = 0; for(Spell spell : this.spellsDiscovered){ - spells[i] = spell.id(); + spells[i] = spell.metadata(); i++; } properties.setIntArray("discoveredSpells", spells); + properties.setTag("recentSpells", NBTExtras.listToNBT(recentSpells, s -> new NBTTagInt(s.metadata()))); + + storedVariables.forEach(k -> k.write(properties, this.spellData.get(k))); + return properties; } @@ -545,36 +542,32 @@ public class WizardData implements INBTSerializable { if(nbt != null){ - this.imbuementDurations = WizardryUtilities.NBTToMap(nbt.getTagList("imbuements", NBT.TAG_COMPOUND), + this.imbuementDurations = NBTExtras.NBTToMap(nbt.getTagList("imbuements", NBT.TAG_COMPOUND), (NBTTagInt tag) -> (Imbuement)Enchantment.getEnchantmentByID(tag.getInt()), NBTTagInt::getInt); - this.hasSpiritWolf = nbt.getBoolean("hasSpiritWolf"); - this.hasSpiritHorse = nbt.getBoolean("hasSpiritHorse"); + this.allies = new HashSet<>(NBTExtras.NBTToList(nbt.getTagList("allies", NBT.TAG_COMPOUND), NBTUtil::getUUIDFromTag)); + this.allyNames = new HashSet<>(NBTExtras.NBTToList(nbt.getTagList("allyNames", NBT.TAG_STRING), NBTTagString::getString)); - this.stoneCircleLocation = BlockPos.fromLong(nbt.getLong("stoneCircleLocation")); - this.stoneCircleDimension = nbt.getInteger("stoneCircleDimension"); - this.tpCountdown = nbt.getInteger("tpCountdown"); - - this.clairvoyanceLocation = BlockPos.fromLong(nbt.getLong("clairvoyanceLocation")); - this.clairvoyanceDimension = nbt.getInteger("clairvoyanceDimension"); - - this.allies = new HashSet(WizardryUtilities.NBTToList(nbt.getTagList("allies", NBT.TAG_COMPOUND), - WizardryUtilities::tagCompoundToUUID)); - - this.allyNames = new HashSet( - WizardryUtilities.NBTToList(nbt.getTagList("allyNames", NBT.TAG_STRING), NBTTagString::getString)); - - this.soulboundCreatures = new HashSet(WizardryUtilities.NBTToList( - nbt.getTagList("soulboundCreatures", NBT.TAG_COMPOUND), WizardryUtilities::tagCompoundToUUID)); - - this.spellsDiscovered = new HashSet(); + this.spellsDiscovered = new HashSet<>(); for(int id : nbt.getIntArray("discoveredSpells")){ - spellsDiscovered.add(Spell.get(id)); + spellsDiscovered.add(Spell.byMetadata(id)); + } + + // Probably won't be null but we may as well just reinitialise it instead of clearing it + this.recentSpells = EvictingQueue.create(MAX_RECENT_SPELLS); + this.recentSpells.addAll(NBTExtras.NBTToList(nbt.getTagList("recentSpells", NBT.TAG_INT), + (NBTTagInt tag) -> Spell.byMetadata(tag.getInt()))); + + try{ + storedVariables.forEach(k -> this.spellData.put(k, k.read(nbt))); + }catch(ClassCastException e){ + // Should only happen if someone manually edits the save file + Wizardry.logger.error("Wizard data NBT tag was not of expected type!", e); } } } - // Event handlers + // ============================================== Event Handlers ============================================== @SubscribeEvent // The type parameter here has to be Entity, not EntityPlayer, or the event won't get fired. @@ -583,11 +576,6 @@ public class WizardData implements INBTSerializable { if(event.getObject() instanceof EntityPlayer) event.addCapability(new ResourceLocation(Wizardry.MODID, "WizardData"), new WizardData.Provider((EntityPlayer)event.getObject())); - - // This demonstrates why capabilities are badly structured: The following code compiles, but what it does is put - // a player into a CapabilityDispatcher, which is in turn stored in that very same player, which makes no sense - // at all! - // event.addCapability(new ResourceLocation(Wizardry.MODID, "WizardData"), event.getObject()); } @SubscribeEvent @@ -597,6 +585,8 @@ public class WizardData implements INBTSerializable { WizardData oldData = WizardData.get(event.getOriginal()); newData.copyFrom(oldData, event.isWasDeath()); + + newData.sync(); // In theory this should fix client/server discrepancies (see #69) } @SubscribeEvent @@ -621,6 +611,8 @@ public class WizardData implements INBTSerializable { } } + // ========================================== Capability Boilerplate ========================================== + /** * This is a nested class for a few reasons: firstly, it makes sense because instances of this and WizardData go * hand-in-hand; secondly, it's too short to be worth a separate file; and thirdly (and most importantly) it allows diff --git a/src/main/java/electroblob/wizardry/enchantment/EnchantmentMagicProtection.java b/src/main/java/electroblob/wizardry/enchantment/EnchantmentMagicProtection.java new file mode 100644 index 00000000..c397d37b --- /dev/null +++ b/src/main/java/electroblob/wizardry/enchantment/EnchantmentMagicProtection.java @@ -0,0 +1,111 @@ +package electroblob.wizardry.enchantment; + +import electroblob.wizardry.util.IElementalDamage; +import electroblob.wizardry.util.MagicDamage; +import net.minecraft.enchantment.Enchantment; +import net.minecraft.enchantment.EnchantmentProtection; +import net.minecraft.enchantment.EnumEnchantmentType; +import net.minecraft.inventory.EntityEquipmentSlot; +import net.minecraft.util.DamageSource; + +import java.util.function.Predicate; + +/** + * This class is for the various magic protection enchantments added by wizardry. + */ +// This was mostly copied from EnchantmentProtection, with the code cleaned up a lot (the vanilla one is awful java...) +public class EnchantmentMagicProtection extends Enchantment { + + /** The type of protection this enchantment gives. */ + public final EnchantmentMagicProtection.Type protectionType; + + public EnchantmentMagicProtection(Enchantment.Rarity rarity, EnchantmentMagicProtection.Type protectionType, EntityEquipmentSlot... slots){ + super(rarity, EnumEnchantmentType.ARMOR, slots); + this.protectionType = protectionType; + } + + // Who knew this was so complicated? + // https://minecraft.gamepedia.com/Tutorials/Enchantment_mechanics#How_enchantments_are_chosen + // https://minecraft.gamepedia.com/Enchanting/Levels <- This is what the results of the 2 methods below are compared to + + @Override + public int getMinEnchantability(int enchantmentLevel){ + return this.protectionType.getMinimalEnchantability() + (enchantmentLevel - 1) * this.protectionType.getEnchantIncreasePerLevel(); + } + + @Override + public int getMaxEnchantability(int enchantmentLevel){ + return this.getMinEnchantability(enchantmentLevel) + this.protectionType.getEnchantIncreasePerLevel(); + } + + @Override + public int getMaxLevel(){ + return 4; + } + + @Override + public int calcModifierDamage(int level, DamageSource source){ + if(source.canHarmInCreative()) return 0; + if(this.protectionType.protectsAgainst(source)) return this.protectionType.getProtectionMultiplier() * level; + return 0; + } + + @Override + public String getName(){ + return "enchantment.ebwizardry:" + this.protectionType.getTypeName() + "_protection"; + } + + @Override + public boolean canApplyTogether(Enchantment ench){ + if(ench instanceof EnchantmentMagicProtection){ + return false; // As per EnchantmentProtection, only feather falling can be applied with other protection types + }else if(ench instanceof EnchantmentProtection){ + return ((EnchantmentProtection)ench).protectionType == EnchantmentProtection.Type.FALL; + }else{ + return super.canApplyTogether(ench); + } + } + + public enum Type { + + MAGIC("magic", 1, 5, 8, s -> s instanceof IElementalDamage), + FROST("frost", 2, 10, 8, s -> s instanceof IElementalDamage && ((IElementalDamage)s).getType() == MagicDamage.DamageType.FROST), + SHOCK("shock", 2, 10, 8, s -> s instanceof IElementalDamage && ((IElementalDamage)s).getType() == MagicDamage.DamageType.SHOCK); + // Fire already exists, and the other types aren't used enough to be worth having + + private final String typeName; + private final int minEnchantability; + private final int levelCost; + // What the heck was levelCostSpan for? Removed since it's never used. + private final Predicate criteria; + private final int protectionMultiplier; + + Type(String name, int protectionMultiplier, int minEnchantability, int perLevelEnchantability, Predicate criteria){ + this.typeName = name; + this.minEnchantability = minEnchantability; + this.levelCost = perLevelEnchantability; + this.criteria = criteria; + this.protectionMultiplier = protectionMultiplier; + } + + public String getTypeName(){ + return this.typeName; + } + + public boolean protectsAgainst(DamageSource source){ + return criteria.test(source); + } + + public int getMinimalEnchantability(){ + return this.minEnchantability; + } + + public int getEnchantIncreasePerLevel(){ + return this.levelCost; + } + + public int getProtectionMultiplier(){ + return protectionMultiplier; + } + } +} \ No newline at end of file diff --git a/src/main/java/electroblob/wizardry/enchantment/Imbuement.java b/src/main/java/electroblob/wizardry/enchantment/Imbuement.java index 18eee9bf..53906427 100644 --- a/src/main/java/electroblob/wizardry/enchantment/Imbuement.java +++ b/src/main/java/electroblob/wizardry/enchantment/Imbuement.java @@ -1,12 +1,10 @@ package electroblob.wizardry.enchantment; -import java.util.Iterator; -import java.util.Map; - import com.google.common.collect.Iterables; import electroblob.wizardry.Wizardry; import electroblob.wizardry.registry.WizardryEnchantments; import electroblob.wizardry.spell.FreezingWeapon; +import electroblob.wizardry.spell.ImbueWeapon; import net.minecraft.enchantment.Enchantment; import net.minecraft.enchantment.EnchantmentHelper; import net.minecraft.entity.EntityLivingBase; @@ -15,7 +13,6 @@ import net.minecraft.entity.projectile.EntityArrow; import net.minecraft.init.Items; import net.minecraft.inventory.ContainerChest; import net.minecraft.inventory.Slot; -import net.minecraft.item.ItemBow; import net.minecraft.item.ItemEnchantedBook; import net.minecraft.item.ItemStack; import net.minecraft.nbt.NBTBase; @@ -28,6 +25,8 @@ import net.minecraftforge.event.entity.player.PlayerContainerEvent; import net.minecraftforge.fml.common.Mod; import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; +import java.util.Iterator; + /** * Interface for temporary enchantments that last for a certain duration ('imbuements'). This interface allows * {@link EnchantmentMagicSword} and {@link EnchantmentTimed} to both be treated as instances of a single type, rather @@ -59,8 +58,7 @@ public interface Imbuement { /** Removes all imbuements from the given itemstack. */ static void removeImbuements(ItemStack stack){ if(stack.isItemEnchanted()){ - // No need to check what enchantments the item has, since remove() does nothing if the element does not - // exist. + // No need to check what enchantments the item has, since remove() does nothing if the element does not exist NBTTagList enchantmentList = stack.getItem() == Items.ENCHANTED_BOOK ? ItemEnchantedBook.getEnchantments(stack) : stack.getEnchantmentTagList(); // Check all enchantments of the item @@ -96,7 +94,7 @@ public interface Imbuement { // If any imbuements were removed, inform about the removal of the enchantment(s), or // delete the book entirely if there are none left. if(enchantmentList.isEmpty()){ - slot.putStack(ItemStack.EMPTY); // NOTE: Will need changing in 1.11 + slot.putStack(ItemStack.EMPTY); Wizardry.logger.info("Deleted enchanted book with illegal enchantments"); }else{ // Inform about enchantment removal @@ -122,9 +120,9 @@ public interface Imbuement { ItemStack bow = archer.getHeldItemMainhand(); - if(!(bow.getItem() instanceof ItemBow)){ + if(!ImbueWeapon.isBow(bow.getItem())){ bow = archer.getHeldItemOffhand(); - if(!(bow.getItem() instanceof ItemBow)) return; + if(!ImbueWeapon.isBow(bow.getItem())) return; } // Taken directly from ItemBow, so it works exactly the same as the power enchantment. diff --git a/src/main/java/electroblob/wizardry/entity/EntityLevitatingBlock.java b/src/main/java/electroblob/wizardry/entity/EntityLevitatingBlock.java new file mode 100644 index 00000000..84305760 --- /dev/null +++ b/src/main/java/electroblob/wizardry/entity/EntityLevitatingBlock.java @@ -0,0 +1,296 @@ +package electroblob.wizardry.entity; + +import electroblob.wizardry.Wizardry; +import electroblob.wizardry.registry.Spells; +import electroblob.wizardry.spell.Spell; +import electroblob.wizardry.util.AllyDesignationSystem; +import electroblob.wizardry.util.MagicDamage; +import electroblob.wizardry.util.WizardryUtilities; +import io.netty.buffer.ByteBuf; +import net.minecraft.block.Block; +import net.minecraft.block.BlockFalling; +import net.minecraft.block.material.Material; +import net.minecraft.block.state.IBlockState; +import net.minecraft.entity.Entity; +import net.minecraft.entity.EntityLivingBase; +import net.minecraft.entity.MoverType; +import net.minecraft.entity.item.EntityFallingBlock; +import net.minecraft.init.Blocks; +import net.minecraft.nbt.NBTBase; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.tileentity.TileEntity; +import net.minecraft.util.EnumFacing; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.RayTraceResult; +import net.minecraft.util.math.Vec3d; +import net.minecraft.world.World; +import net.minecraftforge.fml.common.ObfuscationReflectionHelper; +import net.minecraftforge.fml.common.registry.IEntityAdditionalSpawnData; + +import java.lang.ref.WeakReference; +import java.lang.reflect.Field; +import java.util.List; +import java.util.UUID; + +/** Custom extended version of {@link EntityFallingBlock} for use with the greater telekinesis spell. */ +public class EntityLevitatingBlock extends EntityFallingBlock implements IEntityAdditionalSpawnData { + + private static final Field fallTile; + + static { + fallTile = ObfuscationReflectionHelper.findField(EntityFallingBlock.class, "field_175132_d"); + fallTile.setAccessible(true); + } + + /** The entity that created this levitating block */ + private WeakReference caster; + + /** + * The UUID of the caster. Note that this is only for loading purposes; during normal updates the actual entity + * instance is stored (so that getEntityByUUID is not called constantly), so this will not always be synced (this is + * why it is private). + */ + private UUID casterUUID; + + /** The damage multiplier for this levitating block, determined by the wand with which it was cast. */ + public float damageMultiplier = 1.0f; + + private int suspendTimer = 5; + + public EntityLevitatingBlock(World world){ + super(world); + // EntityFallingBlock never uses this constructor so doesn't bother setting this, but we need to + this.setSize(0.98F, 0.98F); + } + + public EntityLevitatingBlock(World world, double x, double y, double z, IBlockState state){ + super(world, x, y, z, state); + } + + /** Resets the suspension timer to 5 ticks, during which this block will not re-attach itself to the ground. */ + public void suspend(){ + suspendTimer = 5; + } + + @Override + public void onUpdate(){ + + if(suspendTimer > 0){ + suspendTimer--; + } + + if(this.getCaster() == null && this.casterUUID != null){ + Entity entity = WizardryUtilities.getEntityByUUID(world, casterUUID); + if(entity instanceof EntityLivingBase){ + this.caster = new WeakReference<>((EntityLivingBase)entity); + } + } + + if(getBlock() != null){ + + // === Copied from super === + + Block block = getBlock().getBlock(); + + if(getBlock().getMaterial() == Material.AIR){ + this.setDead(); + + }else{ + + this.prevPosX = this.posX; + this.prevPosY = this.posY; + this.prevPosZ = this.posZ; + + if(this.fallTime++ == 0){ + + BlockPos blockpos = new BlockPos(this); + + if(this.world.getBlockState(blockpos).getBlock() == block){ + this.world.setBlockToAir(blockpos); + }else if(!this.world.isRemote){ + this.setDead(); + return; + } + } + + if(!this.hasNoGravity()){ + this.motionY -= 0.03999999910593033D; + } + + this.move(MoverType.SELF, this.motionX, this.motionY, this.motionZ); + + if(!this.world.isRemote){ + + BlockPos blockpos1 = new BlockPos(this); + boolean isConcrete = getBlock().getBlock() == Blocks.CONCRETE_POWDER; + boolean isConcreteInWater = isConcrete && this.world.getBlockState(blockpos1).getMaterial() == Material.WATER; + double d0 = this.motionX * this.motionX + this.motionY * this.motionY + this.motionZ * this.motionZ; + + if(isConcrete && d0 > 1.0D){ + + RayTraceResult raytraceresult = this.world.rayTraceBlocks(new Vec3d(this.prevPosX, this.prevPosY, this.prevPosZ), new Vec3d(this.posX, this.posY, this.posZ), true); + + if(raytraceresult != null && this.world.getBlockState(raytraceresult.getBlockPos()).getMaterial() == Material.WATER){ + blockpos1 = raytraceresult.getBlockPos(); + isConcreteInWater = true; + } + } + + if(!this.onGround && !isConcreteInWater){ + + if(this.fallTime > 100 && !this.world.isRemote && (blockpos1.getY() < 1 || blockpos1.getY() > 256) || this.fallTime > 600){ + this.setDead(); + } + + }else{ + + IBlockState iblockstate = this.world.getBlockState(blockpos1); + + if(this.world.isAirBlock(new BlockPos(this.posX, this.posY - 0.009999999776482582D, this.posZ))){ + if(!isConcreteInWater && BlockFalling.canFallThrough(this.world.getBlockState(new BlockPos(this.posX, this.posY - 0.009999999776482582D, this.posZ)))){ + this.onGround = false; + return; + } + } + + this.motionX *= 0.699999988079071D; + this.motionZ *= 0.699999988079071D; + this.motionY *= -0.5D; + + if(iblockstate.getBlock() != Blocks.PISTON_EXTENSION){ + + if(suspendTimer == 0){ + + this.setDead(); // Moved inside the above if statement + + if(this.world.mayPlace(block, blockpos1, true, EnumFacing.UP, null) + && (isConcreteInWater || !BlockFalling.canFallThrough(this.world.getBlockState(blockpos1.down()))) + && this.world.setBlockState(blockpos1, getBlock(), 3)){ + + if(block instanceof BlockFalling){ + ((BlockFalling)block).onEndFalling(this.world, blockpos1, getBlock(), iblockstate); + } + + if(this.tileEntityData != null && block.hasTileEntity(getBlock())){ + + TileEntity tileentity = this.world.getTileEntity(blockpos1); + + if(tileentity != null){ + + NBTTagCompound nbttagcompound = tileentity.writeToNBT(new NBTTagCompound()); + + for(String s : this.tileEntityData.getKeySet()){ + NBTBase nbtbase = this.tileEntityData.getTag(s); + + if(!"x".equals(s) && !"y".equals(s) && !"z".equals(s)){ + nbttagcompound.setTag(s, nbtbase.copy()); + } + } + + tileentity.readFromNBT(nbttagcompound); + tileentity.markDirty(); + } + } + + }else{ + // Never drops the block, instead if it can't reattach to the world it breaks + world.playEvent(2001, this.getPosition(), Block.getStateId(getBlock())); + } + } + } + } + } + + this.motionX *= 0.9800000190734863D; + this.motionY *= 0.9800000190734863D; + this.motionZ *= 0.9800000190734863D; + } + + // === End super copy === + } + + double velocitySquared = motionX * motionX + motionY * motionY + motionZ * motionZ; + + if(velocitySquared >= 0.2){ + + List list = this.world.getEntitiesWithinAABBExcludingEntity(this, this.getEntityBoundingBox()); + + for(Entity entity : list){ + + if(entity instanceof EntityLivingBase && isValidTarget(entity)){ + + float damage = Spells.greater_telekinesis.getProperty(Spell.DAMAGE).floatValue() * damageMultiplier; + damage *= Math.min(1, velocitySquared/0.4); // Reduce damage at low speeds + + entity.attackEntityFrom(MagicDamage.causeIndirectMagicDamage(this, getCaster(), + MagicDamage.DamageType.FORCE), damage); + + double dx = -this.motionX; + double dz; + for(dz = -this.motionZ; dx * dx + dz * dz < 1.0E-4D; dz = (Math.random() - Math.random()) * 0.01D){ + dx = (Math.random() - Math.random()) * 0.01D; + } + ((EntityLivingBase)entity).knockBack(this, 0.6f, dx, dz); + } + } + } + + } + + /** + * Returns the EntityLivingBase that created this construct, or null if it no longer exists. Cases where the entity + * may no longer exist are: entity died or was deleted, mob despawned, player logged out, entity teleported to + * another dimension, or this construct simply had no caster in the first place. + */ + public EntityLivingBase getCaster(){ + return caster == null ? null : caster.get(); + } + + public void setCaster(EntityLivingBase caster){ + if(getCaster() != caster) this.caster = new WeakReference<>(caster); + } + + /** + * Shorthand for {@link AllyDesignationSystem#isValidTarget(Entity, Entity)}, with the owner of this construct as the + * attacker. Also allows subclasses to override it if they wish to do so. + */ + public boolean isValidTarget(Entity target){ + return AllyDesignationSystem.isValidTarget(this.getCaster(), target); + } + + @Override + protected void readEntityFromNBT(NBTTagCompound nbttagcompound){ + super.readEntityFromNBT(nbttagcompound); + casterUUID = nbttagcompound.getUniqueId("casterUUID"); + damageMultiplier = nbttagcompound.getFloat("damageMultiplier"); + } + + @Override + protected void writeEntityToNBT(NBTTagCompound nbttagcompound){ + super.writeEntityToNBT(nbttagcompound); + if(this.getCaster() != null){ + nbttagcompound.setUniqueId("casterUUID", this.getCaster().getUniqueID()); + } + nbttagcompound.setFloat("damageMultiplier", damageMultiplier); + } + + @Override + public void readSpawnData(ByteBuf buf){ + if(buf.isReadable()){ + Block block = Block.REGISTRY.getObjectById(buf.readInt()); + try{ + fallTile.set(this, block.getStateFromMeta(buf.readInt())); + }catch(IllegalAccessException e){ + Wizardry.logger.error("Error reading levitating block data from packet: ", e); + } + } + } + + @Override + public void writeSpawnData(ByteBuf buf){ + if(getBlock() != null){ + buf.writeInt(Block.REGISTRY.getIDForObject(getBlock().getBlock())); + buf.writeInt(getBlock().getBlock().getMetaFromState(getBlock())); + } + } +} diff --git a/src/main/java/electroblob/wizardry/entity/EntityMeteor.java b/src/main/java/electroblob/wizardry/entity/EntityMeteor.java index 14784b3f..f41d63ad 100644 --- a/src/main/java/electroblob/wizardry/entity/EntityMeteor.java +++ b/src/main/java/electroblob/wizardry/entity/EntityMeteor.java @@ -1,15 +1,15 @@ package electroblob.wizardry.entity; import electroblob.wizardry.Wizardry; +import electroblob.wizardry.registry.Spells; import electroblob.wizardry.registry.WizardryBlocks; import electroblob.wizardry.registry.WizardrySounds; -import electroblob.wizardry.util.WizardryUtilities; +import electroblob.wizardry.spell.Meteor; import net.minecraft.block.state.IBlockState; import net.minecraft.entity.MoverType; import net.minecraft.entity.item.EntityFallingBlock; -import net.minecraft.init.Blocks; import net.minecraft.nbt.NBTTagCompound; -import net.minecraft.util.math.BlockPos; +import net.minecraft.util.SoundCategory; import net.minecraft.world.World; import net.minecraftforge.fml.relauncher.Side; import net.minecraftforge.fml.relauncher.SideOnly; @@ -20,6 +20,7 @@ public class EntityMeteor extends EntityFallingBlock { * The entity blast multiplier. */ public float blastMultiplier; + private boolean damageBlocks; public EntityMeteor(World world){ super(world); @@ -27,11 +28,12 @@ public class EntityMeteor extends EntityFallingBlock { this.setSize(0.98F, 0.98F); } - public EntityMeteor(World world, double x, double y, double z, float blastMultiplier){ + public EntityMeteor(World world, double x, double y, double z, float blastMultiplier, boolean damageBlocks){ super(world, x, y, z, WizardryBlocks.meteor.getDefaultState()); this.motionY = -1.0D; this.setFire(200); this.blastMultiplier = blastMultiplier; + this.damageBlocks = damageBlocks; } @Override @@ -43,7 +45,7 @@ public class EntityMeteor extends EntityFallingBlock { public void onUpdate(){ if(this.ticksExisted % 16 == 1 && world.isRemote){ - Wizardry.proxy.playMovingSound(this, WizardrySounds.SPELL_LOOP_FIRE, 3.0f, 1.0f, false); + Wizardry.proxy.playMovingSound(this, WizardrySounds.ENTITY_METEOR_FALLING, WizardrySounds.SPELLS, 3.0f, 1.0f, false); } // You'd think the best way to do this would be to call super and do all the exploding stuff in fall() instead. @@ -66,21 +68,9 @@ public class EntityMeteor extends EntityFallingBlock { this.motionX *= 0.699999988079071D; this.motionZ *= 0.699999988079071D; this.motionY *= -0.5D; - this.world.createExplosion(this, this.posX, this.posY, this.posZ, 2.0f * blastMultiplier, true); - for(int i1 = -3; i1 < 4; i1++){ - for(int j1 = -3; j1 < 4; j1++){ - int y = WizardryUtilities.getNearestFloorLevelB(this.world, - new BlockPos(this.posX + i1, this.posY, this.posZ + j1), 7); - // System.out.println(y); - double dist = this.getDistance((int)this.posX + i1, y, (int)this.posZ + j1); - // Randomised with weighting so that the nearer the block the more likely it is to be set on - // fire. - if(y != -1 && rand.nextInt((int)dist * 2 + 1) < 3 && dist < 4){ - this.world.setBlockState(new BlockPos(this.posX + i1, y, this.posZ + j1), - Blocks.FIRE.getDefaultState()); - } - } - } + this.world.newExplosion(this, this.posX, this.posY, this.posZ, + Spells.meteor.getProperty(Meteor.BLAST_STRENGTH).floatValue() * blastMultiplier, + damageBlocks, damageBlocks); this.setDead(); } } @@ -123,12 +113,19 @@ public class EntityMeteor extends EntityFallingBlock { public void readEntityFromNBT(NBTTagCompound nbttagcompound){ super.readEntityFromNBT(nbttagcompound); blastMultiplier = nbttagcompound.getFloat("blastMultiplier"); + damageBlocks = nbttagcompound.getBoolean("damageBlocks"); } @Override public void writeEntityToNBT(NBTTagCompound nbttagcompound){ super.writeEntityToNBT(nbttagcompound); nbttagcompound.setFloat("blastMultiplier", blastMultiplier); + nbttagcompound.setBoolean("damageBlocks", damageBlocks); + } + + @Override + public SoundCategory getSoundCategory(){ + return WizardrySounds.SPELLS; } } diff --git a/src/main/java/electroblob/wizardry/entity/EntityShield.java b/src/main/java/electroblob/wizardry/entity/EntityShield.java index 0f483493..7138dc22 100644 --- a/src/main/java/electroblob/wizardry/entity/EntityShield.java +++ b/src/main/java/electroblob/wizardry/entity/EntityShield.java @@ -1,18 +1,20 @@ package electroblob.wizardry.entity; -import java.lang.ref.WeakReference; - -import electroblob.wizardry.WizardData; -import electroblob.wizardry.item.ItemWand; +import electroblob.wizardry.data.WizardData; +import electroblob.wizardry.item.ISpellCastingItem; import electroblob.wizardry.registry.WizardrySounds; +import electroblob.wizardry.spell.Shield; import net.minecraft.entity.Entity; import net.minecraft.entity.IProjectile; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.nbt.NBTTagCompound; import net.minecraft.util.DamageSource; +import net.minecraft.util.SoundCategory; import net.minecraft.util.math.AxisAlignedBB; import net.minecraft.world.World; +import java.lang.ref.WeakReference; + public class EntityShield extends Entity { public WeakReference player; @@ -46,8 +48,8 @@ public class EntityShield extends Entity { entityplayer.posY + 1 + entityplayer.getLookVec().y * 0.3, entityplayer.posZ + entityplayer.getLookVec().z * 0.3, entityplayer.rotationYawHead, entityplayer.rotationPitch); - if(!entityplayer.isHandActive() || !(entityplayer.getHeldItem(entityplayer.getActiveHand()).getItem() instanceof ItemWand)){ - WizardData.get(entityplayer).shield = null; + if(!entityplayer.isHandActive() || !(entityplayer.getHeldItem(entityplayer.getActiveHand()).getItem() instanceof ISpellCastingItem)){ + WizardData.get(entityplayer).setVariable(Shield.SHIELD_KEY, null); this.setDead(); } }else if(!world.isRemote){ @@ -62,13 +64,19 @@ public class EntityShield extends Entity { this.setRotation(par7, par8); } - public boolean attackEntityFrom(DamageSource par1DamageSource, float par2){ - if(par1DamageSource != null && par1DamageSource.getImmediateSource() instanceof IProjectile){ - par1DamageSource.getImmediateSource().playSound(WizardrySounds.SPELL_DEFLECTION, 0.3f, 1.3f); + public boolean attackEntityFrom(DamageSource source, float damage){ + if(source != null && source.getImmediateSource() instanceof IProjectile){ + world.playSound(null, source.getImmediateSource().posX, source.getImmediateSource().posY, + source.getImmediateSource().posZ, WizardrySounds.ENTITY_SHIELD_DEFLECT, WizardrySounds.SPELLS, 0.3f, 1.3f); } - super.attackEntityFrom(par1DamageSource, par2); + super.attackEntityFrom(source, damage); return false; } + + @Override + public SoundCategory getSoundCategory(){ + return WizardrySounds.SPELLS; + } public boolean canBeCollidedWith(){ return !this.isDead; diff --git a/src/main/java/electroblob/wizardry/entity/ICustomHitbox.java b/src/main/java/electroblob/wizardry/entity/ICustomHitbox.java new file mode 100644 index 00000000..95c0baa9 --- /dev/null +++ b/src/main/java/electroblob/wizardry/entity/ICustomHitbox.java @@ -0,0 +1,31 @@ +package electroblob.wizardry.entity; + +import net.minecraft.util.math.Vec3d; + +/** This interface allows implementing entity classes to define their own hitbox for wizardry's raytracing and + * particle collision methods. Typically, entities implementing this interface will return null from the collision + * bounding box methods in {@code Entity} (there are two for some reason) but return true from + * {@link net.minecraft.entity.Entity#canBeCollidedWith()} */ +public interface ICustomHitbox { + + /** + * Calculates the point at which the line starting at the given origin and ending at the given endpoint hits this + * entity, if any. Used in raytracing to allow entities to define fully custom behaviour. See + * {@link electroblob.wizardry.entity.construct.EntityForcefield} for an example implementation of a spherical hitbox. + * @param origin The origin of the line. + * @param endpoint The endpoint of the line. + * @param fuzziness Maximum distance around the line that should still count as a hit. + * @return A {@link Vec3d} representing the point hit, or null if there is no intercept. This should be the first + * point that the line hits, i.e. if there is more than one intercept this method should return the one nearest to + * the given origin. + */ + Vec3d calculateIntercept(Vec3d origin, Vec3d endpoint, float fuzziness); + + /** + * Returns whether the given point is inside this entity. + * @param point The coordinates to test. + * @return True if the point is inside this entity, false if not. + */ + boolean contains(Vec3d point); + +} diff --git a/src/main/java/electroblob/wizardry/entity/construct/EntityArrowRain.java b/src/main/java/electroblob/wizardry/entity/construct/EntityArrowRain.java index b2ecca42..9f26e85b 100644 --- a/src/main/java/electroblob/wizardry/entity/construct/EntityArrowRain.java +++ b/src/main/java/electroblob/wizardry/entity/construct/EntityArrowRain.java @@ -3,6 +3,7 @@ package electroblob.wizardry.entity.construct; import net.minecraft.entity.projectile.EntityTippedArrow; import net.minecraft.init.Items; import net.minecraft.item.ItemStack; +import net.minecraft.util.math.MathHelper; import net.minecraft.world.World; public class EntityArrowRain extends EntityMagicConstruct { @@ -20,9 +21,9 @@ public class EntityArrowRain extends EntityMagicConstruct { if(!this.world.isRemote){ EntityTippedArrow arrow = new EntityTippedArrow(world, this.posX + rand.nextDouble() * 6 - 3, this.posY + rand.nextDouble() * 4 - 2, this.posZ + rand.nextDouble() * 6 - 3); - arrow.motionX = Math.cos(Math.toRadians(this.rotationYaw + 90)); + arrow.motionX = MathHelper.cos((float)Math.toRadians(this.rotationYaw + 90)); arrow.motionY = -0.6; - arrow.motionZ = Math.sin(Math.toRadians(this.rotationYaw + 90)); + arrow.motionZ = MathHelper.sin((float)Math.toRadians(this.rotationYaw + 90)); arrow.shootingEntity = this.getCaster(); arrow.setDamage(7.0d * damageMultiplier); arrow.setPotionEffect(new ItemStack(Items.ARROW)); diff --git a/src/main/java/electroblob/wizardry/entity/construct/EntityBlackHole.java b/src/main/java/electroblob/wizardry/entity/construct/EntityBlackHole.java index 68fc1ae6..378c9066 100644 --- a/src/main/java/electroblob/wizardry/entity/construct/EntityBlackHole.java +++ b/src/main/java/electroblob/wizardry/entity/construct/EntityBlackHole.java @@ -1,13 +1,15 @@ package electroblob.wizardry.entity.construct; -import java.util.List; - +import electroblob.wizardry.Wizardry; +import electroblob.wizardry.item.ItemArtefact; +import electroblob.wizardry.registry.WizardryItems; +import electroblob.wizardry.registry.WizardrySounds; import electroblob.wizardry.util.MagicDamage; import electroblob.wizardry.util.MagicDamage.DamageType; import electroblob.wizardry.util.WizardryUtilities; import net.minecraft.entity.EntityLivingBase; +import net.minecraft.entity.player.EntityPlayer; import net.minecraft.entity.player.EntityPlayerMP; -import net.minecraft.init.SoundEvents; import net.minecraft.nbt.NBTTagCompound; import net.minecraft.network.play.server.SPacketEntityVelocity; import net.minecraft.util.DamageSource; @@ -16,7 +18,11 @@ import net.minecraft.world.World; import net.minecraftforge.fml.relauncher.Side; import net.minecraftforge.fml.relauncher.SideOnly; +import java.util.List; + public class EntityBlackHole extends EntityMagicConstruct { + + private static final double SUCTION_STRENGTH = 0.075; public int[] randomiser; public int[] randomiser2; @@ -69,42 +75,49 @@ public class EntityBlackHole extends EntityMagicConstruct { } if(this.lifetime - this.ticksExisted == 75){ - this.playSound(SoundEvents.BLOCK_PORTAL_TRIGGER, 1.5f, 1.0f); + this.playSound(WizardrySounds.ENTITY_BLACK_HOLE_VANISH, 1.5f, 1.0f); }else if(this.ticksExisted % 80 == 1 && this.ticksExisted + 80 < this.lifetime){ - this.playSound(SoundEvents.BLOCK_PORTAL_AMBIENT, 1.5f, 1.0f); + this.playSound(WizardrySounds.ENTITY_BLACK_HOLE_AMBIENT, 1.5f, 1.0f); } - List targets = WizardryUtilities.getEntitiesWithinRadius(6.0d, this.posX, this.posY, - this.posZ, this.world); - if(!this.world.isRemote){ + List targets = WizardryUtilities.getEntitiesWithinRadius(6.0d, this.posX, this.posY, + this.posZ, this.world); + for(EntityLivingBase target : targets){ if(this.isValidTarget(target)){ - // Sucks the target in - if(this.posX > target.posX && target.motionX < 1){ - target.motionX += 0.1; - }else if(this.posX < target.posX && target.motionX > -1){ - target.motionX -= 0.1; - } + // If the target can't be moved, it isn't sucked in but is still damaged if it gets too close + if(!(target instanceof EntityPlayer && ((getCaster() instanceof EntityPlayer && !Wizardry.settings.playersMoveEachOther) + || ItemArtefact.isArtefactActive((EntityPlayer)target, WizardryItems.amulet_anchoring)))){ - if(this.posY > target.posY && target.motionY < 1){ - target.motionY += 0.1; - }else if(this.posY < target.posY && target.motionY > -1){ - target.motionY -= 0.1; - } + WizardryUtilities.undoGravity(target); - if(this.posZ > target.posZ && target.motionZ < 1){ - target.motionZ += 0.1; - }else if(this.posZ < target.posZ && target.motionZ > -1){ - target.motionZ -= 0.1; - } + // Sucks the target in + if(this.posX > target.posX && target.motionX < 1){ + target.motionX += SUCTION_STRENGTH; + }else if(this.posX < target.posX && target.motionX > -1){ + target.motionX -= SUCTION_STRENGTH; + } - // Player motion is handled on that player's client so needs packets - if(target instanceof EntityPlayerMP){ - ((EntityPlayerMP)target).connection.sendPacket(new SPacketEntityVelocity(target)); + if(this.posY > target.posY && target.motionY < 1){ + target.motionY += SUCTION_STRENGTH; + }else if(this.posY < target.posY && target.motionY > -1){ + target.motionY -= SUCTION_STRENGTH; + } + + if(this.posZ > target.posZ && target.motionZ < 1){ + target.motionZ += SUCTION_STRENGTH; + }else if(this.posZ < target.posZ && target.motionZ > -1){ + target.motionZ -= SUCTION_STRENGTH; + } + + // Player motion is handled on that player's client so needs packets + if(target instanceof EntityPlayerMP){ + ((EntityPlayerMP)target).connection.sendPacket(new SPacketEntityVelocity(target)); + } } if(this.getDistance(target) <= 2){ @@ -128,4 +141,9 @@ public class EntityBlackHole extends EntityMagicConstruct { return true; } + @Override + public boolean shouldRenderInPass(int pass){ + return pass == 1; + } + } diff --git a/src/main/java/electroblob/wizardry/entity/construct/EntityBlizzard.java b/src/main/java/electroblob/wizardry/entity/construct/EntityBlizzard.java index 4d863e0f..9cc90a43 100644 --- a/src/main/java/electroblob/wizardry/entity/construct/EntityBlizzard.java +++ b/src/main/java/electroblob/wizardry/entity/construct/EntityBlizzard.java @@ -1,9 +1,9 @@ package electroblob.wizardry.entity.construct; -import java.util.List; - +import electroblob.wizardry.registry.Spells; import electroblob.wizardry.registry.WizardryPotions; import electroblob.wizardry.registry.WizardrySounds; +import electroblob.wizardry.spell.Spell; import electroblob.wizardry.util.MagicDamage; import electroblob.wizardry.util.MagicDamage.DamageType; import electroblob.wizardry.util.ParticleBuilder; @@ -14,6 +14,8 @@ import net.minecraft.potion.PotionEffect; import net.minecraft.util.DamageSource; import net.minecraft.world.World; +import java.util.List; + public class EntityBlizzard extends EntityMagicConstruct { public EntityBlizzard(World world){ @@ -25,14 +27,18 @@ public class EntityBlizzard extends EntityMagicConstruct { public void onUpdate(){ if(this.ticksExisted % 120 == 1){ - this.playSound(WizardrySounds.SPELL_LOOP_WIND, 1.0f, 1.0f); + this.playSound(WizardrySounds.ENTITY_BLIZZARD_AMBIENT, 1.0f, 1.0f); } super.onUpdate(); + // This is a good example of why you might define a spell base property without necessarily using it in the + // spell - in fact, blizzard doesn't even have a spell class (yet) + double radius = Spells.blizzard.getProperty(Spell.EFFECT_RADIUS).doubleValue(); + if(!this.world.isRemote){ - List targets = WizardryUtilities.getEntitiesWithinRadius(3.0d, this.posX, this.posY, + List targets = WizardryUtilities.getEntitiesWithinRadius(radius, this.posX, this.posY, this.posZ, this.world); for(EntityLivingBase target : targets){ @@ -59,7 +65,7 @@ public class EntityBlizzard extends EntityMagicConstruct { for(int i=1; i<12; i++){ double speed = (rand.nextBoolean() ? 1 : -1) * 0.1 + 0.05 * rand.nextDouble(); ParticleBuilder.create(Type.SNOW).pos(this.posX, this.posY + rand.nextDouble() * 3, this.posZ).vel(0, 0, 0) - .time(100).scale(2).spin(rand.nextDouble() * 2.5 + 0.5, speed).spawn(world); + .time(100).scale(2).spin(rand.nextDouble() * (radius - 0.5) + 0.5, speed).spawn(world); } } } diff --git a/src/main/java/electroblob/wizardry/entity/construct/EntityBubble.java b/src/main/java/electroblob/wizardry/entity/construct/EntityBubble.java index 58c3e0e5..e494c610 100644 --- a/src/main/java/electroblob/wizardry/entity/construct/EntityBubble.java +++ b/src/main/java/electroblob/wizardry/entity/construct/EntityBubble.java @@ -1,14 +1,14 @@ package electroblob.wizardry.entity.construct; -import java.lang.ref.WeakReference; - +import electroblob.wizardry.registry.Spells; +import electroblob.wizardry.registry.WizardrySounds; +import electroblob.wizardry.spell.Entrapment; import electroblob.wizardry.util.MagicDamage; import electroblob.wizardry.util.MagicDamage.DamageType; import electroblob.wizardry.util.WizardryUtilities; import io.netty.buffer.ByteBuf; import net.minecraft.entity.EntityLivingBase; import net.minecraft.entity.MoverType; -import net.minecraft.init.SoundEvents; import net.minecraft.nbt.NBTTagCompound; import net.minecraft.util.DamageSource; import net.minecraft.util.EnumParticleTypes; @@ -17,6 +17,8 @@ import net.minecraftforge.event.entity.living.LivingAttackEvent; import net.minecraftforge.fml.common.Mod; import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; +import java.lang.ref.WeakReference; + @Mod.EventBusSubscriber public class EntityBubble extends EntityMagicConstruct { @@ -46,7 +48,7 @@ public class EntityBubble extends EntityMagicConstruct { if((this.rider == null || this.rider.get() == null) && WizardryUtilities.getRider(this) instanceof EntityLivingBase && !WizardryUtilities.getRider(this).isDead){ - this.rider = new WeakReference((EntityLivingBase)WizardryUtilities.getRider(this)); + this.rider = new WeakReference<>((EntityLivingBase)WizardryUtilities.getRider(this)); } // Prevents dismounting @@ -62,7 +64,8 @@ public class EntityBubble extends EntityMagicConstruct { if(isDarkOrb){ - if(WizardryUtilities.getRider(this) != null && this.ticksExisted % 30 == 0){ + if(WizardryUtilities.getRider(this) != null + && this.ticksExisted % Spells.entrapment.getProperty(Entrapment.DAMAGE_INTERVAL).intValue() == 0){ if(this.getCaster() != null){ WizardryUtilities.getRider(this).attackEntityFrom( MagicDamage.causeIndirectMagicDamage(this, getCaster(), DamageType.MAGIC), @@ -81,16 +84,16 @@ public class EntityBubble extends EntityMagicConstruct { (this.rand.nextDouble() - 0.5D) * 2.0D); } if(lifetime - this.ticksExisted == 75){ - this.playSound(SoundEvents.BLOCK_PORTAL_TRIGGER, 1.5f, 1.0f); + this.playSound(WizardrySounds.ENTITY_ENTRAPMENT_VANISH, 1.5f, 1.0f); }else if(this.ticksExisted % 100 == 1 && this.ticksExisted < 150){ - this.playSound(SoundEvents.BLOCK_PORTAL_AMBIENT, 1.5f, 1.0f); + this.playSound(WizardrySounds.ENTITY_ENTRAPMENT_AMBIENT, 1.5f, 1.0f); } } // Bubble bursts if the entity is hurt (see event handler) or killed, or if the bubble has existed for more than // 10 seconds. if(WizardryUtilities.getRider(this) == null && this.ticksExisted > 1){ - if(!this.isDarkOrb) this.playSound(SoundEvents.ENTITY_ITEM_PICKUP, 1.5f, 1.0f); + if(!this.isDarkOrb) this.playSound(WizardrySounds.ENTITY_BUBBLE_POP, 1.5f, 1.0f); this.setDead(); } } @@ -100,7 +103,7 @@ public class EntityBubble extends EntityMagicConstruct { if(WizardryUtilities.getRider(this) != null){ ((EntityLivingBase)WizardryUtilities.getRider(this)).dismountEntity(this); } - if(!this.isDarkOrb) this.playSound(SoundEvents.ENTITY_ITEM_PICKUP, 1.5f, 1.0f); + if(!this.isDarkOrb) this.playSound(WizardrySounds.ENTITY_BUBBLE_POP, 1.5f, 1.0f); super.despawn(); } @@ -133,7 +136,7 @@ public class EntityBubble extends EntityMagicConstruct { // Bursts bubble when the creature inside takes damage if(event.getEntityLiving().getRidingEntity() instanceof EntityBubble && !((EntityBubble)event.getEntityLiving().getRidingEntity()).isDarkOrb){ - event.getEntityLiving().getRidingEntity().playSound(SoundEvents.ENTITY_ITEM_PICKUP, 1.5f, 1.0f); + event.getEntityLiving().getRidingEntity().playSound(WizardrySounds.ENTITY_BUBBLE_POP, 1.5f, 1.0f); event.getEntityLiving().getRidingEntity().setDead(); } } diff --git a/src/main/java/electroblob/wizardry/entity/construct/EntityCombustionRune.java b/src/main/java/electroblob/wizardry/entity/construct/EntityCombustionRune.java new file mode 100644 index 00000000..f9188d6c --- /dev/null +++ b/src/main/java/electroblob/wizardry/entity/construct/EntityCombustionRune.java @@ -0,0 +1,58 @@ +package electroblob.wizardry.entity.construct; + +import electroblob.wizardry.registry.Spells; +import electroblob.wizardry.spell.Spell; +import electroblob.wizardry.util.WizardryUtilities; +import net.minecraft.entity.EntityLivingBase; +import net.minecraft.util.EnumParticleTypes; +import net.minecraft.util.math.MathHelper; +import net.minecraft.world.World; + +import java.util.List; + +public class EntityCombustionRune extends EntityMagicConstruct { + + public EntityCombustionRune(World world){ + super(world); + this.height = 0.2f; + this.width = 2.0f; + } + + @Override + public void onUpdate(){ + + super.onUpdate(); + + if(!this.world.isRemote){ + + List targets = WizardryUtilities.getEntitiesWithinRadius(width/2, posX, posY, posZ, world); + + for(EntityLivingBase target : targets){ + + if(this.isValidTarget(target)){ + + float strength = Spells.combustion_rune.getProperty(Spell.BLAST_RADIUS).floatValue(); + + world.newExplosion(this.getCaster(), this.posX, this.posY, this.posZ, strength, true, true); + + // The trap is destroyed once triggered. + this.setDead(); + } + } + }else if(this.rand.nextInt(15) == 0){ + double radius = 0.5 + rand.nextDouble() * 0.3; + float angle = rand.nextFloat() * (float)Math.PI * 2; + world.spawnParticle(EnumParticleTypes.FLAME, this.posX + radius * MathHelper.cos(angle), this.posY + 0.1, + this.posZ + radius * MathHelper.sin(angle), 0, 0, 0); + } + } + + @Override + protected void entityInit(){} + + @Override + public boolean canRenderOnFire(){ + return false; + } + +} diff --git a/src/main/java/electroblob/wizardry/entity/construct/EntityDecay.java b/src/main/java/electroblob/wizardry/entity/construct/EntityDecay.java index 7507cbca..e781a2d9 100644 --- a/src/main/java/electroblob/wizardry/entity/construct/EntityDecay.java +++ b/src/main/java/electroblob/wizardry/entity/construct/EntityDecay.java @@ -1,17 +1,20 @@ package electroblob.wizardry.entity.construct; -import java.util.List; - +import electroblob.wizardry.registry.Spells; import electroblob.wizardry.registry.WizardryPotions; +import electroblob.wizardry.registry.WizardrySounds; +import electroblob.wizardry.spell.Spell; import electroblob.wizardry.util.ParticleBuilder; import electroblob.wizardry.util.ParticleBuilder.Type; import electroblob.wizardry.util.WizardryUtilities; import net.minecraft.entity.EntityLivingBase; -import net.minecraft.init.SoundEvents; import net.minecraft.nbt.NBTTagCompound; import net.minecraft.potion.PotionEffect; +import net.minecraft.util.math.MathHelper; import net.minecraft.world.World; +import java.util.List; + public class EntityDecay extends EntityMagicConstruct { public int textureIndex = 0; @@ -29,7 +32,7 @@ public class EntityDecay extends EntityMagicConstruct { super.onUpdate(); if(this.rand.nextInt(700) == 0 && this.ticksExisted + 100 < lifetime) - this.playSound(SoundEvents.BLOCK_LAVA_AMBIENT, 0.2F + rand.nextFloat() * 0.2F, + this.playSound(WizardrySounds.ENTITY_DECAY_AMBIENT, 0.2F + rand.nextFloat() * 0.2F, 0.6F + rand.nextFloat() * 0.15F); if(!this.world.isRemote){ @@ -41,18 +44,19 @@ public class EntityDecay extends EntityMagicConstruct { // damaged each tick. // In this case, we do want particles to be shown. if(!target.isPotionActive(WizardryPotions.decay)) - target.addPotionEffect(new PotionEffect(WizardryPotions.decay, lifetime, 0)); + target.addPotionEffect(new PotionEffect(WizardryPotions.decay, + Spells.decay.getProperty(Spell.EFFECT_DURATION).intValue(), 0)); } } }else if(this.rand.nextInt(15) == 0){ double radius = rand.nextDouble() * 0.8; - double angle = rand.nextDouble() * Math.PI * 2; + float angle = rand.nextFloat() * (float)Math.PI * 2; float brightness = rand.nextFloat() * 0.4f; ParticleBuilder.create(Type.DARK_MAGIC) - .pos(this.posX + radius * Math.cos(angle), this.posY, this.posZ + radius * Math.sin(angle)) + .pos(this.posX + radius * MathHelper.cos(angle), this.posY, this.posZ + radius * MathHelper.sin(angle)) .clr(brightness, 0, brightness + 0.1f) .spawn(world); } diff --git a/src/main/java/electroblob/wizardry/entity/construct/EntityEarthquake.java b/src/main/java/electroblob/wizardry/entity/construct/EntityEarthquake.java index 4a26e83f..2a6f455a 100644 --- a/src/main/java/electroblob/wizardry/entity/construct/EntityEarthquake.java +++ b/src/main/java/electroblob/wizardry/entity/construct/EntityEarthquake.java @@ -1,7 +1,7 @@ package electroblob.wizardry.entity.construct; -import java.util.List; - +import electroblob.wizardry.registry.Spells; +import electroblob.wizardry.spell.Earthquake; import electroblob.wizardry.util.MagicDamage; import electroblob.wizardry.util.MagicDamage.DamageType; import electroblob.wizardry.util.WizardryUtilities; @@ -13,8 +13,11 @@ import net.minecraft.init.MobEffects; import net.minecraft.network.play.server.SPacketEntityVelocity; import net.minecraft.potion.PotionEffect; import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.MathHelper; import net.minecraft.world.World; +import java.util.List; + public class EntityEarthquake extends EntityMagicConstruct { public EntityEarthquake(World world){ @@ -27,21 +30,20 @@ public class EntityEarthquake extends EntityMagicConstruct { super.onUpdate(); + double speed = Spells.earthquake.getProperty(Earthquake.SPREAD_SPEED).doubleValue(); + if(!world.isRemote){ - double speed = 0.4; - // The further the earthquake is going to spread, the finer the angle increments. - for(double angle = 0; angle < 2 * Math.PI; angle += Math.PI / (lifetime * 1.5)){ + for(float angle = 0; angle < 2 * Math.PI; angle += Math.PI / (lifetime * 1.5)){ // Calculates coordinates for the block to be moved. The radius increases with time. The +1.5 is to - // leave - // blocks in the centre untouched. - int x = this.posX < 0 ? (int)(this.posX + ((this.ticksExisted * speed) + 1.5) * Math.sin(angle) - 1) - : (int)(this.posX + ((this.ticksExisted * speed) + 1.5) * Math.sin(angle)); + // leave blocks in the centre untouched. + int x = this.posX < 0 ? (int)(this.posX + ((this.ticksExisted * speed) + 1.5) * MathHelper.sin(angle) - 1) + : (int)(this.posX + ((this.ticksExisted * speed) + 1.5) * MathHelper.sin(angle)); int y = (int)(this.posY - 0.5); - int z = this.posZ < 0 ? (int)(this.posZ + ((this.ticksExisted * speed) + 1.5) * Math.cos(angle) - 1) - : (int)(this.posZ + ((this.ticksExisted * speed) + 1.5) * Math.cos(angle)); + int z = this.posZ < 0 ? (int)(this.posZ + ((this.ticksExisted * speed) + 1.5) * MathHelper.cos(angle) - 1) + : (int)(this.posZ + ((this.ticksExisted * speed) + 1.5) * MathHelper.cos(angle)); BlockPos pos = new BlockPos(x, y, z); @@ -58,50 +60,53 @@ public class EntityEarthquake extends EntityMagicConstruct { } } - List targets = WizardryUtilities - .getEntitiesWithinRadius((this.ticksExisted * speed) + 1.5, this.posX, this.posY, this.posZ, world); + } - // In this particular instance, the caster is completely unaffected because they will always be in the - // centre. - targets.remove(this.getCaster()); + List targets = WizardryUtilities + .getEntitiesWithinRadius((this.ticksExisted * speed) + 1.5, this.posX, this.posY, this.posZ, world); - for(EntityLivingBase target : targets){ + // In this particular instance, the caster is completely unaffected because they will always be in the + // centre. + targets.remove(this.getCaster()); - // Searches in a 1 wide ring. - if(this.getDistance(target) > (this.ticksExisted * speed) + 0.5 && target.posY < this.posY + 1 - && target.posY > this.posY - 1){ + for(EntityLivingBase target : targets){ - // Knockback must be removed in this instance, or the target will fall into the floor. - double motionX = target.motionX; - double motionZ = target.motionZ; + // Searches in a 1 wide ring. + if(this.getDistance(target) > (this.ticksExisted * speed) + 0.5 && target.posY < this.posY + 1 + && target.posY > this.posY - 1){ - if(this.isValidTarget(target)){ - target.attackEntityFrom( - MagicDamage.causeIndirectMagicDamage(this, this.getCaster(), DamageType.BLAST), - 10 * this.damageMultiplier); - target.addPotionEffect(new PotionEffect(MobEffects.WEAKNESS, 400, 1)); - } + // Knockback must be removed in this instance, or the target will fall into the floor. + double motionX = target.motionX; + double motionZ = target.motionZ; - // All targets are thrown, even those immune to the damage, so they don't fall into the ground. - target.motionX = motionX; - target.motionY = 0.8; // Throws target into the air. - target.motionZ = motionZ; + if(this.isValidTarget(target)){ + target.attackEntityFrom( + MagicDamage.causeIndirectMagicDamage(this, this.getCaster(), DamageType.BLAST), + 10 * this.damageMultiplier); + target.addPotionEffect(new PotionEffect(MobEffects.WEAKNESS, 400, 1)); + } - // Player motion is handled on that player's client so needs packets - if(target instanceof EntityPlayerMP){ - ((EntityPlayerMP)target).connection.sendPacket(new SPacketEntityVelocity(target)); - } + // All targets are thrown, even those immune to the damage, so they don't fall into the ground. + target.motionX = motionX; + target.motionY = 0.8; // Throws target into the air. + target.motionZ = motionZ; + + // Player motion is handled on that player's client so needs packets + if(target instanceof EntityPlayerMP){ + ((EntityPlayerMP)target).connection.sendPacket(new SPacketEntityVelocity(target)); } } - }else{ - // Constant 15 blocks for now - List targets = WizardryUtilities.getEntitiesWithinRadius(15, posX, posY, posZ, world, EntityPlayer.class); + } - float magnitude = 6f * ((float)(this.lifetime - this.ticksExisted))/(float)this.lifetime; + if(!world.isRemote){ + // Constant 15 blocks for now + List targets2 = WizardryUtilities.getEntitiesWithinRadius(15, posX, posY, posZ, world, EntityPlayer.class); + + float magnitude = 10f * ((float)(this.lifetime - this.ticksExisted))/(float)this.lifetime; // Makes the screen shake - for(EntityPlayer target : targets){ - target.rotationPitch = this.ticksExisted % 2 == 0 ? magnitude : -magnitude; + for(EntityPlayer target : targets2){ + target.rotationPitch += this.ticksExisted % 2 == 0 ? magnitude : -magnitude; } } } diff --git a/src/main/java/electroblob/wizardry/entity/construct/EntityFireRing.java b/src/main/java/electroblob/wizardry/entity/construct/EntityFireRing.java index 5037b3bf..e6e20e96 100644 --- a/src/main/java/electroblob/wizardry/entity/construct/EntityFireRing.java +++ b/src/main/java/electroblob/wizardry/entity/construct/EntityFireRing.java @@ -1,17 +1,21 @@ package electroblob.wizardry.entity.construct; -import java.util.List; - +import electroblob.wizardry.registry.Spells; +import electroblob.wizardry.registry.WizardrySounds; +import electroblob.wizardry.spell.Spell; import electroblob.wizardry.util.MagicDamage; import electroblob.wizardry.util.MagicDamage.DamageType; import electroblob.wizardry.util.WizardryUtilities; import net.minecraft.entity.EntityLivingBase; -import net.minecraft.init.SoundEvents; import net.minecraft.util.DamageSource; import net.minecraft.world.World; +import java.util.List; + public class EntityFireRing extends EntityMagicConstruct { + // TODO: Implement blast modifiers + public EntityFireRing(World world){ super(world); this.height = 1.0f; @@ -21,7 +25,7 @@ public class EntityFireRing extends EntityMagicConstruct { public void onUpdate(){ if(this.ticksExisted % 40 == 1){ - this.playSound(SoundEvents.BLOCK_FIRE_AMBIENT, 4.0f, 0.7f); + this.playSound(WizardrySounds.ENTITY_FIRE_RING_AMBIENT, 4.0f, 0.7f); } super.onUpdate(); @@ -41,14 +45,15 @@ public class EntityFireRing extends EntityMagicConstruct { if(!MagicDamage.isEntityImmune(DamageType.FIRE, target)){ - target.setFire(10); + target.setFire(Spells.ring_of_fire.getProperty(Spell.BURN_DURATION).intValue()); + + float damage = Spells.ring_of_fire.getProperty(Spell.DAMAGE).floatValue() * damageMultiplier; if(this.getCaster() != null){ - target.attackEntityFrom( - MagicDamage.causeIndirectMagicDamage(this, getCaster(), DamageType.FIRE), - 1 * damageMultiplier); + target.attackEntityFrom(MagicDamage.causeIndirectMagicDamage(this, getCaster(), + DamageType.FIRE), damage); }else{ - target.attackEntityFrom(DamageSource.MAGIC, 1 * damageMultiplier); + target.attackEntityFrom(DamageSource.MAGIC, damage); } } diff --git a/src/main/java/electroblob/wizardry/entity/construct/EntityFireSigil.java b/src/main/java/electroblob/wizardry/entity/construct/EntityFireSigil.java index bb6b7e34..509511ff 100644 --- a/src/main/java/electroblob/wizardry/entity/construct/EntityFireSigil.java +++ b/src/main/java/electroblob/wizardry/entity/construct/EntityFireSigil.java @@ -1,16 +1,19 @@ package electroblob.wizardry.entity.construct; -import java.util.List; - +import electroblob.wizardry.registry.Spells; +import electroblob.wizardry.registry.WizardrySounds; +import electroblob.wizardry.spell.Spell; import electroblob.wizardry.util.MagicDamage; import electroblob.wizardry.util.MagicDamage.DamageType; import electroblob.wizardry.util.WizardryUtilities; import net.minecraft.entity.EntityLivingBase; -import net.minecraft.init.SoundEvents; import net.minecraft.util.DamageSource; import net.minecraft.util.EnumParticleTypes; +import net.minecraft.util.math.MathHelper; import net.minecraft.world.World; +import java.util.List; + public class EntityFireSigil extends EntityMagicConstruct { public EntityFireSigil(World world){ @@ -38,16 +41,18 @@ public class EntityFireSigil extends EntityMagicConstruct { target.attackEntityFrom(this.getCaster() != null ? MagicDamage.causeIndirectMagicDamage(this, this.getCaster(), DamageType.FIRE) - : DamageSource.MAGIC, 6); + : DamageSource.MAGIC, Spells.fire_sigil.getProperty(Spell.DAMAGE).floatValue() + * damageMultiplier); // Removes knockback target.motionX = velX; target.motionY = velY; target.motionZ = velZ; - if(!MagicDamage.isEntityImmune(DamageType.FIRE, target)) target.setFire(10); + if(!MagicDamage.isEntityImmune(DamageType.FIRE, target)) + target.setFire(Spells.fire_sigil.getProperty(Spell.BURN_DURATION).intValue()); - this.playSound(SoundEvents.ENTITY_BLAZE_SHOOT, 1, 1); + this.playSound(WizardrySounds.ENTITY_FIRE_SIGIL_TRIGGER, 1, 1); // The trap is destroyed once triggered. this.setDead(); @@ -55,9 +60,9 @@ public class EntityFireSigil extends EntityMagicConstruct { } }else if(this.rand.nextInt(15) == 0){ double radius = 0.5 + rand.nextDouble() * 0.3; - double angle = rand.nextDouble() * Math.PI * 2; - world.spawnParticle(EnumParticleTypes.FLAME, this.posX + radius * Math.cos(angle), this.posY + 0.1, - this.posZ + radius * Math.sin(angle), 0, 0, 0); + float angle = rand.nextFloat() * (float)Math.PI * 2;; + world.spawnParticle(EnumParticleTypes.FLAME, this.posX + radius * MathHelper.cos(angle), this.posY + 0.1, + this.posZ + radius * MathHelper.sin(angle), 0, 0, 0); } } diff --git a/src/main/java/electroblob/wizardry/entity/construct/EntityForcefield.java b/src/main/java/electroblob/wizardry/entity/construct/EntityForcefield.java index 2a1ab31d..759b7cb9 100644 --- a/src/main/java/electroblob/wizardry/entity/construct/EntityForcefield.java +++ b/src/main/java/electroblob/wizardry/entity/construct/EntityForcefield.java @@ -1,37 +1,89 @@ package electroblob.wizardry.entity.construct; -import java.util.List; - +import electroblob.wizardry.Wizardry; +import electroblob.wizardry.entity.ICustomHitbox; +import electroblob.wizardry.entity.projectile.EntityMagicArrow; +import electroblob.wizardry.item.ItemArtefact; +import electroblob.wizardry.registry.WizardryItems; import electroblob.wizardry.registry.WizardrySounds; +import electroblob.wizardry.util.MagicDamage; import electroblob.wizardry.util.ParticleBuilder; import electroblob.wizardry.util.ParticleBuilder.Type; import electroblob.wizardry.util.WizardryUtilities; +import io.netty.buffer.ByteBuf; import net.minecraft.entity.Entity; import net.minecraft.entity.EntityLivingBase; +import net.minecraft.entity.item.EntityXPOrb; +import net.minecraft.entity.player.EntityPlayer; import net.minecraft.entity.player.EntityPlayerMP; +import net.minecraft.entity.projectile.EntityArrow; +import net.minecraft.entity.projectile.EntityThrowable; import net.minecraft.network.play.server.SPacketEntityVelocity; -import net.minecraft.util.DamageSource; import net.minecraft.util.math.AxisAlignedBB; +import net.minecraft.util.math.MathHelper; +import net.minecraft.util.math.Vec3d; import net.minecraft.world.World; +import net.minecraftforge.event.entity.living.LivingAttackEvent; +import net.minecraftforge.event.entity.player.PlayerInteractEvent; +import net.minecraftforge.event.world.ExplosionEvent; +import net.minecraftforge.fml.common.Mod; +import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; -public class EntityForcefield extends EntityMagicConstruct { +import javax.annotation.Nullable; +import java.util.Arrays; +import java.util.Comparator; +import java.util.List; + +@Mod.EventBusSubscriber +public class EntityForcefield extends EntityMagicConstruct implements ICustomHitbox { + + /** Extra radius to search around the forcefield for incoming entities. Any entities with a velocity greater than + * this could potentially penetrate the forcefield. */ + private static final double SEARCH_BORDER_SIZE = 4; + + private static final float BOUNCINESS = 0.2f; + + private float radius; public EntityForcefield(World world){ super(world); - this.height = 6; - this.width = 6; + setRadius(3); // Shouldn't be needed but it's a good failsafe + this.ignoreFrustumCheck = true; + this.noClip = true; + } + + public void setRadius(float radius){ + this.radius = radius; + this.height = 2 * radius; + this.width = 2 * radius; // y-3 because it needs to be centred on the given position - this.setEntityBoundingBox(new AxisAlignedBB(posX - 3, posY - 3, posZ - 3, posX + 3, posY + 3, posZ + 3)); + this.setEntityBoundingBox(new AxisAlignedBB(posX - radius, posY - radius, posZ - radius, + posX + radius, posY + radius, posZ + radius)); + } + + public float getRadius(){ + return radius; } @Override public boolean canBeCollidedWith(){ - return !this.isDead; + return false;//!this.isDead; } @Override public AxisAlignedBB getCollisionBox(Entity entity){ - return entity.getEntityBoundingBox(); + return null;//entity.getEntityBoundingBox(); + } + + @Nullable + @Override + public AxisAlignedBB getCollisionBoundingBox(){ + return super.getCollisionBoundingBox(); + } + + @Override + public boolean shouldRenderInPass(int pass){ + return pass == 1; } @Override @@ -39,48 +91,182 @@ public class EntityForcefield extends EntityMagicConstruct { super.onUpdate(); - if(!this.world.isRemote){ - // TESTME: This used to say posY+3, but I'm pretty sure that's wrong because of how the bounding box was set... - List targets = WizardryUtilities.getEntitiesWithinRadius(3.5, posX, posY, posZ, world); - - for(EntityLivingBase target : targets){ - if(this.isValidTarget(target)){ - double multiplier = (3.5 - target.getDistance(this.posX, this.posY, this.posZ)) * 0.1; - target.addVelocity((target.posX - this.posX) * multiplier, - (target.posY - this.posY) * multiplier, (target.posZ - this.posZ) * multiplier); - // Player motion is handled on that player's client so needs packets - if(target instanceof EntityPlayerMP){ - ((EntityPlayerMP)target).connection.sendPacket(new SPacketEntityVelocity(target)); + // New forcefield repulsion system: + // Searches for all entities near the forcefield and determines where they will be next tick. + // If they will be inside the forcefield next tick, sets their position and velocity such that they appear to + // bounce off the forcefield and creates impact particle effects and sounds where they hit it + + List targets = WizardryUtilities.getEntitiesWithinRadius(radius + SEARCH_BORDER_SIZE, posX, posY, posZ, world, Entity.class); + + targets.remove(this); + targets.removeIf(t -> t instanceof EntityXPOrb); // Gets annoying since they're attracted to the player + + // Ring of the defender allows players to shoot through their own forcefields + if(getCaster() instanceof EntityPlayer && ItemArtefact.isArtefactActive((EntityPlayer)getCaster(), + WizardryItems.ring_defender)){ + targets.removeIf(t -> t instanceof EntityMagicArrow && !this.isValidTarget(((EntityMagicArrow)t).getCaster()) + || t instanceof EntityThrowable && !this.isValidTarget(((EntityThrowable)t).getThrower()) + || t instanceof EntityArrow && !this.isValidTarget(((EntityArrow)t).shootingEntity)); + } + + for(Entity target : targets){ + + if(this.isValidTarget(target)){ + + Vec3d currentPos = Arrays.stream(WizardryUtilities.getVertices(target.getEntityBoundingBox())) + .min(Comparator.comparingDouble(v -> v.distanceTo(this.getPositionVector()))) + .orElse(target.getPositionVector()); // This will never happen, it's just here to make the compiler happy + + double currentDistance = target.getDistance(this); + + // Estimate the target's position next tick + // We have to assume the same vertex is closest or the velocity will be wrong + Vec3d nextTickPos = currentPos.add(target.motionX, target.motionY, target.motionZ); + double nextTickDistance = nextTickPos.distanceTo(this.getPositionVector()); + + boolean flag; + + if(WizardryUtilities.isLiving(target)){ + // Non-allied living entities shouldn't be inside at all + flag = nextTickDistance <= radius; + }else{ + // Non-living entities will bounce off if they hit the forcefield within the next tick... + flag = (currentDistance > radius && nextTickDistance <= radius) // ...from the outside... + || (currentDistance < radius && nextTickDistance >= radius); // ...or from the inside + } + + if(flag){ + + // Ring of interdiction + if(getCaster() instanceof EntityPlayer && ItemArtefact.isArtefactActive((EntityPlayer)getCaster(), + WizardryItems.ring_interdiction) && WizardryUtilities.isLiving(target)){ + target.attackEntityFrom(MagicDamage.causeIndirectMagicDamage(this, getCaster(), + MagicDamage.DamageType.MAGIC), 1); + } + + Vec3d targetRelativePos = currentPos.subtract(this.getPositionVector()); + + double nudgeVelocity = this.contains(target) ? -0.1 : 0.1; + if(WizardryUtilities.isLiving(target)) nudgeVelocity = 0.25; + Vec3d extraVelocity = targetRelativePos.normalize().scale(nudgeVelocity); + + // ...make it bounce off! + target.motionX = target.motionX * -BOUNCINESS + extraVelocity.x; + target.motionY = target.motionY * -BOUNCINESS + extraVelocity.y; + target.motionZ = target.motionZ * -BOUNCINESS + extraVelocity.z; + + // Prevents the forcefield bouncing things into the floor + if(target.onGround && target.motionY < 0) target.motionY = 0.1; + + // How far the target needs to move towards the centre (negative means away from the centre) + double distanceTowardsCentre = -(targetRelativePos.length() - radius) - (radius - nextTickDistance); + Vec3d targetNewPos = target.getPositionVector().add(targetRelativePos.normalize().scale(distanceTowardsCentre)); + target.setPosition(targetNewPos.x, targetNewPos.y, targetNewPos.z); + + world.playSound(target.posX, target.posY, target.posZ, WizardrySounds.ENTITY_FORCEFIELD_DEFLECT, + WizardrySounds.SPELLS, 0.3f, 1.3f, false); + + if(!world.isRemote){ + // Player motion is handled on that player's client so needs packets + if(target instanceof EntityPlayerMP){ + ((EntityPlayerMP)target).connection.sendPacket(new SPacketEntityVelocity(target)); + } + + }else{ + + Vec3d relativeImpactPos = targetRelativePos.normalize().scale(radius); + + float yaw = (float)Math.atan2(relativeImpactPos.x, -relativeImpactPos.z); + float pitch = (float)Math.asin(relativeImpactPos.y/ radius); + + ParticleBuilder.create(Type.FLASH).pos(this.getPositionVector().add(relativeImpactPos)) + .time(6).face((float)(yaw * 180/Math.PI), (float)(pitch * 180/Math.PI)) + .clr(0.9f, 0.95f, 1).spawn(world); + + for(int i = 0; i < 12; i++){ + + float yaw1 = yaw + 0.3f * (rand.nextFloat() - 0.5f) - (float)Math.PI/2; + float pitch1 = pitch + 0.3f * (rand.nextFloat() - 0.5f); + + float brightness = rand.nextFloat(); + + double r = radius + 0.05; + double x = this.posX + r * MathHelper.cos(yaw1) * MathHelper.cos(pitch1); + double y = this.posY + r * MathHelper.sin(pitch1); + double z = this.posZ + r * MathHelper.sin(yaw1) * MathHelper.cos(pitch1); + + ParticleBuilder.create(Type.DUST).pos(x, y, z).time(6 + rand.nextInt(6)) + .face((float)(yaw1 * 180/Math.PI) + 90, (float)(pitch1 * 180/Math.PI)).scale(1.5f) + .clr(0.7f + 0.3f * brightness, 0.85f + 0.15f * brightness, 1).spawn(world); + } } } } - }else{ - for(int i = 1; i < 40; i++){ - - // Generates a spherical pattern of particles - float brightness = 0.5f + (rand.nextFloat() * 0.5f); - double radius = 3; - double yaw = rand.nextDouble() * Math.PI * 2; - double pitch = (rand.nextDouble() - 0.5) * Math.PI; - - ParticleBuilder.create(Type.DUST) - .pos(this.posX + radius * Math.cos(yaw) * Math.cos(pitch), this.posY + 3 + radius * Math.sin(pitch), - this.posZ + radius * Math.sin(yaw) * Math.cos(pitch)) - .time(48 + this.rand.nextInt(12)) - .clr(brightness, brightness, 1.0f).spawn(world); - } } } @Override - public boolean attackEntityFrom(DamageSource source, float damage){ + public boolean contains(Vec3d vec){ + return vec.distanceTo(this.getPositionVector()) < radius; // The surface counts as outside + } - if(source != null && source.getImmediateSource() != null){ - // Now works for any source of damage. - source.getImmediateSource().playSound(WizardrySounds.SPELL_DEFLECTION, 0.3f, 1.3f); + /** Returns true if the given bounding box is completely inside this forcefield (the surface counts as outside). */ + public boolean contains(AxisAlignedBB box){ + return Arrays.stream(WizardryUtilities.getVertices(box)).allMatch(this::contains); + } + + /** Returns true if the given entity is completely inside this forcefield (the surface counts as outside). */ + public boolean contains(Entity entity){ + return contains(entity.getEntityBoundingBox()); + } + + @Override + public Vec3d calculateIntercept(Vec3d origin, Vec3d endpoint, float fuzziness){ + + // We want the intercept between the line and a sphere + // First we need to find the point where the line is closest to the centre + // Then we can use a bit of geometry to find the intercept + + // Find the closest point to the centre + // http://mathworld.wolfram.com/Point-LineDistance3-Dimensional.html + Vec3d line = endpoint.subtract(origin); + double t = -origin.subtract(this.getPositionVector()).dotProduct(line) / line.lengthSquared(); + Vec3d closestPoint = origin.add(line.scale(t)); + // Now calculate the distance from that point to the centre (squared because that's all we need) + double dsquared = closestPoint.squareDistanceTo(this.getPositionVector()); + double rsquared = Math.pow(radius + fuzziness, 2); + // If the minimum distance is outside the radius (plus fuzziness) then there is no intercept + if(dsquared > rsquared) return null; + // Now do pythagoras to find the other side of the triangle, which is the distance along the line from + // the closest point to the edge of the sphere, and go that far back towards the origin - and that's it! + return closestPoint.subtract(line.normalize().scale(MathHelper.sqrt(rsquared - dsquared))); + } + + // Need to sync the caster because we're now dealing with client-side motion + + @Override + public void writeSpawnData(ByteBuf data){ + super.writeSpawnData(data); + data.writeFloat(getRadius()); + if(getCaster() != null) data.writeInt(getCaster().getEntityId()); + } + + @Override + public void readSpawnData(ByteBuf data){ + + super.readSpawnData(data); + + setRadius(data.readFloat()); + + if(!data.isReadable()) return; + + Entity entity = world.getEntityByID(data.readInt()); + + if(entity instanceof EntityLivingBase){ + setCaster((EntityLivingBase)entity); + }else{ + Wizardry.logger.warn("Forcefield caster with ID in spawn data not found"); } - super.attackEntityFrom(source, damage); - return false; } @Override @@ -88,4 +274,91 @@ public class EntityForcefield extends EntityMagicConstruct { return false; } + // Prevents any kind of interactions or attacks through the forcefield + // We may as well include projectile damage for this, then it will act as a failsafe + + @SubscribeEvent + public static void onLivingAttackEvent(LivingAttackEvent event){ + + if(event.getSource().getTrueSource() instanceof EntityPlayer && event.getSource().isProjectile() + && ItemArtefact.isArtefactActive((EntityPlayer)event.getSource().getTrueSource(), WizardryItems.ring_defender)){ + return; // Players wearing a ring of the defender can shoot stuff as normal, so don't cancel the event + } + + if(!event.getSource().isUnblockable() && event.getSource().getTrueSource() != null && event.getEntityLiving() != null + && !(event.getSource().getImmediateSource() instanceof EntityForcefield)){ // If the damage was from a forcefield that's ok + // This condition will be false if both entities are outside a forcefield or both are in the same one + if(getSurroundingForcefield(event.getEntityLiving()) != getSurroundingForcefield(event.getSource().getTrueSource())){ + event.setCanceled(true); + } + } + } + + @Nullable + private static EntityForcefield getSurroundingForcefield(World world, Vec3d vec){ + + double searchRadius = 20; + + List forcefields = WizardryUtilities.getEntitiesWithinRadius(searchRadius, vec.x, + vec.y, vec.z, world, EntityForcefield.class); + + forcefields.removeIf(f -> !f.contains(vec)); + // There should only be one left at this point since we now have anti-overlap, but commands might bypass that + return forcefields.stream().min(Comparator.comparingDouble(f -> vec.squareDistanceTo(f.getPositionVector()))) + .orElse(null); + } + + @Nullable + private static EntityForcefield getSurroundingForcefield(World world, AxisAlignedBB box, Vec3d vec){ + + double searchRadius = 20; + + List forcefields = WizardryUtilities.getEntitiesWithinRadius(searchRadius, vec.x, + vec.y, vec.z, world, EntityForcefield.class); + + forcefields.removeIf(f -> !f.contains(box)); + // There should only be one left at this point since we now have anti-overlap, but commands might bypass that + return forcefields.stream().min(Comparator.comparingDouble(f -> vec.squareDistanceTo(f.getPositionVector()))) + .orElse(null); + } + + @Nullable + private static EntityForcefield getSurroundingForcefield(Entity entity){ + return getSurroundingForcefield(entity.world, entity.getEntityBoundingBox(), entity.getPositionVector()); + } + + @SubscribeEvent + public static void onPlayerInteractEvent(PlayerInteractEvent event){ + + if(!event.isCancelable()) return; // We don't care about clicking empty space + + // For some reason block bounding boxes are relative whereas entity bounding boxes are absolute + AxisAlignedBB box = event.getWorld().getBlockState(event.getPos()).getBoundingBox(event.getWorld(), event.getPos()) + .offset(event.getPos().getX(), event.getPos().getY(), event.getPos().getZ()); + + if(event instanceof PlayerInteractEvent.EntityInteract){ + box = ((PlayerInteractEvent.EntityInteract)event).getTarget().getEntityBoundingBox(); + }else if(event instanceof PlayerInteractEvent.EntityInteractSpecific){ + box = ((PlayerInteractEvent.EntityInteractSpecific)event).getTarget().getEntityBoundingBox(); + } + + // If the player is trying to interact across a forcefield boundary, cancel the event + // The most pragmatic solution here is to use the centres - it's not perfect, but it's simple! + if(getSurroundingForcefield(event.getWorld(), WizardryUtilities.getCentre(box)) + != getSurroundingForcefield(event.getWorld(), event.getEntityPlayer().getPositionVector())){ + event.setCanceled(true); + } + } + + @SubscribeEvent + public static void onExplosionEvent(ExplosionEvent event){ + + EntityForcefield forcefield = getSurroundingForcefield(event.getWorld(), event.getExplosion().getPosition()); + // Not a particularly efficient way of doing it but explosions are laggy anyway, and the code is neat :P + event.getExplosion().getAffectedBlockPositions().removeIf(p -> getSurroundingForcefield(event.getWorld(), + new Vec3d(p).add(0.5, 0.5, 0.5)) != forcefield); + + event.getExplosion().getPlayerKnockbackMap().keySet().removeIf(p -> getSurroundingForcefield(p) != forcefield); + } + } diff --git a/src/main/java/electroblob/wizardry/entity/construct/EntityFrostSigil.java b/src/main/java/electroblob/wizardry/entity/construct/EntityFrostSigil.java index 1632335b..690e7ec8 100644 --- a/src/main/java/electroblob/wizardry/entity/construct/EntityFrostSigil.java +++ b/src/main/java/electroblob/wizardry/entity/construct/EntityFrostSigil.java @@ -1,9 +1,9 @@ package electroblob.wizardry.entity.construct; -import java.util.List; - +import electroblob.wizardry.registry.Spells; import electroblob.wizardry.registry.WizardryPotions; import electroblob.wizardry.registry.WizardrySounds; +import electroblob.wizardry.spell.Spell; import electroblob.wizardry.util.MagicDamage; import electroblob.wizardry.util.MagicDamage.DamageType; import electroblob.wizardry.util.ParticleBuilder; @@ -12,8 +12,11 @@ import electroblob.wizardry.util.WizardryUtilities; import net.minecraft.entity.EntityLivingBase; import net.minecraft.potion.PotionEffect; import net.minecraft.util.DamageSource; +import net.minecraft.util.math.MathHelper; import net.minecraft.world.World; +import java.util.List; + public class EntityFrostSigil extends EntityMagicConstruct { public EntityFrostSigil(World world){ @@ -38,12 +41,15 @@ public class EntityFrostSigil extends EntityMagicConstruct { WizardryUtilities.attackEntityWithoutKnockback(target, this.getCaster() != null ? MagicDamage.causeIndirectMagicDamage(this, this.getCaster(), DamageType.FROST) - : DamageSource.MAGIC, 8); + : DamageSource.MAGIC, Spells.frost_sigil.getProperty(Spell.DAMAGE).floatValue() + * damageMultiplier); if(!MagicDamage.isEntityImmune(DamageType.FROST, target)) - target.addPotionEffect(new PotionEffect(WizardryPotions.frost, 200, 1)); + target.addPotionEffect(new PotionEffect(WizardryPotions.frost, + Spells.frost_sigil.getProperty(Spell.EFFECT_DURATION).intValue(), + Spells.frost_sigil.getProperty(Spell.EFFECT_STRENGTH).intValue())); - this.playSound(WizardrySounds.SPELL_FREEZE, 1.0f, 1.0f); + this.playSound(WizardrySounds.ENTITY_FROST_SIGIL_TRIGGER, 1.0f, 1.0f); // The trap is destroyed once triggered. this.setDead(); @@ -51,9 +57,9 @@ public class EntityFrostSigil extends EntityMagicConstruct { } }else if(this.rand.nextInt(15) == 0){ double radius = 0.5 + rand.nextDouble() * 0.3; - double angle = rand.nextDouble() * Math.PI * 2; + float angle = rand.nextFloat() * (float)Math.PI * 2;; ParticleBuilder.create(Type.SNOW) - .pos(this.posX + radius * Math.cos(angle), this.posY + 0.1, this.posZ + radius * Math.sin(angle)) + .pos(this.posX + radius * MathHelper.cos(angle), this.posY + 0.1, this.posZ + radius * MathHelper.sin(angle)) .vel(0, 0, 0) // Required since default for snow is not stationary .spawn(world); } diff --git a/src/main/java/electroblob/wizardry/entity/construct/EntityHailstorm.java b/src/main/java/electroblob/wizardry/entity/construct/EntityHailstorm.java index 6a2baaab..f792d4ef 100644 --- a/src/main/java/electroblob/wizardry/entity/construct/EntityHailstorm.java +++ b/src/main/java/electroblob/wizardry/entity/construct/EntityHailstorm.java @@ -1,6 +1,7 @@ package electroblob.wizardry.entity.construct; import electroblob.wizardry.entity.projectile.EntityIceShard; +import net.minecraft.util.math.MathHelper; import net.minecraft.world.World; public class EntityHailstorm extends EntityMagicConstruct { @@ -20,9 +21,9 @@ public class EntityHailstorm extends EntityMagicConstruct { EntityIceShard iceshard = new EntityIceShard(world); iceshard.setPosition(this.posX + rand.nextDouble() * 6 - 3, this.posY + rand.nextDouble() * 4 - 2, this.posZ + rand.nextDouble() * 6 - 3); - iceshard.motionX = Math.cos(Math.toRadians(this.rotationYaw + 90)); + iceshard.motionX = MathHelper.cos((float)Math.toRadians(this.rotationYaw + 90)); iceshard.motionY = -0.6; - iceshard.motionZ = Math.sin(Math.toRadians(this.rotationYaw + 90)); + iceshard.motionZ = MathHelper.sin((float)Math.toRadians(this.rotationYaw + 90)); iceshard.setCaster(this.getCaster()); iceshard.damageMultiplier = this.damageMultiplier; this.world.spawnEntity(iceshard); diff --git a/src/main/java/electroblob/wizardry/entity/construct/EntityHammer.java b/src/main/java/electroblob/wizardry/entity/construct/EntityHammer.java index 80bec470..8a56a293 100644 --- a/src/main/java/electroblob/wizardry/entity/construct/EntityHammer.java +++ b/src/main/java/electroblob/wizardry/entity/construct/EntityHammer.java @@ -1,32 +1,44 @@ package electroblob.wizardry.entity.construct; -import java.util.List; - import electroblob.wizardry.Wizardry; +import electroblob.wizardry.item.ItemArtefact; +import electroblob.wizardry.item.ItemLightningHammer; +import electroblob.wizardry.registry.Spells; +import electroblob.wizardry.registry.WizardryItems; import electroblob.wizardry.registry.WizardrySounds; +import electroblob.wizardry.spell.LightningHammer; +import electroblob.wizardry.spell.Spell; import electroblob.wizardry.util.MagicDamage; import electroblob.wizardry.util.MagicDamage.DamageType; import electroblob.wizardry.util.ParticleBuilder; import electroblob.wizardry.util.ParticleBuilder.Type; import electroblob.wizardry.util.WizardryUtilities; +import io.netty.buffer.ByteBuf; import net.minecraft.block.Block; import net.minecraft.block.state.IBlockState; +import net.minecraft.entity.Entity; import net.minecraft.entity.EntityLivingBase; import net.minecraft.entity.MoverType; import net.minecraft.entity.effect.EntityLightningBolt; -import net.minecraft.init.SoundEvents; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.item.ItemStack; import net.minecraft.nbt.NBTTagCompound; import net.minecraft.util.DamageSource; +import net.minecraft.util.EnumHand; import net.minecraft.util.EnumParticleTypes; import net.minecraft.util.math.AxisAlignedBB; import net.minecraft.util.math.BlockPos; import net.minecraft.world.World; +import java.util.List; + public class EntityHammer extends EntityMagicConstruct { /** How long the hammer has been falling for. */ public int fallTime; + public boolean spin = false; + public EntityHammer(World world){ super(world); this.setSize(1.0f, 1.9F); @@ -51,15 +63,20 @@ public class EntityHammer extends EntityMagicConstruct { return this.getEntityBoundingBox(); } + @Override + public void applyEntityCollision(Entity entity){ + super.applyEntityCollision(entity); + } + @Override public void onUpdate(){ super.onUpdate(); - if(this.ticksExisted % 20 == 1 && !this.onGround && world.isRemote){ - // Though this sound does repeat, it stops when it hits the ground. - Wizardry.proxy.playMovingSound(this, WizardrySounds.SPELL_LOOP_LIGHTNING, 3.0f, 1.0f, false); - } +// if(this.ticksExisted % 20 == 1 && !this.onGround && world.isRemote){ +// // Though this sound does repeat, it stops when it hits the ground. +// Wizardry.proxy.playMovingSound(this, WizardrySounds.ENTITY_HAMMER_FALLING, WizardrySounds.SPELLS, 3.0f, 1.0f, false); +// } if(this.world.isRemote && this.ticksExisted % 3 == 0){ ParticleBuilder.create(Type.SPARK) @@ -67,65 +84,81 @@ public class EntityHammer extends EntityMagicConstruct { .spawn(world); } - if(!this.world.isRemote){ + this.prevPosX = this.posX; + this.prevPosY = this.posY; + this.prevPosZ = this.posZ; + ++this.fallTime; + this.motionY -= 0.03999999910593033D; + this.move(MoverType.SELF, this.motionX, this.motionY, this.motionZ); + this.motionX *= 0.9800000190734863D; + this.motionY *= 0.9800000190734863D; + this.motionZ *= 0.9800000190734863D; - this.prevPosX = this.posX; - this.prevPosY = this.posY; - this.prevPosZ = this.posZ; - ++this.fallTime; - this.motionY -= 0.03999999910593033D; - this.move(MoverType.SELF, this.motionX, this.motionY, this.motionZ); - this.motionX *= 0.9800000190734863D; - this.motionY *= 0.9800000190734863D; - this.motionZ *= 0.9800000190734863D; + if(this.onGround){ - if(this.onGround){ + this.motionX *= 0.699999988079071D; + this.motionZ *= 0.699999988079071D; + this.motionY *= -0.5D; - this.motionX *= 0.699999988079071D; - this.motionZ *= 0.699999988079071D; - this.motionY *= -0.5D; + this.rotationPitch = 0; + this.spin = false; - if(this.ticksExisted % 40 == 0){ + if(this.ticksExisted % Spells.lightning_hammer.getProperty(LightningHammer.ATTACK_INTERVAL).floatValue() == 0){ - double seekerRange = 10.0d; + double seekerRange = Spells.lightning_hammer.getProperty(Spell.EFFECT_RADIUS).doubleValue(); - List targets = WizardryUtilities.getEntitiesWithinRadius(seekerRange, this.posX, - this.posY + 1, this.posZ, world); + List targets = WizardryUtilities.getEntitiesWithinRadius(seekerRange, this.posX, + this.posY + 1, this.posZ, world); - // For this spell there is no limit to the amount of secondary targets! - for(EntityLivingBase target : targets){ + int maxTargets = Spells.lightning_hammer.getProperty(LightningHammer.SECONDARY_MAX_TARGETS).intValue(); + while(targets.size() > maxTargets) targets.remove(targets.size() - 1); - if(this.isValidTarget(target)){ + for(EntityLivingBase target : targets){ - if(world.isRemote){ - - ParticleBuilder.create(Type.LIGHTNING).pos(posX, posY + height - 0.1, posZ) .target(target).spawn(world); - - ParticleBuilder.spawnShockParticles(world, target.posX, - target.getEntityBoundingBox().minY + target.height, target.posZ); - } + if(WizardryUtilities.isLiving(target) && this.isValidTarget(target)){ - target.playSound(WizardrySounds.SPELL_SPARK, 1.0F, rand.nextFloat() * 0.4F + 1.5F); + if(world.isRemote){ - if(this.getCaster() != null){ - WizardryUtilities.attackEntityWithoutKnockback(target, - MagicDamage.causeIndirectMagicDamage(this, getCaster(), DamageType.SHOCK), - 6 * damageMultiplier); - WizardryUtilities.applyStandardKnockback(this, target); - }else{ - target.attackEntityFrom(DamageSource.MAGIC, 6 * damageMultiplier); - } + ParticleBuilder.create(Type.LIGHTNING).pos(posX, posY + height - 0.1, posZ) .target(target).spawn(world); + + ParticleBuilder.spawnShockParticles(world, target.posX, + target.getEntityBoundingBox().minY + target.height, target.posZ); + } + + target.playSound(WizardrySounds.ENTITY_HAMMER_ATTACK, 1.0F, rand.nextFloat() * 0.4F + 1.5F); + + float damage = Spells.lightning_hammer.getProperty(Spell.SPLASH_DAMAGE).floatValue() * damageMultiplier; + + if(this.getCaster() != null){ + WizardryUtilities.attackEntityWithoutKnockback(target, MagicDamage.causeIndirectMagicDamage( + this, getCaster(), DamageType.SHOCK), damage); + WizardryUtilities.applyStandardKnockback(this, target); + }else{ + target.attackEntityFrom(DamageSource.MAGIC, damage); } } } } + + }else{ + + if(spin) this.setRotation(this.rotationYaw, this.rotationPitch + 15); + + List collided = world.getEntitiesInAABBexcluding(this, this.getCollisionBoundingBox(), e -> e instanceof EntityLivingBase); + + float damage = Spells.lightning_hammer.getProperty(Spell.DIRECT_DAMAGE).floatValue() * damageMultiplier; + + for(Entity entity : collided){ + entity.attackEntityFrom(MagicDamage.causeIndirectMagicDamage(this, getCaster(), DamageType.SHOCK), damage); + //if(entity instanceof EntityLivingBase) ((EntityLivingBase)entity).knockBack(this, 2, -this.motionX, -this.motionZ); + } } } @Override public void despawn(){ - this.playSound(SoundEvents.ENTITY_GENERIC_EXPLODE, 1.0F, 1.0f); + this.playSound(WizardrySounds.ENTITY_HAMMER_EXPLODE, 1.0F, 1.0f); if(this.world.isRemote){ this.world.spawnParticle(EnumParticleTypes.EXPLOSION_LARGE, this.posX, this.posY, this.posZ, 0, 0, 0); @@ -156,6 +189,30 @@ public class EntityHammer extends EntityMagicConstruct { false); world.addWeatherEffect(entitylightning); } + + this.playSound(WizardrySounds.ENTITY_HAMMER_LAND, 1.0F, 0.6f); + } + } + + @Override + public boolean processInitialInteract(EntityPlayer player, EnumHand hand){ + + if(player == this.getCaster() && ItemArtefact.isArtefactActive(player, WizardryItems.ring_hammer) + && player.getHeldItemMainhand().isEmpty() && ticksExisted > 10){ + + this.setDead(); + + ItemStack hammer = new ItemStack(WizardryItems.lightning_hammer); + if(!hammer.hasTagCompound()) hammer.setTagCompound(new NBTTagCompound()); + hammer.getTagCompound().setInteger(ItemLightningHammer.DURATION_NBT_KEY, lifetime); + hammer.setItemDamage(ticksExisted); + hammer.getTagCompound().setFloat(ItemLightningHammer.DAMAGE_MULTIPLIER_NBT_KEY, damageMultiplier); + + player.setHeldItem(EnumHand.MAIN_HAND, hammer); + return true; + + }else{ + return super.processInitialInteract(player, hand); } } @@ -163,12 +220,39 @@ public class EntityHammer extends EntityMagicConstruct { public void writeEntityToNBT(NBTTagCompound nbttagcompound){ super.writeEntityToNBT(nbttagcompound); nbttagcompound.setByte("Time", (byte)this.fallTime); + nbttagcompound.setBoolean("Spin", spin); } @Override public void readEntityFromNBT(NBTTagCompound nbttagcompound){ super.readEntityFromNBT(nbttagcompound); this.fallTime = nbttagcompound.getByte("Time") & 255; + this.spin = nbttagcompound.getBoolean("Spin"); + } + + // Need to sync the caster so they don't have particles spawned at them + + @Override + public void writeSpawnData(ByteBuf data){ + super.writeSpawnData(data); + data.writeBoolean(spin); + if(getCaster() != null) data.writeInt(getCaster().getEntityId()); + } + + @Override + public void readSpawnData(ByteBuf data){ + super.readSpawnData(data); + spin = data.readBoolean(); + + if(!data.isReadable()) return; + + Entity entity = world.getEntityByID(data.readInt()); + + if(entity instanceof EntityLivingBase){ + setCaster((EntityLivingBase)entity); + }else{ + Wizardry.logger.warn("Lightning hammer caster with ID in spawn data not found"); + } } @Override diff --git a/src/main/java/electroblob/wizardry/entity/construct/EntityHealAura.java b/src/main/java/electroblob/wizardry/entity/construct/EntityHealAura.java index 14406109..df3dd462 100644 --- a/src/main/java/electroblob/wizardry/entity/construct/EntityHealAura.java +++ b/src/main/java/electroblob/wizardry/entity/construct/EntityHealAura.java @@ -1,8 +1,8 @@ package electroblob.wizardry.entity.construct; -import java.util.List; - +import electroblob.wizardry.registry.Spells; import electroblob.wizardry.registry.WizardrySounds; +import electroblob.wizardry.spell.Spell; import electroblob.wizardry.util.MagicDamage; import electroblob.wizardry.util.MagicDamage.DamageType; import electroblob.wizardry.util.ParticleBuilder; @@ -10,10 +10,15 @@ import electroblob.wizardry.util.ParticleBuilder.Type; import electroblob.wizardry.util.WizardryUtilities; import net.minecraft.entity.EntityLivingBase; import net.minecraft.util.DamageSource; +import net.minecraft.util.math.MathHelper; import net.minecraft.world.World; +import java.util.List; + public class EntityHealAura extends EntityMagicConstruct { + // TODO: Implement blast modifiers + public EntityHealAura(World world){ super(world); this.height = 1.0f; @@ -24,7 +29,7 @@ public class EntityHealAura extends EntityMagicConstruct { public void onUpdate(){ if(this.ticksExisted % 25 == 1){ - this.playSound(WizardrySounds.SPELL_LOOP_SPARKLE, 0.1f, 1.0f); + this.playSound(WizardrySounds.ENTITY_HEAL_AURA_AMBIENT, 0.1f, 1.0f); } super.onUpdate(); @@ -46,9 +51,9 @@ public class EntityHealAura extends EntityMagicConstruct { if(this.getCaster() != null){ target.attackEntityFrom( MagicDamage.causeIndirectMagicDamage(this, getCaster(), DamageType.RADIANT), - 1 * damageMultiplier); + Spells.healing_aura.getProperty(Spell.DAMAGE).floatValue() * damageMultiplier); }else{ - target.attackEntityFrom(DamageSource.MAGIC, 1 * damageMultiplier); + target.attackEntityFrom(DamageSource.MAGIC, Spells.healing_aura.getProperty(Spell.DAMAGE).floatValue() * damageMultiplier); } // Removes knockback @@ -58,16 +63,16 @@ public class EntityHealAura extends EntityMagicConstruct { } }else if(target.getHealth() < target.getMaxHealth() && this.ticksExisted % 5 == 0){ - target.heal(1 * damageMultiplier); + target.heal(Spells.healing_aura.getProperty(Spell.HEALTH).floatValue() * damageMultiplier); } } }else{ for(int i=1; i<3; i++){ float brightness = 0.5f + (rand.nextFloat() * 0.5f); double radius = rand.nextDouble() * 2.0; - double angle = rand.nextDouble() * Math.PI * 2; + float angle = rand.nextFloat() * (float)Math.PI * 2;; ParticleBuilder.create(Type.SPARKLE) - .pos(this.posX + radius * Math.cos(angle), this.posY, this.posZ + radius * Math.sin(angle)) + .pos(this.posX + radius * MathHelper.cos(angle), this.posY, this.posZ + radius * MathHelper.sin(angle)) .vel(0, 0.05, 0) .time(48 + this.rand.nextInt(12)) .clr(1.0f, 1.0f, brightness) diff --git a/src/main/java/electroblob/wizardry/entity/construct/EntityIceSpike.java b/src/main/java/electroblob/wizardry/entity/construct/EntityIceSpike.java index 86817bb4..75a83bc4 100644 --- a/src/main/java/electroblob/wizardry/entity/construct/EntityIceSpike.java +++ b/src/main/java/electroblob/wizardry/entity/construct/EntityIceSpike.java @@ -1,35 +1,62 @@ package electroblob.wizardry.entity.construct; +import electroblob.wizardry.registry.Spells; import electroblob.wizardry.registry.WizardryPotions; import electroblob.wizardry.registry.WizardrySounds; +import electroblob.wizardry.spell.Spell; import electroblob.wizardry.util.MagicDamage; import electroblob.wizardry.util.MagicDamage.DamageType; +import electroblob.wizardry.util.WizardryUtilities; import net.minecraft.entity.EntityLivingBase; import net.minecraft.entity.MoverType; import net.minecraft.potion.PotionEffect; +import net.minecraft.util.EnumFacing; +import net.minecraft.util.math.AxisAlignedBB; +import net.minecraft.util.math.Vec3d; import net.minecraft.world.World; public class EntityIceSpike extends EntityMagicConstruct { + private EnumFacing facing; + public EntityIceSpike(World world){ super(world); this.setSize(0.5f, 1.0f); } + public void setFacing(EnumFacing facing){ + this.facing = facing; + this.setRotation(-facing.getHorizontalAngle(), WizardryUtilities.getPitch(facing)); + float yaw = (-facing.getHorizontalAngle()) * (float)Math.PI/180; + float pitch = (WizardryUtilities.getPitch(facing) - 90) * (float)Math.PI/180; + Vec3d min = new Vec3d(-width/2, 0, -width/2).rotatePitch(pitch).rotateYaw(yaw); + Vec3d max = new Vec3d(width/2, height, width/2).rotatePitch(pitch).rotateYaw(yaw); + this.setEntityBoundingBox(new AxisAlignedBB(this.getPositionVector().add(min), this.getPositionVector().add(max))); + } + + public EnumFacing getFacing(){ + return facing; + } + @Override public void onUpdate(){ + double extensionSpeed = 0; + if(lifetime - this.ticksExisted < 15){ - this.motionY = -0.01 * (this.ticksExisted - (lifetime - 15)); + extensionSpeed = -0.01 * (this.ticksExisted - (lifetime - 15)); }else if(lifetime - this.ticksExisted < 25){ - this.motionY = 0; + extensionSpeed = 0; }else if(lifetime - this.ticksExisted < 28){ - this.motionY = 0.25; + extensionSpeed = 0.25; } - this.move(MoverType.SELF, this.motionX, this.motionY, this.motionZ); + if(facing != null){ // Will probably be null on the client side, but should never be on the server side + this.move(MoverType.SELF, this.facing.getXOffset() * extensionSpeed, this.facing.getYOffset() * extensionSpeed, + this.facing.getZOffset() * extensionSpeed); + } - if(lifetime - this.ticksExisted == 30) this.playSound(WizardrySounds.SPELL_ICE, 1, 2); + if(lifetime - this.ticksExisted == 30) this.playSound(WizardrySounds.ENTITY_ICE_SPIKE_EXTEND, 1, 2); if(!this.world.isRemote){ for(Object entity : this.world.getEntitiesWithinAABBExcludingEntity(this, this.getEntityBoundingBox())){ @@ -37,8 +64,10 @@ public class EntityIceSpike extends EntityMagicConstruct { // Potion effect only gets added if the damage succeeded. if(((EntityLivingBase)entity).attackEntityFrom( MagicDamage.causeDirectMagicDamage(this.getCaster(), DamageType.FROST), - 5 * this.damageMultiplier)) - ((EntityLivingBase)entity).addPotionEffect(new PotionEffect(WizardryPotions.frost, 100, 0)); + Spells.ice_spikes.getProperty(Spell.DAMAGE).floatValue() * this.damageMultiplier)) + ((EntityLivingBase)entity).addPotionEffect(new PotionEffect(WizardryPotions.frost, + Spells.ice_spikes.getProperty(Spell.EFFECT_DURATION).intValue(), + Spells.ice_spikes.getProperty(Spell.EFFECT_STRENGTH).intValue())); } } } @@ -46,4 +75,8 @@ public class EntityIceSpike extends EntityMagicConstruct { super.onUpdate(); } + @Override + public int getBrightnessForRender(){ + return 15728880; + } } diff --git a/src/main/java/electroblob/wizardry/entity/construct/EntityLightningSigil.java b/src/main/java/electroblob/wizardry/entity/construct/EntityLightningSigil.java index 589cea82..412df121 100644 --- a/src/main/java/electroblob/wizardry/entity/construct/EntityLightningSigil.java +++ b/src/main/java/electroblob/wizardry/entity/construct/EntityLightningSigil.java @@ -1,8 +1,8 @@ package electroblob.wizardry.entity.construct; -import java.util.List; - +import electroblob.wizardry.registry.Spells; import electroblob.wizardry.registry.WizardrySounds; +import electroblob.wizardry.spell.Spell; import electroblob.wizardry.util.MagicDamage; import electroblob.wizardry.util.MagicDamage.DamageType; import electroblob.wizardry.util.ParticleBuilder; @@ -10,10 +10,15 @@ import electroblob.wizardry.util.ParticleBuilder.Type; import electroblob.wizardry.util.WizardryUtilities; import net.minecraft.entity.EntityLivingBase; import net.minecraft.util.DamageSource; +import net.minecraft.util.math.MathHelper; import net.minecraft.world.World; +import java.util.List; + public class EntityLightningSigil extends EntityMagicConstruct { + public static final String SECONDARY_MAX_TARGETS = "secondary_max_targets"; + public EntityLightningSigil(World world){ super(world); this.height = 0.2f; @@ -42,22 +47,24 @@ public class EntityLightningSigil extends EntityMagicConstruct { // Only works if target is actually damaged to account for hurtResistantTime if(target.attackEntityFrom(getCaster() != null ? MagicDamage.causeIndirectMagicDamage(this, getCaster(), - DamageType.SHOCK) : DamageSource.MAGIC, 6)){ + DamageType.SHOCK) : DamageSource.MAGIC, Spells.lightning_sigil.getProperty(Spell.DIRECT_DAMAGE) + .floatValue() * damageMultiplier)){ // Removes knockback target.motionX = velX; target.motionY = velY; target.motionZ = velZ; - this.playSound(WizardrySounds.SPELL_SPARK, 1.0f, 1.0f); + this.playSound(WizardrySounds.ENTITY_LIGHTNING_SIGIL_TRIGGER, 1.0f, 1.0f); // Secondary chaining effect - double seekerRange = 5.0d; + double seekerRange = Spells.lightning_sigil.getProperty(Spell.EFFECT_RADIUS).doubleValue(); List secondaryTargets = WizardryUtilities.getEntitiesWithinRadius(seekerRange, target.posX, target.posY + target.height / 2, target.posZ, world); - for(int j = 0; j < Math.min(secondaryTargets.size(), 3); j++){ + for(int j = 0; j < Math.min(secondaryTargets.size(), + Spells.lightning_sigil.getProperty(SECONDARY_MAX_TARGETS).floatValue()); j++){ EntityLivingBase secondaryTarget = secondaryTargets.get(j); @@ -73,11 +80,12 @@ public class EntityLightningSigil extends EntityMagicConstruct { secondaryTarget.posZ); } - secondaryTarget.playSound(WizardrySounds.SPELL_SPARK, 1.0F, + secondaryTarget.playSound(WizardrySounds.ENTITY_LIGHTNING_SIGIL_TRIGGER, 1.0F, world.rand.nextFloat() * 0.4F + 1.5F); secondaryTarget.attackEntityFrom( - MagicDamage.causeIndirectMagicDamage(this, getCaster(), DamageType.SHOCK), 4); + MagicDamage.causeIndirectMagicDamage(this, getCaster(), DamageType.SHOCK), + Spells.lightning_sigil.getProperty(Spell.SPLASH_DAMAGE).floatValue() * damageMultiplier); } } @@ -89,9 +97,9 @@ public class EntityLightningSigil extends EntityMagicConstruct { if(this.world.isRemote && this.rand.nextInt(15) == 0){ double radius = 0.5 + rand.nextDouble() * 0.3; - double angle = rand.nextDouble() * Math.PI * 2; + float angle = rand.nextFloat() * (float)Math.PI * 2;; ParticleBuilder.create(Type.SPARK) - .pos(this.posX + radius * Math.cos(angle), this.posY + 0.1, this.posZ + radius * Math.sin(angle)) + .pos(this.posX + radius * MathHelper.cos(angle), this.posY + 0.1, this.posZ + radius * MathHelper.sin(angle)) .spawn(world); } } diff --git a/src/main/java/electroblob/wizardry/entity/construct/EntityMagicConstruct.java b/src/main/java/electroblob/wizardry/entity/construct/EntityMagicConstruct.java index 8951c743..14b514a9 100644 --- a/src/main/java/electroblob/wizardry/entity/construct/EntityMagicConstruct.java +++ b/src/main/java/electroblob/wizardry/entity/construct/EntityMagicConstruct.java @@ -1,38 +1,38 @@ package electroblob.wizardry.entity.construct; -import java.lang.ref.WeakReference; -import java.util.UUID; - +import electroblob.wizardry.Wizardry; +import electroblob.wizardry.registry.WizardrySounds; +import electroblob.wizardry.util.AllyDesignationSystem; import electroblob.wizardry.util.WizardryUtilities; import io.netty.buffer.ByteBuf; import net.minecraft.entity.Entity; import net.minecraft.entity.EntityLivingBase; +import net.minecraft.entity.IEntityOwnable; import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.util.SoundCategory; import net.minecraft.world.World; import net.minecraftforge.fml.common.registry.IEntityAdditionalSpawnData; import net.minecraftforge.fml.relauncher.Side; import net.minecraftforge.fml.relauncher.SideOnly; +import javax.annotation.Nullable; +import java.util.UUID; + /** * This class is for all inanimate magical constructs which are not projectiles. It was made from scratch to provide a * unifying superclass for black hole, blizzard, tornado and a few others which all share some characteristics. The - * EntityPlayer instance of the caster, the lifetime and the damage multiplier are stored and synced here. - *

    + * caster UUID, lifetime and damage multiplier are stored here, and lifetime is also synced here. + *

    * When extending this class, override both constructors. Generally speaking, subclasses of this class are areas of * effect which deal damage or apply effects over time. * * @since Wizardry 1.0 */ -public abstract class EntityMagicConstruct extends Entity implements IEntityAdditionalSpawnData { +public abstract class EntityMagicConstruct extends Entity implements IEntityOwnable, IEntityAdditionalSpawnData { - /** The entity that created this construct */ - private WeakReference caster; - - /** - * The UUID of the caster. Note that this is only for loading purposes; during normal updates the actual entity - * instance is stored (so that getEntityByUUID is not called constantly), so this will not always be synced (this is - * why it is private). - */ + /** The UUID of the caster. As of Wizardry 4.2, this is synced, and rather than storing the caster + * instance via a weak reference, it is fetched from the UUID each time it is needed in + * {@link EntityMagicConstruct#getCaster()}. */ private UUID casterUUID; /** @@ -62,13 +62,6 @@ public abstract class EntityMagicConstruct extends Entity implements IEntityAddi public void onUpdate(){ - if(this.getCaster() == null && this.casterUUID != null){ - Entity entity = WizardryUtilities.getEntityByUUID(world, casterUUID); - if(entity instanceof EntityLivingBase){ - this.caster = new WeakReference((EntityLivingBase)entity); - } - } - if(this.ticksExisted > lifetime && lifetime != -1){ this.despawn(); } @@ -118,25 +111,51 @@ public abstract class EntityMagicConstruct extends Entity implements IEntityAddi lifetime = data.readInt(); } + @Nullable + @Override + public UUID getOwnerId(){ + return casterUUID; + } + + @Nullable + @Override + public Entity getOwner(){ + return getCaster(); // Delegate to getCaster + } + /** * Returns the EntityLivingBase that created this construct, or null if it no longer exists. Cases where the entity * may no longer exist are: entity died or was deleted, mob despawned, player logged out, entity teleported to * another dimension, or this construct simply had no caster in the first place. */ - public EntityLivingBase getCaster(){ - return caster == null ? null : caster.get(); + @Nullable + public EntityLivingBase getCaster(){ // Kept despite the above method because it returns an EntityLivingBase + + Entity entity = WizardryUtilities.getEntityByUUID(world, getOwnerId()); + + if(entity != null && !(entity instanceof EntityLivingBase)){ // Should never happen + Wizardry.logger.warn("{} has a non-living owner!", this); + entity = null; + } + + return (EntityLivingBase)entity; } - public void setCaster(EntityLivingBase caster){ - this.caster = new WeakReference(caster); + public void setCaster(@Nullable EntityLivingBase caster){ + this.casterUUID = caster == null ? null : caster.getUniqueID(); } /** - * Shorthand for {@link WizardryUtilities#isValidTarget(Entity, Entity)}, with the owner of this construct as the + * Shorthand for {@link AllyDesignationSystem#isValidTarget(Entity, Entity)}, with the owner of this construct as the * attacker. Also allows subclasses to override it if they wish to do so. */ public boolean isValidTarget(Entity target){ - return WizardryUtilities.isValidTarget(this.getCaster(), target); + return AllyDesignationSystem.isValidTarget(this.getCaster(), target); + } + + @Override + public SoundCategory getSoundCategory(){ + return WizardrySounds.SPELLS; } @Override diff --git a/src/main/java/electroblob/wizardry/entity/construct/EntityTornado.java b/src/main/java/electroblob/wizardry/entity/construct/EntityTornado.java index 3571aaa4..18c8d51d 100644 --- a/src/main/java/electroblob/wizardry/entity/construct/EntityTornado.java +++ b/src/main/java/electroblob/wizardry/entity/construct/EntityTornado.java @@ -1,10 +1,12 @@ package electroblob.wizardry.entity.construct; -import java.util.List; - import electroblob.wizardry.Wizardry; -import electroblob.wizardry.registry.WizardryAdvancementTriggers; +import electroblob.wizardry.item.ItemArtefact; +import electroblob.wizardry.registry.Spells; +import electroblob.wizardry.registry.WizardryItems; import electroblob.wizardry.registry.WizardrySounds; +import electroblob.wizardry.spell.Spell; +import electroblob.wizardry.spell.Tornado; import electroblob.wizardry.util.MagicDamage; import electroblob.wizardry.util.MagicDamage.DamageType; import electroblob.wizardry.util.ParticleBuilder; @@ -15,15 +17,18 @@ import net.minecraft.block.material.Material; import net.minecraft.block.state.IBlockState; import net.minecraft.entity.EntityLivingBase; import net.minecraft.entity.MoverType; -import net.minecraft.entity.passive.EntityPig; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.entity.player.EntityPlayerMP; import net.minecraft.nbt.NBTTagCompound; import net.minecraft.network.play.server.SPacketEntityVelocity; import net.minecraft.util.DamageSource; +import net.minecraft.util.EnumFacing; +import net.minecraft.util.ResourceLocation; import net.minecraft.util.math.BlockPos; import net.minecraft.world.World; +import java.util.List; + public class EntityTornado extends EntityMagicConstruct { private double velX, velZ; @@ -45,63 +50,69 @@ public class EntityTornado extends EntityMagicConstruct { super.onUpdate(); + double radius = Spells.tornado.getProperty(Spell.EFFECT_RADIUS).doubleValue(); + if(this.ticksExisted % 120 == 1 && world.isRemote){ // Repeat is false so that the sound fades out when the tornado does rather than stopping suddenly - Wizardry.proxy.playMovingSound(this, WizardrySounds.SPELL_LOOP_WIND, 1.0f, 1.0f, false); + Wizardry.proxy.playMovingSound(this, WizardrySounds.ENTITY_TORNADO_AMBIENT, WizardrySounds.SPELLS, 1.0f, 1.0f, false); } this.move(MoverType.SELF, velX, motionY, velZ); BlockPos pos = new BlockPos(this); - int y = WizardryUtilities.getNearestFloorLevelC(world, pos.up(3), 5); - pos = new BlockPos(pos.getX(), y, pos.getZ()); + Integer y = WizardryUtilities.getNearestSurface(world, pos.up(3), EnumFacing.UP, 5, true, WizardryUtilities.SurfaceCriteria.NOT_AIR_TO_AIR); - if(this.world.getBlockState(pos).getMaterial() == Material.LAVA){ - // Fire tornado! - this.setFire(5); + if(y != null){ + + pos = new BlockPos(pos.getX(), y, pos.getZ()); + + if(this.world.getBlockState(pos).getMaterial() == Material.LAVA){ + // Fire tornado! + this.setFire(5); + } } if(!this.world.isRemote){ - List targets = WizardryUtilities.getEntitiesWithinRadius(4.0d, this.posX, this.posY, + List targets = WizardryUtilities.getEntitiesWithinRadius(radius, this.posX, this.posY, this.posZ, this.world); for(EntityLivingBase target : targets){ + if(target instanceof EntityPlayer && ((getCaster() instanceof EntityPlayer && !Wizardry.settings.playersMoveEachOther) + || ItemArtefact.isArtefactActive((EntityPlayer)target, WizardryItems.amulet_anchoring))){ + continue; + } + if(this.isValidTarget(target)){ double velY = target.motionY; - double dx = this.posX - target.posX > 0 ? 0.5 - (this.posX - target.posX) / 8 - : -0.5 - (this.posX - target.posX) / 8; - double dz = this.posZ - target.posZ > 0 ? 0.5 - (this.posZ - target.posZ) / 8 - : -0.5 - (this.posZ - target.posZ) / 8; + // TODO: This doesn't seem right... + double dx = (this.posX - target.posX > 0 ? 0.5 : -0.5) - (this.posX - target.posX) * 0.125; + double dz = (this.posZ - target.posZ > 0 ? 0.5 : -0.5) - (this.posZ - target.posZ) * 0.125; if(this.isBurning()){ - target.setFire(4); + target.setFire(4); // Just a fun Easter egg so no properties here! } + float damage = Spells.tornado.getProperty(Spell.DAMAGE).floatValue() * damageMultiplier; + if(this.getCaster() != null){ - target.attackEntityFrom( - MagicDamage.causeIndirectMagicDamage(this, getCaster(), DamageType.MAGIC), - 1 * damageMultiplier); + target.attackEntityFrom( MagicDamage.causeIndirectMagicDamage(this, getCaster(), + DamageType.MAGIC), damage); }else{ - target.attackEntityFrom(DamageSource.MAGIC, 1 * damageMultiplier); + target.attackEntityFrom(DamageSource.MAGIC, damage); } target.motionX = dx; - target.motionY = velY + 0.2; + target.motionY = velY + Spells.tornado.getProperty(Tornado.UPWARD_ACCELERATION).floatValue(); target.motionZ = dz; // Player motion is handled on that player's client so needs packets if(target instanceof EntityPlayerMP){ ((EntityPlayerMP)target).connection.sendPacket(new SPacketEntityVelocity(target)); } - - // The 'Not Again...' achievement - if(target instanceof EntityPig && WizardryUtilities.getRider(target) instanceof EntityPlayer){ - WizardryAdvancementTriggers.pig_tornado.triggerFor((EntityPlayer)WizardryUtilities.getRider(target)); - } } } }else{ @@ -114,38 +125,43 @@ public class EntityTornado extends EntityMagicConstruct { BlockPos pos1 = new BlockPos(blockX, this.posY + 3, blockZ); - int blockY = WizardryUtilities.getNearestFloorLevelC(world, pos1, 5) - 1; + Integer blockY = WizardryUtilities.getNearestSurface(world, pos1, EnumFacing.UP, 5, true, WizardryUtilities.SurfaceCriteria.NOT_AIR_TO_AIR); - pos1 = new BlockPos(pos1.getX(), blockY, pos1.getZ()); + if(blockY != null){ - IBlockState block = this.world.getBlockState(pos1); + blockY--; - // If the block it found was air or something it can't pick up, it makes a best guess based on the - // biome. - if(!canTornadoPickUpBitsOf(block)){ - block = world.getBiome(pos1).topBlock; - } + pos1 = new BlockPos(pos1.getX(), blockY, pos1.getZ()); - Wizardry.proxy.spawnTornadoParticle(world, this.posX, this.posY + yPos, this.posZ, this.velX, this.velZ, - yPos / 3 + 0.5d, 100, block, pos1); - Wizardry.proxy.spawnTornadoParticle(world, this.posX, this.posY + yPos, this.posZ, this.velX, this.velZ, - yPos / 3 + 0.5d, 100, block, pos1); - - // Sometimes spawns leaf particles if the block is leaves, or snow particles if the block is snow - if(this.rand.nextInt(3) == 0){ + IBlockState block = this.world.getBlockState(pos1); - Type type = null; - - if(block.getMaterial() == Material.LEAVES) type = Type.LEAF; - if(block.getMaterial() == Material.SNOW || block.getMaterial() == Material.CRAFTED_SNOW) type = Type.SNOW; - - if(type != null){ - double yPos1 = rand.nextDouble() * 8; - ParticleBuilder.create(type) - .pos(this.posX + (rand.nextDouble() * 2 - 1) * (yPos1 / 3 + 0.5d), this.posY + yPos1, - this.posZ + (rand.nextDouble() * 2 - 1) * (yPos1 / 3 + 0.5d)) - .time(40 + rand.nextInt(10)) - .spawn(world); + // If the block it found was air or something it can't pick up, it makes a best guess based on the biome + if(!canTornadoPickUpBitsOf(block)){ + block = world.getBiome(pos1).topBlock; + } + + Wizardry.proxy.spawnTornadoParticle(world, this.posX, this.posY + yPos, this.posZ, this.velX, this.velZ, + yPos / 3 + 0.5d, 100, block, pos1); + Wizardry.proxy.spawnTornadoParticle(world, this.posX, this.posY + yPos, this.posZ, this.velX, this.velZ, + yPos / 3 + 0.5d, 100, block, pos1); + + // Sometimes spawns leaf particles if the block is leaves, or snow particles if the block is snow + if(this.rand.nextInt(3) == 0){ + + ResourceLocation type = null; + + if(block.getMaterial() == Material.LEAVES) type = Type.LEAF; + if(block.getMaterial() == Material.SNOW || block.getMaterial() == Material.CRAFTED_SNOW) + type = Type.SNOW; + + if(type != null){ + double yPos1 = rand.nextDouble() * 8; + ParticleBuilder.create(type) + .pos(this.posX + (rand.nextDouble() * 2 - 1) * (yPos1 / 3 + 0.5d), this.posY + yPos1, + this.posZ + (rand.nextDouble() * 2 - 1) * (yPos1 / 3 + 0.5d)) + .time(40 + rand.nextInt(10)) + .spawn(world); + } } } } diff --git a/src/main/java/electroblob/wizardry/entity/living/EntityAIAttackSpell.java b/src/main/java/electroblob/wizardry/entity/living/EntityAIAttackSpell.java index 85b9d65d..d0cd4c93 100644 --- a/src/main/java/electroblob/wizardry/entity/living/EntityAIAttackSpell.java +++ b/src/main/java/electroblob/wizardry/entity/living/EntityAIAttackSpell.java @@ -1,8 +1,5 @@ package electroblob.wizardry.entity.living; -import java.util.ArrayList; -import java.util.List; - import electroblob.wizardry.event.SpellCastEvent; import electroblob.wizardry.event.SpellCastEvent.Source; import electroblob.wizardry.packet.PacketNPCCastSpell; @@ -18,6 +15,9 @@ import net.minecraftforge.common.MinecraftForge; import net.minecraftforge.fml.common.network.NetworkRegistry.TargetPoint; import net.minecraftforge.fml.common.network.simpleimpl.IMessage; +import java.util.ArrayList; +import java.util.List; + /** * Entity AI class for use by instances of {@link ISpellCaster}. This deals with pathing, the spell casting itself and * the attack cooldown. Also provides an automatic implementation of continuous spell casting using the methods @@ -106,7 +106,7 @@ public class EntityAIAttackSpell extends attacker.setContinuousSpell(spell); WizardryPacketHandler.net.sendToAllAround( new PacketNPCCastSpell.Message(attacker.getEntityId(), target == null ? -1 : target.getEntityId(), - EnumHand.MAIN_HAND, spell.id(), modifiers), + EnumHand.MAIN_HAND, spell, modifiers), // Particles are usually only visible from 16 blocks away, so 128 is more than far enough. // TODO: Why is this one a 128 block radius, whilst the other one is all in dimension? new TargetPoint(attacker.dimension, attacker.posX, attacker.posY, attacker.posZ, 128)); @@ -143,8 +143,8 @@ public class EntityAIAttackSpell extends if(distanceSq > (double)this.maxAttackDistance || !targetIsVisible // ...or the spell is cancelled via events... || MinecraftForge.EVENT_BUS - .post(new SpellCastEvent.Tick(attacker, attacker.getContinuousSpell(), attacker.getModifiers(), - Source.NPC, this.continuousSpellDuration - this.continuousSpellTimer)) + .post(new SpellCastEvent.Tick(Source.NPC, attacker.getContinuousSpell(), attacker, + attacker.getModifiers(), this.continuousSpellDuration - this.continuousSpellTimer)) // ...or the spell no longer succeeds... || !attacker.getContinuousSpell().cast(attacker.world, attacker, EnumHand.MAIN_HAND, this.continuousSpellDuration - this.continuousSpellTimer, target, attacker.getModifiers()) @@ -159,8 +159,8 @@ public class EntityAIAttackSpell extends }else if(this.continuousSpellDuration - this.continuousSpellTimer == 1){ // On the first tick, if the spell did succeed, fire SpellCastEvent.Post. - MinecraftForge.EVENT_BUS.post(new SpellCastEvent.Post(attacker, attacker.getContinuousSpell(), - attacker.getModifiers(), Source.NPC)); + MinecraftForge.EVENT_BUS.post(new SpellCastEvent.Post(Source.NPC, attacker.getContinuousSpell(), + attacker, attacker.getModifiers())); } }else if(--this.cooldown == 0){ @@ -209,7 +209,7 @@ public class EntityAIAttackSpell extends private boolean attemptCastSpell(Spell spell, SpellModifiers modifiers){ // If anything stops the spell working at this point, nothing else happens. - if(MinecraftForge.EVENT_BUS.post(new SpellCastEvent.Pre(attacker, spell, modifiers, Source.NPC))){ + if(MinecraftForge.EVENT_BUS.post(new SpellCastEvent.Pre(Source.NPC, spell, attacker, modifiers))){ return false; } @@ -222,16 +222,16 @@ public class EntityAIAttackSpell extends }else{ - MinecraftForge.EVENT_BUS.post(new SpellCastEvent.Post(attacker, spell, modifiers, Source.NPC)); + MinecraftForge.EVENT_BUS.post(new SpellCastEvent.Post(Source.NPC, spell, attacker, modifiers)); // For now, the cooldown is just added to the constant base cooldown. I think this // is a reasonable way of doing things; it's certainly better than before. - this.cooldown = this.baseCooldown + spell.cooldown; + this.cooldown = this.baseCooldown + spell.getCooldown(); - if(spell.doesSpellRequirePacket()){ + if(spell.requiresPacket()){ // Sends a packet to all players in dimension to tell them to spawn particles. IMessage msg = new PacketNPCCastSpell.Message(attacker.getEntityId(), target.getEntityId(), - EnumHand.MAIN_HAND, spell.id(), modifiers); + EnumHand.MAIN_HAND, spell, modifiers); WizardryPacketHandler.net.sendToDimension(msg, attacker.world.provider.getDimension()); } } diff --git a/src/main/java/electroblob/wizardry/entity/living/EntityBlazeMinion.java b/src/main/java/electroblob/wizardry/entity/living/EntityBlazeMinion.java index 2bab8ebd..fc7873b2 100644 --- a/src/main/java/electroblob/wizardry/entity/living/EntityBlazeMinion.java +++ b/src/main/java/electroblob/wizardry/entity/living/EntityBlazeMinion.java @@ -1,8 +1,5 @@ package electroblob.wizardry.entity.living; -import java.lang.ref.WeakReference; -import java.util.UUID; - import electroblob.wizardry.Wizardry; import net.minecraft.entity.EntityLivingBase; import net.minecraft.entity.ai.EntityAIHurtByTarget; @@ -16,13 +13,15 @@ import net.minecraft.util.EnumParticleTypes; import net.minecraft.util.ResourceLocation; import net.minecraft.util.text.ITextComponent; import net.minecraft.util.text.TextComponentTranslation; +import net.minecraft.world.EnumDifficulty; import net.minecraft.world.World; +import java.util.UUID; + public class EntityBlazeMinion extends EntityBlaze implements ISummonedCreature { // Field implementations - private int lifetime = 600; - private WeakReference casterReference; + private int lifetime = -1; private UUID casterUUID; // Setter + getter implementations @@ -37,22 +36,12 @@ public class EntityBlazeMinion extends EntityBlaze implements ISummonedCreature } @Override - public WeakReference getCasterReference(){ - return casterReference; - } - - @Override - public void setCasterReference(WeakReference reference){ - casterReference = reference; - } - - @Override - public UUID getCasterUUID(){ + public UUID getOwnerId(){ return casterUUID; } @Override - public void setCasterUUID(UUID uuid){ + public void setOwnerId(UUID uuid){ this.casterUUID = uuid; } @@ -65,13 +54,13 @@ public class EntityBlazeMinion extends EntityBlaze implements ISummonedCreature // EntityBlaze overrides // This particular override is pretty standard: let the superclass handle basic AI like swimming, but replace its - // targeting system with one that targets hostile mobs and takes the ADS into account. + // targeting system with one that targets hostile mobs and takes the AllyDesignationSystem into account. @Override protected void initEntityAI(){ super.initEntityAI(); this.targetTasks.taskEntries.clear(); this.targetTasks.addTask(1, new EntityAIHurtByTarget(this, false)); - this.targetTasks.addTask(2, new EntityAINearestAttackableTarget(this, EntityLivingBase.class, + this.targetTasks.addTask(2, new EntityAINearestAttackableTarget<>(this, EntityLivingBase.class, 0, false, true, this.getTargetSelector())); } @@ -142,8 +131,16 @@ public class EntityBlazeMinion extends EntityBlaze implements ISummonedCreature @Override protected Item getDropItem(){ return null; } @Override protected ResourceLocation getLootTable(){ return null; } @Override public boolean canPickUpLoot(){ return false; } + // This vanilla method has nothing to do with the custom despawn() method. - @Override protected boolean canDespawn(){ return false; } + @Override protected boolean canDespawn(){ + return getCaster() == null && getOwnerId() == null; + } + + @Override + public boolean getCanSpawnHere(){ + return this.world.getDifficulty() != EnumDifficulty.PEACEFUL; + } @Override public boolean canAttackClass(Class entityType){ @@ -163,6 +160,6 @@ public class EntityBlazeMinion extends EntityBlaze implements ISummonedCreature @Override public boolean hasCustomName(){ // If this returns true, the renderer will show the nameplate when looking directly at the entity - return Wizardry.settings.showSummonedCreatureNames && getCaster() != null; + return Wizardry.settings.summonedCreatureNames && getCaster() != null; } } diff --git a/src/main/java/electroblob/wizardry/entity/living/EntityDecoy.java b/src/main/java/electroblob/wizardry/entity/living/EntityDecoy.java index 1444d6f9..8dc135d2 100644 --- a/src/main/java/electroblob/wizardry/entity/living/EntityDecoy.java +++ b/src/main/java/electroblob/wizardry/entity/living/EntityDecoy.java @@ -1,10 +1,7 @@ package electroblob.wizardry.entity.living; -import java.lang.ref.WeakReference; - import electroblob.wizardry.util.ParticleBuilder; import electroblob.wizardry.util.ParticleBuilder.Type; -import io.netty.buffer.ByteBuf; import net.minecraft.entity.EntityLivingBase; import net.minecraft.entity.SharedMonsterAttributes; import net.minecraft.entity.ai.EntityAILookIdle; @@ -99,18 +96,19 @@ public class EntityDecoy extends EntitySummonedCreature { return false; } - @Override - public void writeSpawnData(ByteBuf data){ - super.writeSpawnData(data); - if(this.getCaster() != null) data.writeInt(this.getCaster().getEntityId()); - } - - @Override - public void readSpawnData(ByteBuf data){ - super.readSpawnData(data); - if(!data.isReadable()) return; - this.setCasterReference( - new WeakReference((EntityLivingBase)this.world.getEntityByID(data.readInt()))); - } + // TESTME: Why was this here? It gets done in ISummonedCreature anyway +// @Override +// public void writeSpawnData(ByteBuf data){ +// super.writeSpawnData(data); +// if(this.getCaster() != null) data.writeInt(this.getCaster().getEntityId()); +// } +// +// @Override +// public void readSpawnData(ByteBuf data){ +// super.readSpawnData(data); +// if(!data.isReadable()) return; +// this.setCasterReference( +// new WeakReference((EntityLivingBase)this.world.getEntityByID(data.readInt()))); +// } } diff --git a/src/main/java/electroblob/wizardry/entity/living/EntityEvilWizard.java b/src/main/java/electroblob/wizardry/entity/living/EntityEvilWizard.java index 356281ea..4a9c8755 100644 --- a/src/main/java/electroblob/wizardry/entity/living/EntityEvilWizard.java +++ b/src/main/java/electroblob/wizardry/entity/living/EntityEvilWizard.java @@ -1,11 +1,6 @@ package electroblob.wizardry.entity.living; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; - import com.google.common.base.Predicate; - import electroblob.wizardry.Wizardry; import electroblob.wizardry.constants.Element; import electroblob.wizardry.constants.Tier; @@ -15,31 +10,18 @@ import electroblob.wizardry.registry.WizardryItems; import electroblob.wizardry.registry.WizardryPotions; import electroblob.wizardry.registry.WizardrySounds; import electroblob.wizardry.spell.Spell; -import electroblob.wizardry.util.ParticleBuilder; -import electroblob.wizardry.util.SpellModifiers; +import electroblob.wizardry.util.*; import electroblob.wizardry.util.ParticleBuilder.Type; -import electroblob.wizardry.util.WizardryUtilities; import io.netty.buffer.ByteBuf; -import net.minecraft.entity.Entity; -import net.minecraft.entity.EntityList; -import net.minecraft.entity.EntityLivingBase; -import net.minecraft.entity.IEntityLivingData; -import net.minecraft.entity.SharedMonsterAttributes; -import net.minecraft.entity.ai.EntityAIHurtByTarget; -import net.minecraft.entity.ai.EntityAIMoveTowardsRestriction; -import net.minecraft.entity.ai.EntityAINearestAttackableTarget; -import net.minecraft.entity.ai.EntityAIOpenDoor; -import net.minecraft.entity.ai.EntityAIRestrictOpenDoor; -import net.minecraft.entity.ai.EntityAISwimming; -import net.minecraft.entity.ai.EntityAIWander; -import net.minecraft.entity.ai.EntityAIWatchClosest2; +import net.minecraft.entity.*; +import net.minecraft.entity.ai.*; import net.minecraft.entity.monster.EntityMob; import net.minecraft.entity.player.EntityPlayer; -import net.minecraft.init.SoundEvents; import net.minecraft.inventory.EntityEquipmentSlot; import net.minecraft.item.ItemStack; import net.minecraft.nbt.NBTTagCompound; import net.minecraft.nbt.NBTTagInt; +import net.minecraft.nbt.NBTUtil; import net.minecraft.network.datasync.DataParameter; import net.minecraft.network.datasync.DataSerializers; import net.minecraft.network.datasync.EntityDataManager; @@ -55,13 +37,21 @@ import net.minecraft.world.World; import net.minecraftforge.common.util.Constants.NBT; import net.minecraftforge.fml.common.registry.IEntityAdditionalSpawnData; +import javax.annotation.Nullable; +import java.util.*; + public class EntityEvilWizard extends EntityMob implements ISpellCaster, IEntityAdditionalSpawnData { - private EntityAIAttackSpell spellCastingAI = new EntityAIAttackSpell(this, 0.5D, 14.0F, 30, 50); + private EntityAIAttackSpell spellCastingAI = new EntityAIAttackSpell<>(this, 0.5D, 14.0F, 30, 50); public int textureIndex = 0; - public boolean hasTower = false; + /** True if this evil wizard was spawned as part of a structure (tower or shrine), false if it spawned naturally. */ + public boolean hasStructure = false; + + /** Stores the UUIDs of the other evil wizards spawned in the same group, if any. The wizard will not revenge-target + * entities whose UUIDs are in this set. This is currently used only for shrines. */ + public final Set groupUUIDs = new HashSet<>(); /** The entity selector passed into the new AI methods. */ protected Predicate targetSelector; @@ -95,11 +85,12 @@ public class EntityEvilWizard extends EntityMob implements ISpellCaster, IEntity protected void entityInit(){ super.entityInit(); this.dataManager.register(HEAL_COOLDOWN, -1); - this.dataManager.register(ELEMENT, 0); + this.dataManager.register(ELEMENT, -1); } @Override protected void initEntityAI(){ + this.tasks.addTask(0, new EntityAISwimming(this)); this.tasks.addTask(4, new EntityAIRestrictOpenDoor(this)); this.tasks.addTask(5, new EntityAIOpenDoor(this, true)); @@ -107,34 +98,31 @@ public class EntityEvilWizard extends EntityMob implements ISpellCaster, IEntity this.tasks.addTask(7, new EntityAIWatchClosest2(this, EntityPlayer.class, 3.0F, 1.0F)); this.tasks.addTask(7, new EntityAIWander(this, 0.6D)); - this.targetSelector = new Predicate(){ + this.targetSelector = entity -> { - public boolean apply(Entity entity){ + // If the target is valid and not invisible... + if(entity != null && !entity.isInvisible() + && AllyDesignationSystem.isValidTarget(EntityEvilWizard.this, entity)){ - // If the target is valid and not invisible... - if(entity != null && !entity.isInvisible() - && WizardryUtilities.isValidTarget(EntityEvilWizard.this, entity)){ - - // ... and is a player, a summoned creature, another (non-evil) wizard ... - if(entity instanceof EntityPlayer - || (entity instanceof ISummonedCreature || entity instanceof EntityWizard - // ... or in the whitelist ... - || Arrays.asList(Wizardry.settings.summonedCreatureTargetsWhitelist) - .contains(EntityList.getKey(entity.getClass()))) - // ... and isn't in the blacklist ... - && !Arrays.asList(Wizardry.settings.summonedCreatureTargetsBlacklist) - .contains(EntityList.getKey(entity.getClass()))){ - // ... it can be attacked. - return true; - } + // ... and is a player, a summoned creature, another (non-evil) wizard ... + if(entity instanceof EntityPlayer + || (entity instanceof ISummonedCreature || entity instanceof EntityWizard + // ... or in the whitelist ... + || Arrays.asList(Wizardry.settings.summonedCreatureTargetsWhitelist) + .contains(EntityList.getKey(entity.getClass()))) + // ... and isn't in the blacklist ... + && !Arrays.asList(Wizardry.settings.summonedCreatureTargetsBlacklist) + .contains(EntityList.getKey(entity.getClass()))){ + // ... it can be attacked. + return true; } - - return false; } + + return false; }; this.targetTasks.addTask(1, new EntityAIHurtByTarget(this, true)); - this.targetTasks.addTask(0, new EntityAINearestAttackableTarget(this, EntityLivingBase.class, + this.targetTasks.addTask(0, new EntityAINearestAttackableTarget<>(this, EntityLivingBase.class, 0, false, true, this.targetSelector)); } @@ -154,7 +142,8 @@ public class EntityEvilWizard extends EntityMob implements ISpellCaster, IEntity } public Element getElement(){ - return Element.values()[this.dataManager.get(ELEMENT)]; + int n = this.dataManager.get(ELEMENT); + return n == -1 ? null : Element.values()[n]; } public void setElement(Element element){ @@ -192,6 +181,11 @@ public class EntityEvilWizard extends EntityMob implements ISpellCaster, IEntity } } + @Override + public void setRevengeTarget(@Nullable EntityLivingBase target){ + if(target == null || !groupUUIDs.contains(target.getUniqueID())) super.setRevengeTarget(target); + } + @Override public void onLivingUpdate(){ @@ -225,13 +219,13 @@ public class EntityEvilWizard extends EntityMob implements ISpellCaster, IEntity } }else{ if(this.getHealth() < 10){ - // Wizards heal themseselves more often if they have low health + // Wizards heal themselves more often if they have low health this.setHealCooldown(150); }else{ this.setHealCooldown(400); } - this.playSound(WizardrySounds.SPELL_HEAL, 0.7F, rand.nextFloat() * 0.4F + 1.0F); + this.playSound(Spells.heal.getSounds()[0], 0.7F, rand.nextFloat() * 0.4F + 1.0F); } } if(healCooldown > 0){ @@ -250,8 +244,8 @@ public class EntityEvilWizard extends EntityMob implements ISpellCaster, IEntity // Spell.get(spells[3]).getDisplayName())); // When right-clicked with a spell book in creative, sets one of the spells to that spell - if(player.capabilities.isCreativeMode && stack.getItem() instanceof ItemSpellBook){ - Spell spell = Spell.get(stack.getItemDamage()); + if(player.isCreative() && stack.getItem() instanceof ItemSpellBook){ + Spell spell = Spell.byMetadata(stack.getItemDamage()); if(this.spells.size() >= 4 && spell.canBeCastByNPCs()){ // The set(...) method returns the element that was replaced - neat! player.sendMessage(new TextComponentTranslation("item." + Wizardry.MODID + ":spell_book.apply_to_wizard", @@ -269,8 +263,9 @@ public class EntityEvilWizard extends EntityMob implements ISpellCaster, IEntity super.writeEntityToNBT(nbt); nbt.setInteger("element", this.getElement().ordinal()); nbt.setInteger("skin", this.textureIndex); - nbt.setTag("spells", WizardryUtilities.listToNBT(spells, spell -> new NBTTagInt(spell.id()))); - nbt.setBoolean("hasTower", this.hasTower); + nbt.setTag("spells", NBTExtras.listToNBT(spells, spell -> new NBTTagInt(spell.metadata()))); + nbt.setBoolean("hasStructure", this.hasStructure); + nbt.setTag("groupUUIDs", NBTExtras.listToNBT(groupUUIDs, NBTUtil::createUUIDTag)); } @Override @@ -278,9 +273,10 @@ public class EntityEvilWizard extends EntityMob implements ISpellCaster, IEntity super.readEntityFromNBT(nbt); this.setElement(Element.values()[nbt.getInteger("element")]); this.textureIndex = nbt.getInteger("skin"); - this.spells = (List)WizardryUtilities.NBTToList(nbt.getTagList("spells", NBT.TAG_INT), - (NBTTagInt tag) -> Spell.get(tag.getInt())); - this.hasTower = nbt.getBoolean("hasTower"); + this.spells = (List)NBTExtras.NBTToList(nbt.getTagList("spells", NBT.TAG_INT), + (NBTTagInt tag) -> Spell.byMetadata(tag.getInt())); + this.hasStructure = nbt.getBoolean("hasStructure"); + this.groupUUIDs.addAll(NBTExtras.NBTToList(nbt.getTagList("groupUUIDs", NBT.TAG_COMPOUND), NBTUtil::getUUIDFromTag)); } @Override @@ -291,7 +287,7 @@ public class EntityEvilWizard extends EntityMob implements ISpellCaster, IEntity @Override public boolean getCanSpawnHere(){ // Evil wizards can only spawn in the specified dimensions - for(int id : Wizardry.settings.evilWizardDimensions){ + for(int id : Wizardry.settings.mobSpawnDimensions){ if(this.dimension == id) return super.getCanSpawnHere(); } @@ -301,27 +297,27 @@ public class EntityEvilWizard extends EntityMob implements ISpellCaster, IEntity @Override protected boolean canDespawn(){ // Evil wizards can only despawn if they don't have a tower (i.e. if they spawned naturally at night) - return !this.hasTower; + return !this.hasStructure; } - @Override - protected float getSoundPitch(){ - return (this.rand.nextFloat() - this.rand.nextFloat()) * 0.2F + 0.6F; - } +// @Override +// protected float getSoundPitch(){ +// return (this.rand.nextFloat() - this.rand.nextFloat()) * 0.2F + 0.6F; +// } @Override protected SoundEvent getAmbientSound(){ - return SoundEvents.ENTITY_WITCH_AMBIENT; + return WizardrySounds.ENTITY_EVIL_WIZARD_AMBIENT; } @Override protected SoundEvent getHurtSound(DamageSource source){ - return SoundEvents.ENTITY_WITCH_HURT; + return WizardrySounds.ENTITY_EVIL_WIZARD_HURT; } @Override protected SoundEvent getDeathSound(){ - return SoundEvents.ENTITY_WITCH_DEATH; + return WizardrySounds.ENTITY_EVIL_WIZARD_DEATH; } // Although it *looks* like this is still called, in actual fact the only method that calls it is overridden in @@ -340,7 +336,7 @@ public class EntityEvilWizard extends EntityMob implements ISpellCaster, IEntity // the dropRareDrop method because that would be just as rare as normal mobs; instead this is half as rare. if(this.spells.size() > 0 && rand.nextInt(100) - lootingLevel < 5) this.entityDropItem(new ItemStack(WizardryItems.spell_book, 1, - this.spells.get(1 + rand.nextInt(this.spells.size() - 1)).id()), 0); + this.spells.get(1 + rand.nextInt(this.spells.size() - 1)).metadata()), 0); } @Override @@ -355,17 +351,19 @@ public class EntityEvilWizard extends EntityMob implements ISpellCaster, IEntity textureIndex = this.rand.nextInt(6); - if(rand.nextBoolean()){ - this.setElement(Element.values()[rand.nextInt(Element.values().length - 1) + 1]); - }else{ - this.setElement(Element.MAGIC); + if(getElement() == null){ + if(rand.nextBoolean()){ + this.setElement(Element.values()[rand.nextInt(Element.values().length - 1) + 1]); + }else{ + this.setElement(Element.MAGIC); + } } Element element = this.getElement(); // Adds armour. for(EntityEquipmentSlot slot : WizardryUtilities.ARMOUR_SLOTS){ - this.setItemStackToSlot(slot, new ItemStack(WizardryUtilities.getArmour(element, slot))); + this.setItemStackToSlot(slot, new ItemStack(WizardryItems.getArmour(element, slot))); } // Default chance is 0.085f, for reference. @@ -375,12 +373,12 @@ public class EntityEvilWizard extends EntityMob implements ISpellCaster, IEntity // All wizards know magic missile, even if it is disabled. spells.add(Spells.magic_missile); - Tier maxTier = EntityWizard.populateSpells(spells, element, 3, rand); + Tier maxTier = EntityWizard.populateSpells(spells, element, hasStructure, 3, rand); // Now done after the spells so it can take the tier into account. For evil wizards this is slightly different; // it picks a random wand which is at least a high enough tier for the spells the wizard has. Tier tier = Tier.values()[maxTier.ordinal() + rand.nextInt(Tier.values().length - maxTier.ordinal())]; - this.setItemStackToSlot(EntityEquipmentSlot.MAINHAND, new ItemStack(WizardryUtilities.getWand(tier, element))); + this.setItemStackToSlot(EntityEquipmentSlot.MAINHAND, new ItemStack(WizardryItems.getWand(tier, element))); return data; } diff --git a/src/main/java/electroblob/wizardry/entity/living/EntityHuskMinion.java b/src/main/java/electroblob/wizardry/entity/living/EntityHuskMinion.java new file mode 100644 index 00000000..3a146734 --- /dev/null +++ b/src/main/java/electroblob/wizardry/entity/living/EntityHuskMinion.java @@ -0,0 +1,42 @@ +package electroblob.wizardry.entity.living; + +import net.minecraft.entity.Entity; +import net.minecraft.entity.EntityLivingBase; +import net.minecraft.init.MobEffects; +import net.minecraft.init.SoundEvents; +import net.minecraft.potion.PotionEffect; +import net.minecraft.util.DamageSource; +import net.minecraft.util.SoundEvent; +import net.minecraft.util.math.BlockPos; +import net.minecraft.world.World; + +public class EntityHuskMinion extends EntityZombieMinion { + + /** Creates a new husk minion in the given world. */ + public EntityHuskMinion(World world){ + super(world); + } + + @Override + protected boolean shouldBurnInDay(){ + return false; + } + + @Override protected SoundEvent getAmbientSound(){ return SoundEvents.ENTITY_HUSK_AMBIENT; } + @Override protected SoundEvent getHurtSound(DamageSource damageSourceIn){ return SoundEvents.ENTITY_HUSK_HURT; } + @Override protected SoundEvent getDeathSound(){ return SoundEvents.ENTITY_HUSK_DEATH; } + @Override protected SoundEvent getStepSound(){ return SoundEvents.ENTITY_HUSK_STEP; } + + @Override + public boolean attackEntityAsMob(Entity target){ + + boolean flag = super.attackEntityAsMob(target); + + if(flag && this.getHeldItemMainhand().isEmpty() && target instanceof EntityLivingBase){ + float f = this.world.getDifficultyForLocation(new BlockPos(this)).getAdditionalDifficulty(); + ((EntityLivingBase)target).addPotionEffect(new PotionEffect(MobEffects.HUNGER, 140 * (int)f)); + } + + return flag; + } +} \ No newline at end of file diff --git a/src/main/java/electroblob/wizardry/entity/living/EntityIceGiant.java b/src/main/java/electroblob/wizardry/entity/living/EntityIceGiant.java index 8003f7f8..c3b118e7 100644 --- a/src/main/java/electroblob/wizardry/entity/living/EntityIceGiant.java +++ b/src/main/java/electroblob/wizardry/entity/living/EntityIceGiant.java @@ -1,8 +1,5 @@ package electroblob.wizardry.entity.living; -import java.lang.ref.WeakReference; -import java.util.UUID; - import electroblob.wizardry.Wizardry; import electroblob.wizardry.registry.WizardryPotions; import electroblob.wizardry.registry.WizardrySounds; @@ -10,15 +7,9 @@ import electroblob.wizardry.util.ParticleBuilder; import electroblob.wizardry.util.ParticleBuilder.Type; import net.minecraft.entity.EntityFlying; import net.minecraft.entity.EntityLivingBase; -import net.minecraft.entity.ai.EntityAIAttackMelee; -import net.minecraft.entity.ai.EntityAIHurtByTarget; -import net.minecraft.entity.ai.EntityAILookIdle; -import net.minecraft.entity.ai.EntityAIMoveTowardsTarget; -import net.minecraft.entity.ai.EntityAINearestAttackableTarget; -import net.minecraft.entity.ai.EntityAIWatchClosest; +import net.minecraft.entity.ai.*; import net.minecraft.entity.monster.EntityIronGolem; import net.minecraft.entity.player.EntityPlayer; -import net.minecraft.init.SoundEvents; import net.minecraft.item.Item; import net.minecraft.nbt.NBTTagCompound; import net.minecraft.potion.PotionEffect; @@ -27,22 +18,22 @@ import net.minecraft.util.ResourceLocation; import net.minecraft.util.text.ITextComponent; import net.minecraft.util.text.TextComponentTranslation; import net.minecraft.village.Village; +import net.minecraft.world.EnumDifficulty; import net.minecraft.world.World; +import java.util.UUID; + public class EntityIceGiant extends EntityIronGolem implements ISummonedCreature { // Field implementations - private int lifetime = 600; - private WeakReference casterReference; + private int lifetime = -1; private UUID casterUUID; // Setter + getter implementations @Override public int getLifetime(){ return lifetime; } @Override public void setLifetime(int lifetime){ this.lifetime = lifetime; } - @Override public WeakReference getCasterReference(){ return casterReference; } - @Override public void setCasterReference(WeakReference reference){ casterReference = reference; } - @Override public UUID getCasterUUID(){ return casterUUID; } - @Override public void setCasterUUID(UUID uuid){ this.casterUUID = uuid; } + @Override public UUID getOwnerId(){ return casterUUID; } + @Override public void setOwnerId(UUID uuid){ this.casterUUID = uuid; } /** Creates a new ice giant in the given world. */ public EntityIceGiant(World world){ @@ -91,7 +82,7 @@ public class EntityIceGiant extends EntityIronGolem implements ISummonedCreature @Override public void onDespawn(){ - this.playSound(WizardrySounds.SPELL_FREEZE, 1.0f, 1.0f); + this.playSound(WizardrySounds.ENTITY_ICE_GIANT_DESPAWN, 1.0f, 1.0f); this.spawnParticleEffect(); } @@ -126,7 +117,7 @@ public class EntityIceGiant extends EntityIronGolem implements ISummonedCreature this.applyEnchantments(this, target); - this.playSound(SoundEvents.ENTITY_IRONGOLEM_ATTACK, 1.0F, 1.0F); + this.playSound(WizardrySounds.ENTITY_ICE_GIANT_ATTACK, 1.0F, 1.0F); } @Override @@ -160,8 +151,16 @@ public class EntityIceGiant extends EntityIronGolem implements ISummonedCreature @Override protected Item getDropItem(){ return null; } @Override protected ResourceLocation getLootTable(){ return null; } @Override public boolean canPickUpLoot(){ return false; } + // This vanilla method has nothing to do with the custom despawn() method. - @Override protected boolean canDespawn(){ return false; } + @Override protected boolean canDespawn(){ + return getCaster() == null && getOwnerId() == null; + } + + @Override + public boolean getCanSpawnHere(){ + return this.world.getDifficulty() != EnumDifficulty.PEACEFUL; + } @Override public boolean canAttackClass(Class entityType){ @@ -182,7 +181,7 @@ public class EntityIceGiant extends EntityIronGolem implements ISummonedCreature @Override public boolean hasCustomName(){ // If this returns true, the renderer will show the nameplate when looking directly at the entity - return Wizardry.settings.showSummonedCreatureNames && getCaster() != null; + return Wizardry.settings.summonedCreatureNames && getCaster() != null; } } diff --git a/src/main/java/electroblob/wizardry/entity/living/EntityIceWraith.java b/src/main/java/electroblob/wizardry/entity/living/EntityIceWraith.java index 5d9fee8b..467fc3ad 100644 --- a/src/main/java/electroblob/wizardry/entity/living/EntityIceWraith.java +++ b/src/main/java/electroblob/wizardry/entity/living/EntityIceWraith.java @@ -1,16 +1,13 @@ package electroblob.wizardry.entity.living; +import electroblob.wizardry.Wizardry; import electroblob.wizardry.registry.Spells; import electroblob.wizardry.registry.WizardrySounds; import electroblob.wizardry.util.ParticleBuilder; -import electroblob.wizardry.util.SpellModifiers; import electroblob.wizardry.util.ParticleBuilder.Type; +import electroblob.wizardry.util.SpellModifiers; import net.minecraft.entity.EntityLivingBase; -import net.minecraft.entity.ai.EntityAIBase; -import net.minecraft.entity.ai.EntityAILookIdle; -import net.minecraft.entity.ai.EntityAIMoveTowardsRestriction; -import net.minecraft.entity.ai.EntityAIWander; -import net.minecraft.entity.ai.EntityAIWatchClosest; +import net.minecraft.entity.ai.*; import net.minecraft.entity.monster.EntityBlaze; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.init.MobEffects; @@ -66,7 +63,7 @@ public class EntityIceWraith extends EntityBlazeMinion { } if(this.rand.nextInt(24) == 0){ - this.playSound(WizardrySounds.SPELL_LOOP_WIND, 0.3F + this.rand.nextFloat() / 4, + this.playSound(WizardrySounds.ENTITY_ICE_WRAITH_AMBIENT, 0.3F + this.rand.nextFloat() / 4, this.rand.nextFloat() * 0.7F + 1.4F); } @@ -181,14 +178,24 @@ public class EntityIceWraith extends EntityBlazeMinion { @Override public boolean isBurning(){ // Uses the datawatcher on both sides because fire is private to Entity (and I'm not using reflection here). - // TESTME: This should work, but there may be some issues with updating, so if it doesn't work, copy the + // This should work, but there may be some issues with updating, so if it doesn't work, copy the // version from Entity and use reflection to access the fire field. return this.getFlag(0); } + @Override + public boolean getCanSpawnHere(){ + // Only spawns in the specified dimensions + for(int id : Wizardry.settings.mobSpawnDimensions){ + if(this.dimension == id) return super.getCanSpawnHere() && this.isValidLightLevel(); + } + + return false; + } + /** * Copied straight from EntityBlaze.AIFireballAttack, with the only changes being replacement of fireball spawning - * with a one-liner call to WizardryRegistry.iceShard.cast(...) and the removal of redundant local variables. + * with a one-liner call to WizardryLoot.iceShard.cast(...) and the removal of redundant local variables. */ static class AIIceShardAttack extends EntityAIBase { @@ -222,6 +229,7 @@ public class EntityIceWraith extends EntityBlazeMinion { public void updateTask(){ --this.attackTime; EntityLivingBase entitylivingbase = this.blaze.getAttackTarget(); + if(entitylivingbase == null) return; // Dynamic stealth breaks things, let's un-break them double d0 = this.blaze.getDistanceSq(entitylivingbase); if(d0 < 4.0D){ @@ -251,7 +259,6 @@ public class EntityIceWraith extends EntityBlazeMinion { // Proof, if it were at all needed, of the elegance and versatility of the spell system. Spells.ice_shard.cast(this.blaze.world, this.blaze, EnumHand.MAIN_HAND, 0, entitylivingbase, new SpellModifiers()); - // TODO: Decide if an event should be fired here. I'm guessing no. } } diff --git a/src/main/java/electroblob/wizardry/entity/living/EntityLightningWraith.java b/src/main/java/electroblob/wizardry/entity/living/EntityLightningWraith.java index a97c52af..d396735f 100644 --- a/src/main/java/electroblob/wizardry/entity/living/EntityLightningWraith.java +++ b/src/main/java/electroblob/wizardry/entity/living/EntityLightningWraith.java @@ -1,15 +1,12 @@ package electroblob.wizardry.entity.living; +import electroblob.wizardry.Wizardry; import electroblob.wizardry.registry.Spells; import electroblob.wizardry.util.ParticleBuilder; -import electroblob.wizardry.util.SpellModifiers; import electroblob.wizardry.util.ParticleBuilder.Type; +import electroblob.wizardry.util.SpellModifiers; import net.minecraft.entity.EntityLivingBase; -import net.minecraft.entity.ai.EntityAIBase; -import net.minecraft.entity.ai.EntityAILookIdle; -import net.minecraft.entity.ai.EntityAIMoveTowardsRestriction; -import net.minecraft.entity.ai.EntityAIWander; -import net.minecraft.entity.ai.EntityAIWatchClosest; +import net.minecraft.entity.ai.*; import net.minecraft.entity.monster.EntityBlaze; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.init.MobEffects; @@ -75,9 +72,21 @@ public class EntityLightningWraith extends EntityBlazeMinion { return this.getFlag(0); } + @Override + public boolean getCanSpawnHere(){ + // Only spawns in the specified dimensions, during thunderstorms + if(!world.isThundering()) return false; + + for(int id : Wizardry.settings.mobSpawnDimensions){ + if(this.dimension == id) return super.getCanSpawnHere() && this.isValidLightLevel(); + } + + return false; + } + /** * Copied straight from EntityBlaze.AIFireballAttack, with the only changes being replacement of fireball spawning - * with a one-liner call to WizardryRegistry.arc.cast(...) and the removal of redundant local variables. + * with a one-liner call to WizardryLoot.arc.cast(...) and the removal of redundant local variables. */ static class AILightningAttack extends EntityAIBase { @@ -111,6 +120,7 @@ public class EntityLightningWraith extends EntityBlazeMinion { public void updateTask(){ --this.attackTime; EntityLivingBase entitylivingbase = this.blaze.getAttackTarget(); + if(entitylivingbase == null) return; // Dynamic stealth breaks things, let's un-break them double d0 = this.blaze.getDistanceSq(entitylivingbase); if(d0 < 4.0D){ @@ -139,7 +149,6 @@ public class EntityLightningWraith extends EntityBlazeMinion { if(this.attackStep > 1){ // Proof, if it were at all needed, of the elegance and versatility of the spell system. Spells.arc.cast(this.blaze.world, this.blaze, EnumHand.MAIN_HAND, 0, entitylivingbase, new SpellModifiers()); - // TODO: Decide if an event should be fired here. I'm guessing no. } } diff --git a/src/main/java/electroblob/wizardry/entity/living/EntityMagicSlime.java b/src/main/java/electroblob/wizardry/entity/living/EntityMagicSlime.java index 1c9da3ce..183fb155 100644 --- a/src/main/java/electroblob/wizardry/entity/living/EntityMagicSlime.java +++ b/src/main/java/electroblob/wizardry/entity/living/EntityMagicSlime.java @@ -1,16 +1,11 @@ package electroblob.wizardry.entity.living; -import java.lang.ref.WeakReference; -import java.util.UUID; - -import javax.annotation.Nullable; - +import electroblob.wizardry.registry.WizardrySounds; import net.minecraft.entity.EntityLivingBase; import net.minecraft.entity.IEntityLivingData; import net.minecraft.entity.monster.EntitySlime; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.init.MobEffects; -import net.minecraft.init.SoundEvents; import net.minecraft.item.Item; import net.minecraft.nbt.NBTTagCompound; import net.minecraft.potion.PotionEffect; @@ -22,21 +17,21 @@ import net.minecraft.world.DifficultyInstance; import net.minecraft.world.EnumDifficulty; import net.minecraft.world.World; +import javax.annotation.Nullable; +import java.util.UUID; + /** As of Wizardry 1.2, this is now an ISummonedCreature like the rest of them, and it extends EntitySlime. */ public class EntityMagicSlime extends EntitySlime implements ISummonedCreature { // Field implementations private int lifetime = 200; - private WeakReference casterReference; private UUID casterUUID; // Setter + getter implementations @Override public int getLifetime(){ return lifetime; } @Override public void setLifetime(int lifetime){ this.lifetime = lifetime; } - @Override public WeakReference getCasterReference(){ return casterReference; } - @Override public void setCasterReference(WeakReference reference){ casterReference = reference; } - @Override public UUID getCasterUUID(){ return casterUUID; } - @Override public void setCasterUUID(UUID uuid){ this.casterUUID = uuid; } + @Override public UUID getOwnerId(){ return casterUUID; } + @Override public void setOwnerId(UUID uuid){ this.casterUUID = uuid; } public EntityMagicSlime(World world){ super(world); @@ -57,7 +52,7 @@ public class EntityMagicSlime extends EntitySlime implements ISummonedCreature { super(world); this.setPosition(target.posX, target.posY, target.posZ); this.startRiding(target); - this.casterReference = new WeakReference(caster); + this.setOwnerId(caster.getUniqueID()); this.setSlimeSize(2, false); // Needs to be called before setting the experience value to 0 this.experienceValue = 0; this.lifetime = lifetime; @@ -83,8 +78,8 @@ public class EntityMagicSlime extends EntitySlime implements ISummonedCreature { this.world.spawnParticle(EnumParticleTypes.SLIME, x, y, z, (x - this.posX) * 2, (y - this.posY) * 2, (z - this.posZ) * 2); } - this.playSound(SoundEvents.ENTITY_SLIME_ATTACK, 2.5f, 0.6f); - this.playSound(SoundEvents.ENTITY_FIREWORK_BLAST_FAR, 1.0f, 0.5f); + this.playSound(WizardrySounds.ENTITY_MAGIC_SLIME_SPLAT, 2.5f, 0.6f); + this.playSound(WizardrySounds.ENTITY_MAGIC_SLIME_EXPLODE, 1.0f, 0.5f); } @Override @@ -127,7 +122,7 @@ public class EntityMagicSlime extends EntitySlime implements ISummonedCreature { this.getRidingEntity().attackEntityFrom(DamageSource.MAGIC, 1); ((EntityLivingBase)this.getRidingEntity()) .addPotionEffect(new PotionEffect(MobEffects.SLOWNESS, 20, 2)); - this.playSound(SoundEvents.ENTITY_SLIME_ATTACK, 1.0f, 1.0f); + this.playSound(WizardrySounds.ENTITY_MAGIC_SLIME_ATTACK, 1.0f, 1.0f); this.squishAmount = 0.5F; } }else{ @@ -174,7 +169,10 @@ public class EntityMagicSlime extends EntitySlime implements ISummonedCreature { @Override protected Item getDropItem(){ return null; } @Override protected ResourceLocation getLootTable(){ return null; } @Override public boolean canPickUpLoot(){ return false; } + // This vanilla method has nothing to do with the custom despawn() method. - @Override protected boolean canDespawn(){ return false; } + @Override protected boolean canDespawn(){ + return getCaster() == null && getOwnerId() == null; + } } diff --git a/src/main/java/electroblob/wizardry/entity/living/EntityPhoenix.java b/src/main/java/electroblob/wizardry/entity/living/EntityPhoenix.java index 73170416..e04428b0 100644 --- a/src/main/java/electroblob/wizardry/entity/living/EntityPhoenix.java +++ b/src/main/java/electroblob/wizardry/entity/living/EntityPhoenix.java @@ -1,9 +1,7 @@ package electroblob.wizardry.entity.living; -import java.util.Collections; -import java.util.List; - import electroblob.wizardry.registry.Spells; +import electroblob.wizardry.registry.WizardrySounds; import electroblob.wizardry.spell.Spell; import electroblob.wizardry.util.SpellModifiers; import electroblob.wizardry.util.WizardryUtilities; @@ -13,7 +11,6 @@ import net.minecraft.entity.ai.EntityAIHurtByTarget; import net.minecraft.entity.ai.EntityAILookIdle; import net.minecraft.entity.ai.EntityAINearestAttackableTarget; import net.minecraft.entity.ai.EntityAIWatchClosest; -import net.minecraft.init.SoundEvents; import net.minecraft.util.DamageSource; import net.minecraft.util.EnumParticleTypes; import net.minecraft.util.SoundEvent; @@ -22,6 +19,9 @@ import net.minecraft.world.World; import net.minecraftforge.fml.relauncher.Side; import net.minecraftforge.fml.relauncher.SideOnly; +import java.util.Collections; +import java.util.List; + public class EntityPhoenix extends EntitySummonedCreature implements ISpellCaster { private double AISpeed = 0.5; @@ -97,17 +97,17 @@ public class EntityPhoenix extends EntitySummonedCreature implements ISpellCaste @Override protected SoundEvent getAmbientSound(){ - return SoundEvents.ENTITY_BLAZE_AMBIENT; + return WizardrySounds.ENTITY_PHOENIX_AMBIENT; } @Override protected SoundEvent getHurtSound(DamageSource source){ - return SoundEvents.ENTITY_BLAZE_HURT; + return WizardrySounds.ENTITY_PHOENIX_HURT; } @Override protected SoundEvent getDeathSound(){ - return SoundEvents.ENTITY_BLAZE_DEATH; + return WizardrySounds.ENTITY_PHOENIX_DEATH; } @Override @@ -144,9 +144,9 @@ public class EntityPhoenix extends EntitySummonedCreature implements ISpellCaste public void onLivingUpdate(){ // Makes the phoenix hover. - int floorLevel = WizardryUtilities.getNearestFloorLevel(world, new BlockPos(this), 4); + Integer floorLevel = WizardryUtilities.getNearestFloor(world, new BlockPos(this), 4); - if(this.posY - floorLevel > 3){ + if(floorLevel == null || this.posY - floorLevel > 3){ this.motionY = -0.1; }else if(this.posY - floorLevel < 2){ this.motionY = 0.1; @@ -156,13 +156,13 @@ public class EntityPhoenix extends EntitySummonedCreature implements ISpellCaste // Living sound if(this.rand.nextInt(24) == 0){ - this.playSound(SoundEvents.BLOCK_FIRE_AMBIENT, 1.0F + this.rand.nextFloat(), + this.playSound(WizardrySounds.ENTITY_PHOENIX_BURN, 1.0F + this.rand.nextFloat(), this.rand.nextFloat() * 0.7F + 0.3F); } // Flapping sound effect if(this.ticksExisted % 22 == 0){ - this.playSound(SoundEvents.ENTITY_ENDERDRAGON_FLAP, 1.0F, 1.0f); + this.playSound(WizardrySounds.ENTITY_PHOENIX_FLAP, 1.0F, 1.0f); } for(int i = 0; i < 2; i++){ diff --git a/src/main/java/electroblob/wizardry/entity/living/EntityShadowWraith.java b/src/main/java/electroblob/wizardry/entity/living/EntityShadowWraith.java index d09a3326..55963b90 100644 --- a/src/main/java/electroblob/wizardry/entity/living/EntityShadowWraith.java +++ b/src/main/java/electroblob/wizardry/entity/living/EntityShadowWraith.java @@ -1,22 +1,15 @@ package electroblob.wizardry.entity.living; -import java.util.Collections; -import java.util.List; - import electroblob.wizardry.registry.Spells; +import electroblob.wizardry.registry.WizardrySounds; import electroblob.wizardry.spell.Spell; import electroblob.wizardry.util.ParticleBuilder; -import electroblob.wizardry.util.SpellModifiers; import electroblob.wizardry.util.ParticleBuilder.Type; +import electroblob.wizardry.util.SpellModifiers; import net.minecraft.entity.EntityLivingBase; import net.minecraft.entity.SharedMonsterAttributes; -import net.minecraft.entity.ai.EntityAIAttackMelee; -import net.minecraft.entity.ai.EntityAIHurtByTarget; -import net.minecraft.entity.ai.EntityAILookIdle; -import net.minecraft.entity.ai.EntityAINearestAttackableTarget; -import net.minecraft.entity.ai.EntityAIWander; +import net.minecraft.entity.ai.*; import net.minecraft.init.MobEffects; -import net.minecraft.init.SoundEvents; import net.minecraft.potion.PotionEffect; import net.minecraft.util.DamageSource; import net.minecraft.util.EnumParticleTypes; @@ -25,6 +18,9 @@ import net.minecraft.world.World; import net.minecraftforge.fml.relauncher.Side; import net.minecraftforge.fml.relauncher.SideOnly; +import java.util.Collections; +import java.util.List; + public class EntityShadowWraith extends EntitySummonedCreature implements ISpellCaster { // TODO: This currently doesn't fly like it used to. Should it, or does it not matter? @@ -96,17 +92,17 @@ public class EntityShadowWraith extends EntitySummonedCreature implements ISpell @Override protected SoundEvent getAmbientSound(){ - return SoundEvents.ENTITY_BLAZE_AMBIENT; + return WizardrySounds.ENTITY_SHADOW_WRAITH_AMBIENT; } @Override protected SoundEvent getHurtSound(DamageSource source){ - return SoundEvents.ENTITY_BLAZE_HURT; + return WizardrySounds.ENTITY_SHADOW_WRAITH_HURT; } @Override protected SoundEvent getDeathSound(){ - return SoundEvents.ENTITY_BLAZE_DEATH; + return WizardrySounds.ENTITY_SHADOW_WRAITH_DEATH; } @Override @@ -135,7 +131,7 @@ public class EntityShadowWraith extends EntitySummonedCreature implements ISpell public void onLivingUpdate(){ if(this.rand.nextInt(24) == 0){ - this.playSound(SoundEvents.BLOCK_PORTAL_AMBIENT, 1.0F + this.rand.nextFloat(), + this.playSound(WizardrySounds.ENTITY_SHADOW_WRAITH_NOISE, 1.0F + this.rand.nextFloat(), this.rand.nextFloat() * 0.7F + 0.3F); } diff --git a/src/main/java/electroblob/wizardry/entity/living/EntitySilverfishMinion.java b/src/main/java/electroblob/wizardry/entity/living/EntitySilverfishMinion.java index e0275389..d7d92d76 100644 --- a/src/main/java/electroblob/wizardry/entity/living/EntitySilverfishMinion.java +++ b/src/main/java/electroblob/wizardry/entity/living/EntitySilverfishMinion.java @@ -1,8 +1,5 @@ package electroblob.wizardry.entity.living; -import java.lang.ref.WeakReference; -import java.util.UUID; - import electroblob.wizardry.Wizardry; import electroblob.wizardry.util.ParticleBuilder; import electroblob.wizardry.util.ParticleBuilder.Type; @@ -20,22 +17,26 @@ import net.minecraft.util.EnumHand; import net.minecraft.util.ResourceLocation; import net.minecraft.util.text.ITextComponent; import net.minecraft.util.text.TextComponentTranslation; +import net.minecraft.world.EnumDifficulty; import net.minecraft.world.World; +import java.util.UUID; + public class EntitySilverfishMinion extends EntitySilverfish implements ISummonedCreature { + public static final int MAX_GENERATIONS = 5; + // Field implementations - private int lifetime = 600; - private WeakReference casterReference; + private int lifetime = -1; private UUID casterUUID; + private int generation = 1; + // Setter + getter implementations @Override public int getLifetime(){ return lifetime; } @Override public void setLifetime(int lifetime){ this.lifetime = lifetime; } - @Override public WeakReference getCasterReference(){ return casterReference; } - @Override public void setCasterReference(WeakReference reference){ casterReference = reference; } - @Override public UUID getCasterUUID(){ return casterUUID; } - @Override public void setCasterUUID(UUID uuid){ this.casterUUID = uuid; } + @Override public UUID getOwnerId(){ return casterUUID; } + @Override public void setOwnerId(UUID uuid){ this.casterUUID = uuid; } /** Creates a new silverfish minion in the given world. */ public EntitySilverfishMinion(World world){ @@ -50,7 +51,7 @@ public class EntitySilverfishMinion extends EntitySilverfish implements ISummone this.tasks.addTask(1, new EntityAISwimming(this)); this.tasks.addTask(4, new EntityAIAttackMelee(this, 1.0D, false)); this.targetTasks.addTask(1, new EntityAIHurtByTarget(this, false)); - this.targetTasks.addTask(2, new EntityAINearestAttackableTarget(this, EntityLivingBase.class, + this.targetTasks.addTask(2, new EntityAINearestAttackableTarget<>(this, EntityLivingBase.class, 0, false, true, this.getTargetSelector())); } @@ -99,7 +100,7 @@ public class EntitySilverfishMinion extends EntitySilverfish implements ISummone public void onKillEntity(EntityLivingBase victim){ // If the silverfish has a summoner, this is actually called from Wizardry's event handler rather than by // Minecraft itself, because the damagesource being changed causes it not to get called. - if(!this.world.isRemote){ + if(!this.world.isRemote && generation < MAX_GENERATIONS){ // Summons 1-4 more silverfish int alliesToSummon = rand.nextInt(4) + 1; @@ -108,6 +109,7 @@ public class EntitySilverfishMinion extends EntitySilverfish implements ISummone silverfish.setPosition(victim.posX, victim.posY, victim.posZ); silverfish.setCaster(this.getCaster()); silverfish.setLifetime(this.getLifetime()); + silverfish.generation = this.generation + 1; this.world.spawnEntity(silverfish); } } @@ -129,12 +131,14 @@ public class EntitySilverfishMinion extends EntitySilverfish implements ISummone public void writeEntityToNBT(NBTTagCompound nbttagcompound){ super.writeEntityToNBT(nbttagcompound); this.writeNBTDelegate(nbttagcompound); + nbttagcompound.setInteger("generation", this.generation); } @Override public void readEntityFromNBT(NBTTagCompound nbttagcompound){ super.readEntityFromNBT(nbttagcompound); this.readNBTDelegate(nbttagcompound); + this.generation = nbttagcompound.getInteger("generation"); } // Recommended overrides @@ -144,8 +148,16 @@ public class EntitySilverfishMinion extends EntitySilverfish implements ISummone @Override protected Item getDropItem(){ return null; } @Override protected ResourceLocation getLootTable(){ return null; } @Override public boolean canPickUpLoot(){ return false; } + // This vanilla method has nothing to do with the custom despawn() method. - @Override protected boolean canDespawn(){ return false; } + @Override protected boolean canDespawn(){ + return getCaster() == null && getOwnerId() == null; + } + + @Override + public boolean getCanSpawnHere(){ + return this.world.getDifficulty() != EnumDifficulty.PEACEFUL; + } @Override public boolean canAttackClass(Class entityType){ @@ -166,6 +178,6 @@ public class EntitySilverfishMinion extends EntitySilverfish implements ISummone @Override public boolean hasCustomName(){ // If this returns true, the renderer will show the nameplate when looking directly at the entity - return Wizardry.settings.showSummonedCreatureNames && getCaster() != null; + return Wizardry.settings.summonedCreatureNames && getCaster() != null; } } \ No newline at end of file diff --git a/src/main/java/electroblob/wizardry/entity/living/EntitySkeletonMinion.java b/src/main/java/electroblob/wizardry/entity/living/EntitySkeletonMinion.java index c1801d76..2d10fd34 100644 --- a/src/main/java/electroblob/wizardry/entity/living/EntitySkeletonMinion.java +++ b/src/main/java/electroblob/wizardry/entity/living/EntitySkeletonMinion.java @@ -1,12 +1,7 @@ package electroblob.wizardry.entity.living; -import java.lang.ref.WeakReference; -import java.util.Calendar; -import java.util.UUID; - -import javax.annotation.Nullable; - import electroblob.wizardry.Wizardry; +import electroblob.wizardry.util.WizardryUtilities.Operations; import net.minecraft.entity.EntityFlying; import net.minecraft.entity.EntityLivingBase; import net.minecraft.entity.IEntityLivingData; @@ -14,37 +9,39 @@ import net.minecraft.entity.SharedMonsterAttributes; import net.minecraft.entity.ai.EntityAIHurtByTarget; import net.minecraft.entity.ai.EntityAINearestAttackableTarget; import net.minecraft.entity.ai.attributes.AttributeModifier; -import net.minecraft.entity.monster.EntitySkeleton; +import net.minecraft.entity.monster.AbstractSkeleton; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.init.Blocks; import net.minecraft.init.Items; +import net.minecraft.init.SoundEvents; import net.minecraft.inventory.EntityEquipmentSlot; import net.minecraft.item.Item; import net.minecraft.item.ItemBow; import net.minecraft.item.ItemStack; import net.minecraft.nbt.NBTTagCompound; -import net.minecraft.util.EnumHand; -import net.minecraft.util.EnumParticleTypes; -import net.minecraft.util.ResourceLocation; +import net.minecraft.util.*; import net.minecraft.util.text.ITextComponent; import net.minecraft.util.text.TextComponentTranslation; import net.minecraft.world.DifficultyInstance; +import net.minecraft.world.EnumDifficulty; import net.minecraft.world.World; -public class EntitySkeletonMinion extends EntitySkeleton implements ISummonedCreature { +import javax.annotation.Nullable; +import java.util.Calendar; +import java.util.UUID; + +// Extends AbstractSkeleton because EntitySkeleton drops skulls, which we don't want +public class EntitySkeletonMinion extends AbstractSkeleton implements ISummonedCreature { // Field implementations - private int lifetime = 600; - private WeakReference casterReference; + private int lifetime = -1; private UUID casterUUID; // Setter + getter implementations @Override public int getLifetime(){ return lifetime; } @Override public void setLifetime(int lifetime){ this.lifetime = lifetime; } - @Override public WeakReference getCasterReference(){ return casterReference; } - @Override public void setCasterReference(WeakReference reference){ casterReference = reference; } - @Override public UUID getCasterUUID(){ return casterUUID; } - @Override public void setCasterUUID(UUID uuid){ this.casterUUID = uuid; } + @Override public UUID getOwnerId(){ return casterUUID; } + @Override public void setOwnerId(UUID uuid){ this.casterUUID = uuid; } /** Creates a new skeleton minion in the given world. */ public EntitySkeletonMinion(World world){ @@ -55,13 +52,13 @@ public class EntitySkeletonMinion extends EntitySkeleton implements ISummonedCre // EntitySkeleton overrides // This particular override is pretty standard: let the superclass handle basic AI like swimming, but replace its - // targeting system with one that targets hostile mobs and takes the ADS into account. + // targeting system with one that targets hostile mobs and takes the AllyDesignationSystem into account. @Override protected void initEntityAI(){ super.initEntityAI(); this.targetTasks.taskEntries.clear(); this.targetTasks.addTask(1, new EntityAIHurtByTarget(this, false)); - this.targetTasks.addTask(2, new EntityAINearestAttackableTarget(this, EntityLivingBase.class, + this.targetTasks.addTask(2, new EntityAINearestAttackableTarget<>(this, EntityLivingBase.class, 0, false, true, this.getTargetSelector())); } @@ -76,7 +73,7 @@ public class EntitySkeletonMinion extends EntitySkeleton implements ISummonedCre public IEntityLivingData onInitialSpawn(DifficultyInstance difficulty, @Nullable IEntityLivingData livingdata){ // Can't call super, so the code from the next level up (EntityLiving) had to be copied as well. this.getEntityAttribute(SharedMonsterAttributes.FOLLOW_RANGE) - .applyModifier(new AttributeModifier("Random spawn bonus", this.rand.nextGaussian() * 0.05D, 1)); + .applyModifier(new AttributeModifier("Random spawn bonus", this.rand.nextGaussian() * 0.05D, Operations.MULTIPLY_FLAT)); if(this.rand.nextFloat() < 0.05F){ this.setLeftHanded(true); @@ -98,6 +95,12 @@ public class EntitySkeletonMinion extends EntitySkeleton implements ISummonedCre return livingdata; } + // Since we're extending AbstractSkeleton these aren't set by the superclass like normal + @Override protected SoundEvent getAmbientSound(){ return SoundEvents.ENTITY_SKELETON_AMBIENT; } + @Override protected SoundEvent getHurtSound(DamageSource source){ return SoundEvents.ENTITY_SKELETON_HURT; } + @Override protected SoundEvent getDeathSound(){ return SoundEvents.ENTITY_SKELETON_DEATH; } + @Override protected SoundEvent getStepSound(){ return SoundEvents.ENTITY_SKELETON_STEP; } + // Implementations @Override @@ -161,8 +164,16 @@ public class EntitySkeletonMinion extends EntitySkeleton implements ISummonedCre @Override protected Item getDropItem(){ return null; } @Override protected ResourceLocation getLootTable(){ return null; } @Override public boolean canPickUpLoot(){ return false; } + // This vanilla method has nothing to do with the custom despawn() method. - @Override protected boolean canDespawn(){ return false; } + @Override protected boolean canDespawn(){ + return getCaster() == null && getOwnerId() == null; + } + + @Override + public boolean getCanSpawnHere(){ + return this.world.getDifficulty() != EnumDifficulty.PEACEFUL; + } @Override public boolean canAttackClass(Class entityType){ @@ -183,6 +194,6 @@ public class EntitySkeletonMinion extends EntitySkeleton implements ISummonedCre @Override public boolean hasCustomName(){ // If this returns true, the renderer will show the nameplate when looking directly at the entity - return Wizardry.settings.showSummonedCreatureNames && getCaster() != null; + return Wizardry.settings.summonedCreatureNames && getCaster() != null; } } diff --git a/src/main/java/electroblob/wizardry/entity/living/EntitySpiderMinion.java b/src/main/java/electroblob/wizardry/entity/living/EntitySpiderMinion.java index 328e988c..b4efebc2 100644 --- a/src/main/java/electroblob/wizardry/entity/living/EntitySpiderMinion.java +++ b/src/main/java/electroblob/wizardry/entity/living/EntitySpiderMinion.java @@ -1,11 +1,9 @@ package electroblob.wizardry.entity.living; -import java.lang.ref.WeakReference; -import java.util.UUID; - import electroblob.wizardry.Wizardry; import electroblob.wizardry.util.ParticleBuilder; import electroblob.wizardry.util.ParticleBuilder.Type; +import electroblob.wizardry.util.WizardryUtilities.Operations; import net.minecraft.entity.EntityFlying; import net.minecraft.entity.EntityLivingBase; import net.minecraft.entity.IEntityLivingData; @@ -27,20 +25,19 @@ import net.minecraft.world.DifficultyInstance; import net.minecraft.world.EnumDifficulty; import net.minecraft.world.World; +import java.util.UUID; + public class EntitySpiderMinion extends EntityCaveSpider implements ISummonedCreature { // Field implementations - private int lifetime = 600; - private WeakReference casterReference; + private int lifetime = -1; private UUID casterUUID; // Setter + getter implementations @Override public int getLifetime(){ return lifetime; } @Override public void setLifetime(int lifetime){ this.lifetime = lifetime; } - @Override public WeakReference getCasterReference(){ return casterReference; } - @Override public void setCasterReference(WeakReference reference){ casterReference = reference; } - @Override public UUID getCasterUUID(){ return casterUUID; } - @Override public void setCasterUUID(UUID uuid){ this.casterUUID = uuid; } + @Override public UUID getOwnerId(){ return casterUUID; } + @Override public void setOwnerId(UUID uuid){ this.casterUUID = uuid; } /** Creates a new spider minion in the given world. */ public EntitySpiderMinion(World world){ @@ -51,7 +48,7 @@ public class EntitySpiderMinion extends EntityCaveSpider implements ISummonedCre // EntitySpider overrides // This particular override is pretty standard: let the superclass handle basic AI like swimming, but replace its - // targeting system with one that targets hostile mobs and takes the ADS into account. + // targeting system with one that targets hostile mobs and takes the AllyDesignationSystem into account. @Override protected void initEntityAI(){ super.initEntityAI(); @@ -70,7 +67,7 @@ public class EntitySpiderMinion extends EntityCaveSpider implements ISummonedCre // Can't call super, so the code from the next level up (EntityLiving) had to be copied as well. this.getEntityAttribute(SharedMonsterAttributes.FOLLOW_RANGE) - .applyModifier(new AttributeModifier("Random spawn bonus", this.rand.nextGaussian() * 0.05D, 1)); + .applyModifier(new AttributeModifier("Random spawn bonus", this.rand.nextGaussian() * 0.05D, Operations.MULTIPLY_FLAT)); if(this.rand.nextFloat() < 0.05F){ this.setLeftHanded(true); @@ -163,8 +160,16 @@ public class EntitySpiderMinion extends EntityCaveSpider implements ISummonedCre @Override protected Item getDropItem(){ return null; } @Override protected ResourceLocation getLootTable(){ return null; } @Override public boolean canPickUpLoot(){ return false; } + // This vanilla method has nothing to do with the custom despawn() method. - @Override protected boolean canDespawn(){ return false; } + @Override protected boolean canDespawn(){ + return getCaster() == null && getOwnerId() == null; + } + + @Override + public boolean getCanSpawnHere(){ + return this.world.getDifficulty() != EnumDifficulty.PEACEFUL; + } @Override public boolean canAttackClass(Class entityType){ @@ -185,6 +190,6 @@ public class EntitySpiderMinion extends EntityCaveSpider implements ISummonedCre @Override public boolean hasCustomName(){ // If this returns true, the renderer will show the nameplate when looking directly at the entity - return Wizardry.settings.showSummonedCreatureNames && getCaster() != null; + return Wizardry.settings.summonedCreatureNames && getCaster() != null; } } diff --git a/src/main/java/electroblob/wizardry/entity/living/EntitySpiritHorse.java b/src/main/java/electroblob/wizardry/entity/living/EntitySpiritHorse.java index 67284bde..98deb764 100644 --- a/src/main/java/electroblob/wizardry/entity/living/EntitySpiritHorse.java +++ b/src/main/java/electroblob/wizardry/entity/living/EntitySpiritHorse.java @@ -1,8 +1,7 @@ package electroblob.wizardry.entity.living; -import electroblob.wizardry.WizardData; import electroblob.wizardry.Wizardry; -import electroblob.wizardry.item.ItemWand; +import electroblob.wizardry.item.ISpellCastingItem; import electroblob.wizardry.registry.WizardrySounds; import electroblob.wizardry.util.ParticleBuilder; import electroblob.wizardry.util.ParticleBuilder.Type; @@ -16,7 +15,6 @@ import net.minecraft.entity.passive.EntityHorse; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.item.Item; import net.minecraft.item.ItemStack; -import net.minecraft.util.DamageSource; import net.minecraft.util.EnumHand; import net.minecraft.util.ResourceLocation; import net.minecraft.util.text.ITextComponent; @@ -34,6 +32,10 @@ public class EntitySpiritHorse extends EntityHorse { private int idleTimer = 0; + private int dispelTimer = 0; + + private static final int DISPEL_TIME = 10; + public EntitySpiritHorse(World par1World){ super(par1World); } @@ -93,19 +95,13 @@ public class EntitySpiritHorse extends EntityHorse { // Allows the owner (but not other players) to dispel the spirit horse using a wand (shift-clicking, because // clicking mounts the horse in this case). - if(itemstack.getItem() instanceof ItemWand && this.getOwner() == player && player.isSneaking()){ + if(itemstack.getItem() instanceof ISpellCastingItem && this.getOwner() == player && player.isSneaking()){ // Prevents accidental double clicking. if(this.ticksExisted > 20){ + + this.dispelTimer++; - this.spawnAppearParticles(); - - this.setDead(); - - if(WizardData.get(player) != null){ - WizardData.get(player).hasSpiritHorse = false; - } - - this.playSound(WizardrySounds.SPELL_HEAL, 0.7F, rand.nextFloat() * 0.4F + 1.0F); + this.playSound(WizardrySounds.ENTITY_SPIRIT_HORSE_VANISH, 0.7F, rand.nextFloat() * 0.4F + 1.0F); // This is necessary to prevent the wand's spell being cast when performing this action. return true; } @@ -124,17 +120,6 @@ public class EntitySpiritHorse extends EntityHorse { } } - @Override - public void onDeath(DamageSource par1DamageSource){ - - super.onDeath(par1DamageSource); - - // Allows player to summon another spirit horse once this one has died. - if(this.getOwner() instanceof EntityPlayer && WizardData.get((EntityPlayer)this.getOwner()) != null){ - WizardData.get((EntityPlayer)this.getOwner()).hasSpiritHorse = false; - } - } - // I wrote this one! private EntityLivingBase getOwner(){ @@ -148,11 +133,21 @@ public class EntitySpiritHorse extends EntityHorse { } } + public float getOpacity(){ + return 1 - (float)dispelTimer/DISPEL_TIME; + } + @Override public void onUpdate(){ super.onUpdate(); + if(dispelTimer > 0){ + if(dispelTimer++ > DISPEL_TIME){ + this.setDead(); + } + } + // Adds a dust particle effect if(this.world.isRemote){ double x = this.posX - this.width / 2 + this.rand.nextFloat() * width; @@ -170,17 +165,9 @@ public class EntitySpiritHorse extends EntityHorse { if(this.idleTimer > 200){ - if(this.world.isRemote){ - this.spawnAppearParticles(); - } + this.playSound(WizardrySounds.ENTITY_SPIRIT_HORSE_VANISH, 0.7F, rand.nextFloat() * 0.4F + 1.0F); - this.playSound(WizardrySounds.SPELL_HEAL, 0.7F, rand.nextFloat() * 0.4F + 1.0F); - // Allows player to summon another spirit horse once this one has disappeared. - if(this.getOwner() instanceof EntityPlayer && WizardData.get((EntityPlayer)this.getOwner()) != null){ - WizardData.get((EntityPlayer)this.getOwner()).hasSpiritHorse = false; - } - - this.setDead(); + this.dispelTimer++; } } @@ -213,7 +200,7 @@ public class EntitySpiritHorse extends EntityHorse { @Override public boolean hasCustomName(){ // If this returns true, the renderer will show the nameplate when looking directly at the entity - return Wizardry.settings.showSummonedCreatureNames && getOwner() != null; + return Wizardry.settings.summonedCreatureNames && getOwner() != null; } } diff --git a/src/main/java/electroblob/wizardry/entity/living/EntitySpiritWolf.java b/src/main/java/electroblob/wizardry/entity/living/EntitySpiritWolf.java index f18601f9..3c8929b5 100644 --- a/src/main/java/electroblob/wizardry/entity/living/EntitySpiritWolf.java +++ b/src/main/java/electroblob/wizardry/entity/living/EntitySpiritWolf.java @@ -1,29 +1,17 @@ package electroblob.wizardry.entity.living; -import electroblob.wizardry.WizardData; import electroblob.wizardry.Wizardry; -import electroblob.wizardry.item.ItemWand; +import electroblob.wizardry.item.ISpellCastingItem; import electroblob.wizardry.registry.WizardrySounds; import electroblob.wizardry.util.ParticleBuilder; import electroblob.wizardry.util.ParticleBuilder.Type; import net.minecraft.entity.EntityAgeable; import net.minecraft.entity.IEntityLivingData; -import net.minecraft.entity.ai.EntityAIAttackMelee; -import net.minecraft.entity.ai.EntityAIFollowOwner; -import net.minecraft.entity.ai.EntityAIHurtByTarget; -import net.minecraft.entity.ai.EntityAILeapAtTarget; -import net.minecraft.entity.ai.EntityAILookIdle; -import net.minecraft.entity.ai.EntityAIOwnerHurtByTarget; -import net.minecraft.entity.ai.EntityAIOwnerHurtTarget; -import net.minecraft.entity.ai.EntityAISit; -import net.minecraft.entity.ai.EntityAISwimming; -import net.minecraft.entity.ai.EntityAIWander; -import net.minecraft.entity.ai.EntityAIWatchClosest; +import net.minecraft.entity.ai.*; import net.minecraft.entity.passive.EntityWolf; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.item.Item; import net.minecraft.item.ItemStack; -import net.minecraft.util.DamageSource; import net.minecraft.util.EnumHand; import net.minecraft.util.ResourceLocation; import net.minecraft.util.text.ITextComponent; @@ -37,9 +25,12 @@ import net.minecraft.world.World; */ public class EntitySpiritWolf extends EntityWolf { - public EntitySpiritWolf(World par1World){ + private int dispelTimer = 0; - super(par1World); + private static final int DISPEL_TIME = 10; + + public EntitySpiritWolf(World world){ + super(world); this.experienceValue = 0; } @@ -60,18 +51,6 @@ public class EntitySpiritWolf extends EntityWolf { this.targetTasks.addTask(3, new EntityAIHurtByTarget(this, true, new Class[0])); } - @Override - public void onDeath(DamageSource source){ - - // Allows player to summon another spirit wolf once this one has died. - // NOTE: This has been known to work incorrectly. - if(this.getOwner() instanceof EntityPlayer && WizardData.get((EntityPlayer)this.getOwner()) != null){ - WizardData.get((EntityPlayer)this.getOwner()).hasSpiritWolf = false; - } - - super.onDeath(source); - } - @Override public IEntityLivingData onInitialSpawn(DifficultyInstance difficulty, IEntityLivingData livingdata){ @@ -92,12 +71,22 @@ public class EntitySpiritWolf extends EntityWolf { ParticleBuilder.create(Type.SPARKLE).pos(x, y, z).clr(0.8f, 0.8f, 1.0f).spawn(world); } } + + public float getOpacity(){ + return 1 - (float)dispelTimer/DISPEL_TIME; + } @Override public void onUpdate(){ super.onUpdate(); + if(dispelTimer > 0){ + if(dispelTimer++ > DISPEL_TIME){ + this.setDead(); + } + } + // Adds a dust particle effect if(this.world.isRemote){ double x = this.posX - this.width / 2 + this.rand.nextFloat() * width; @@ -116,21 +105,13 @@ public class EntitySpiritWolf extends EntityWolf { // Allows the owner (but not other players) to dispel the spirit wolf using a // wand. - if(stack.getItem() instanceof ItemWand && this.getOwner() == player && player.isSneaking()){ + if(stack.getItem() instanceof ISpellCastingItem && this.getOwner() == player && player.isSneaking()){ // Prevents accidental double clicking. if(this.ticksExisted > 20){ - if(this.world.isRemote){ - this.spawnAppearParticles(); - } + this.dispelTimer++; - this.setDead(); - - if(WizardData.get(player) != null){ - WizardData.get(player).hasSpiritWolf = false; - } - - this.playSound(WizardrySounds.SPELL_HEAL, 0.7F, rand.nextFloat() * 0.4F + 1.0F); + this.playSound(WizardrySounds.ENTITY_SPIRIT_WOLF_VANISH, 0.7F, rand.nextFloat() * 0.4F + 1.0F); // This is necessary to prevent the wand's spell being cast when performing this // action. return true; @@ -181,7 +162,7 @@ public class EntitySpiritWolf extends EntityWolf { public boolean hasCustomName(){ // If this returns true, the renderer will show the nameplate when looking // directly at the entity - return Wizardry.settings.showSummonedCreatureNames && getOwner() != null; + return Wizardry.settings.summonedCreatureNames && getOwner() != null; } } diff --git a/src/main/java/electroblob/wizardry/entity/living/EntityStormElemental.java b/src/main/java/electroblob/wizardry/entity/living/EntityStormElemental.java index 29776335..ce87a216 100644 --- a/src/main/java/electroblob/wizardry/entity/living/EntityStormElemental.java +++ b/src/main/java/electroblob/wizardry/entity/living/EntityStormElemental.java @@ -1,23 +1,15 @@ package electroblob.wizardry.entity.living; -import java.util.Collections; -import java.util.List; - import electroblob.wizardry.registry.Spells; import electroblob.wizardry.registry.WizardrySounds; import electroblob.wizardry.spell.Spell; import electroblob.wizardry.util.ParticleBuilder; -import electroblob.wizardry.util.SpellModifiers; import electroblob.wizardry.util.ParticleBuilder.Type; +import electroblob.wizardry.util.SpellModifiers; import net.minecraft.entity.EntityLivingBase; import net.minecraft.entity.SharedMonsterAttributes; -import net.minecraft.entity.ai.EntityAIAttackMelee; -import net.minecraft.entity.ai.EntityAIHurtByTarget; -import net.minecraft.entity.ai.EntityAILookIdle; -import net.minecraft.entity.ai.EntityAINearestAttackableTarget; -import net.minecraft.entity.ai.EntityAIWander; +import net.minecraft.entity.ai.*; import net.minecraft.entity.effect.EntityLightningBolt; -import net.minecraft.init.SoundEvents; import net.minecraft.util.DamageSource; import net.minecraft.util.EnumParticleTypes; import net.minecraft.util.SoundEvent; @@ -25,6 +17,9 @@ import net.minecraft.world.World; import net.minecraftforge.fml.relauncher.Side; import net.minecraftforge.fml.relauncher.SideOnly; +import java.util.Collections; +import java.util.List; + public class EntityStormElemental extends EntitySummonedCreature implements ISpellCaster { private double AISpeed = 1.0; @@ -90,17 +85,17 @@ public class EntityStormElemental extends EntitySummonedCreature implements ISpe @Override protected SoundEvent getAmbientSound(){ - return SoundEvents.ENTITY_BLAZE_AMBIENT; + return WizardrySounds.ENTITY_STORM_ELEMENTAL_AMBIENT; } @Override protected SoundEvent getHurtSound(DamageSource source){ - return SoundEvents.ENTITY_BLAZE_HURT; + return WizardrySounds.ENTITY_STORM_ELEMENTAL_HURT; } @Override protected SoundEvent getDeathSound(){ - return SoundEvents.ENTITY_BLAZE_DEATH; + return WizardrySounds.ENTITY_STORM_ELEMENTAL_DEATH; } @Override @@ -118,11 +113,11 @@ public class EntityStormElemental extends EntitySummonedCreature implements ISpe public void onLivingUpdate(){ if(this.ticksExisted % 120 == 1){ - this.playSound(WizardrySounds.SPELL_LOOP_WIND, 1.0f, 1.0f); + this.playSound(WizardrySounds.ENTITY_STORM_ELEMENTAL_WIND, 1.0f, 1.0f); } if(this.rand.nextInt(24) == 0){ - this.playSound(SoundEvents.ENTITY_BLAZE_BURN, 1.0F + this.rand.nextFloat(), + this.playSound(WizardrySounds.ENTITY_STORM_ELEMENTAL_BURN, 1.0F + this.rand.nextFloat(), this.rand.nextFloat() * 0.7F + 0.3F); } diff --git a/src/main/java/electroblob/wizardry/entity/living/EntityStrayMinion.java b/src/main/java/electroblob/wizardry/entity/living/EntityStrayMinion.java new file mode 100644 index 00000000..6edcc700 --- /dev/null +++ b/src/main/java/electroblob/wizardry/entity/living/EntityStrayMinion.java @@ -0,0 +1,35 @@ +package electroblob.wizardry.entity.living; + +import net.minecraft.entity.projectile.EntityArrow; +import net.minecraft.entity.projectile.EntityTippedArrow; +import net.minecraft.init.MobEffects; +import net.minecraft.init.SoundEvents; +import net.minecraft.potion.PotionEffect; +import net.minecraft.util.DamageSource; +import net.minecraft.util.SoundEvent; +import net.minecraft.world.World; + +public class EntityStrayMinion extends EntitySkeletonMinion { + + /** Creates a new stray minion in the given world. */ + public EntityStrayMinion(World world){ + super(world); + } + + @Override protected SoundEvent getAmbientSound(){ return SoundEvents.ENTITY_STRAY_AMBIENT; } + @Override protected SoundEvent getHurtSound(DamageSource source){ return SoundEvents.ENTITY_STRAY_HURT; } + @Override protected SoundEvent getDeathSound(){ return SoundEvents.ENTITY_STRAY_DEATH; } + @Override protected SoundEvent getStepSound(){ return SoundEvents.ENTITY_STRAY_STEP; } + + @Override + protected EntityArrow getArrow(float distanceFactor){ + + EntityArrow entityarrow = super.getArrow(distanceFactor); + + if(entityarrow instanceof EntityTippedArrow){ + ((EntityTippedArrow)entityarrow).addEffect(new PotionEffect(MobEffects.SLOWNESS, 600)); + } + + return entityarrow; + } +} diff --git a/src/main/java/electroblob/wizardry/entity/living/EntitySummonedCreature.java b/src/main/java/electroblob/wizardry/entity/living/EntitySummonedCreature.java index 2ef50929..12d623e7 100644 --- a/src/main/java/electroblob/wizardry/entity/living/EntitySummonedCreature.java +++ b/src/main/java/electroblob/wizardry/entity/living/EntitySummonedCreature.java @@ -1,8 +1,5 @@ package electroblob.wizardry.entity.living; -import java.lang.ref.WeakReference; -import java.util.UUID; - import electroblob.wizardry.Wizardry; import net.minecraft.entity.EntityCreature; import net.minecraft.entity.EntityFlying; @@ -14,8 +11,11 @@ import net.minecraft.util.EnumHand; import net.minecraft.util.ResourceLocation; import net.minecraft.util.text.ITextComponent; import net.minecraft.util.text.TextComponentTranslation; +import net.minecraft.world.EnumDifficulty; import net.minecraft.world.World; +import java.util.UUID; + /** * Abstract base implementation of {@link ISummonedCreature} which is the superclass to all custom summoned entities * (i.e. entities that don't extend vanilla/mod creatures). Also serves as an example of how to correctly implement the @@ -29,8 +29,7 @@ import net.minecraft.world.World; public abstract class EntitySummonedCreature extends EntityCreature implements ISummonedCreature { // Field implementations - private int lifetime = 600; - private WeakReference casterReference; + private int lifetime = -1; private UUID casterUUID; // Setter + getter implementations @@ -45,22 +44,12 @@ public abstract class EntitySummonedCreature extends EntityCreature implements I } @Override - public WeakReference getCasterReference(){ - return casterReference; - } - - @Override - public void setCasterReference(WeakReference reference){ - casterReference = reference; - } - - @Override - public UUID getCasterUUID(){ + public UUID getOwnerId(){ return casterUUID; } @Override - public void setCasterUUID(UUID uuid){ + public void setOwnerId(UUID uuid){ this.casterUUID = uuid; } @@ -122,8 +111,16 @@ public abstract class EntitySummonedCreature extends EntityCreature implements I @Override protected Item getDropItem(){ return null; } @Override protected ResourceLocation getLootTable(){ return null; } @Override public boolean canPickUpLoot(){ return false; } + // This vanilla method has nothing to do with the custom despawn() method. - @Override protected boolean canDespawn(){ return false; } + @Override protected boolean canDespawn(){ + return getCaster() == null && getOwnerId() == null; + } + + @Override + public boolean getCanSpawnHere(){ + return this.world.getDifficulty() != EnumDifficulty.PEACEFUL; + } @Override public boolean canAttackClass(Class entityType){ @@ -144,7 +141,7 @@ public abstract class EntitySummonedCreature extends EntityCreature implements I @Override public boolean hasCustomName(){ // If this returns true, the renderer will show the nameplate when looking directly at the entity - return Wizardry.settings.showSummonedCreatureNames && getCaster() != null; + return Wizardry.settings.summonedCreatureNames && getCaster() != null; } // Specific to EntitySummonedCreature, remove if copying diff --git a/src/main/java/electroblob/wizardry/entity/living/EntityVexMinion.java b/src/main/java/electroblob/wizardry/entity/living/EntityVexMinion.java new file mode 100644 index 00000000..73ed60ba --- /dev/null +++ b/src/main/java/electroblob/wizardry/entity/living/EntityVexMinion.java @@ -0,0 +1,151 @@ +package electroblob.wizardry.entity.living; + +import electroblob.wizardry.Wizardry; +import electroblob.wizardry.util.ParticleBuilder; +import electroblob.wizardry.util.ParticleBuilder.Type; +import net.minecraft.entity.EntityLiving; +import net.minecraft.entity.EntityLivingBase; +import net.minecraft.entity.ai.EntityAIHurtByTarget; +import net.minecraft.entity.ai.EntityAINearestAttackableTarget; +import net.minecraft.entity.monster.EntityVex; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.item.Item; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.util.EnumHand; +import net.minecraft.util.ResourceLocation; +import net.minecraft.util.text.ITextComponent; +import net.minecraft.util.text.TextComponentTranslation; +import net.minecraft.world.EnumDifficulty; +import net.minecraft.world.World; + +import javax.annotation.Nullable; +import java.util.UUID; + +public class EntityVexMinion extends EntityVex implements ISummonedCreature { + + // Field implementations + private int lifetime = -1; + private UUID casterUUID; + + // Setter + getter implementations + @Override public int getLifetime(){ return lifetime; } + @Override public void setLifetime(int lifetime){ this.lifetime = lifetime; } + @Override public UUID getOwnerId(){ return casterUUID; } + @Override public void setOwnerId(UUID uuid){ this.casterUUID = uuid; } + + /** Creates a new vex minion in the given world. */ + public EntityVexMinion(World world){ + super(world); + this.experienceValue = 0; + } + + // ISummonedCreature overrides + @Override + public void setCaster(@Nullable EntityLivingBase caster){ + // Integrates the summoned creature caster system with the (subtly different) vex owner system for NPC casters + ISummonedCreature.super.setCaster(caster); + if(caster instanceof EntityLiving) this.setOwner((EntityLiving)caster); + } + + // EntityVex overrides + @Override + protected void initEntityAI(){ + super.initEntityAI(); + this.targetTasks.taskEntries.clear(); + this.targetTasks.addTask(1, new EntityAIHurtByTarget(this, false)); + this.targetTasks.addTask(2, new EntityAINearestAttackableTarget<>(this, EntityLivingBase.class, + 0, false, false, this.getTargetSelector())); + } + + // Implementations + + @Override + public void setRevengeTarget(EntityLivingBase entity){ + if(this.shouldRevengeTarget(entity)) super.setRevengeTarget(entity); + } + + @Override + public void onUpdate(){ + super.onUpdate(); + this.updateDelegate(); + } + + @Override + public void onSpawn(){ + this.spawnParticleEffect(); + } + + @Override + public void onDespawn(){ + this.spawnParticleEffect(); + } + + private void spawnParticleEffect(){ + if(this.world.isRemote){ + for(int i = 0; i < 15; i++){ + ParticleBuilder.create(Type.DARK_MAGIC) + .pos(this.posX + this.rand.nextFloat(), this.posY + this.rand.nextFloat(), this.posZ + this.rand.nextFloat()) + .clr(0.3f, 0.3f, 0.3f) + .spawn(world); + } + } + } + + @Override + public boolean hasParticleEffect(){ + return true; + } + + @Override + protected boolean processInteract(EntityPlayer player, EnumHand hand){ + // In this case, the delegate method determines whether super is called. + // Rather handily, we can make use of Java's short-circuiting method of evaluating OR statements. + return this.interactDelegate(player, hand) || super.processInteract(player, hand); + } + + @Override + public void writeEntityToNBT(NBTTagCompound nbttagcompound){ + super.writeEntityToNBT(nbttagcompound); + this.writeNBTDelegate(nbttagcompound); + } + + @Override + public void readEntityFromNBT(NBTTagCompound nbttagcompound){ + super.readEntityFromNBT(nbttagcompound); + this.readNBTDelegate(nbttagcompound); + } + + // Recommended overrides + + @Override protected int getExperiencePoints(EntityPlayer player){ return 0; } + @Override protected boolean canDropLoot(){ return false; } + @Override protected Item getDropItem(){ return null; } + @Override protected ResourceLocation getLootTable(){ return null; } + @Override public boolean canPickUpLoot(){ return false; } + + // This vanilla method has nothing to do with the custom despawn() method. + @Override protected boolean canDespawn(){ + return getCaster() == null && getOwnerId() == null; + } + + @Override + public boolean getCanSpawnHere(){ + return this.world.getDifficulty() != EnumDifficulty.PEACEFUL; + } + + @Override + public ITextComponent getDisplayName(){ + if(getCaster() != null){ + return new TextComponentTranslation(NAMEPLATE_TRANSLATION_KEY, getCaster().getName(), + new TextComponentTranslation("entity." + this.getEntityString() + ".name")); + }else{ + return super.getDisplayName(); + } + } + + @Override + public boolean hasCustomName(){ + // If this returns true, the renderer will show the nameplate when looking directly at the entity + return Wizardry.settings.summonedCreatureNames && getCaster() != null; + } +} \ No newline at end of file diff --git a/src/main/java/electroblob/wizardry/entity/living/EntityWitherSkeletonMinion.java b/src/main/java/electroblob/wizardry/entity/living/EntityWitherSkeletonMinion.java index 8606978b..4ec2238a 100644 --- a/src/main/java/electroblob/wizardry/entity/living/EntityWitherSkeletonMinion.java +++ b/src/main/java/electroblob/wizardry/entity/living/EntityWitherSkeletonMinion.java @@ -1,12 +1,7 @@ package electroblob.wizardry.entity.living; -import java.lang.ref.WeakReference; -import java.util.Calendar; -import java.util.UUID; - -import javax.annotation.Nullable; - import electroblob.wizardry.Wizardry; +import electroblob.wizardry.util.WizardryUtilities.Operations; import net.minecraft.entity.EntityFlying; import net.minecraft.entity.EntityLivingBase; import net.minecraft.entity.IEntityLivingData; @@ -31,22 +26,24 @@ import net.minecraft.util.ResourceLocation; import net.minecraft.util.text.ITextComponent; import net.minecraft.util.text.TextComponentTranslation; import net.minecraft.world.DifficultyInstance; +import net.minecraft.world.EnumDifficulty; import net.minecraft.world.World; +import javax.annotation.Nullable; +import java.util.Calendar; +import java.util.UUID; + public class EntityWitherSkeletonMinion extends EntityWitherSkeleton implements ISummonedCreature { // Field implementations - private int lifetime = 600; - private WeakReference casterReference; + private int lifetime = -1; private UUID casterUUID; // Setter + getter implementations @Override public int getLifetime(){ return lifetime; } @Override public void setLifetime(int lifetime){ this.lifetime = lifetime; } - @Override public WeakReference getCasterReference(){ return casterReference; } - @Override public void setCasterReference(WeakReference reference){ casterReference = reference; } - @Override public UUID getCasterUUID(){ return casterUUID; } - @Override public void setCasterUUID(UUID uuid){ this.casterUUID = uuid; } + @Override public UUID getOwnerId(){ return casterUUID; } + @Override public void setOwnerId(UUID uuid){ this.casterUUID = uuid; } /** Creates a new wither skeleton minion in the given world. */ public EntityWitherSkeletonMinion(World world){ @@ -57,7 +54,7 @@ public class EntityWitherSkeletonMinion extends EntityWitherSkeleton implements // EntitySkeleton overrides // This particular override is pretty standard: let the superclass handle basic AI like swimming, but replace its - // targeting system with one that targets hostile mobs and takes the ADS into account. + // targeting system with one that targets hostile mobs and takes the AllyDesignationSystem into account. @Override protected void initEntityAI(){ super.initEntityAI(); @@ -78,7 +75,7 @@ public class EntityWitherSkeletonMinion extends EntityWitherSkeleton implements public IEntityLivingData onInitialSpawn(DifficultyInstance difficulty, @Nullable IEntityLivingData livingdata){ // Can't call super, so the code from the next level up (EntityLiving) had to be copied as well. this.getEntityAttribute(SharedMonsterAttributes.FOLLOW_RANGE) - .applyModifier(new AttributeModifier("Random spawn bonus", this.rand.nextGaussian() * 0.05D, 1)); + .applyModifier(new AttributeModifier("Random spawn bonus", this.rand.nextGaussian() * 0.05D, Operations.MULTIPLY_FLAT)); if(this.rand.nextFloat() < 0.05F){ this.setLeftHanded(true); @@ -171,8 +168,16 @@ public class EntityWitherSkeletonMinion extends EntityWitherSkeleton implements @Override protected Item getDropItem(){ return null; } @Override protected ResourceLocation getLootTable(){ return null; } @Override public boolean canPickUpLoot(){ return false; } + // This vanilla method has nothing to do with the custom despawn() method. - @Override protected boolean canDespawn(){ return false; } + @Override protected boolean canDespawn(){ + return getCaster() == null && getOwnerId() == null; + } + + @Override + public boolean getCanSpawnHere(){ + return this.world.getDifficulty() != EnumDifficulty.PEACEFUL; + } @Override public boolean canAttackClass(Class entityType){ @@ -193,6 +198,6 @@ public class EntityWitherSkeletonMinion extends EntityWitherSkeleton implements @Override public boolean hasCustomName(){ // If this returns true, the renderer will show the nameplate when looking directly at the entity - return Wizardry.settings.showSummonedCreatureNames && getCaster() != null; + return Wizardry.settings.summonedCreatureNames && getCaster() != null; } } diff --git a/src/main/java/electroblob/wizardry/entity/living/EntityWizard.java b/src/main/java/electroblob/wizardry/entity/living/EntityWizard.java index 7115fcd9..2d5ac7b0 100644 --- a/src/main/java/electroblob/wizardry/entity/living/EntityWizard.java +++ b/src/main/java/electroblob/wizardry/entity/living/EntityWizard.java @@ -1,70 +1,37 @@ package electroblob.wizardry.entity.living; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.HashSet; -import java.util.List; -import java.util.Random; -import java.util.Set; - -import javax.annotation.Nullable; - import com.google.common.base.Predicate; - import electroblob.wizardry.Wizardry; import electroblob.wizardry.constants.Element; import electroblob.wizardry.constants.Tier; +import electroblob.wizardry.data.WizardData; +import electroblob.wizardry.event.DiscoverSpellEvent; +import electroblob.wizardry.item.ItemArtefact; import electroblob.wizardry.item.ItemSpellBook; -import electroblob.wizardry.registry.Spells; -import electroblob.wizardry.registry.WizardryAdvancementTriggers; -import electroblob.wizardry.registry.WizardryItems; -import electroblob.wizardry.registry.WizardryPotions; -import electroblob.wizardry.registry.WizardrySounds; +import electroblob.wizardry.misc.WildcardTradeList; +import electroblob.wizardry.registry.*; import electroblob.wizardry.spell.Spell; -import electroblob.wizardry.util.ParticleBuilder; -import electroblob.wizardry.util.ParticleBuilder.Type; -import electroblob.wizardry.util.SpellModifiers; -import electroblob.wizardry.util.WandHelper; -import electroblob.wizardry.util.WildcardTradeList; -import electroblob.wizardry.util.WizardryUtilities; +import electroblob.wizardry.util.*; import io.netty.buffer.ByteBuf; -import net.minecraft.entity.Entity; -import net.minecraft.entity.EntityCreature; -import net.minecraft.entity.EntityList; -import net.minecraft.entity.EntityLiving; -import net.minecraft.entity.IEntityLivingData; -import net.minecraft.entity.IMerchant; -import net.minecraft.entity.INpc; -import net.minecraft.entity.SharedMonsterAttributes; -import net.minecraft.entity.ai.EntityAIBase; -import net.minecraft.entity.ai.EntityAIHurtByTarget; -import net.minecraft.entity.ai.EntityAIMoveTowardsRestriction; -import net.minecraft.entity.ai.EntityAINearestAttackableTarget; -import net.minecraft.entity.ai.EntityAIOpenDoor; -import net.minecraft.entity.ai.EntityAIRestrictOpenDoor; -import net.minecraft.entity.ai.EntityAISwimming; -import net.minecraft.entity.ai.EntityAIWander; -import net.minecraft.entity.ai.EntityAIWatchClosest; -import net.minecraft.entity.ai.EntityAIWatchClosest2; +import net.minecraft.entity.*; +import net.minecraft.entity.ai.*; import net.minecraft.entity.monster.IMob; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.init.Blocks; import net.minecraft.init.Items; import net.minecraft.init.MobEffects; -import net.minecraft.init.SoundEvents; import net.minecraft.inventory.EntityEquipmentSlot; import net.minecraft.item.Item; import net.minecraft.item.ItemStack; -import net.minecraft.nbt.NBTTagCompound; -import net.minecraft.nbt.NBTTagInt; -import net.minecraft.nbt.NBTTagLong; +import net.minecraft.nbt.*; import net.minecraft.network.datasync.DataParameter; import net.minecraft.network.datasync.DataSerializers; import net.minecraft.network.datasync.EntityDataManager; import net.minecraft.potion.PotionEffect; import net.minecraft.util.DamageSource; import net.minecraft.util.EnumHand; +import net.minecraft.util.ResourceLocation; +import net.minecraft.util.SoundEvent; import net.minecraft.util.math.BlockPos; import net.minecraft.util.text.ITextComponent; import net.minecraft.util.text.TextComponentTranslation; @@ -73,6 +40,7 @@ import net.minecraft.village.MerchantRecipeList; import net.minecraft.world.DifficultyInstance; import net.minecraft.world.EnumDifficulty; import net.minecraft.world.World; +import net.minecraftforge.common.MinecraftForge; import net.minecraftforge.common.util.Constants.NBT; import net.minecraftforge.common.util.FakePlayer; import net.minecraftforge.event.world.BlockEvent; @@ -83,6 +51,9 @@ import net.minecraftforge.fml.relauncher.Side; import net.minecraftforge.fml.relauncher.SideOnly; import net.minecraftforge.oredict.OreDictionary; +import javax.annotation.Nullable; +import java.util.*; + @Mod.EventBusSubscriber public class EntityWizard extends EntityCreature implements INpc, IMerchant, ISpellCaster, IEntityAdditionalSpawnData { @@ -150,7 +121,7 @@ public class EntityWizard extends EntityCreature implements INpc, IMerchant, ISp // If the target is valid and not invisible... if(entity != null && !entity.isInvisible() - && WizardryUtilities.isValidTarget(EntityWizard.this, entity)){ + && AllyDesignationSystem.isValidTarget(EntityWizard.this, entity)){ // ... and is a mob, a summoned creature ... if((entity instanceof IMob || entity instanceof ISummonedCreature @@ -247,7 +218,7 @@ public class EntityWizard extends EntityCreature implements INpc, IMerchant, ISp // Copied from EntityVillager if(!this.world.isRemote && this.livingSoundTime > -this.getTalkInterval() + 20){ this.livingSoundTime = -this.getTalkInterval(); - this.playSound(stack.isEmpty() ? SoundEvents.ENTITY_VILLAGER_NO : SoundEvents.ENTITY_VILLAGER_YES, this.getSoundVolume(), this.getSoundPitch()); + this.playSound(stack.isEmpty() ? WizardrySounds.ENTITY_WIZARD_NO : WizardrySounds.ENTITY_WIZARD_YES, this.getSoundVolume(), this.getSoundPitch()); } } @@ -267,8 +238,14 @@ public class EntityWizard extends EntityCreature implements INpc, IMerchant, ISp // Apparently nothing goes here, and nothing's here in EntityVillager either... } + // TESTME: Should this be getName instead? @Override public ITextComponent getDisplayName(){ + + if(this.hasCustomName()){ + return super.getDisplayName(); + } + return this.getElement().getWizardName(); } @@ -276,6 +253,21 @@ public class EntityWizard extends EntityCreature implements INpc, IMerchant, ISp protected boolean canDespawn(){ return false; } + + @Override + protected SoundEvent getAmbientSound(){ + return this.isTrading() ? WizardrySounds.ENTITY_WIZARD_TRADING : WizardrySounds.ENTITY_WIZARD_AMBIENT; + } + + @Override + protected SoundEvent getHurtSound(DamageSource source){ + return WizardrySounds.ENTITY_WIZARD_HURT; + } + + @Override + protected SoundEvent getDeathSound(){ + return WizardrySounds.ENTITY_WIZARD_DEATH; + } @Override public void onLivingUpdate(){ @@ -301,14 +293,7 @@ public class EntityWizard extends EntityCreature implements INpc, IMerchant, ISp // Heal particles TODO: Change this so it uses the heal spell directly if(world.isRemote){ - for(int i=0; i<10; i++){ - double x = (double)((float)this.posX + rand.nextFloat() * 2 - 1.0F); - // Apparently the client side spawns the particles 1 block higher than it should... hence the - - // 0.5F. - double y = (double)((float)this.posY - 0.5F + rand.nextFloat()); - double z = (double)((float)this.posZ + rand.nextFloat() * 2 - 1.0F); - ParticleBuilder.create(Type.SPARKLE).pos(x, y, z).vel(0, 0.1F, 0).clr(1, 1, 0.3f).spawn(world); - } + ParticleBuilder.spawnHealParticles(world, this); }else{ if(this.getHealth() < 10){ // Wizards heal themseselves more often if they have low health @@ -317,7 +302,7 @@ public class EntityWizard extends EntityCreature implements INpc, IMerchant, ISp this.setHealCooldown(400); } - this.playSound(WizardrySounds.SPELL_HEAL, 0.7F, rand.nextFloat() * 0.4F + 1.0F); + this.playSound(Spells.heal.getSounds()[0], 0.7F, rand.nextFloat() * 0.4F + 1.0F); } } @@ -370,8 +355,8 @@ public class EntityWizard extends EntityCreature implements INpc, IMerchant, ISp // Spell.get(spells[3]).getDisplayName())); // When right-clicked with a spell book in creative, sets one of the spells to that spell - if(player.capabilities.isCreativeMode && stack.getItem() instanceof ItemSpellBook){ - Spell spell = Spell.get(stack.getItemDamage()); + if(player.isCreative() && stack.getItem() instanceof ItemSpellBook){ + Spell spell = Spell.byMetadata(stack.getItemDamage()); if(this.spells.size() >= 4 && spell.canBeCastByNPCs()){ // The set(...) method returns the element that was replaced - neat! player.sendMessage(new TextComponentTranslation("item." + Wizardry.MODID + ":spell_book.apply_to_wizard", @@ -407,11 +392,10 @@ public class EntityWizard extends EntityCreature implements INpc, IMerchant, ISp nbt.setInteger("element", this.getElement().ordinal()); nbt.setInteger("skin", this.textureIndex); - nbt.setTag("spells", WizardryUtilities.listToNBT(spells, spell -> new NBTTagInt(spell.id()))); + nbt.setTag("spells", NBTExtras.listToNBT(spells, spell -> new NBTTagInt(spell.metadata()))); if(this.towerBlocks != null && this.towerBlocks.size() > 0){ - nbt.setTag("towerBlocks", - WizardryUtilities.listToNBT(this.towerBlocks, pos -> new NBTTagLong(pos.toLong()))); + nbt.setTag("towerBlocks", NBTExtras.listToNBT(this.towerBlocks, NBTUtil::createPosTag)); } } @@ -427,11 +411,17 @@ public class EntityWizard extends EntityCreature implements INpc, IMerchant, ISp this.setElement(Element.values()[nbt.getInteger("element")]); this.textureIndex = nbt.getInteger("skin"); - this.spells = (List)WizardryUtilities.NBTToList(nbt.getTagList("spells", NBT.TAG_INT), - (NBTTagInt tag) -> Spell.get(tag.getInt())); + this.spells = (List)NBTExtras.NBTToList(nbt.getTagList("spells", NBT.TAG_INT), + (NBTTagInt tag) -> Spell.byMetadata(tag.getInt())); - this.towerBlocks = new HashSet(WizardryUtilities.NBTToList( - nbt.getTagList("towerBlocks", NBT.TAG_LONG), (NBTTagLong tag) -> BlockPos.fromLong(tag.getLong()))); + NBTTagList tagList = nbt.getTagList("towerBlocks", NBT.TAG_LONG); + if(!tagList.isEmpty()){ + this.towerBlocks = new HashSet<>(NBTExtras.NBTToList(tagList, NBTUtil::getPosFromTag)); + }else{ + // Fallback to old packed long format + this.towerBlocks = new HashSet<>(NBTExtras.NBTToList(nbt.getTagList("towerBlocks", NBT.TAG_LONG), + (NBTTagLong tag) -> BlockPos.fromLong(tag.getLong()))); + } } @Override @@ -439,20 +429,42 @@ public class EntityWizard extends EntityCreature implements INpc, IMerchant, ISp merchantrecipe.incrementToolUses(); this.livingSoundTime = -this.getTalkInterval(); - this.playSound(SoundEvents.ENTITY_VILLAGER_YES, this.getSoundVolume(), this.getSoundPitch()); + this.playSound(WizardrySounds.ENTITY_WIZARD_YES, this.getSoundVolume(), this.getSoundPitch()); - // Achievements if(this.getCustomer() != null){ + + // Achievements WizardryAdvancementTriggers.wizard_trade.triggerFor(this.getCustomer()); - if(merchantrecipe.getItemToSell().getItem() instanceof ItemSpellBook - && Spell.get(merchantrecipe.getItemToSell().getItemDamage()).tier == Tier.MASTER){ - WizardryAdvancementTriggers.buy_master_spell.triggerFor(this.getCustomer()); + if(merchantrecipe.getItemToSell().getItem() instanceof ItemSpellBook){ + + Spell spell = Spell.byMetadata(merchantrecipe.getItemToSell().getItemDamage()); + + if(spell.getTier() == Tier.MASTER) WizardryAdvancementTriggers.buy_master_spell.triggerFor(this.getCustomer()); + + // Spell discovery (a lot of this is the same as in the event handler) + WizardData data = WizardData.get(this.getCustomer()); + + if(data != null){ + + if(!MinecraftForge.EVENT_BUS.post(new DiscoverSpellEvent(this.getCustomer(), spell, + DiscoverSpellEvent.Source.PURCHASE)) && data.discoverSpell(spell)){ + + data.sync(); + + if(!world.isRemote && !this.getCustomer().isCreative() && Wizardry.settings.discoveryMode){ + // Sound and text only happen server-side, in survival, with discovery mode on + WizardryUtilities.playSoundAtPlayer(this.getCustomer(), WizardrySounds.MISC_DISCOVER_SPELL, 1.25f, 1); + this.getCustomer().sendMessage(new TextComponentTranslation("spell.discover", + spell.getNameForTranslationFormatted())); + } + } + } } } // Changed to a 4 in 5 chance of unlocking a new recipe. - if(this.rand.nextInt(5) > 0){ + if(this.rand.nextInt(5) > 0 || ItemArtefact.isArtefactActive(customer, WizardryItems.charm_haggler)){ this.timeUntilReset = 40; this.updateRecipes = true; @@ -500,7 +512,7 @@ public class EntityWizard extends EntityCreature implements INpc, IMerchant, ISp boolean itemAlreadySold = true; - Tier tier = Tier.BASIC; + Tier tier = Tier.NOVICE; while(itemAlreadySold){ @@ -515,7 +527,7 @@ public class EntityWizard extends EntityCreature implements INpc, IMerchant, ISp double tierIncreaseChance = 0.5 + 0.04 * (Math.max(this.trades.size() - 4, 0)); - tier = Tier.BASIC; + tier = Tier.NOVICE; if(rand.nextDouble() < tierIncreaseChance){ tier = Tier.APPRENTICE; @@ -545,8 +557,10 @@ public class EntityWizard extends EntityCreature implements INpc, IMerchant, ISp // Don't know how it can ever be empty here, but it's a failsafe. if(itemToSell.isEmpty()) return; - merchantrecipelist.add(new MerchantRecipe(this.getRandomPrice(tier), - new ItemStack(WizardryItems.magic_crystal, tier.ordinal() * 3 + 1 + rand.nextInt(4)), itemToSell)); + ItemStack secondItemToBuy = tier == Tier.MASTER ? new ItemStack(WizardryItems.astral_diamond) + : new ItemStack(WizardryItems.magic_crystal, tier.ordinal() * 3 + 1 + rand.nextInt(4)); + + merchantrecipelist.add(new MerchantRecipe(this.getRandomPrice(tier), secondItemToBuy, itemToSell)); } Collections.shuffle(merchantrecipelist); @@ -555,27 +569,31 @@ public class EntityWizard extends EntityCreature implements INpc, IMerchant, ISp this.trades = new WildcardTradeList(); } - for(int j1 = 0; j1 < merchantrecipelist.size(); ++j1){ - this.trades.add(merchantrecipelist.get(j1)); - } + this.trades.addAll(merchantrecipelist); } // TODO: Switch all of this over to some kind of loot pool system? private ItemStack getRandomPrice(Tier tier){ - ItemStack itemstack = ItemStack.EMPTY; - switch(this.rand.nextInt(3)){ - case 0: - itemstack = new ItemStack(Items.GOLD_INGOT, (tier.ordinal() + 1) * 8 - 1 + rand.nextInt(6)); - break; - case 1: - itemstack = new ItemStack(Items.DIAMOND, (tier.ordinal() + 1) * 4 - 2 + rand.nextInt(3)); - break; - case 2: - itemstack = new ItemStack(Items.EMERALD, (tier.ordinal() + 1) * 6 - 1 + rand.nextInt(3)); - break; + + Map map = Wizardry.settings.currencyItems; + // This isn't that efficient but it's not called very often really so it doesn't matter + ResourceLocation itemName = map.keySet().toArray(new ResourceLocation[0])[rand.nextInt(map.size())]; + Item item = Item.REGISTRY.getObject(itemName); + int value; + + if(item == null){ + Wizardry.logger.warn("Invalid item in currency items: {}", itemName); + item = Items.EMERALD; // Fallback item + value = 6; + }else{ + value = map.get(itemName); } - return itemstack; + + // ((tier.ordinal() + 1) * 16 + rand.nextInt(6)) gives a 'value' for the item being bought + // This is then divided by the value of the currency item to give a price + // The absolute maximum stack size that can result from this calculation (with value = 1) is 64. + return new ItemStack(item, (8 + tier.ordinal() * 16 + rand.nextInt(9)) / value); } private ItemStack getRandomItemOfTier(Tier tier){ @@ -583,32 +601,36 @@ public class EntityWizard extends EntityCreature implements INpc, IMerchant, ISp int randomiser; // All enabled spells of the given tier - List spells = Spell.getSpells(new Spell.TierElementFilter(tier, null)); + List spells = Spell.getSpells(new Spell.TierElementFilter(tier, null, SpellProperties.Context.TRADES)); // All enabled spells of the given tier that match this wizard's element - List specialismSpells = Spell.getSpells(new Spell.TierElementFilter(tier, this.getElement())); + List specialismSpells = Spell.getSpells(new Spell.TierElementFilter(tier, this.getElement(), SpellProperties.Context.TRADES)); + + // Wizards don't sell scrolls + spells.removeIf(s -> !s.isEnabled(SpellProperties.Context.BOOK)); + specialismSpells.removeIf(s -> !s.isEnabled(SpellProperties.Context.BOOK)); // This code is sooooooo much neater with the new filter system! switch(tier){ - case BASIC: + case NOVICE: randomiser = rand.nextInt(5); if(randomiser < 4 && !spells.isEmpty()){ if(this.getElement() != Element.MAGIC && rand.nextInt(4) > 0 && !specialismSpells.isEmpty()){ // This means it is more likely for spell books sold to be of the same element as the wizard if the // wizard has an element. return new ItemStack(WizardryItems.spell_book, 1, - specialismSpells.get(rand.nextInt(specialismSpells.size())).id()); + specialismSpells.get(rand.nextInt(specialismSpells.size())).metadata()); }else{ - return new ItemStack(WizardryItems.spell_book, 1, spells.get(rand.nextInt(spells.size())).id()); + return new ItemStack(WizardryItems.spell_book, 1, spells.get(rand.nextInt(spells.size())).metadata()); } }else{ if(this.getElement() != Element.MAGIC && rand.nextInt(4) > 0){ // This means it is more likely for wands sold to be of the same element as the wizard if the wizard // has an element. - return new ItemStack(WizardryUtilities.getWand(tier, this.getElement())); + return new ItemStack(WizardryItems.getWand(tier, this.getElement())); }else{ return new ItemStack( - WizardryUtilities.getWand(tier, Element.values()[rand.nextInt(Element.values().length)])); + WizardryItems.getWand(tier, Element.values()[rand.nextInt(Element.values().length)])); } } @@ -619,18 +641,18 @@ public class EntityWizard extends EntityCreature implements INpc, IMerchant, ISp // This means it is more likely for spell books sold to be of the same element as the wizard if the // wizard has an element. return new ItemStack(WizardryItems.spell_book, 1, - specialismSpells.get(rand.nextInt(specialismSpells.size())).id()); + specialismSpells.get(rand.nextInt(specialismSpells.size())).metadata()); }else{ - return new ItemStack(WizardryItems.spell_book, 1, spells.get(rand.nextInt(spells.size())).id()); + return new ItemStack(WizardryItems.spell_book, 1, spells.get(rand.nextInt(spells.size())).metadata()); } }else if(randomiser < 6){ if(this.getElement() != Element.MAGIC && rand.nextInt(4) > 0){ // This means it is more likely for wands sold to be of the same element as the wizard if the wizard // has an element. - return new ItemStack(WizardryUtilities.getWand(tier, this.getElement())); + return new ItemStack(WizardryItems.getWand(tier, this.getElement())); }else{ return new ItemStack( - WizardryUtilities.getWand(tier, Element.values()[rand.nextInt(Element.values().length)])); + WizardryItems.getWand(tier, Element.values()[rand.nextInt(Element.values().length)])); } }else if(randomiser < 8){ return new ItemStack(WizardryItems.arcane_tome, 1, 1); @@ -639,10 +661,10 @@ public class EntityWizard extends EntityCreature implements INpc, IMerchant, ISp if(this.getElement() != Element.MAGIC && rand.nextInt(4) > 0){ // This means it is more likely for armour sold to be of the same element as the wizard if the // wizard has an element. - return new ItemStack(WizardryUtilities.getArmour(this.getElement(), slot)); + return new ItemStack(WizardryItems.getArmour(this.getElement(), slot)); }else{ return new ItemStack( - WizardryUtilities.getArmour(Element.values()[rand.nextInt(Element.values().length)], slot)); + WizardryItems.getArmour(Element.values()[rand.nextInt(Element.values().length)], slot)); } }else{ // Don't need to check for discovery mode here since it is done above @@ -656,18 +678,18 @@ public class EntityWizard extends EntityCreature implements INpc, IMerchant, ISp // This means it is more likely for spell books sold to be of the same element as the wizard if the // wizard has an element. return new ItemStack(WizardryItems.spell_book, 1, - specialismSpells.get(rand.nextInt(specialismSpells.size())).id()); + specialismSpells.get(rand.nextInt(specialismSpells.size())).metadata()); }else{ - return new ItemStack(WizardryItems.spell_book, 1, spells.get(rand.nextInt(spells.size())).id()); + return new ItemStack(WizardryItems.spell_book, 1, spells.get(rand.nextInt(spells.size())).metadata()); } }else if(randomiser < 6){ if(this.getElement() != Element.MAGIC && rand.nextInt(4) > 0){ // This means it is more likely for wands sold to be of the same element as the wizard if the wizard // has an element. - return new ItemStack(WizardryUtilities.getWand(tier, this.getElement())); + return new ItemStack(WizardryItems.getWand(tier, this.getElement())); }else{ return new ItemStack( - WizardryUtilities.getWand(tier, Element.values()[rand.nextInt(Element.values().length)])); + WizardryItems.getWand(tier, Element.values()[rand.nextInt(Element.values().length)])); } }else if(randomiser < 8){ return new ItemStack(WizardryItems.arcane_tome, 1, 2); @@ -684,12 +706,12 @@ public class EntityWizard extends EntityCreature implements INpc, IMerchant, ISp if(randomiser < 5 && this.getElement() != Element.MAGIC && !specialismSpells.isEmpty()){ // Master spells can only be sold by a specialist in that element. return new ItemStack(WizardryItems.spell_book, 1, - specialismSpells.get(rand.nextInt(specialismSpells.size())).id()); + specialismSpells.get(rand.nextInt(specialismSpells.size())).metadata()); }else if(randomiser < 6){ if(this.getElement() != Element.MAGIC && rand.nextInt(4) > 0){ // Master elemental wands can only be sold by a specialist in that element. - return new ItemStack(WizardryUtilities.getWand(tier, this.getElement())); + return new ItemStack(WizardryItems.getWand(tier, this.getElement())); }else{ return new ItemStack(WizardryItems.master_wand); } @@ -718,7 +740,7 @@ public class EntityWizard extends EntityCreature implements INpc, IMerchant, ISp // Adds armour. for(EntityEquipmentSlot slot : WizardryUtilities.ARMOUR_SLOTS){ - this.setItemStackToSlot(slot, new ItemStack(WizardryUtilities.getArmour(element, slot))); + this.setItemStackToSlot(slot, new ItemStack(WizardryItems.getArmour(element, slot))); } // Default chance is 0.085f, for reference. @@ -728,11 +750,16 @@ public class EntityWizard extends EntityCreature implements INpc, IMerchant, ISp // All wizards know magic missile, even if it is disabled. spells.add(Spells.magic_missile); - Tier maxTier = populateSpells(spells, element, 3, rand); + Tier maxTier = populateSpells(spells, element, false, 3, rand); // Now done after the spells so it can take the tier into account. - this.setItemStackToSlot(EntityEquipmentSlot.MAINHAND, - new ItemStack(WizardryUtilities.getWand(maxTier, element))); + ItemStack wand = new ItemStack(WizardryItems.getWand(maxTier, element)); + ArrayList list = new ArrayList<>(spells); + list.add(Spells.heal); + WandHelper.setSpells(wand, list.toArray(new Spell[5])); + this.setItemStackToSlot(EntityEquipmentSlot.MAINHAND, wand); + + this.setHealCooldown(50); return livingdata; } @@ -747,14 +774,14 @@ public class EntityWizard extends EntityCreature implements INpc, IMerchant, ISp * @param random A random number generator to use. * @return The tier of the highest-tier spell that was added to the list. */ - static Tier populateSpells(List spells, Element e, int n, Random random){ + static Tier populateSpells(List spells, Element e, boolean master, int n, Random random){ // This is the tier of the highest tier spell added. - Tier maxTier = Tier.BASIC; + Tier maxTier = Tier.NOVICE; List npcSpells = Spell.getSpells(Spell.npcSpells); - for(int i = 0; i < 3; i++){ + for(int i = 0; i < n; i++){ Tier tier; // If the wizard has no element, it picks a random one each time. @@ -764,17 +791,19 @@ public class EntityWizard extends EntityCreature implements INpc, IMerchant, ISp // Uses its own special weighting if(randomiser < 10){ - tier = Tier.BASIC; + tier = Tier.NOVICE; }else if(randomiser < 16){ tier = Tier.APPRENTICE; - }else{ + }else if(randomiser < 19 || !master){ tier = Tier.ADVANCED; + }else{ + tier = Tier.MASTER; } if(tier.ordinal() > maxTier.ordinal()) maxTier = tier; // Finds all the spells of the chosen tier and element - List list = Spell.getSpells(new Spell.TierElementFilter(tier, element)); + List list = Spell.getSpells(new Spell.TierElementFilter(tier, element, SpellProperties.Context.NPCS)); // Keeps only spells which can be cast by NPCs list.retainAll(npcSpells); // Removes spells that the wizard already has @@ -828,12 +857,7 @@ public class EntityWizard extends EntityCreature implements INpc, IMerchant, ISp this.towerBlocks = blocks; } - /** - * Tests whether the block at the given coordinates is part of this wizard's tower. - * - * @param pos - * @return - */ + /** Tests whether the block at the given coordinates is part of this wizard's tower. */ public boolean isBlockPartOfTower(BlockPos pos){ if(this.towerBlocks == null) return false; // Uses .equals() rather than == so this will work fine. diff --git a/src/main/java/electroblob/wizardry/entity/living/EntityZombieMinion.java b/src/main/java/electroblob/wizardry/entity/living/EntityZombieMinion.java index 3613d614..f61e33a3 100644 --- a/src/main/java/electroblob/wizardry/entity/living/EntityZombieMinion.java +++ b/src/main/java/electroblob/wizardry/entity/living/EntityZombieMinion.java @@ -1,8 +1,5 @@ package electroblob.wizardry.entity.living; -import java.lang.ref.WeakReference; -import java.util.UUID; - import electroblob.wizardry.Wizardry; import net.minecraft.entity.EntityFlying; import net.minecraft.entity.EntityLivingBase; @@ -12,6 +9,7 @@ import net.minecraft.entity.ai.EntityAINearestAttackableTarget; import net.minecraft.entity.monster.EntityZombie; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.item.Item; +import net.minecraft.item.ItemStack; import net.minecraft.nbt.NBTTagCompound; import net.minecraft.util.EnumHand; import net.minecraft.util.EnumParticleTypes; @@ -19,22 +17,22 @@ import net.minecraft.util.ResourceLocation; import net.minecraft.util.text.ITextComponent; import net.minecraft.util.text.TextComponentTranslation; import net.minecraft.world.DifficultyInstance; +import net.minecraft.world.EnumDifficulty; import net.minecraft.world.World; +import java.util.UUID; + public class EntityZombieMinion extends EntityZombie implements ISummonedCreature { // Field implementations - private int lifetime = 600; - private WeakReference casterReference; + private int lifetime = -1; private UUID casterUUID; // Setter + getter implementations @Override public int getLifetime(){ return lifetime; } @Override public void setLifetime(int lifetime){ this.lifetime = lifetime; } - @Override public WeakReference getCasterReference(){ return casterReference; } - @Override public void setCasterReference(WeakReference reference){ casterReference = reference; } - @Override public UUID getCasterUUID(){ return casterUUID; } - @Override public void setCasterUUID(UUID uuid){ this.casterUUID = uuid; } + @Override public UUID getOwnerId(){ return casterUUID; } + @Override public void setOwnerId(UUID uuid){ this.casterUUID = uuid; } /** Creates a new zombie minion in the given world. */ public EntityZombieMinion(World world){ @@ -42,13 +40,13 @@ public class EntityZombieMinion extends EntityZombie implements ISummonedCreatur this.experienceValue = 0; } - // EntityZombie overrides (EntityZombie is a long class so there are lots of these) + // EntityZombie overrides (EntityZombie is a complex class so there are lots of these) @Override protected void applyEntityAI(){ this.tasks.addTask(6, new EntityAIMoveThroughVillage(this, 1.0D, false)); this.targetTasks.addTask(1, new EntityAIHurtByTarget(this, false)); - this.targetTasks.addTask(2, new EntityAINearestAttackableTarget(this, EntityLivingBase.class, + this.targetTasks.addTask(2, new EntityAINearestAttackableTarget<>(this, EntityLivingBase.class, 0, false, true, this.getTargetSelector())); } @@ -57,6 +55,7 @@ public class EntityZombieMinion extends EntityZombie implements ISummonedCreatur @Override protected void setEquipmentBasedOnDifficulty(DifficultyInstance difficulty){} // They don't have equipment! @Override public void onKillEntity(EntityLivingBase entityLivingIn){} // Turns villagers to zombies in EntityZombie @Override public void setChildSize(boolean isChild){} + @Override protected ItemStack getSkullDrop(){ return ItemStack.EMPTY; } // Implementations @@ -121,8 +120,16 @@ public class EntityZombieMinion extends EntityZombie implements ISummonedCreatur @Override protected Item getDropItem(){ return null; } @Override protected ResourceLocation getLootTable(){ return null; } @Override public boolean canPickUpLoot(){ return false; } + // This vanilla method has nothing to do with the custom despawn() method. - @Override protected boolean canDespawn(){ return false; } + @Override protected boolean canDespawn(){ + return getCaster() == null && getOwnerId() == null; + } + + @Override + public boolean getCanSpawnHere(){ + return this.world.getDifficulty() != EnumDifficulty.PEACEFUL; + } @Override public boolean canAttackClass(Class entityType){ @@ -143,7 +150,7 @@ public class EntityZombieMinion extends EntityZombie implements ISummonedCreatur @Override public boolean hasCustomName(){ // If this returns true, the renderer will show the nameplate when looking directly at the entity - return Wizardry.settings.showSummonedCreatureNames && getCaster() != null; + return Wizardry.settings.summonedCreatureNames && getCaster() != null; } } \ No newline at end of file diff --git a/src/main/java/electroblob/wizardry/entity/living/IIntelligentSpellCaster.java b/src/main/java/electroblob/wizardry/entity/living/IIntelligentSpellCaster.java index 978f5457..939414d5 100644 --- a/src/main/java/electroblob/wizardry/entity/living/IIntelligentSpellCaster.java +++ b/src/main/java/electroblob/wizardry/entity/living/IIntelligentSpellCaster.java @@ -1,9 +1,9 @@ package electroblob.wizardry.entity.living; -import java.util.List; - import electroblob.wizardry.spell.Spell; +import java.util.List; + /** * [NYI] Interface for entities that can select between spells based on their current circumstances, to be used in * conjunction with {@link EntityAISelectSpell}. diff --git a/src/main/java/electroblob/wizardry/entity/living/ISpellCaster.java b/src/main/java/electroblob/wizardry/entity/living/ISpellCaster.java index 86eda769..6b336783 100644 --- a/src/main/java/electroblob/wizardry/entity/living/ISpellCaster.java +++ b/src/main/java/electroblob/wizardry/entity/living/ISpellCaster.java @@ -1,24 +1,23 @@ package electroblob.wizardry.entity.living; -import java.util.List; - -import javax.annotation.Nonnull; - import electroblob.wizardry.registry.Spells; import electroblob.wizardry.spell.Spell; import electroblob.wizardry.util.SpellModifiers; import electroblob.wizardry.util.WizardryUtilities; import net.minecraft.world.EnumDifficulty; +import javax.annotation.Nonnull; +import java.util.List; + /** * Interface for entities that can cast spells. Mainly intended for use by wizard-type entities, but can be implemented * by any subclass of EntityLiving. Designed to be as flexible as possible - ranging from the simplest use of giving an * entity a specific spell as an attack, to a complex AI which selects different spell types depending on the situation. * The only restriction is that the spells must be castable by NPCs. - *

    + *

    * This is intended for entities that use {@link EntityAIAttackSpell}. If so, all the spell casting code (including * packets) is handled by that class, and all the implementor needs to do is decide which spell(s) to select. - *

    + *

    * This class also allows Wizardry to do all the syncing necessary for continuous spell casting. All the implementor * needs to do is store the actual fields involved. */ diff --git a/src/main/java/electroblob/wizardry/entity/living/ISummonedCreature.java b/src/main/java/electroblob/wizardry/entity/living/ISummonedCreature.java index 5e27cb57..5b9e06da 100644 --- a/src/main/java/electroblob/wizardry/entity/living/ISummonedCreature.java +++ b/src/main/java/electroblob/wizardry/entity/living/ISummonedCreature.java @@ -1,28 +1,15 @@ package electroblob.wizardry.entity.living; -import java.lang.ref.WeakReference; -import java.util.Arrays; -import java.util.UUID; - -import javax.annotation.Nullable; - import com.google.common.base.Predicate; - -import electroblob.wizardry.WizardData; import electroblob.wizardry.Wizardry; +import electroblob.wizardry.data.WizardData; import electroblob.wizardry.integration.DamageSafetyChecker; -import electroblob.wizardry.item.ItemWand; -import electroblob.wizardry.util.IElementalDamage; -import electroblob.wizardry.util.IndirectMinionDamage; +import electroblob.wizardry.item.ISpellCastingItem; +import electroblob.wizardry.util.*; import electroblob.wizardry.util.MagicDamage.DamageType; -import electroblob.wizardry.util.MinionDamage; -import electroblob.wizardry.util.ParticleBuilder; import electroblob.wizardry.util.ParticleBuilder.Type; -import electroblob.wizardry.util.WizardryUtilities; import io.netty.buffer.ByteBuf; -import net.minecraft.entity.Entity; -import net.minecraft.entity.EntityList; -import net.minecraft.entity.EntityLivingBase; +import net.minecraft.entity.*; import net.minecraft.entity.monster.IMob; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.item.ItemStack; @@ -36,28 +23,33 @@ import net.minecraftforge.fml.common.Mod; import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; import net.minecraftforge.fml.common.registry.IEntityAdditionalSpawnData; +import javax.annotation.Nullable; +import java.lang.ref.WeakReference; +import java.util.Arrays; +import java.util.UUID; + /** * Interface for all summoned creatures. The code for summoned creatures has been overhauled in Wizardry 2.1, and this * interface allows summoned creatures to extend vanilla (or indeed modded) entity classes, so * EntitySummonedZombie now extends EntityZombie, for example. This change has two major * benefits: - *

    + *

    * - There is no longer any need for separate render classes, because summoned creatures are now instances of vanilla * types. You don't even need to assign a render class because the supertype should already be assigned the * correct one.
    * - Summoned creature classes are now much more robust when it comes to changes between Minecraft versions, since none * of the vanilla code needs to be copied. - *

    + *

    * Summoned creatures that do not emulate vanilla entities do not directly implement this interface. Instead, * they should extend the abstract base implementation, {@link EntitySummonedCreature}. - *

    + *

    * All damage dealt by ISummonedCreature instances is redirected via - * {@link ISummonedCreature#onLivingAttackEvent(net.minecraftforge.event.entity.living.LivingAttackEvent) + * {@link ISummonedCreature#onLivingAttackEvent(LivingAttackEvent) * ISummonedCreature.onLivingAttackEvent(LivingAttackEvent)} and replaced by an instance of - * {@link electroblob.wizardry.util.IElementalDamage IElementalDamage} with the summoner of that creature as the source + * {@link IElementalDamage IElementalDamage} with the summoner of that creature as the source * rather than the creature itself. This means that kills by summoned creatures register as kills for their owner, * dropping xp and rare loot if that owner is a player. - *

    + *

    * Though this system is a lot better than the previous system, it is not a perfect solution. The old * EntitySummonedCreature class overrode some methods from Entity in order to add shared functionality, but this cannot * be done with an interface. To get around this problem, this interface contains 5 delegate methods that do the same @@ -67,12 +59,12 @@ import net.minecraftforge.fml.common.registry.IEntityAdditionalSpawnData; * work properly unless it is adhered to. The position of the delegate method call is unimportant, but by convention * it is usually at the start of the calling method, which avoids it being unintentionally skipped by a return * statement (except for methods where the result of the delegate method should itself be returned). - *

    + *

    * It is recommended that when implementing this interface, you begin by copying {@link EntitySummonedCreature} to * ensure all the relevant methods are duplicated. You can then change the superclass, override any additional methods * and add functionality to any that are already overridden. You will always want to override the AI methods at the very * least. - *

    + *

    * Due to the limitations of interfaces, some methods that really ought to be protected are public. These are clearly * marked as 'Internal, DO NOT CALL'. Don't call them, only implement them. * @@ -83,7 +75,7 @@ import net.minecraftforge.fml.common.registry.IEntityAdditionalSpawnData; * sacrifices have to be made when it comes to Java style - because adding on to a pre-existing program is not a good * way of doing this sort of thing anyway, but we have no choice about that! */ @Mod.EventBusSubscriber -public interface ISummonedCreature extends IEntityAdditionalSpawnData { +public interface ISummonedCreature extends IEntityAdditionalSpawnData, IEntityOwnable { // Remember that ALL fields are static and final in interfaces, even if they don't explicitly state that. String NAMEPLATE_TRANSLATION_KEY = "entity." + Wizardry.MODID + ":summonedcreature.nameplate"; @@ -101,43 +93,51 @@ public interface ISummonedCreature extends IEntityAdditionalSpawnData { */ int getLifetime(); - /** - * Sets the WeakReference object which refers to the owner of this summoned creature. Internal, don't call unless - * you know what you are doing. - */ - void setCasterReference(WeakReference reference); + /** Internal, do not use. Implementing classes should implement this to set their owner UUID field. */ + void setOwnerId(UUID uuid); - /** - * Returns a WeakReference object which refers to the owner of this summoned creature. Subclasses should store this - * as a private field. This may be null; as such it is preferable to use {@link ISummonedCreature#getCaster()} to - * get the caster object itself. - */ + /** Returns the UUID of the owner of this summoned creature, or null if it does not have an owner. + * Implementing classes should implement this to return their owner UUID field. */ @Nullable - WeakReference getCasterReference(); + @Override + UUID getOwnerId(); // Only overridden because I wanted to add javadoc! - /** Internal, DO NOT CALL. */ - void setCasterUUID(UUID uuid); - - /** Internal, DO NOT CALL. This is for loading purposes only and is not usually synchronised. */ - UUID getCasterUUID(); + @Nullable + @Override + default Entity getOwner(){ + return getCaster(); // Delegate to getCaster + } /** * Returns the EntityLivingBase that summoned this creature, or null if it no longer exists. Cases where the entity * may no longer exist are: entity died or was deleted, mob despawned, player logged out, entity teleported to - * another dimension, or this creature simply had no caster in the first place. This is the correct method to use - * to get the owner of this summoned creature. + * another dimension, or this creature simply had no caster in the first place. */ @Nullable - default EntityLivingBase getCaster(){ - return getCasterReference() == null ? null : getCasterReference().get(); + default EntityLivingBase getCaster(){ // Kept despite the above method because it returns an EntityLivingBase + + if(this instanceof Entity){ // Bit of a cheat but it saves having yet another method just to get the world + + Entity entity = WizardryUtilities.getEntityByUUID(((Entity)this).world, getOwnerId()); + + if(entity != null && !(entity instanceof EntityLivingBase)){ // Should never happen + Wizardry.logger.warn("{} has a non-living owner!", this); + return null; + } + + return (EntityLivingBase)entity; + + }else{ + Wizardry.logger.warn("{} implements ISummonedCreature but is not an SoundLoopSpellEntity!", this.getClass()); + return null; + } } /** - * Sets the EntityLivingBase that summoned this creature. This is the correct method to use to set the owner of - * this summoned creature. + * Sets the EntityLivingBase that summoned this creature. */ default void setCaster(@Nullable EntityLivingBase caster){ - setCasterReference(new WeakReference(caster)); + setOwnerId(caster == null ? null : caster.getUniqueID()); } // Miscellaneous @@ -164,17 +164,56 @@ public interface ISummonedCreature extends IEntityAdditionalSpawnData { default void readSpawnData(ByteBuf buffer){ int id = buffer.readInt(); // We're on the client side here, so we can safely use Minecraft.getMinecraft().world via proxies. - if(id > -1) setCasterReference( - new WeakReference((EntityLivingBase)Wizardry.proxy.getTheWorld().getEntityByID(id))); + if(id > -1){ + Entity entity = Wizardry.proxy.getTheWorld().getEntityByID(id); + if(entity instanceof EntityLivingBase) setCaster((EntityLivingBase)entity); + else Wizardry.logger.warn("Received a spawn packet for entity {}, but no living entity matched the supplied ID", this); + } setLifetime(buffer.readInt()); } /** - * Shorthand for {@link WizardryUtilities#isValidTarget(Entity, Entity)}, with the owner of this creature as the - * attacker. Also allows implementors to override it if they wish to do so. + * Determines whether the given target is valid. Used by the default target selector (see + * {@link ISummonedCreature#getTargetSelector()}) and revenge targeting checks. This method is responsible for the + * ally designation system, default classes that may be targeted and the config whitelist/blacklist. + * Implementors may override this if they want to do something different or add their own checks. + * @see AllyDesignationSystem#isValidTarget(Entity, Entity) */ default boolean isValidTarget(Entity target){ - return WizardryUtilities.isValidTarget(this.getCaster(), target); + // If the target is valid based on the ADS... + if(AllyDesignationSystem.isValidTarget(this.getCaster(), target)){ + + // ...and is a player, they can be attacked, since players can't be in the whitelist or the + // blacklist... + if(target instanceof EntityPlayer){ + // ...unless the creature was summoned by a good wizard who the player has not angered. + if(getCaster() instanceof EntityWizard){ + if(getCaster().getRevengeTarget() != target + && ((EntityWizard)getCaster()).getAttackTarget() != target) { + return false; + } + } + + return true; + } + + // ...and is a mob, a summoned creature, a wizard... + if((target instanceof IMob || target instanceof ISummonedCreature + || (target instanceof EntityWizard && !(getCaster() instanceof EntityWizard)) + // ...or something that's attacking the owner... + || (target instanceof EntityLiving && ((EntityLiving)target).getAttackTarget() == getCaster()) + // ...or in the whitelist... + || Arrays.asList(Wizardry.settings.summonedCreatureTargetsWhitelist) + .contains(EntityList.getKey(target.getClass()))) + // ...and isn't in the blacklist... + && !Arrays.asList(Wizardry.settings.summonedCreatureTargetsBlacklist) + .contains(EntityList.getKey(target.getClass()))){ + // ...it can be attacked. + return true; + } + } + + return false; } /** @@ -182,45 +221,7 @@ public interface ISummonedCreature extends IEntityAdditionalSpawnData { * possible for implementors to override this in order to do something special when selecting a target. */ default Predicate getTargetSelector(){ - - return new Predicate(){ - - public boolean apply(Entity entity){ - // TODO: Backport invisibility check (also in wizards) - // If the target is valid and not invisible... - if(!entity.isInvisible() && isValidTarget(entity)){ - - // ... and is a player, they can be attacked, since players can't be in the whitelist or the - // blacklist ... - if(entity instanceof EntityPlayer){ - // ... unless the creature was summoned by a good wizard who the player has not angered. - if(getCaster() instanceof EntityWizard){ - if(((EntityWizard)getCaster()).getRevengeTarget() != entity - && ((EntityWizard)getCaster()).getAttackTarget() != entity) { - return false; - } - } - - return true; - } - - // ... and is a mob, a summoned creature, a wizard ... - if((entity instanceof IMob || entity instanceof ISummonedCreature - || (entity instanceof EntityWizard && !(getCaster() instanceof EntityWizard)) - // ... or in the whitelist ... - || Arrays.asList(Wizardry.settings.summonedCreatureTargetsWhitelist) - .contains(EntityList.getKey(entity.getClass()))) - // ... and isn't in the blacklist ... - && !Arrays.asList(Wizardry.settings.summonedCreatureTargetsBlacklist) - .contains(EntityList.getKey(entity.getClass()))){ - // ... it can be attacked. - return true; - } - } - - return false; - } - }; + return entity -> getCaster() == null ? entity instanceof EntityPlayer : !entity.isInvisible() && isValidTarget(entity); } /** @@ -241,7 +242,7 @@ public interface ISummonedCreature extends IEntityAdditionalSpawnData { * Called from the event handler after the damage change is applied. Does nothing by default, but can be overridden * to do something when a successful attack is made. This was added because the event-based damage source system can * cause parts of attackEntityAsMob not to fire, since attackEntityFrom is intercepted and canceled. - *

    + *

    * Usage examples: {@link EntitySilverfishMinion} uses this to summon more silverfish if the target is killed, * {@link EntitySkeletonMinion} and {@link EntitySpiderMinion} use this to add potion effects to the target. */ @@ -266,7 +267,7 @@ public interface ISummonedCreature extends IEntityAdditionalSpawnData { * very little point in doing that since anything extra could just be added to readEntityFromNBT anyway. */ default void readNBTDelegate(NBTTagCompound tagcompound){ - this.setCasterUUID(tagcompound.getUniqueId("casterUUID")); + this.setOwnerId(tagcompound.getUniqueId("casterUUID")); this.setLifetime(tagcompound.getInteger("lifetime")); } @@ -275,8 +276,8 @@ public interface ISummonedCreature extends IEntityAdditionalSpawnData { * returns true. */ default boolean shouldRevengeTarget(EntityLivingBase entity){ - // Allows the config to prevent minions from revenge-targeting their owners. - return entity != this.getCaster() || Wizardry.settings.minionRevengeTargeting; + // Allows the config to prevent minions from revenge-targeting their owners (or anything else, for that matter) + return Wizardry.settings.minionRevengeTargeting || isValidTarget(entity); } /** @@ -286,22 +287,17 @@ public interface ISummonedCreature extends IEntityAdditionalSpawnData { default void updateDelegate(){ if(!(this instanceof Entity)) - throw new ClassCastException("Implementations of ISummonedCreature must extend Entity!"); + throw new ClassCastException("Implementations of ISummonedCreature must extend SoundLoopSpellEntity!"); Entity thisEntity = ((Entity)this); - if(this.getCaster() == null && this.getCasterUUID() != null){ - Entity entity = WizardryUtilities.getEntityByUUID(thisEntity.world, getCasterUUID()); - if(entity instanceof EntityLivingBase){ - this.setCasterReference(new WeakReference((EntityLivingBase)entity)); - } - } - if(thisEntity.ticksExisted == 1){ this.onSpawn(); } - if(thisEntity.ticksExisted > this.getLifetime() && this.getLifetime() != -1){ + // For some reason Minecraft reads the entity from NBT just after the entity is created, so setting -1 as a + // default lifetime doesn't work. The easiest way around this is to use 0 - nobody's going to need it! + if(thisEntity.ticksExisted > this.getLifetime() && this.getLifetime() > 0){ this.onDespawn(); thisEntity.setDead(); } @@ -322,20 +318,20 @@ public interface ISummonedCreature extends IEntityAdditionalSpawnData { ItemStack stack = player.getHeldItem(hand); - WizardData properties = WizardData.get(player); + WizardData data = WizardData.get(player); // Selects one of the player's minions. - if(player.isSneaking() && stack.getItem() instanceof ItemWand){ + if(player.isSneaking() && stack.getItem() instanceof ISpellCastingItem){ - if(!player.world.isRemote && properties != null && this.getCaster() == player){ + if(!player.world.isRemote && data != null && this.getCaster() == player){ - if(properties.selectedMinion != null && properties.selectedMinion.get() == this){ + if(data.selectedMinion != null && data.selectedMinion.get() == this){ // Deselects the selected minion if right-clicked again - properties.selectedMinion = null; + data.selectedMinion = null; }else{ // Selects this minion - properties.selectedMinion = new WeakReference(this); + data.selectedMinion = new WeakReference<>(this); } - properties.sync(); + data.sync(); } return true; } @@ -346,7 +342,7 @@ public interface ISummonedCreature extends IEntityAdditionalSpawnData { // Damage system @SubscribeEvent - public static void onLivingAttackEvent(LivingAttackEvent event){ + static void onLivingAttackEvent(LivingAttackEvent event){ // Rather than bother overriding entire attack methods in ISummonedCreature implementations, it's easier (and // more robust) to use LivingAttackEvent to modify the damage source. diff --git a/src/main/java/electroblob/wizardry/entity/projectile/EntityDarknessOrb.java b/src/main/java/electroblob/wizardry/entity/projectile/EntityDarknessOrb.java index d9aee1e5..484457ba 100644 --- a/src/main/java/electroblob/wizardry/entity/projectile/EntityDarknessOrb.java +++ b/src/main/java/electroblob/wizardry/entity/projectile/EntityDarknessOrb.java @@ -1,5 +1,8 @@ package electroblob.wizardry.entity.projectile; +import electroblob.wizardry.registry.Spells; +import electroblob.wizardry.registry.WizardrySounds; +import electroblob.wizardry.spell.Spell; import electroblob.wizardry.util.MagicDamage; import electroblob.wizardry.util.MagicDamage.DamageType; import electroblob.wizardry.util.ParticleBuilder; @@ -7,7 +10,6 @@ import electroblob.wizardry.util.ParticleBuilder.Type; import net.minecraft.entity.Entity; import net.minecraft.entity.EntityLivingBase; import net.minecraft.init.MobEffects; -import net.minecraft.init.SoundEvents; import net.minecraft.potion.PotionEffect; import net.minecraft.util.math.RayTraceResult; import net.minecraft.world.World; @@ -24,16 +26,19 @@ public class EntityDarknessOrb extends EntityMagicProjectile { Entity target = rayTrace.entityHit; if(target != null && !MagicDamage.isEntityImmune(DamageType.WITHER, target)){ - float damage = 8 * damageMultiplier; + + float damage = Spells.darkness_orb.getProperty(Spell.DAMAGE).floatValue() * damageMultiplier; target.attackEntityFrom( MagicDamage.causeIndirectMagicDamage(this, this.getThrower(), DamageType.WITHER).setProjectile(), damage); if(target instanceof EntityLivingBase && !MagicDamage.isEntityImmune(DamageType.WITHER, target)) - ((EntityLivingBase)target).addPotionEffect(new PotionEffect(MobEffects.WITHER, 150, 1)); + ((EntityLivingBase)target).addPotionEffect(new PotionEffect(MobEffects.WITHER, + Spells.darkness_orb.getProperty(Spell.EFFECT_DURATION).intValue(), + Spells.darkness_orb.getProperty(Spell.EFFECT_STRENGTH).intValue())); - this.playSound(SoundEvents.ENTITY_WITHER_HURT, 1.0F, 1.2F / (this.rand.nextFloat() * 0.2F + 0.9F)); + this.playSound(WizardrySounds.ENTITY_DARKNESS_ORB_HIT, 1.0F, 1.2F / (this.rand.nextFloat() * 0.2F + 0.9F)); } this.setDead(); @@ -53,10 +58,6 @@ public class EntityDarknessOrb extends EntityMagicProjectile { ParticleBuilder.create(Type.DARK_MAGIC, this).clr(0.1f, 0.0f, 0.0f).spawn(world); } - if(this.ticksExisted > 150){ - this.setDead(); - } - // Cancels out the slowdown effect in EntityThrowable this.motionX /= 0.99; this.motionY /= 0.99; @@ -67,4 +68,9 @@ public class EntityDarknessOrb extends EntityMagicProjectile { public boolean hasNoGravity(){ return true; } + + @Override + public int getLifetime(){ + return 60; + } } diff --git a/src/main/java/electroblob/wizardry/entity/projectile/EntityDart.java b/src/main/java/electroblob/wizardry/entity/projectile/EntityDart.java index 146b0c4e..6fd4cb3c 100644 --- a/src/main/java/electroblob/wizardry/entity/projectile/EntityDart.java +++ b/src/main/java/electroblob/wizardry/entity/projectile/EntityDart.java @@ -1,11 +1,14 @@ package electroblob.wizardry.entity.projectile; +import electroblob.wizardry.registry.Spells; +import electroblob.wizardry.registry.WizardrySounds; +import electroblob.wizardry.spell.Spell; import electroblob.wizardry.util.ParticleBuilder; import electroblob.wizardry.util.ParticleBuilder.Type; import net.minecraft.entity.EntityLivingBase; import net.minecraft.init.MobEffects; -import net.minecraft.init.SoundEvents; import net.minecraft.potion.PotionEffect; +import net.minecraft.util.math.RayTraceResult; import net.minecraft.world.World; public class EntityDart extends EntityMagicArrow { @@ -15,7 +18,7 @@ public class EntityDart extends EntityMagicArrow { super(world); } - @Override public double getDamage(){ return 4; } + @Override public double getDamage(){ return Spells.dart.getProperty(Spell.DAMAGE).doubleValue(); } @Override public boolean doGravity(){ return true; } @@ -24,13 +27,14 @@ public class EntityDart extends EntityMagicArrow { @Override public void onEntityHit(EntityLivingBase entityHit){ // Adds a weakness effect to the target. - entityHit.addPotionEffect(new PotionEffect(MobEffects.WEAKNESS, 200, 1, false, false)); - this.playSound(SoundEvents.ENTITY_GENERIC_HURT, 1.0F, 1.2F / (this.rand.nextFloat() * 0.2F + 0.9F)); + entityHit.addPotionEffect(new PotionEffect(MobEffects.WEAKNESS, Spells.dart.getProperty(Spell.EFFECT_DURATION).intValue(), + Spells.dart.getProperty(Spell.EFFECT_STRENGTH).intValue(), false, false)); + this.playSound(WizardrySounds.ENTITY_DART_HIT, 1.0F, 1.2F / (this.rand.nextFloat() * 0.2F + 0.9F)); } @Override - public void onBlockHit(){ - this.playSound(SoundEvents.ENTITY_ARROW_HIT, 1.0F, 1.2F / (this.rand.nextFloat() * 0.2F + 0.9F)); + public void onBlockHit(RayTraceResult hit){ + this.playSound(WizardrySounds.ENTITY_DART_HIT_BLOCK, 1.0F, 1.2F / (this.rand.nextFloat() * 0.2F + 0.9F)); } @Override @@ -51,4 +55,8 @@ public class EntityDart extends EntityMagicArrow { @Override protected void entityInit(){} + @Override + public int getLifetime(){ + return -1; + } } \ No newline at end of file diff --git a/src/main/java/electroblob/wizardry/entity/projectile/EntityEmber.java b/src/main/java/electroblob/wizardry/entity/projectile/EntityEmber.java new file mode 100644 index 00000000..13325283 --- /dev/null +++ b/src/main/java/electroblob/wizardry/entity/projectile/EntityEmber.java @@ -0,0 +1,87 @@ +package electroblob.wizardry.entity.projectile; + +import electroblob.wizardry.registry.Spells; +import electroblob.wizardry.spell.Disintegration; +import electroblob.wizardry.spell.Spell; +import net.minecraft.entity.Entity; +import net.minecraft.entity.EntityLivingBase; +import net.minecraft.util.EnumFacing; +import net.minecraft.util.EnumParticleTypes; +import net.minecraft.util.math.AxisAlignedBB; +import net.minecraft.util.math.RayTraceResult; +import net.minecraft.world.World; + +public class EntityEmber extends EntityMagicProjectile { + + private int extraLifetime; + + public EntityEmber(World world){ + super(world); + } + + public EntityEmber(World world, EntityLivingBase caster){ + super(world); + this.thrower = caster; + extraLifetime = rand.nextInt(30); + this.setSize(0.1f, 0.1f); + } + + @Override + public AxisAlignedBB getCollisionBoundingBox(){ + return null;//this.getEntityBoundingBox(); + } + + @Override + public int getLifetime(){ + return Spells.disintegration.getProperty(Disintegration.EMBER_LIFETIME).intValue() + extraLifetime; + } + + @Override + protected void onImpact(RayTraceResult result){ + + if(result.entityHit != null){ + result.entityHit.setFire(Spells.disintegration.getProperty(Spell.BURN_DURATION).intValue()); + } + + if(result.typeOfHit == RayTraceResult.Type.BLOCK){ + this.inGround = true; + this.collided = true; + if(result.sideHit.getAxis() == EnumFacing.Axis.X) motionX = 0; + if(result.sideHit.getAxis() == EnumFacing.Axis.Y){ + motionY = 0; + this.collidedVertically = true; + } + if(result.sideHit.getAxis() == EnumFacing.Axis.Z) motionZ = 0; + } + } + + @Override + public void applyEntityCollision(Entity entity){ + + super.applyEntityCollision(entity); + + if(entity instanceof EntityLivingBase){ + entity.setFire(Spells.disintegration.getProperty(Spell.BURN_DURATION).intValue()); + } + } + + @Override + public void onUpdate(){ + + super.onUpdate(); + + if(this.collidedVertically){ + this.motionY += this.getGravityVelocity(); + this.motionX *= 0.5; + this.motionZ *= 0.5; + } + + world.getEntitiesInAABBexcluding(thrower, this.getEntityBoundingBox(), e -> e instanceof EntityLivingBase) + .forEach(e -> e.setFire(Spells.disintegration.getProperty(Spell.BURN_DURATION).intValue())); + + // Copied from ParticleLava + if(this.rand.nextFloat() > (float)this.ticksExisted / this.getLifetime()){ + this.world.spawnParticle(EnumParticleTypes.SMOKE_NORMAL, this.posX, this.posY, this.posZ, this.motionX, this.motionY, this.motionZ); + } + } +} diff --git a/src/main/java/electroblob/wizardry/entity/projectile/EntityFirebolt.java b/src/main/java/electroblob/wizardry/entity/projectile/EntityFirebolt.java index 50c5e648..454aad3e 100644 --- a/src/main/java/electroblob/wizardry/entity/projectile/EntityFirebolt.java +++ b/src/main/java/electroblob/wizardry/entity/projectile/EntityFirebolt.java @@ -1,9 +1,12 @@ package electroblob.wizardry.entity.projectile; +import electroblob.wizardry.registry.Spells; +import electroblob.wizardry.registry.WizardrySounds; +import electroblob.wizardry.spell.Spell; import electroblob.wizardry.util.MagicDamage; import electroblob.wizardry.util.MagicDamage.DamageType; +import electroblob.wizardry.util.ParticleBuilder; import net.minecraft.entity.Entity; -import net.minecraft.init.SoundEvents; import net.minecraft.util.EnumParticleTypes; import net.minecraft.util.math.RayTraceResult; import net.minecraft.world.World; @@ -16,19 +19,22 @@ public class EntityFirebolt extends EntityMagicProjectile { @Override protected void onImpact(RayTraceResult rayTrace){ + Entity entityHit = rayTrace.entityHit; if(entityHit != null){ - float damage = 5 * damageMultiplier; + + float damage = Spells.firebolt.getProperty(Spell.DAMAGE).floatValue() * damageMultiplier; entityHit.attackEntityFrom( MagicDamage.causeIndirectMagicDamage(this, this.getThrower(), DamageType.FIRE).setProjectile(), damage); - if(!MagicDamage.isEntityImmune(DamageType.FIRE, entityHit)) entityHit.setFire(5); + if(!MagicDamage.isEntityImmune(DamageType.FIRE, entityHit)) + entityHit.setFire(Spells.firebolt.getProperty(Spell.BURN_DURATION).intValue()); } - this.playSound(SoundEvents.BLOCK_LAVA_POP, 2, 0.8f + rand.nextFloat() * 0.3f); + this.playSound(WizardrySounds.ENTITY_FIREBOLT_HIT, 2, 0.8f + rand.nextFloat() * 0.3f); // Particle effect if(world.isRemote){ @@ -47,16 +53,20 @@ public class EntityFirebolt extends EntityMagicProjectile { super.onUpdate(); if(world.isRemote){ - for(int i = 0; i < 4; i++){ - world.spawnParticle(EnumParticleTypes.FLAME, this.posX + rand.nextFloat() * 0.2 - 0.1, - this.posY + this.height / 2 + rand.nextFloat() * 0.2 - 0.1, - this.posZ + rand.nextFloat() * 0.2 - 0.1, 0, 0, 0); + ParticleBuilder.create(ParticleBuilder.Type.MAGIC_FIRE, this).time(14).spawn(world); + + if(this.ticksExisted > 1){ // Don't spawn particles behind where it started! + double x = posX - motionX/2 + rand.nextFloat() * 0.2 - 0.1; + double y = posY + this.height/2 - motionY/2 + rand.nextFloat() * 0.2 - 0.1; + double z = posZ - motionZ/2 + rand.nextFloat() * 0.2 - 0.1; + ParticleBuilder.create(ParticleBuilder.Type.MAGIC_FIRE).pos(x, y, z).time(14).spawn(world); } } + } - if(this.ticksExisted > 8){ - this.setDead(); - } + @Override + public int getLifetime(){ + return 6; } @Override diff --git a/src/main/java/electroblob/wizardry/entity/projectile/EntityFirebomb.java b/src/main/java/electroblob/wizardry/entity/projectile/EntityFirebomb.java index 32c42bf3..0c4693ce 100644 --- a/src/main/java/electroblob/wizardry/entity/projectile/EntityFirebomb.java +++ b/src/main/java/electroblob/wizardry/entity/projectile/EntityFirebomb.java @@ -1,7 +1,8 @@ package electroblob.wizardry.entity.projectile; -import java.util.List; - +import electroblob.wizardry.registry.Spells; +import electroblob.wizardry.registry.WizardrySounds; +import electroblob.wizardry.spell.Spell; import electroblob.wizardry.util.MagicDamage; import electroblob.wizardry.util.MagicDamage.DamageType; import electroblob.wizardry.util.ParticleBuilder; @@ -9,17 +10,23 @@ import electroblob.wizardry.util.ParticleBuilder.Type; import electroblob.wizardry.util.WizardryUtilities; import net.minecraft.entity.Entity; import net.minecraft.entity.EntityLivingBase; -import net.minecraft.init.SoundEvents; import net.minecraft.util.EnumParticleTypes; import net.minecraft.util.math.RayTraceResult; import net.minecraft.world.World; +import java.util.List; + public class EntityFirebomb extends EntityBomb { public EntityFirebomb(World world){ super(world); } + @Override + public int getLifetime(){ + return -1; + } + @Override protected void onImpact(RayTraceResult rayTrace){ @@ -27,13 +34,14 @@ public class EntityFirebomb extends EntityBomb { if(entityHit != null){ // This is if the firebomb gets a direct hit - float damage = 5 * damageMultiplier; + float damage = Spells.firebomb.getProperty(Spell.DIRECT_DAMAGE).floatValue() * damageMultiplier; entityHit.attackEntityFrom( MagicDamage.causeIndirectMagicDamage(this, this.getThrower(), DamageType.FIRE).setProjectile(), damage); - if(!MagicDamage.isEntityImmune(DamageType.FIRE, entityHit)) entityHit.setFire(10); + if(!MagicDamage.isEntityImmune(DamageType.FIRE, entityHit)) + entityHit.setFire(Spells.firebomb.getProperty(Spell.BURN_DURATION).intValue()); } // Particle effect @@ -45,7 +53,7 @@ public class EntityFirebomb extends EntityBomb { for(int i = 0; i < 60 * blastMultiplier; i++){ ParticleBuilder.create(Type.MAGIC_FIRE, rand, posX, posY, posZ, 2*blastMultiplier, false) - .time(15 + rand.nextInt(5)).scale(2 + rand.nextFloat()).spawn(world); + .time(10 + rand.nextInt(4)).scale(2 + rand.nextFloat()).spawn(world); ParticleBuilder.create(Type.DARK_MAGIC, rand, posX, posY, posZ, 2*blastMultiplier, false) .clr(1.0f, 0.2f + rand.nextFloat() * 0.4f, 0.0f).spawn(world); @@ -56,10 +64,10 @@ public class EntityFirebomb extends EntityBomb { if(!this.world.isRemote){ - this.playSound(SoundEvents.ENTITY_SPLASH_POTION_BREAK, 1.5F, rand.nextFloat() * 0.4F + 0.6F); - this.playSound(SoundEvents.ENTITY_BLAZE_SHOOT, 1, 1); + this.playSound(WizardrySounds.ENTITY_FIREBOMB_SMASH, 1.5F, rand.nextFloat() * 0.4F + 0.6F); + this.playSound(WizardrySounds.ENTITY_FIREBOMB_FIRE, 1, 1); - double range = 3.0d * blastMultiplier; + double range = Spells.firebomb.getProperty(Spell.BLAST_RADIUS).floatValue() * blastMultiplier; List targets = WizardryUtilities.getEntitiesWithinRadius(range, this.posX, this.posY, this.posZ, this.world); @@ -70,8 +78,8 @@ public class EntityFirebomb extends EntityBomb { // Splash damage does not count as projectile damage target.attackEntityFrom( MagicDamage.causeIndirectMagicDamage(this, this.getThrower(), DamageType.FIRE), - 4.0f * damageMultiplier); - target.setFire(7); + Spells.firebomb.getProperty(Spell.SPLASH_DAMAGE).floatValue() * damageMultiplier); + target.setFire(Spells.firebomb.getProperty(Spell.BURN_DURATION).intValue()); } } diff --git a/src/main/java/electroblob/wizardry/entity/projectile/EntityForceArrow.java b/src/main/java/electroblob/wizardry/entity/projectile/EntityForceArrow.java index 8fcf251d..0b5bb9cb 100644 --- a/src/main/java/electroblob/wizardry/entity/projectile/EntityForceArrow.java +++ b/src/main/java/electroblob/wizardry/entity/projectile/EntityForceArrow.java @@ -1,53 +1,100 @@ package electroblob.wizardry.entity.projectile; +import electroblob.wizardry.item.IManaStoringItem; +import electroblob.wizardry.item.ISpellCastingItem; +import electroblob.wizardry.item.ItemArtefact; +import electroblob.wizardry.registry.Spells; +import electroblob.wizardry.registry.WizardryItems; +import electroblob.wizardry.registry.WizardrySounds; +import electroblob.wizardry.spell.Spell; import electroblob.wizardry.util.MagicDamage.DamageType; import electroblob.wizardry.util.ParticleBuilder; import electroblob.wizardry.util.ParticleBuilder.Type; +import electroblob.wizardry.util.WizardryUtilities; import net.minecraft.entity.EntityLivingBase; -import net.minecraft.init.SoundEvents; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.item.ItemStack; +import net.minecraft.util.math.RayTraceResult; +import net.minecraft.util.math.Vec3d; import net.minecraft.world.World; +import java.util.Arrays; + public class EntityForceArrow extends EntityMagicArrow { + /** The mana used to cast this force arrow, used for artefacts. */ + private int mana = 0; + /** Creates a new force arrow in the given world. */ public EntityForceArrow(World world){ super(world); } + public void setMana(int mana){ + this.mana = mana; + } + @Override public void onEntityHit(EntityLivingBase entityHit){ - this.playSound(SoundEvents.ENTITY_FIREWORK_BLAST, 1.0F, 1.0F); + this.playSound(WizardrySounds.ENTITY_FORCE_ARROW_HIT, 1.0F, 1.0F); if(this.world.isRemote) ParticleBuilder.create(Type.FLASH).pos(posX, posY, posZ).scale(1.3f).clr(0.75f, 1, 0.85f).spawn(world); } @Override public void tickInGround(){ + returnManaToCaster(); this.setDead(); } @Override - public void onBlockHit(){ - this.playSound(SoundEvents.ENTITY_FIREWORK_BLAST, 1.0F, 1.0F); + public void onUpdate(){ + + if(getLifetime() >=0 && this.ticksExisted > getLifetime()){ // The last tick before it disappears + returnManaToCaster(); + } + + super.onUpdate(); + } + + private void returnManaToCaster(){ + + if(mana > 0 && getCaster() instanceof EntityPlayer){ + + EntityPlayer player = (EntityPlayer)getCaster(); + + if(!player.capabilities.isCreativeMode && ItemArtefact.isArtefactActive(player, WizardryItems.ring_mana_return)){ + + for(ItemStack stack : WizardryUtilities.getPrioritisedHotbarAndOffhand(player)){ + if(stack.getItem() instanceof ISpellCastingItem && stack.getItem() instanceof IManaStoringItem + && Arrays.asList(((ISpellCastingItem)stack.getItem()).getSpells(stack)).contains(Spells.force_arrow)){ + ((IManaStoringItem)stack.getItem()).rechargeMana(stack, mana); + } + } + } + } + } + + @Override + public void onBlockHit(RayTraceResult hit){ + this.playSound(WizardrySounds.ENTITY_FORCE_ARROW_HIT, 1.0F, 1.0F); if(this.world.isRemote){ // Gets a position slightly away from the block hit so the particle doesn't get cut in half by the block face Vec3d vec = hit.hitVec.add(new Vec3d(hit.sideHit.getDirectionVec()).scale(0.15)); ParticleBuilder.create(Type.FLASH).pos(vec).scale(1.3f).clr(0.75f, 1, 0.85f).spawn(world); - vec = hit.hitVec.add(new Vec3d(hit.sideHit.getDirectionVec()).scale(WizardryUtilities.ANTI_Z_FIGHTING_OFFSET)); - ParticleBuilder.create(Type.SCORCH).pos(vec).face(hit.sideHit).clr(0, 1, 0.5f).spawn(world); + //vec = hit.hitVec.add(new Vec3d(hit.sideHit.getDirectionVec()).scale(WizardryUtilities.ANTI_Z_FIGHTING_OFFSET)); + //ParticleBuilder.create(Type.SCORCH).pos(vec).face(hit.sideHit).clr(0, 1, 0.5f).spawn(world); } } @Override - public void tickInAir(){ - if(this.ticksExisted > 20){ - this.setDead(); - } + public int getLifetime(){ + return 20; } @Override public double getDamage(){ - return 7.0d; + return Spells.force_arrow.getProperty(Spell.DAMAGE).floatValue(); } @Override diff --git a/src/main/java/electroblob/wizardry/entity/projectile/EntityForceOrb.java b/src/main/java/electroblob/wizardry/entity/projectile/EntityForceOrb.java index 73373a40..3967b0ba 100644 --- a/src/main/java/electroblob/wizardry/entity/projectile/EntityForceOrb.java +++ b/src/main/java/electroblob/wizardry/entity/projectile/EntityForceOrb.java @@ -1,30 +1,37 @@ package electroblob.wizardry.entity.projectile; -import java.util.List; - +import electroblob.wizardry.registry.Spells; +import electroblob.wizardry.registry.WizardrySounds; +import electroblob.wizardry.spell.Spell; import electroblob.wizardry.util.MagicDamage; import electroblob.wizardry.util.MagicDamage.DamageType; import electroblob.wizardry.util.ParticleBuilder; import electroblob.wizardry.util.ParticleBuilder.Type; import electroblob.wizardry.util.WizardryUtilities; import net.minecraft.entity.EntityLivingBase; -import net.minecraft.init.SoundEvents; import net.minecraft.util.EnumParticleTypes; import net.minecraft.util.math.RayTraceResult; import net.minecraft.world.World; +import java.util.List; + public class EntityForceOrb extends EntityBomb { public EntityForceOrb(World world){ super(world); } + @Override + public int getLifetime(){ + return -1; + } + @Override protected void onImpact(RayTraceResult par1RayTraceResult){ if(par1RayTraceResult.entityHit != null){ // This is if the force orb gets a direct hit - this.playSound(SoundEvents.ENTITY_GENERIC_HURT, 1.0F, 1.2F / (this.rand.nextFloat() * 0.2F + 0.9F)); + this.playSound(WizardrySounds.ENTITY_FORCE_ORB_HIT, 1.0F, 1.2F / (this.rand.nextFloat() * 0.2F + 0.9F)); } // Particle effect @@ -41,10 +48,10 @@ public class EntityForceOrb extends EntityBomb { // 2 gives a cool flanging effect! float pitch = this.rand.nextFloat() * 0.2F + 0.3F; - this.playSound(SoundEvents.ENTITY_FIREWORK_BLAST, 1.5F, pitch); - this.playSound(SoundEvents.ENTITY_FIREWORK_BLAST, 1.5F, pitch - 0.01f); + this.playSound(WizardrySounds.ENTITY_FORCE_ORB_HIT_BLOCK, 1.5F, pitch); + this.playSound(WizardrySounds.ENTITY_FORCE_ORB_HIT_BLOCK, 1.5F, pitch - 0.01f); - double blastRadius = 4.0d * blastMultiplier; + double blastRadius = Spells.force_orb.getProperty(Spell.BLAST_RADIUS).floatValue() * blastMultiplier; List targets = WizardryUtilities.getEntitiesWithinRadius(blastRadius, this.posX, this.posY, this.posZ, this.world); @@ -59,7 +66,7 @@ public class EntityForceOrb extends EntityBomb { double dz = this.posZ - target.posZ > 0 ? -0.5 - (this.posZ - target.posZ) / 8 : 0.5 - (this.posZ - target.posZ) / 8; - float damage = 4 * damageMultiplier; + float damage = Spells.force_orb.getProperty(Spell.DAMAGE).floatValue() * damageMultiplier; target.attackEntityFrom( MagicDamage.causeIndirectMagicDamage(this, this.getThrower(), DamageType.BLAST), damage); diff --git a/src/main/java/electroblob/wizardry/entity/projectile/EntityIceCharge.java b/src/main/java/electroblob/wizardry/entity/projectile/EntityIceCharge.java index 1f35f8d6..048d47c9 100644 --- a/src/main/java/electroblob/wizardry/entity/projectile/EntityIceCharge.java +++ b/src/main/java/electroblob/wizardry/entity/projectile/EntityIceCharge.java @@ -1,9 +1,9 @@ package electroblob.wizardry.entity.projectile; -import java.util.List; - +import electroblob.wizardry.registry.Spells; import electroblob.wizardry.registry.WizardryPotions; import electroblob.wizardry.registry.WizardrySounds; +import electroblob.wizardry.spell.Spell; import electroblob.wizardry.util.MagicDamage; import electroblob.wizardry.util.MagicDamage.DamageType; import electroblob.wizardry.util.ParticleBuilder; @@ -12,43 +12,55 @@ import electroblob.wizardry.util.WizardryUtilities; import net.minecraft.entity.Entity; import net.minecraft.entity.EntityLivingBase; import net.minecraft.init.Blocks; -import net.minecraft.init.SoundEvents; import net.minecraft.potion.PotionEffect; +import net.minecraft.util.EnumFacing; import net.minecraft.util.EnumParticleTypes; import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.RayTraceResult; import net.minecraft.world.World; +import java.util.List; + public class EntityIceCharge extends EntityBomb { + public static final String ICE_SHARDS = "ice_shards"; + public EntityIceCharge(World world){ super(world); } @Override - protected void onImpact(RayTraceResult par1RayTraceResult){ - Entity entityHit = par1RayTraceResult.entityHit; + public int getLifetime(){ + return -1; + } + + @Override + protected void onImpact(RayTraceResult rayTrace){ + + Entity entityHit = rayTrace.entityHit; if(entityHit != null){ // This is if the ice charge gets a direct hit - float damage = 4 * damageMultiplier; + float damage = Spells.ice_charge.getProperty(Spell.DAMAGE).floatValue() * damageMultiplier; entityHit.attackEntityFrom( MagicDamage.causeIndirectMagicDamage(this, this.getThrower(), DamageType.FROST).setProjectile(), damage); if(entityHit instanceof EntityLivingBase && !MagicDamage.isEntityImmune(DamageType.FROST, entityHit)) - ((EntityLivingBase)entityHit).addPotionEffect(new PotionEffect(WizardryPotions.frost, 120, 1)); + ((EntityLivingBase)entityHit).addPotionEffect(new PotionEffect(WizardryPotions.frost, + Spells.ice_charge.getProperty(Spell.DIRECT_EFFECT_DURATION).intValue(), + Spells.ice_charge.getProperty(Spell.DIRECT_EFFECT_STRENGTH).intValue())); } // Particle effect if(world.isRemote){ this.world.spawnParticle(EnumParticleTypes.EXPLOSION_LARGE, this.posX, this.posY, this.posZ, 0, 0, 0); for(int i = 0; i < 30 * blastMultiplier; i++){ - + ParticleBuilder.create(Type.ICE, rand, this.posX, this.posY, this.posZ, 2 * blastMultiplier, false) .time(35).gravity(true).spawn(world); - + float brightness = 0.4f + rand.nextFloat() * 0.5f; ParticleBuilder.create(Type.DARK_MAGIC, rand, this.posX, this.posY, this.posZ, 2 * blastMultiplier, false) .clr(brightness, brightness + 0.1f, 1.0f).spawn(world); @@ -57,10 +69,10 @@ public class EntityIceCharge extends EntityBomb { if(!this.world.isRemote){ - this.playSound(SoundEvents.ENTITY_SPLASH_POTION_BREAK, 1.5f, rand.nextFloat() * 0.4f + 0.6f); - this.playSound(WizardrySounds.SPELL_ICE, 1.2f, rand.nextFloat() * 0.4f + 1.2f); + this.playSound(WizardrySounds.ENTITY_ICE_CHARGE_SMASH, 1.5f, rand.nextFloat() * 0.4f + 0.6f); + this.playSound(WizardrySounds.ENTITY_ICE_CHARGE_ICE, 1.2f, rand.nextFloat() * 0.4f + 1.2f); - double radius = 3.0d * blastMultiplier; + double radius = Spells.ice_charge.getProperty(Spell.EFFECT_RADIUS).floatValue() * blastMultiplier; List targets = WizardryUtilities.getEntitiesWithinRadius(radius, this.posX, this.posY, this.posZ, this.world); @@ -69,7 +81,9 @@ public class EntityIceCharge extends EntityBomb { for(EntityLivingBase target : targets){ if(target != entityHit && target != this.getThrower()){ if(!MagicDamage.isEntityImmune(DamageType.FROST, target)) - target.addPotionEffect(new PotionEffect(WizardryPotions.frost, 100, 0)); + target.addPotionEffect(new PotionEffect(WizardryPotions.frost, + Spells.ice_charge.getProperty(Spell.SPLASH_EFFECT_DURATION).intValue(), + Spells.ice_charge.getProperty(Spell.SPLASH_EFFECT_STRENGTH).intValue())); } } @@ -79,35 +93,39 @@ public class EntityIceCharge extends EntityBomb { BlockPos pos = new BlockPos(this.posX + i, this.posY, this.posZ + j); - int y = WizardryUtilities.getNearestFloorLevelB(world, pos, 7); + Integer y = WizardryUtilities.getNearestSurface(world, pos, EnumFacing.UP, 7, true, + WizardryUtilities.SurfaceCriteria.SOLID_LIQUID_TO_AIR); - pos = new BlockPos(pos.getX(), y, pos.getZ()); + if(y != null){ - double dist = this.getDistance(pos.getX(), pos.getY(), pos.getZ()); + pos = new BlockPos(pos.getX(), y, pos.getZ()); - // Randomised with weighting so that the nearer the block the more likely it is to be snowed. - if(y != -1 && rand.nextInt((int)dist * 2 + 1) < 1 && dist < 2){ - if(world.getBlockState(pos.down()).getBlock() == Blocks.WATER){ - world.setBlockState(pos.down(), Blocks.ICE.getDefaultState()); - }else{ - // Don't need to check whether the block at pos can be replaced since getNearestFloorLevelB - // only ever returns floors with air above them. - world.setBlockState(pos, Blocks.SNOW_LAYER.getDefaultState()); + double dist = this.getDistance(pos.getX(), pos.getY(), pos.getZ()); + + // Randomised with weighting so that the nearer the block the more likely it is to be snowed. + if(rand.nextInt((int)dist * 2 + 1) < 1 && dist < 2){ + if(world.getBlockState(pos.down()).getBlock() == Blocks.WATER){ + world.setBlockState(pos.down(), Blocks.ICE.getDefaultState()); + }else{ + // Don't need to check whether the block at pos can be replaced since getNearestFloorLevelB + // only ever returns floors with air above them. + world.setBlockState(pos, Blocks.SNOW_LAYER.getDefaultState()); + } } } } } // Releases shards - for(int i = 0; i < 10; i++){ + for(int i = 0; i < Spells.ice_charge.getProperty(ICE_SHARDS).intValue(); i++){ double dx = rand.nextDouble() - 0.5; double dy = rand.nextDouble() - 0.5; double dz = rand.nextDouble() - 0.5; EntityIceShard iceshard = new EntityIceShard(world); iceshard.setPosition(this.posX + dx, this.posY + dy, this.posZ + dz); - iceshard.motionX = dx; - iceshard.motionY = dy; - iceshard.motionZ = dz; + iceshard.motionX = dx * 1.5; + iceshard.motionY = dy * 1.5; + iceshard.motionZ = dz * 1.5; iceshard.setCaster(this.getThrower()); iceshard.damageMultiplier = this.damageMultiplier; world.spawnEntity(iceshard); diff --git a/src/main/java/electroblob/wizardry/entity/projectile/EntityIceLance.java b/src/main/java/electroblob/wizardry/entity/projectile/EntityIceLance.java index 1863f343..a9c2032e 100644 --- a/src/main/java/electroblob/wizardry/entity/projectile/EntityIceLance.java +++ b/src/main/java/electroblob/wizardry/entity/projectile/EntityIceLance.java @@ -1,13 +1,16 @@ package electroblob.wizardry.entity.projectile; +import electroblob.wizardry.registry.Spells; import electroblob.wizardry.registry.WizardryPotions; +import electroblob.wizardry.registry.WizardrySounds; +import electroblob.wizardry.spell.Spell; import electroblob.wizardry.util.MagicDamage; import electroblob.wizardry.util.MagicDamage.DamageType; import electroblob.wizardry.util.ParticleBuilder; import electroblob.wizardry.util.ParticleBuilder.Type; import net.minecraft.entity.EntityLivingBase; -import net.minecraft.init.SoundEvents; import net.minecraft.potion.PotionEffect; +import net.minecraft.util.math.RayTraceResult; import net.minecraft.world.World; public class EntityIceLance extends EntityMagicArrow { @@ -18,7 +21,9 @@ public class EntityIceLance extends EntityMagicArrow { this.setKnockbackStrength(1); } - @Override public double getDamage(){ return 10.0d; } + @Override public double getDamage(){ return Spells.ice_lance.getProperty(Spell.DAMAGE).floatValue(); } + + @Override public int getLifetime(){ return -1; } @Override public DamageType getDamageType(){ return DamageType.FROST; } @@ -35,13 +40,15 @@ public class EntityIceLance extends EntityMagicArrow { // Adds a freeze effect to the target. if(!MagicDamage.isEntityImmune(DamageType.FROST, entityHit)) - entityHit.addPotionEffect(new PotionEffect(WizardryPotions.frost, 300, 0)); + entityHit.addPotionEffect(new PotionEffect(WizardryPotions.frost, + Spells.ice_lance.getProperty(Spell.EFFECT_DURATION).intValue(), + Spells.ice_lance.getProperty(Spell.EFFECT_STRENGTH).intValue())); - this.playSound(SoundEvents.ENTITY_GENERIC_HURT, 1.0F, 1.2F / (this.rand.nextFloat() * 0.2F + 0.9F)); + this.playSound(WizardrySounds.ENTITY_ICE_LANCE_HIT, 1.0F, 1.2F / (this.rand.nextFloat() * 0.2F + 0.9F)); } @Override - public void onBlockHit(){ + public void onBlockHit(RayTraceResult hit){ // Adds a particle effect when the ice lance hits a block. if(this.world.isRemote){ for(int j = 0; j < 10; j++){ @@ -49,8 +56,8 @@ public class EntityIceLance extends EntityMagicArrow { .time(20 + rand.nextInt(10)).gravity(true).spawn(world); } } - // Parameters for sound: sound event name, volume, pitch. - this.playSound(SoundEvents.ENTITY_SPLASH_POTION_BREAK, 1.0F, rand.nextFloat() * 0.4F + 1.2F); + + this.playSound(WizardrySounds.ENTITY_ICE_LANCE_SMASH, 1.0F, rand.nextFloat() * 0.4F + 1.2F); } diff --git a/src/main/java/electroblob/wizardry/entity/projectile/EntityIceShard.java b/src/main/java/electroblob/wizardry/entity/projectile/EntityIceShard.java index c4d42bfa..72a2cfdf 100644 --- a/src/main/java/electroblob/wizardry/entity/projectile/EntityIceShard.java +++ b/src/main/java/electroblob/wizardry/entity/projectile/EntityIceShard.java @@ -1,13 +1,17 @@ package electroblob.wizardry.entity.projectile; +import electroblob.wizardry.registry.Spells; import electroblob.wizardry.registry.WizardryPotions; +import electroblob.wizardry.registry.WizardrySounds; +import electroblob.wizardry.spell.Spell; import electroblob.wizardry.util.MagicDamage; import electroblob.wizardry.util.MagicDamage.DamageType; import electroblob.wizardry.util.ParticleBuilder; import electroblob.wizardry.util.ParticleBuilder.Type; import net.minecraft.entity.EntityLivingBase; -import net.minecraft.init.SoundEvents; import net.minecraft.potion.PotionEffect; +import net.minecraft.util.math.RayTraceResult; +import net.minecraft.util.math.Vec3d; import net.minecraft.world.World; public class EntityIceShard extends EntityMagicArrow { @@ -17,7 +21,9 @@ public class EntityIceShard extends EntityMagicArrow { super(world); } - @Override public double getDamage(){ return 6; } + @Override public double getDamage(){ return Spells.ice_shard.getProperty(Spell.DAMAGE).floatValue(); } + + @Override public int getLifetime(){ return -1; } @Override public DamageType getDamageType(){ return DamageType.FROST; } @@ -32,13 +38,16 @@ public class EntityIceShard extends EntityMagicArrow { // Adds a freeze effect to the target. if(!MagicDamage.isEntityImmune(DamageType.FROST, entityHit)) - entityHit.addPotionEffect(new PotionEffect(WizardryPotions.frost, 200, 0)); + entityHit.addPotionEffect(new PotionEffect(WizardryPotions.frost, + Spells.ice_shard.getProperty(Spell.EFFECT_DURATION).intValue(), + Spells.ice_shard.getProperty(Spell.EFFECT_STRENGTH).intValue())); - this.playSound(SoundEvents.ENTITY_GENERIC_HURT, 1.0F, 1.2F / (this.rand.nextFloat() * 0.2F + 0.9F)); + this.playSound(WizardrySounds.ENTITY_ICE_SHARD_HIT, 1.0F, 1.2F / (this.rand.nextFloat() * 0.2F + 0.9F)); } @Override - public void onBlockHit(){ + public void onBlockHit(RayTraceResult hit){ + // Adds a particle effect when the ice shard hits a block. if(this.world.isRemote){ // Gets a position slightly away from the block hit so the particle doesn't get cut in half by the block face @@ -51,7 +60,7 @@ public class EntityIceShard extends EntityMagicArrow { } } // Parameters for sound: sound event name, volume, pitch. - this.playSound(SoundEvents.ENTITY_SPLASH_POTION_BREAK, 1.0F, rand.nextFloat() * 0.4F + 1.2F); + this.playSound(WizardrySounds.ENTITY_ICE_SHARD_SMASH, 1.0F, rand.nextFloat() * 0.4F + 1.2F); } diff --git a/src/main/java/electroblob/wizardry/entity/projectile/EntityIceball.java b/src/main/java/electroblob/wizardry/entity/projectile/EntityIceball.java new file mode 100644 index 00000000..7a34b09d --- /dev/null +++ b/src/main/java/electroblob/wizardry/entity/projectile/EntityIceball.java @@ -0,0 +1,117 @@ +package electroblob.wizardry.entity.projectile; + +import electroblob.wizardry.registry.Spells; +import electroblob.wizardry.registry.WizardryPotions; +import electroblob.wizardry.registry.WizardrySounds; +import electroblob.wizardry.spell.Spell; +import electroblob.wizardry.util.MagicDamage; +import electroblob.wizardry.util.MagicDamage.DamageType; +import electroblob.wizardry.util.ParticleBuilder; +import electroblob.wizardry.util.WizardryUtilities; +import net.minecraft.entity.Entity; +import net.minecraft.entity.EntityLiving; +import net.minecraft.entity.EntityLivingBase; +import net.minecraft.init.Blocks; +import net.minecraft.potion.PotionEffect; +import net.minecraft.util.EnumFacing; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.RayTraceResult; +import net.minecraft.world.World; + +public class EntityIceball extends EntityMagicProjectile { + + public EntityIceball(World world){ + super(world); + this.setSize(0.5f, 0.5f); + } + + @Override + protected void onImpact(RayTraceResult rayTrace){ + + if(!world.isRemote){ + + Entity entityHit = rayTrace.entityHit; + + if(entityHit != null){ + + float damage = Spells.iceball.getProperty(Spell.DAMAGE).floatValue() * damageMultiplier; + + entityHit.attackEntityFrom( + MagicDamage.causeIndirectMagicDamage(this, this.getThrower(), DamageType.FROST).setProjectile(), + damage); + + if(entityHit instanceof EntityLivingBase && !MagicDamage.isEntityImmune(DamageType.FROST, entityHit)){ + ((EntityLivingBase)entityHit).addPotionEffect(new PotionEffect(WizardryPotions.frost, + Spells.iceball.getProperty(Spell.EFFECT_DURATION).intValue(), + Spells.iceball.getProperty(Spell.EFFECT_STRENGTH).intValue())); + } + + }else{ + + boolean flag = true; + + if(this.getThrower() != null && this.getThrower() instanceof EntityLiving){ + flag = net.minecraftforge.event.ForgeEventFactory.getMobGriefingEvent(this.world, this.getThrower()); + } + + if(flag){ + + BlockPos pos = rayTrace.getBlockPos(); + + if(rayTrace.sideHit == EnumFacing.UP && !world.isRemote && world.isSideSolid(pos, EnumFacing.UP) + && WizardryUtilities.canBlockBeReplaced(world, pos.up())){ + world.setBlockState(pos.up(), Blocks.SNOW_LAYER.getDefaultState()); + } + } + } + + this.playSound(WizardrySounds.ENTITY_ICEBALL_HIT, 2, 0.8f + rand.nextFloat() * 0.3f); + + this.setDead(); + } + } + + @Override + public void onUpdate(){ + + super.onUpdate(); + + if(world.isRemote){ + + for(int i=0; i<5; i++){ + + double dx = (rand.nextDouble() - 0.5) * width; + double dy = (rand.nextDouble() - 0.5) * height + this.height/2; + double dz = (rand.nextDouble() - 0.5) * width; + double v = 0.06; + ParticleBuilder.create(ParticleBuilder.Type.SNOW) + .pos(this.getPositionVector().add(dx - this.motionX/2, dy, dz - this.motionZ/2)) + .vel(-v * dx, -v * dy, -v * dz).scale(width*2).time(8 + rand.nextInt(4)).spawn(world); + + if(ticksExisted > 1){ + dx = (rand.nextDouble() - 0.5) * width; + dy = (rand.nextDouble() - 0.5) * height + this.height / 2; + dz = (rand.nextDouble() - 0.5) * width; + ParticleBuilder.create(ParticleBuilder.Type.SNOW) + .pos(this.getPositionVector().add(dx - this.motionX, dy, dz - this.motionZ)) + .vel(-v * dx, -v * dy, -v * dz).scale(width*2).time(8 + rand.nextInt(4)).spawn(world); + } + } + } + } + + @Override + public int getLifetime(){ + return 16; + } + + @Override + public boolean hasNoGravity(){ + return true; + } + + @Override + public boolean canRenderOnFire(){ + return false; + } +} diff --git a/src/main/java/electroblob/wizardry/entity/projectile/EntityLargeMagicFireball.java b/src/main/java/electroblob/wizardry/entity/projectile/EntityLargeMagicFireball.java new file mode 100644 index 00000000..e78574a4 --- /dev/null +++ b/src/main/java/electroblob/wizardry/entity/projectile/EntityLargeMagicFireball.java @@ -0,0 +1,106 @@ +package electroblob.wizardry.entity.projectile; + +import electroblob.wizardry.Wizardry; +import electroblob.wizardry.registry.Spells; +import electroblob.wizardry.spell.Spell; +import io.netty.buffer.ByteBuf; +import net.minecraft.entity.projectile.EntityLargeFireball; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.util.math.RayTraceResult; +import net.minecraft.world.World; +import net.minecraftforge.event.entity.EntityJoinWorldEvent; +import net.minecraftforge.fml.common.Mod; +import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; + +/** + * It's like {@link EntityMagicFireball}, but bigger... the wizardry version of vanilla's + * {@link net.minecraft.entity.projectile.EntityLargeFireball} + */ +@Mod.EventBusSubscriber +public class EntityLargeMagicFireball extends EntityMagicFireball { + + public static final String EXPLOSION_POWER = "explosion_power"; + + /** The entity blast multiplier. This is now synced and saved centrally from {@link EntityBomb}. */ + public float blastMultiplier = 1.0f; + + /** The explosion power of this fireball. If this is -1, the damage for the fireball + * spell will be used instead; this is for when the fireball is not from a spell (i.e. a vanilla fireball replacement). */ + protected float explosionPower = -1; + + public EntityLargeMagicFireball(World world){ + super(world); + this.setSize(1, 1); + } + + public void setExplosionPower(float explosionPower){ + this.explosionPower = explosionPower; + } + + public float getExplosionPower(){ + return explosionPower == -1 ? Spells.greater_fireball.getProperty(EXPLOSION_POWER).floatValue() : explosionPower; + } + + @Override + public float getDamage(){ + return damage == -1 ? Spells.greater_fireball.getProperty(Spell.DAMAGE).floatValue() : damage; + } + + @Override + protected void onImpact(RayTraceResult rayTrace){ + + if(!world.isRemote){ + boolean flag = net.minecraftforge.event.ForgeEventFactory.getMobGriefingEvent(this.world, this.thrower); + this.world.newExplosion(null, this.posX, this.posY, this.posZ, getExplosionPower() * blastMultiplier, flag, flag); + } + + super.onImpact(rayTrace); + } + + @Override + public void writeSpawnData(ByteBuf buffer){ + buffer.writeFloat(blastMultiplier); + super.writeSpawnData(buffer); + } + + @Override + public void readSpawnData(ByteBuf buffer){ + blastMultiplier = buffer.readFloat(); + super.readSpawnData(buffer); + } + + @Override + public void readEntityFromNBT(NBTTagCompound nbttagcompound){ + super.readEntityFromNBT(nbttagcompound); + blastMultiplier = nbttagcompound.getFloat("blastMultiplier"); + } + + @Override + public void writeEntityToNBT(NBTTagCompound nbttagcompound){ + super.writeEntityToNBT(nbttagcompound); + nbttagcompound.setFloat("blastMultiplier", blastMultiplier); + } + + @SubscribeEvent + public static void onEntityJoinWorldEvent(EntityJoinWorldEvent event){ + // Replaces all vanilla large fireballs with wizardry ones + if(Wizardry.settings.replaceVanillaFireballs && event.getEntity() instanceof EntityLargeFireball){ + + event.setCanceled(true); + + EntityLargeMagicFireball fireball = new EntityLargeMagicFireball(event.getWorld()); + fireball.thrower = ((EntityLargeFireball)event.getEntity()).shootingEntity; + fireball.setPosition(event.getEntity().posX, event.getEntity().posY, event.getEntity().posZ); + fireball.setDamage(6); + // Don't set the burn duration because vanilla large fireballs don't set mobs on fire directly + fireball.setExplosionPower(((EntityLargeFireball)event.getEntity()).explosionPower); + fireball.setLifetime(75); + + fireball.motionX = ((EntityLargeFireball)event.getEntity()).accelerationX * ACCELERATION_CONVERSION_FACTOR; + fireball.motionY = ((EntityLargeFireball)event.getEntity()).accelerationY * ACCELERATION_CONVERSION_FACTOR; + fireball.motionZ = ((EntityLargeFireball)event.getEntity()).accelerationZ * ACCELERATION_CONVERSION_FACTOR; + + event.getWorld().spawnEntity(fireball); + } + } +} diff --git a/src/main/java/electroblob/wizardry/entity/projectile/EntityLightningArrow.java b/src/main/java/electroblob/wizardry/entity/projectile/EntityLightningArrow.java index 63857276..2f166bfd 100644 --- a/src/main/java/electroblob/wizardry/entity/projectile/EntityLightningArrow.java +++ b/src/main/java/electroblob/wizardry/entity/projectile/EntityLightningArrow.java @@ -1,6 +1,8 @@ package electroblob.wizardry.entity.projectile; +import electroblob.wizardry.registry.Spells; import electroblob.wizardry.registry.WizardrySounds; +import electroblob.wizardry.spell.Spell; import electroblob.wizardry.util.MagicDamage.DamageType; import electroblob.wizardry.util.ParticleBuilder; import electroblob.wizardry.util.ParticleBuilder.Type; @@ -14,7 +16,9 @@ public class EntityLightningArrow extends EntityMagicArrow { super(world); } - @Override public double getDamage(){ return 7.0d; } + @Override public double getDamage(){ return Spells.lightning_arrow.getProperty(Spell.DAMAGE).doubleValue(); } + + @Override public int getLifetime(){ return 20; } @Override public DamageType getDamageType(){ return DamageType.SHOCK; } @@ -31,26 +35,22 @@ public class EntityLightningArrow extends EntityMagicArrow { } } - this.playSound(WizardrySounds.SPELL_SPARK, 1.0F, 1.0F); - @Override - public void onBlockHit(RayTraceResult hit){ - if(this.world.isRemote){ - Vec3d vec = hit.hitVec.add(new Vec3d(hit.sideHit.getDirectionVec()).scale(WizardryUtilities.ANTI_Z_FIGHTING_OFFSET)); - ParticleBuilder.create(Type.SCORCH).pos(vec).face(hit.sideHit).clr(0.4f, 0.8f, 1).scale(0.6f).spawn(world); - } + this.playSound(WizardrySounds.ENTITY_LIGHTNING_ARROW_HIT, 1.0F, 1.0F); } + +// @Override +// public void onBlockHit(RayTraceResult hit){ +// if(this.world.isRemote){ +// Vec3d vec = hit.hitVec.add(new Vec3d(hit.sideHit.getDirectionVec()).scale(WizardryUtilities.ANTI_Z_FIGHTING_OFFSET)); +// ParticleBuilder.create(Type.SCORCH).pos(vec).face(hit.sideHit).clr(0.4f, 0.8f, 1).scale(0.6f).spawn(world); +// } +// } @Override public void tickInAir(){ - - if(this.ticksExisted > 20){ - this.setDead(); - } - if(world.isRemote){ ParticleBuilder.create(Type.SPARK).pos(posX, posY, posZ).spawn(world); } - } @Override diff --git a/src/main/java/electroblob/wizardry/entity/projectile/EntityLightningDisc.java b/src/main/java/electroblob/wizardry/entity/projectile/EntityLightningDisc.java index afa24ff8..7f745f87 100644 --- a/src/main/java/electroblob/wizardry/entity/projectile/EntityLightningDisc.java +++ b/src/main/java/electroblob/wizardry/entity/projectile/EntityLightningDisc.java @@ -1,15 +1,13 @@ package electroblob.wizardry.entity.projectile; -import java.util.List; - +import electroblob.wizardry.registry.Spells; import electroblob.wizardry.registry.WizardrySounds; +import electroblob.wizardry.spell.Spell; import electroblob.wizardry.util.MagicDamage; import electroblob.wizardry.util.MagicDamage.DamageType; import electroblob.wizardry.util.ParticleBuilder; import electroblob.wizardry.util.ParticleBuilder.Type; -import electroblob.wizardry.util.WizardryUtilities; import net.minecraft.entity.Entity; -import net.minecraft.entity.EntityLivingBase; import net.minecraft.util.math.RayTraceResult; import net.minecraft.world.World; @@ -27,13 +25,12 @@ public class EntityLightningDisc extends EntityMagicProjectile { Entity entityHit = result.entityHit; if(entityHit != null){ - float damage = 12 * damageMultiplier; - - entityHit.attackEntityFrom(MagicDamage.causeIndirectMagicDamage(this, this.getThrower(), DamageType.SHOCK), - damage); + float damage = Spells.lightning_disc.getProperty(Spell.DAMAGE).floatValue() * damageMultiplier; + entityHit.attackEntityFrom(MagicDamage.causeIndirectMagicDamage(this, this.getThrower(), + DamageType.SHOCK), damage); } - this.playSound(WizardrySounds.SPELL_SPARK, 1.0F, 1.2F / (this.rand.nextFloat() * 0.2F + 0.9F)); + this.playSound(WizardrySounds.ENTITY_LIGHTNING_DISC_HIT, 1.0F, 1.2F / (this.rand.nextFloat() * 0.2F + 0.9F)); if(result.typeOfHit == RayTraceResult.Type.BLOCK) this.setDead(); } @@ -46,47 +43,27 @@ public class EntityLightningDisc extends EntityMagicProjectile { // Particle effect if(world.isRemote){ for(int i = 0; i < 8; i++){ - // TODO: Why are the x and z parameters different? ParticleBuilder.create(Type.SPARK).pos(this.posX + rand.nextFloat() * 2 - 1, this.posY, this.posZ + rand.nextFloat() * 2 - 1).spawn(world); } } - if(!this.collided && !world.isRemote){ - - double seekingRange = 5.0d; - - List entities = WizardryUtilities.getEntitiesWithinRadius(seekingRange, this.posX, - this.posY, this.posZ, this.world); - Entity target = null; - - for(Entity possibleTarget : entities){ - // Decides if current entity should be replaced. - if(target == null || this.getDistance(target) > this.getDistance(possibleTarget)){ - // Decides if new entity is a valid target. - if(WizardryUtilities.isValidTarget(this.getThrower(), possibleTarget)){ - target = possibleTarget; - } - } - } - - if(target != null && Math.abs(this.motionX) < 1 && Math.abs(this.motionY) < 1 - && Math.abs(this.motionZ) < 1){ - this.addVelocity((target.posX - this.posX) / 30, (target.posY + target.height / 2 - this.posY) / 30, - (target.posZ - this.posZ) / 30); - } - } - - if(this.ticksExisted > 50){ - this.setDead(); - } - // Cancels out the slowdown effect in EntityThrowable this.motionX /= 0.99; this.motionY /= 0.99; this.motionZ /= 0.99; } + @Override + public float getSeekingStrength(){ + return Spells.lightning_disc.getProperty(Spell.SEEKING_STRENGTH).floatValue(); + } + + @Override + public int getLifetime(){ + return 30; + } + @Override public boolean hasNoGravity(){ return true; diff --git a/src/main/java/electroblob/wizardry/entity/projectile/EntityMagicArrow.java b/src/main/java/electroblob/wizardry/entity/projectile/EntityMagicArrow.java index 9b84d8f7..2dd166e6 100644 --- a/src/main/java/electroblob/wizardry/entity/projectile/EntityMagicArrow.java +++ b/src/main/java/electroblob/wizardry/entity/projectile/EntityMagicArrow.java @@ -1,11 +1,12 @@ package electroblob.wizardry.entity.projectile; -import java.lang.ref.WeakReference; -import java.util.List; -import java.util.UUID; - +import electroblob.wizardry.item.ItemArtefact; +import electroblob.wizardry.registry.WizardryItems; +import electroblob.wizardry.registry.WizardrySounds; +import electroblob.wizardry.util.AllyDesignationSystem; import electroblob.wizardry.util.MagicDamage; import electroblob.wizardry.util.MagicDamage.DamageType; +import electroblob.wizardry.util.RayTracer; import electroblob.wizardry.util.WizardryUtilities; import io.netty.buffer.ByteBuf; import net.minecraft.block.Block; @@ -23,22 +24,23 @@ import net.minecraft.network.play.server.SPacketChangeGameState; import net.minecraft.util.DamageSource; import net.minecraft.util.EnumParticleTypes; import net.minecraft.util.ResourceLocation; -import net.minecraft.util.math.AxisAlignedBB; -import net.minecraft.util.math.BlockPos; -import net.minecraft.util.math.MathHelper; -import net.minecraft.util.math.RayTraceResult; -import net.minecraft.util.math.Vec3d; +import net.minecraft.util.SoundCategory; +import net.minecraft.util.math.*; import net.minecraft.world.World; import net.minecraftforge.fml.common.registry.IEntityAdditionalSpawnData; import net.minecraftforge.fml.relauncher.Side; import net.minecraftforge.fml.relauncher.SideOnly; +import java.lang.ref.WeakReference; +import java.util.List; +import java.util.UUID; + /** * This class was copied from EntityArrow in the 1.7.10 update as part of the overhaul and major cleanup of the code for * the projectiles. It provides a unifying superclass for all directed projectiles (i.e. not spherical stuff like * snowballs), namely magic missile, ice shard, force arrow, lightning arrow and dart. All spherical projectiles should * extend {@link EntityMagicProjectile}. - *

    + *

    * This class handles saving of the damage multiplier and all shared logic. Methods are provided which are triggered at * useful points during the entity update cycle as well as a few getters for various properties. Override any of these * to change the behaviour (no need to call super for any of them). @@ -46,8 +48,12 @@ import net.minecraftforge.fml.relauncher.SideOnly; * @since Wizardry 1.0 * @author Electroblob */ +// TODO: Might be a good idea to have this implement IEntityOwnable as well public abstract class EntityMagicArrow extends Entity implements IProjectile, IEntityAdditionalSpawnData { + public static final double LAUNCH_Y_OFFSET = 0.1; + public static final int SEEKING_TIME = 15; + private int blockX = -1; private int blockY = -1; private int blockZ = -1; @@ -81,14 +87,14 @@ public abstract class EntityMagicArrow extends Entity implements IProjectile, IE // Initialiser methods - /** Sets the shooter of the projectile to the given caster, positions the projctile at the given caster's eyes and + /** Sets the shooter of the projectile to the given caster, positions the projectile at the given caster's eyes and * aims it in the direction they are looking with the given speed. */ public void aim(EntityLivingBase caster, float speed){ this.setCaster(caster); - this.setLocationAndAngles(caster.posX, caster.posY + (double)caster.getEyeHeight(), caster.posZ, - caster.rotationYaw, caster.rotationPitch); + this.setLocationAndAngles(caster.posX, caster.getEntityBoundingBox().minY + (double)caster.getEyeHeight() - LAUNCH_Y_OFFSET, + caster.posZ, caster.rotationYaw, caster.rotationPitch); this.posX -= (double)(MathHelper.cos(this.rotationYaw / 180.0F * (float)Math.PI) * 0.16F); this.posY -= 0.10000000149011612D; @@ -106,7 +112,7 @@ public abstract class EntityMagicArrow extends Entity implements IProjectile, IE this.shoot(this.motionX, this.motionY, this.motionZ, speed * 1.5F, 1.0F); } - /** Sets the shooter of the projectile to the given caster, positions the projctile at the given caster's eyes and + /** Sets the shooter of the projectile to the given caster, positions the projectile at the given caster's eyes and * aims it at the given target with the given speed. The trajectory will be altered slightly by a random amount * determined by the aimingError parameter. For reference, skeletons set this to 10 on easy, 6 on normal and 2 on hard * difficulty. */ @@ -114,7 +120,7 @@ public abstract class EntityMagicArrow extends Entity implements IProjectile, IE this.setCaster(caster); - this.posY = caster.posY + (double)caster.getEyeHeight() - 0.1d; + this.posY = caster.getEntityBoundingBox().minY + (double)caster.getEyeHeight() - LAUNCH_Y_OFFSET; double dx = target.posX - caster.posX; double dy = this.doGravity() ? target.getEntityBoundingBox().minY + (double)(target.height / 3.0f) - this.posY : target.getEntityBoundingBox().minY + (double)(target.height / 2.0f) - this.posY; @@ -141,6 +147,10 @@ public abstract class EntityMagicArrow extends Entity implements IProjectile, IE /** Subclasses must override this to set their own base damage. */ public abstract double getDamage(); + /** Returns the maximum flight time in ticks before this projectile disappears, or -1 if it can continue + * indefinitely until it hits something. This should be constant. */ + public abstract int getLifetime(); + /** Override this to specify the damage type dealt. Defaults to {@link DamageType#MAGIC}. */ public DamageType getDamageType(){ return DamageType.MAGIC; @@ -167,6 +177,16 @@ public abstract class EntityMagicArrow extends Entity implements IProjectile, IE return false; } + /** + * Returns the seeking strength of this projectile, or the maximum distance from a target the projectile can be + * heading for that will make it curve towards that target. By default, this is 2 if the caster is wearing a ring + * of attraction, otherwise it is 0. + */ + public float getSeekingStrength(){ + return getCaster() instanceof EntityPlayer && ItemArtefact.isArtefactActive((EntityPlayer)getCaster(), + WizardryItems.ring_seeking) ? 2 : 0; + } + // Setters and getters /** Sets the amount of knockback the projectile applies when it hits a mob. */ @@ -184,7 +204,7 @@ public abstract class EntityMagicArrow extends Entity implements IProjectile, IE } public void setCaster(EntityLivingBase entity){ - caster = new WeakReference(entity); + caster = new WeakReference<>(entity); } // Methods triggered during the update cycle @@ -211,10 +231,15 @@ public abstract class EntityMagicArrow extends Entity implements IProjectile, IE super.onUpdate(); + // Projectile disappears after its lifetime (if it has one) has elapsed + if(getLifetime() >=0 && this.ticksExisted > getLifetime()){ + this.setDead(); + } + if(this.getCaster() == null && this.casterUUID != null){ Entity entity = WizardryUtilities.getEntityByUUID(world, casterUUID); if(entity instanceof EntityLivingBase){ - this.caster = new WeakReference((EntityLivingBase)entity); + this.caster = new WeakReference<>((EntityLivingBase)entity); } } @@ -323,8 +348,7 @@ public abstract class EntityMagicArrow extends Entity implements IProjectile, IE if(this.getCaster() == null){ damagesource = DamageSource.causeThrownDamage(this, this); }else{ - damagesource = MagicDamage.causeIndirectMagicDamage(this, - (EntityLivingBase)this.getCaster(), this.getDamageType()).setProjectile(); + damagesource = MagicDamage.causeIndirectMagicDamage(this, this.getCaster(), this.getDamageType()).setProjectile(); } if(raytraceresult.entityHit.attackEntityFrom(damagesource, @@ -347,11 +371,9 @@ public abstract class EntityMagicArrow extends Entity implements IProjectile, IE } // Thorns enchantment - if(this.getCaster() != null - && this.getCaster() instanceof EntityLivingBase){ + if(this.getCaster() != null){ EnchantmentHelper.applyThornEnchantments(entityHit, this.getCaster()); - EnchantmentHelper.applyArthropodEnchantments((EntityLivingBase)this.getCaster(), - entityHit); + EnchantmentHelper.applyArthropodEnchantments(this.getCaster(), entityHit); } if(this.getCaster() != null && raytraceresult.entityHit != this.getCaster() @@ -401,6 +423,29 @@ public abstract class EntityMagicArrow extends Entity implements IProjectile, IE } } + // Seeking + if(getSeekingStrength() > 0){ + + Vec3d velocity = new Vec3d(motionX, motionY, motionZ); + + RayTraceResult hit = RayTracer.rayTrace(world, this.getPositionVector(), + this.getPositionVector().add(velocity.scale(SEEKING_TIME)), getSeekingStrength(), false, + true, false, EntityLivingBase.class, RayTracer.ignoreEntityFilter(null)); + + if(hit != null && hit.entityHit != null){ + + if(AllyDesignationSystem.isValidTarget(getCaster(), hit.entityHit)){ + + Vec3d direction = new Vec3d(hit.entityHit.posX, hit.entityHit.posY + hit.entityHit.height/2, + hit.entityHit.posZ).subtract(this.getPositionVector()).normalize().scale(velocity.length()); + + motionX = motionX + 2 * (direction.x - motionX) / SEEKING_TIME; + motionY = motionY + 2 * (direction.y - motionY) / SEEKING_TIME; + motionZ = motionZ + 2 * (direction.z - motionZ) / SEEKING_TIME; + } + } + } + this.posX += this.motionX; this.posY += this.motionY; this.posZ += this.motionZ; @@ -510,8 +555,7 @@ public abstract class EntityMagicArrow extends Entity implements IProjectile, IE tag.setShort("zTile", (short)this.blockZ); tag.setShort("life", (short)this.ticksInGround); if(this.stuckInBlock != null){ - ResourceLocation resourcelocation = (ResourceLocation)Block.REGISTRY - .getNameForObject(this.stuckInBlock.getBlock()); + ResourceLocation resourcelocation = Block.REGISTRY.getNameForObject(this.stuckInBlock.getBlock()); tag.setString("inTile", resourcelocation == null ? "" : resourcelocation.toString()); } tag.setByte("inData", (byte)this.inData); @@ -529,7 +573,7 @@ public abstract class EntityMagicArrow extends Entity implements IProjectile, IE this.blockY = tag.getShort("yTile"); this.blockZ = tag.getShort("zTile"); this.ticksInGround = tag.getShort("life"); - // Commented out for now because there's some funny stuff going on with blockstates and metadata. + // Commented out for now because there's some funny stuff going on with blockstates and id. // this.stuckInBlock = Block.getBlockById(tag.getByte("inTile") & 255); this.inData = tag.getByte("inData") & 255; this.arrowShake = tag.getByte("shake") & 255; @@ -545,7 +589,7 @@ public abstract class EntityMagicArrow extends Entity implements IProjectile, IE @Override public void readSpawnData(ByteBuf buffer){ - if(buffer.isReadable()) this.caster = new WeakReference( + if(buffer.isReadable()) this.caster = new WeakReference<>( (EntityLivingBase)this.world.getEntityByID(buffer.readInt())); } @@ -565,6 +609,11 @@ public abstract class EntityMagicArrow extends Entity implements IProjectile, IE public float getShadowSize(){ return 0.0F; } + + @Override + public SoundCategory getSoundCategory(){ + return WizardrySounds.SPELLS; + } @Override protected void entityInit(){} diff --git a/src/main/java/electroblob/wizardry/entity/projectile/EntityMagicFireball.java b/src/main/java/electroblob/wizardry/entity/projectile/EntityMagicFireball.java new file mode 100644 index 00000000..0089966a --- /dev/null +++ b/src/main/java/electroblob/wizardry/entity/projectile/EntityMagicFireball.java @@ -0,0 +1,198 @@ +package electroblob.wizardry.entity.projectile; + +import electroblob.wizardry.Wizardry; +import electroblob.wizardry.registry.Spells; +import electroblob.wizardry.spell.Spell; +import electroblob.wizardry.util.MagicDamage; +import electroblob.wizardry.util.MagicDamage.DamageType; +import electroblob.wizardry.util.ParticleBuilder; +import io.netty.buffer.ByteBuf; +import net.minecraft.entity.Entity; +import net.minecraft.entity.EntityLiving; +import net.minecraft.entity.projectile.EntitySmallFireball; +import net.minecraft.init.Blocks; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.RayTraceResult; +import net.minecraft.world.World; +import net.minecraftforge.event.entity.EntityJoinWorldEvent; +import net.minecraftforge.fml.common.Mod; +import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; + +/** + * It's a fireball - but unlike vanilla fireballs, it actually looks like a fireball, and isn't completely useless for + * attacking things (acceleration from stationary? Really, Mojang? No wonder I had so many blaze rods back in the day...) + */ +@Mod.EventBusSubscriber +public class EntityMagicFireball extends EntityMagicProjectile { + + protected static final int ACCELERATION_CONVERSION_FACTOR = 10; + + /** The damage dealt by this fireball. If this is -1, the damage for the fireball spell will be used instead; + * this is for when the fireball is not from a spell (i.e. a vanilla fireball replacement). */ + protected float damage = -1; + /** The number of seconds entities are set on fire by this fireball. If this is -1, the damage for the fireball + * spell will be used instead; this is for when the fireball is not from a spell (i.e. a vanilla fireball replacement). */ + protected int burnDuration = -1; + /** The lifetime of this fireball in ticks. This needs to be stored so that it can be changed for vanilla replacements, + * or mobs that shoot fireballs would have severely reduced range! */ + protected int lifetime = 16; + + public EntityMagicFireball(World world){ + super(world); + this.setSize(0.5f, 0.5f); + } + + public void setDamage(float damage){ + this.damage = damage; + } + + public void setBurnDuration(int burnDuration){ + this.burnDuration = burnDuration; + } + + public float getDamage(){ + // I'm lazy, I'd rather not have an entire fireball spell class just to set two fields on the entity + return damage == -1 ? Spells.fireball.getProperty(Spell.DAMAGE).floatValue() : damage; + } + + public int getBurnDuration(){ + return burnDuration == -1 ? Spells.fireball.getProperty(Spell.BURN_DURATION).intValue() : burnDuration; + } + + @Override + protected void onImpact(RayTraceResult rayTrace){ + + if(!world.isRemote){ + + Entity entityHit = rayTrace.entityHit; + + if(entityHit != null){ + + float damage = getDamage() * damageMultiplier; + + entityHit.attackEntityFrom( + MagicDamage.causeIndirectMagicDamage(this, this.getThrower(), DamageType.FIRE).setProjectile(), + damage); + + if(!MagicDamage.isEntityImmune(DamageType.FIRE, entityHit) && getBurnDuration() > 0) + entityHit.setFire(getBurnDuration()); + + }else{ + + boolean flag = true; + + if(this.getThrower() != null && this.getThrower() instanceof EntityLiving){ + flag = net.minecraftforge.event.ForgeEventFactory.getMobGriefingEvent(this.world, this.getThrower()); + } + + if(flag){ + + BlockPos blockpos = rayTrace.getBlockPos().offset(rayTrace.sideHit); + + if(this.world.isAirBlock(blockpos)){ + this.world.setBlockState(blockpos, Blocks.FIRE.getDefaultState()); + } + } + } + + //this.playSound(WizardrySounds.ENTITY_MAGIC_FIREBALL_HIT, 2, 0.8f + rand.nextFloat() * 0.3f); + + this.setDead(); + } + } + + @Override + public void onUpdate(){ + + super.onUpdate(); + + if(world.isRemote){ + + for(int i=0; i<5; i++){ + + double dx = (rand.nextDouble() - 0.5) * width; + double dy = (rand.nextDouble() - 0.5) * height + this.height/2 - 0.1; // -0.1 because flames aren't centred + double dz = (rand.nextDouble() - 0.5) * width; + double v = 0.06; + ParticleBuilder.create(ParticleBuilder.Type.MAGIC_FIRE) + .pos(this.getPositionVector().add(dx - this.motionX/2, dy, dz - this.motionZ/2)) + .vel(-v * dx, -v * dy, -v * dz).scale(width*2).time(10).spawn(world); + + if(ticksExisted > 1){ + dx = (rand.nextDouble() - 0.5) * width; + dy = (rand.nextDouble() - 0.5) * height + this.height / 2 - 0.1; + dz = (rand.nextDouble() - 0.5) * width; + ParticleBuilder.create(ParticleBuilder.Type.MAGIC_FIRE) + .pos(this.getPositionVector().add(dx - this.motionX, dy, dz - this.motionZ)) + .vel(-v * dx, -v * dy, -v * dz).scale(width*2).time(10).spawn(world); + } + } + } + } + + public void setLifetime(int lifetime){ + this.lifetime = lifetime; + } + + @Override + public int getLifetime(){ + return lifetime; + } + + @Override + public boolean hasNoGravity(){ + return true; + } + + @Override + public boolean canRenderOnFire(){ + return false; + } + + @Override + public void writeSpawnData(ByteBuf buffer){ + buffer.writeInt(lifetime); + super.writeSpawnData(buffer); + } + + @Override + public void readSpawnData(ByteBuf buffer){ + lifetime = buffer.readInt(); + super.readSpawnData(buffer); + } + + @Override + public void readEntityFromNBT(NBTTagCompound nbttagcompound){ + super.readEntityFromNBT(nbttagcompound); + lifetime = nbttagcompound.getInteger("lifetime"); + } + + @Override + public void writeEntityToNBT(NBTTagCompound nbttagcompound){ + super.writeEntityToNBT(nbttagcompound); + nbttagcompound.setInteger("lifetime", lifetime); + } + + @SubscribeEvent + public static void onEntityJoinWorldEvent(EntityJoinWorldEvent event){ + // Replaces all vanilla fireballs with wizardry ones + if(Wizardry.settings.replaceVanillaFireballs && event.getEntity() instanceof EntitySmallFireball){ + + event.setCanceled(true); + + EntityMagicFireball fireball = new EntityMagicFireball(event.getWorld()); + fireball.thrower = ((EntitySmallFireball)event.getEntity()).shootingEntity; + fireball.setPosition(event.getEntity().posX, event.getEntity().posY, event.getEntity().posZ); + fireball.setDamage(5); + fireball.setBurnDuration(5); + fireball.setLifetime(40); + + fireball.motionX = ((EntitySmallFireball)event.getEntity()).accelerationX * ACCELERATION_CONVERSION_FACTOR; + fireball.motionY = ((EntitySmallFireball)event.getEntity()).accelerationY * ACCELERATION_CONVERSION_FACTOR; + fireball.motionZ = ((EntitySmallFireball)event.getEntity()).accelerationZ * ACCELERATION_CONVERSION_FACTOR; + + event.getWorld().spawnEntity(fireball); + } + } +} diff --git a/src/main/java/electroblob/wizardry/entity/projectile/EntityMagicMissile.java b/src/main/java/electroblob/wizardry/entity/projectile/EntityMagicMissile.java index 676ba719..9649b84a 100644 --- a/src/main/java/electroblob/wizardry/entity/projectile/EntityMagicMissile.java +++ b/src/main/java/electroblob/wizardry/entity/projectile/EntityMagicMissile.java @@ -1,24 +1,25 @@ package electroblob.wizardry.entity.projectile; +import electroblob.wizardry.registry.Spells; +import electroblob.wizardry.registry.WizardrySounds; +import electroblob.wizardry.spell.Spell; import electroblob.wizardry.util.ParticleBuilder; import electroblob.wizardry.util.ParticleBuilder.Type; import net.minecraft.entity.EntityLivingBase; -import net.minecraft.init.SoundEvents; import net.minecraft.util.math.RayTraceResult; import net.minecraft.util.math.Vec3d; import net.minecraft.world.World; public class EntityMagicMissile extends EntityMagicArrow { - - /** The number of ticks the magic missile flies for before vanishing; effectively determines its range. */ - private static final int LIFETIME = 12; /** Creates a new magic missile in the given world. */ public EntityMagicMissile(World world){ super(world); } - @Override public double getDamage(){ return 4; } + @Override public double getDamage(){ return Spells.magic_missile.getProperty(Spell.DAMAGE).floatValue(); } + + @Override public int getLifetime(){ return 12; } @Override public boolean doGravity(){ return false; } @@ -26,8 +27,8 @@ public class EntityMagicMissile extends EntityMagicArrow { @Override public void onEntityHit(EntityLivingBase entityHit){ - this.playSound(SoundEvents.ENTITY_GENERIC_HURT, 1.0F, 1.2F / (this.rand.nextFloat() * 0.2F + 0.9F)); - if(this.world.isRemote) spawnImpactParticles(); + this.playSound(WizardrySounds.ENTITY_MAGIC_MISSILE_HIT, 1.0F, 1.2F / (this.rand.nextFloat() * 0.2F + 0.9F)); + if(this.world.isRemote) ParticleBuilder.create(Type.FLASH).pos(posX, posY, posZ).clr(1, 1, 0.65f).spawn(world); } @Override @@ -42,10 +43,6 @@ public class EntityMagicMissile extends EntityMagicArrow { @Override public void tickInAir(){ - if(this.ticksExisted > LIFETIME){ - this.setDead(); - } - if(this.world.isRemote){ ParticleBuilder.create(Type.SPARKLE, rand, posX, posY, posZ, 0.03, true).clr(1, 1, 0.65f).fade(0.7f, 0, 1) .time(20 + rand.nextInt(10)).spawn(world); diff --git a/src/main/java/electroblob/wizardry/entity/projectile/EntityMagicProjectile.java b/src/main/java/electroblob/wizardry/entity/projectile/EntityMagicProjectile.java index 93e5b9ef..3246d818 100644 --- a/src/main/java/electroblob/wizardry/entity/projectile/EntityMagicProjectile.java +++ b/src/main/java/electroblob/wizardry/entity/projectile/EntityMagicProjectile.java @@ -1,11 +1,20 @@ package electroblob.wizardry.entity.projectile; +import electroblob.wizardry.item.ItemArtefact; +import electroblob.wizardry.registry.WizardryItems; +import electroblob.wizardry.registry.WizardrySounds; +import electroblob.wizardry.util.AllyDesignationSystem; +import electroblob.wizardry.util.RayTracer; import io.netty.buffer.ByteBuf; import net.minecraft.entity.Entity; import net.minecraft.entity.EntityLivingBase; +import net.minecraft.entity.player.EntityPlayer; import net.minecraft.entity.projectile.EntityThrowable; import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.util.SoundCategory; import net.minecraft.util.math.MathHelper; +import net.minecraft.util.math.RayTraceResult; +import net.minecraft.util.math.Vec3d; import net.minecraft.world.World; import net.minecraftforge.fml.common.registry.IEntityAdditionalSpawnData; @@ -13,7 +22,7 @@ import net.minecraftforge.fml.common.registry.IEntityAdditionalSpawnData; * This class is a generic superclass for all non-directed projectiles, namely: darkness orb, firebolt, firebomb, * force orb, ice charge, lightning disc, poison bomb, spark, spark bomb and thunderbolt. Directed (arrow-like) * projectiles should instead extend {@link EntityMagicArrow}. - *

    + *

    * This class purely handles saving of the damage multiplier; EntityThrowable is pretty well suited to my purposes as it * is. Range is done via the velocity when the constructor is called. Caster is already handled by * EntityThrowable.getThrower(), though due to a bug in vanilla it has to be synced by this class. @@ -24,6 +33,9 @@ import net.minecraftforge.fml.common.registry.IEntityAdditionalSpawnData; */ public abstract class EntityMagicProjectile extends EntityThrowable implements IEntityAdditionalSpawnData { + public static final double LAUNCH_Y_OFFSET = 0.1; + public static final int SEEKING_TIME = 15; + public float damageMultiplier = 1.0f; /** Creates a new projectile in the given world. */ @@ -33,10 +45,10 @@ public abstract class EntityMagicProjectile extends EntityThrowable implements I // Initialiser methods - /** Sets the shooter of the projectile to the given caster, positions the projctile at the given caster's eyes and + /** Sets the shooter of the projectile to the given caster, positions the projectile at the given caster's eyes and * aims it in the direction they are looking with the given speed. */ public void aim(EntityLivingBase caster, float speed){ - this.setPosition(caster.posX, caster.posY + (double)caster.getEyeHeight() - 0.1d, caster.posZ); + this.setPosition(caster.posX, caster.getEntityBoundingBox().minY + (double)caster.getEyeHeight() - LAUNCH_Y_OFFSET, caster.posZ); // This is the standard set of parameters for this method, used by snowballs and ender pearls amongst others. this.shoot(caster, caster.rotationPitch, caster.rotationYaw, 0.0f, speed, 1.0f); this.thrower = caster; @@ -44,7 +56,7 @@ public abstract class EntityMagicProjectile extends EntityThrowable implements I this.ignoreEntity = caster; } - /** Sets the shooter of the projectile to the given caster, positions the projctile at the given caster's eyes and + /** Sets the shooter of the projectile to the given caster, positions the projectile at the given caster's eyes and * aims it at the given target with the given speed. The trajectory will be altered slightly by a random amount * determined by the aimingError parameter. For reference, skeletons set this to 10 on easy, 6 on normal and 2 on hard * difficulty. */ @@ -54,7 +66,7 @@ public abstract class EntityMagicProjectile extends EntityThrowable implements I // Mojang's 'fix' for the projectile-hitting-thrower bug actually made the problem worse, hence the following line. this.ignoreEntity = thrower; - this.posY = caster.posY + (double)caster.getEyeHeight() - 0.1d; + this.posY = caster.getEntityBoundingBox().minY + (double)caster.getEyeHeight() - LAUNCH_Y_OFFSET; double dx = target.posX - caster.posX; double dy = !this.hasNoGravity() ? target.getEntityBoundingBox().minY + (double)(target.height / 3.0f) - this.posY : target.getEntityBoundingBox().minY + (double)(target.height / 2.0f) - this.posY; @@ -75,6 +87,54 @@ public abstract class EntityMagicProjectile extends EntityThrowable implements I } } + public void setCaster(EntityLivingBase caster){ + this.thrower = caster; + this.ignoreEntity = caster; + } + + /** + * Returns the seeking strength of this projectile, or the maximum distance from a target the projectile can be + * heading for that will make it curve towards that target. By default, this is 2 if the caster is wearing a ring + * of attraction, otherwise it is 0. + */ + public float getSeekingStrength(){ + return getThrower() instanceof EntityPlayer && ItemArtefact.isArtefactActive((EntityPlayer)getThrower(), + WizardryItems.ring_seeking) ? 2 : 0; + } + + @Override + public void onUpdate(){ + + super.onUpdate(); + + if(getLifetime() >=0 && this.ticksExisted > getLifetime()){ + this.setDead(); + } + + // Seeking + if(getSeekingStrength() > 0){ + + Vec3d velocity = new Vec3d(motionX, motionY, motionZ); + + RayTraceResult hit = RayTracer.rayTrace(world, this.getPositionVector(), + this.getPositionVector().add(velocity.scale(SEEKING_TIME)), getSeekingStrength(), false, + true, false, EntityLivingBase.class, RayTracer.ignoreEntityFilter(null)); + + if(hit != null && hit.entityHit != null){ + + if(AllyDesignationSystem.isValidTarget(getThrower(), hit.entityHit)){ + + Vec3d direction = new Vec3d(hit.entityHit.posX, hit.entityHit.posY + hit.entityHit.height/2, + hit.entityHit.posZ).subtract(this.getPositionVector()).normalize().scale(velocity.length()); + + motionX = motionX + 2 * (direction.x - motionX) / SEEKING_TIME; + motionY = motionY + 2 * (direction.y - motionY) / SEEKING_TIME; + motionZ = motionZ + 2 * (direction.z - motionZ) / SEEKING_TIME; + } + } + } + } + @Override public void readEntityFromNBT(NBTTagCompound nbttagcompound){ super.readEntityFromNBT(nbttagcompound); @@ -88,20 +148,26 @@ public abstract class EntityMagicProjectile extends EntityThrowable implements I } @Override - // For now, we're only writing when the thrower exists, so subclasses MUST CALL SUPER LAST. - // TODO: Figure out whether there's a default value we can write that is never used as an entity id (0? -1? +/-MAX_VALUE?) public void writeSpawnData(ByteBuf data){ - if(this.getThrower() != null) data.writeInt(this.getThrower().getEntityId()); + data.writeInt(this.getThrower() == null ? -1 : this.getThrower().getEntityId()); } @Override - // For now, we're only writing when the thrower exists, so subclasses MUST CALL SUPER LAST. public void readSpawnData(ByteBuf data){ - if(data.isReadable()){ - Entity entity = this.world.getEntityByID(data.readInt()); - if(entity instanceof EntityLivingBase) this.thrower = (EntityLivingBase)entity; - this.ignoreEntity = this.thrower; - } + int id = data.readInt(); + if(id == -1) return; + Entity entity = this.world.getEntityByID(id); + if(entity instanceof EntityLivingBase) this.thrower = (EntityLivingBase)entity; + this.ignoreEntity = this.thrower; + } + + @Override + public SoundCategory getSoundCategory(){ + return WizardrySounds.SPELLS; } + /** Returns the maximum flight time in ticks before this projectile disappears, or -1 if it can continue + * indefinitely until it hits something. This should be constant. */ + public abstract int getLifetime(); + } diff --git a/src/main/java/electroblob/wizardry/entity/projectile/EntityPoisonBomb.java b/src/main/java/electroblob/wizardry/entity/projectile/EntityPoisonBomb.java index 5dfd2f8e..286e7259 100644 --- a/src/main/java/electroblob/wizardry/entity/projectile/EntityPoisonBomb.java +++ b/src/main/java/electroblob/wizardry/entity/projectile/EntityPoisonBomb.java @@ -1,7 +1,8 @@ package electroblob.wizardry.entity.projectile; -import java.util.List; - +import electroblob.wizardry.registry.Spells; +import electroblob.wizardry.registry.WizardrySounds; +import electroblob.wizardry.spell.Spell; import electroblob.wizardry.util.MagicDamage; import electroblob.wizardry.util.MagicDamage.DamageType; import electroblob.wizardry.util.ParticleBuilder; @@ -10,18 +11,24 @@ import electroblob.wizardry.util.WizardryUtilities; import net.minecraft.entity.Entity; import net.minecraft.entity.EntityLivingBase; import net.minecraft.init.MobEffects; -import net.minecraft.init.SoundEvents; import net.minecraft.potion.PotionEffect; import net.minecraft.util.EnumParticleTypes; import net.minecraft.util.math.RayTraceResult; import net.minecraft.world.World; +import java.util.List; + public class EntityPoisonBomb extends EntityBomb { public EntityPoisonBomb(World world){ super(world); } - + + @Override + public int getLifetime(){ + return -1; + } + @Override protected void onImpact(RayTraceResult rayTrace){ @@ -29,14 +36,16 @@ public class EntityPoisonBomb extends EntityBomb { if(entityHit != null){ // This is if the poison bomb gets a direct hit - float damage = 5 * damageMultiplier; + float damage = Spells.poison_bomb.getProperty(Spell.DIRECT_DAMAGE).floatValue() * damageMultiplier; entityHit.attackEntityFrom( MagicDamage.causeIndirectMagicDamage(this, this.getThrower(), DamageType.POISON).setProjectile(), damage); if(entityHit instanceof EntityLivingBase && !MagicDamage.isEntityImmune(DamageType.POISON, entityHit)) - ((EntityLivingBase)entityHit).addPotionEffect(new PotionEffect(MobEffects.POISON, 120, 1)); + ((EntityLivingBase)entityHit).addPotionEffect(new PotionEffect(MobEffects.POISON, + Spells.poison_bomb.getProperty(Spell.DIRECT_EFFECT_DURATION).intValue(), + Spells.poison_bomb.getProperty(Spell.DIRECT_EFFECT_STRENGTH).intValue())); } // Particle effect @@ -48,7 +57,7 @@ public class EntityPoisonBomb extends EntityBomb { for(int i = 0; i < 60 * blastMultiplier; i++){ ParticleBuilder.create(Type.SPARKLE, rand, posX, posY, posZ, 2*blastMultiplier, false).time(35) - .clr(0.2f + rand.nextFloat() * 0.3f, 0.6f, 0.0f).spawn(world); + .scale(2).clr(0.2f + rand.nextFloat() * 0.3f, 0.6f, 0.0f).spawn(world); ParticleBuilder.create(Type.DARK_MAGIC, rand, posX, posY, posZ, 2*blastMultiplier, false) .clr(0.2f + rand.nextFloat() * 0.2f, 0.8f, 0.0f).spawn(world); @@ -60,10 +69,10 @@ public class EntityPoisonBomb extends EntityBomb { if(!this.world.isRemote){ - this.playSound(SoundEvents.ENTITY_SPLASH_POTION_BREAK, 1.5F, rand.nextFloat() * 0.4F + 0.6F); - this.playSound(SoundEvents.BLOCK_FIRE_EXTINGUISH, 1.2F, 1.0f); + this.playSound(WizardrySounds.ENTITY_POISON_BOMB_SMASH, 1.5F, rand.nextFloat() * 0.4F + 0.6F); + this.playSound(WizardrySounds.ENTITY_POISON_BOMB_POISON, 1.2F, 1.0f); - double range = 3.0d * blastMultiplier; + double range = Spells.poison_bomb.getProperty(Spell.EFFECT_RADIUS).floatValue() * blastMultiplier; List targets = WizardryUtilities.getEntitiesWithinRadius(range, this.posX, this.posY, this.posZ, this.world); @@ -73,8 +82,10 @@ public class EntityPoisonBomb extends EntityBomb { && !MagicDamage.isEntityImmune(DamageType.POISON, target)){ target.attackEntityFrom( MagicDamage.causeIndirectMagicDamage(this, this.getThrower(), DamageType.POISON), - 4.0f * damageMultiplier); - target.addPotionEffect(new PotionEffect(MobEffects.POISON, 100, 1)); + Spells.poison_bomb.getProperty(Spell.SPLASH_DAMAGE).floatValue() * damageMultiplier); + target.addPotionEffect(new PotionEffect(MobEffects.POISON, + Spells.poison_bomb.getProperty(Spell.SPLASH_EFFECT_DURATION).intValue(), + Spells.poison_bomb.getProperty(Spell.SPLASH_EFFECT_STRENGTH).intValue())); } } diff --git a/src/main/java/electroblob/wizardry/entity/projectile/EntitySmokeBomb.java b/src/main/java/electroblob/wizardry/entity/projectile/EntitySmokeBomb.java index e19592a6..cbdb5315 100644 --- a/src/main/java/electroblob/wizardry/entity/projectile/EntitySmokeBomb.java +++ b/src/main/java/electroblob/wizardry/entity/projectile/EntitySmokeBomb.java @@ -1,8 +1,9 @@ package electroblob.wizardry.entity.projectile; -import java.util.List; - +import electroblob.wizardry.registry.Spells; import electroblob.wizardry.registry.WizardryPotions; +import electroblob.wizardry.registry.WizardrySounds; +import electroblob.wizardry.spell.Spell; import electroblob.wizardry.util.ParticleBuilder; import electroblob.wizardry.util.ParticleBuilder.Type; import electroblob.wizardry.util.WizardryUtilities; @@ -10,18 +11,24 @@ import net.minecraft.entity.EntityLiving; import net.minecraft.entity.EntityLivingBase; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.init.MobEffects; -import net.minecraft.init.SoundEvents; import net.minecraft.potion.PotionEffect; import net.minecraft.util.EnumParticleTypes; import net.minecraft.util.math.RayTraceResult; import net.minecraft.world.World; +import java.util.List; + public class EntitySmokeBomb extends EntityBomb { public EntitySmokeBomb(World world){ super(world); } + @Override + public int getLifetime(){ + return -1; + } + @Override protected void onImpact(RayTraceResult rayTrace){ @@ -47,25 +54,26 @@ public class EntitySmokeBomb extends EntityBomb { if(!this.world.isRemote){ - this.playSound(SoundEvents.ENTITY_SPLASH_POTION_BREAK, 1.5F, rand.nextFloat() * 0.4F + 0.6F); - this.playSound(SoundEvents.BLOCK_FIRE_EXTINGUISH, 1.2F, 1.0f); + this.playSound(WizardrySounds.ENTITY_SMOKE_BOMB_SMASH, 1.5F, rand.nextFloat() * 0.4F + 0.6F); + this.playSound(WizardrySounds.ENTITY_SMOKE_BOMB_SMOKE, 1.2F, 1.0f); - double range = 3.0d * blastMultiplier; + double range = Spells.smoke_bomb.getProperty(Spell.BLAST_RADIUS).floatValue() * blastMultiplier; List targets = WizardryUtilities.getEntitiesWithinRadius(range, this.posX, this.posY, this.posZ, this.world); + int duration = Spells.smoke_bomb.getProperty(Spell.EFFECT_DURATION).intValue(); + for(EntityLivingBase target : targets){ if(target != this.getThrower()){ // Gives the target blindness if it is a player, mind trick otherwise (since this has the desired // effect of preventing targeting) if(target instanceof EntityPlayer){ - target.addPotionEffect(new PotionEffect(MobEffects.BLINDNESS, 120, 0)); + target.addPotionEffect(new PotionEffect(MobEffects.BLINDNESS, duration, 0)); }else if(target instanceof EntityLiving){ // New AI ((EntityLiving)target).setAttackTarget(null); - - target.addPotionEffect(new PotionEffect(WizardryPotions.mind_trick, 120, 0)); + target.addPotionEffect(new PotionEffect(WizardryPotions.mind_trick, duration, 0)); } } } diff --git a/src/main/java/electroblob/wizardry/entity/projectile/EntitySpark.java b/src/main/java/electroblob/wizardry/entity/projectile/EntitySpark.java index f4aed2bc..93d1d756 100644 --- a/src/main/java/electroblob/wizardry/entity/projectile/EntitySpark.java +++ b/src/main/java/electroblob/wizardry/entity/projectile/EntitySpark.java @@ -1,15 +1,13 @@ package electroblob.wizardry.entity.projectile; -import java.util.List; - +import electroblob.wizardry.registry.Spells; import electroblob.wizardry.registry.WizardrySounds; +import electroblob.wizardry.spell.Spell; import electroblob.wizardry.util.MagicDamage; import electroblob.wizardry.util.MagicDamage.DamageType; import electroblob.wizardry.util.ParticleBuilder; import electroblob.wizardry.util.ParticleBuilder.Type; -import electroblob.wizardry.util.WizardryUtilities; import net.minecraft.entity.Entity; -import net.minecraft.entity.EntityLivingBase; import net.minecraft.util.math.RayTraceResult; import net.minecraft.world.World; @@ -26,13 +24,13 @@ public class EntitySpark extends EntityMagicProjectile { if(entityHit != null){ - float damage = 6 * damageMultiplier; - entityHit.attackEntityFrom(MagicDamage.causeIndirectMagicDamage(this, this.getThrower(), DamageType.SHOCK), - damage); + float damage = Spells.homing_spark.getProperty(Spell.DAMAGE).floatValue() * damageMultiplier; + entityHit.attackEntityFrom(MagicDamage.causeIndirectMagicDamage(this, this.getThrower(), + DamageType.SHOCK), damage); } - this.playSound(WizardrySounds.SPELL_SPARK, 1.0F, 1.2F / (this.rand.nextFloat() * 0.2F + 0.9F)); + this.playSound(WizardrySounds.ENTITY_HOMING_SPARK_HIT, 1.0F, 1.2F / (this.rand.nextFloat() * 0.2F + 0.9F)); // Particle effect if(world.isRemote){ @@ -47,40 +45,16 @@ public class EntitySpark extends EntityMagicProjectile { this.setDead(); } - public void onUpdate(){ - - super.onUpdate(); - - if(!this.collided && !world.isRemote){ - - double seekingRange = 5.0d; - - List entities = WizardryUtilities.getEntitiesWithinRadius(seekingRange, this.posX, - this.posY, this.posZ, this.world); - Entity target = null; - - for(Entity possibleTarget : entities){ - // Decides if current entity should be replaced. - if(target == null || this.getDistance(target) > this.getDistance(possibleTarget)){ - // Decides if new entity is a valid target. - if(WizardryUtilities.isValidTarget(this.getThrower(), possibleTarget)){ - target = possibleTarget; - } - } - } - - if(target != null && Math.abs(this.motionX) < 1 && Math.abs(this.motionY) < 1 - && Math.abs(this.motionZ) < 1){ - this.addVelocity((target.posX - this.posX) / 30, (target.posY + target.height / 2 - this.posY) / 30, - (target.posZ - this.posZ) / 30); - } - } - - if(this.ticksExisted > 100){ - this.setDead(); - } + @Override + public float getSeekingStrength(){ + return Spells.homing_spark.getProperty(Spell.SEEKING_STRENGTH).floatValue(); } - + + @Override + public int getLifetime(){ + return 50; + } + @Override public boolean hasNoGravity(){ return true; diff --git a/src/main/java/electroblob/wizardry/entity/projectile/EntitySparkBomb.java b/src/main/java/electroblob/wizardry/entity/projectile/EntitySparkBomb.java index 28ddbf8a..721a06a2 100644 --- a/src/main/java/electroblob/wizardry/entity/projectile/EntitySparkBomb.java +++ b/src/main/java/electroblob/wizardry/entity/projectile/EntitySparkBomb.java @@ -1,8 +1,8 @@ package electroblob.wizardry.entity.projectile; -import java.util.List; - +import electroblob.wizardry.registry.Spells; import electroblob.wizardry.registry.WizardrySounds; +import electroblob.wizardry.spell.Spell; import electroblob.wizardry.util.MagicDamage; import electroblob.wizardry.util.MagicDamage.DamageType; import electroblob.wizardry.util.ParticleBuilder; @@ -11,28 +11,36 @@ import electroblob.wizardry.util.WizardryUtilities; import net.minecraft.entity.Entity; import net.minecraft.entity.EntityLivingBase; import net.minecraft.entity.player.EntityPlayer; -import net.minecraft.init.SoundEvents; import net.minecraft.util.math.RayTraceResult; import net.minecraft.world.World; +import java.util.List; + public class EntitySparkBomb extends EntityBomb { + public static final String SECONDARY_MAX_TARGETS = "secondary_max_targets"; + public EntitySparkBomb(World world){ super(world); } + @Override + public int getLifetime(){ + return -1; + } + @Override protected void onImpact(RayTraceResult rayTrace){ - this.playSound(SoundEvents.ENTITY_FIREWORK_BLAST_FAR, 0.5f, 0.5f); + this.playSound(WizardrySounds.ENTITY_SPARK_BOMB_HIT_BLOCK, 0.5f, 0.5f); Entity entityHit = rayTrace.entityHit; if(entityHit != null){ // This is if the spark bomb gets a direct hit - float damage = 6 * damageMultiplier; + float damage = Spells.spark_bomb.getProperty(Spell.DIRECT_DAMAGE).floatValue() * damageMultiplier; - this.playSound(SoundEvents.ENTITY_GENERIC_HURT, 1.0F, 1.2F / (this.rand.nextFloat() * 0.2F + 0.9F)); + this.playSound(WizardrySounds.ENTITY_SPARK_BOMB_HIT, 1.0F, 1.2F / (this.rand.nextFloat() * 0.2F + 0.9F)); entityHit.attackEntityFrom( MagicDamage.causeIndirectMagicDamage(this, this.getThrower(), DamageType.SHOCK).setProjectile(), @@ -45,19 +53,19 @@ public class EntitySparkBomb extends EntityBomb { ParticleBuilder.spawnShockParticles(world, posX, posY + height/2, posZ); } - double seekerRange = 5.0d * blastMultiplier; + double seekerRange = Spells.spark_bomb.getProperty(Spell.EFFECT_RADIUS).doubleValue() * blastMultiplier; List targets = WizardryUtilities.getEntitiesWithinRadius(seekerRange, this.posX, this.posY, this.posZ, this.world); - for(int i = 0; i < Math.min(targets.size(), 4); i++){ + for(int i = 0; i < Math.min(targets.size(), Spells.spark_bomb.getProperty(SECONDARY_MAX_TARGETS).intValue()); i++){ boolean flag = targets.get(i) != entityHit && targets.get(i) != this.getThrower() && !(targets.get(i) instanceof EntityPlayer - && ((EntityPlayer)targets.get(i)).capabilities.isCreativeMode); + && ((EntityPlayer)targets.get(i)).isCreative()); // Detects (client side) if target is the thrower, to stop particles being spawned around them. - //if(flag && world.isRemote && targets.get(i).getEntityId() == this.casterID) flag = false; + //if(flag && world.isRemote && targets.get(i).getEntityId() == this.playerID) flag = false; if(flag){ @@ -69,7 +77,7 @@ public class EntitySparkBomb extends EntityBomb { target.attackEntityFrom( MagicDamage.causeIndirectMagicDamage(this, this.getThrower(), DamageType.SHOCK), - 5.0f * damageMultiplier); + Spells.spark_bomb.getProperty(Spell.SPLASH_DAMAGE).floatValue() * damageMultiplier); }else{ ParticleBuilder.create(Type.LIGHTNING).pos(this.getPositionVector()).target(target).spawn(world); diff --git a/src/main/java/electroblob/wizardry/entity/projectile/EntityThunderbolt.java b/src/main/java/electroblob/wizardry/entity/projectile/EntityThunderbolt.java index 7508b150..48e90dd8 100644 --- a/src/main/java/electroblob/wizardry/entity/projectile/EntityThunderbolt.java +++ b/src/main/java/electroblob/wizardry/entity/projectile/EntityThunderbolt.java @@ -1,17 +1,21 @@ package electroblob.wizardry.entity.projectile; +import electroblob.wizardry.registry.Spells; +import electroblob.wizardry.registry.WizardrySounds; +import electroblob.wizardry.spell.Spell; import electroblob.wizardry.util.MagicDamage; import electroblob.wizardry.util.MagicDamage.DamageType; import electroblob.wizardry.util.ParticleBuilder; import electroblob.wizardry.util.ParticleBuilder.Type; import net.minecraft.entity.Entity; -import net.minecraft.init.SoundEvents; import net.minecraft.util.EnumParticleTypes; import net.minecraft.util.math.RayTraceResult; import net.minecraft.world.World; public class EntityThunderbolt extends EntityMagicProjectile { + public static final String KNOCKBACK_STRENGTH = "knockback_strength"; + public EntityThunderbolt(World par1World){ super(par1World); } @@ -27,17 +31,19 @@ public class EntityThunderbolt extends EntityMagicProjectile { if(entityHit != null){ - float damage = 3 * damageMultiplier; + float damage = Spells.thunderbolt.getProperty(Spell.DAMAGE).floatValue() * damageMultiplier; entityHit.attackEntityFrom( MagicDamage.causeIndirectMagicDamage(this, this.getThrower(), DamageType.SHOCK).setProjectile(), damage); + float knockbackStrength = Spells.thunderbolt.getProperty(KNOCKBACK_STRENGTH).floatValue(); + // Knockback - entityHit.addVelocity(this.motionX * 0.2, this.motionY * 0.2, this.motionZ * 0.2); + entityHit.addVelocity(this.motionX * knockbackStrength, this.motionY * knockbackStrength, this.motionZ * knockbackStrength); } - this.playSound(SoundEvents.ENTITY_FIREWORK_LARGE_BLAST, 1.4F, 0.5f + this.rand.nextFloat() * 0.1F); + this.playSound(WizardrySounds.ENTITY_THUNDERBOLT_HIT, 1.4F, 0.5f + this.rand.nextFloat() * 0.1F); // Particle effect if(world.isRemote){ @@ -60,10 +66,11 @@ public class EntityThunderbolt extends EntityMagicProjectile { this.posZ + rand.nextFloat() * 0.2 - 0.1, 0, 0, 0); } } - - if(this.ticksExisted > 8){ - this.setDead(); - } } - + + @Override + public int getLifetime(){ + return 8; + } + } diff --git a/src/main/java/electroblob/wizardry/event/DiscoverSpellEvent.java b/src/main/java/electroblob/wizardry/event/DiscoverSpellEvent.java index 8e22c499..79fb9916 100644 --- a/src/main/java/electroblob/wizardry/event/DiscoverSpellEvent.java +++ b/src/main/java/electroblob/wizardry/event/DiscoverSpellEvent.java @@ -6,6 +6,8 @@ import net.minecraftforge.common.MinecraftForge; import net.minecraftforge.event.entity.player.PlayerEvent; import net.minecraftforge.fml.common.eventhandler.Cancelable; +import javax.annotation.Nullable; + /** * DiscoverSpellEvent is fired when a player discovers a spell by any method.
    *
    @@ -41,13 +43,30 @@ public class DiscoverSpellEvent extends PlayerEvent { public enum Source { /** Signifies that the spell was discovered by trying to cast it. */ - CASTING, + CASTING("casting"), /** Signifies that the spell was discovered using a scroll of identification. */ - IDENTIFICATION_SCROLL, + IDENTIFICATION_SCROLL("identification_scroll"), /** Signifies that the spell was discovered using commands. */ - COMMAND, + COMMAND("command"), + /** Signifies that the spell was discovered by purchasing it from a wizard. */ + PURCHASE("purchase"), /** Signifies that the spell was discovered by some other means. */ - OTHER + OTHER("other"); + + String name; + + Source(String name){ + this.name = name; + } + + /** Returns the spell discovery source with the given name, or null if no such source exists. */ + @Nullable + public static Source byName(String name){ + for(Source source : values()){ + if(source.name.equals(name)) return source; + } + return null; + } } } \ No newline at end of file diff --git a/src/main/java/electroblob/wizardry/event/SpellCastEvent.java b/src/main/java/electroblob/wizardry/event/SpellCastEvent.java index 3cd0a88e..ec471598 100644 --- a/src/main/java/electroblob/wizardry/event/SpellCastEvent.java +++ b/src/main/java/electroblob/wizardry/event/SpellCastEvent.java @@ -1,34 +1,71 @@ package electroblob.wizardry.event; +import electroblob.wizardry.data.WizardData; import electroblob.wizardry.entity.living.ISpellCaster; import electroblob.wizardry.spell.Spell; import electroblob.wizardry.util.SpellModifiers; import net.minecraft.entity.EntityLivingBase; +import net.minecraft.util.EnumFacing; +import net.minecraft.world.World; import net.minecraftforge.common.MinecraftForge; -import net.minecraftforge.event.entity.living.LivingEvent; import net.minecraftforge.fml.common.eventhandler.Cancelable; +import net.minecraftforge.fml.common.eventhandler.Event; + +import javax.annotation.Nullable; /** * SpellCastEvent is the parent event class for all spell casting events. Methods which subscribe to this event will - * receive all three child events (it is recommended that you use {@link SpellCastEvent.Pre}, - * {@link SpellCastEvent.Post} or {@link SpellCastEvent.Tick}, depending on the application).
    + * receive all four child events (it is recommended that you use {@link SpellCastEvent.Pre}, + * {@link SpellCastEvent.Post}, {@link SpellCastEvent.Tick} or {@link SpellCastEvent.Finish}, depending on the application).
    *
    + * A note about spell modifiers: As of Wizardry 4.2, item-based spell casting has been reorganised, a notable change + * being that spell modifiers are no longer recalculated each tick for continuous spells. Instead, spell modifiers + * are stored in {@link WizardData WizardData} at the start (after {@code SpellCastEvent.Pre}) + * and simply passed in each tick. This means the {@code SpellModifiers} object received by {@code SpellCastEvent.Tick} + * contains those modified values, and any changes made to them will not persist between ticks. + *

    + * This means that where before you had to change the modifiers in {@code Pre} and {@code Tick}, you now only + * need to change them in {@code Pre} unless you want them to change partway through casting.
    + *

    * This event is fired on the {@link MinecraftForge#EVENT_BUS}. * * @author Electroblob * @since Wizardry 2.1 */ -public abstract class SpellCastEvent extends LivingEvent { +public abstract class SpellCastEvent extends Event { private final Spell spell; private final SpellModifiers modifiers; private final Source source; + private final EntityLivingBase caster; + private final World world; + private final double x, y, z; + private final EnumFacing direction; - public SpellCastEvent(EntityLivingBase caster, Spell spell, SpellModifiers modifiers, Source source){ - super(caster); + public SpellCastEvent(Source source, Spell spell, EntityLivingBase caster, SpellModifiers modifiers){ + super(); this.spell = spell; this.modifiers = modifiers; this.source = source; + this.caster = caster; + this.world = caster.world; // World is required for the position-based casting, but we may as well set it here + this.x = Double.NaN; // Better to use NaN than some arbitrary number, because NaN will throw an exception when + this.y = Double.NaN; // someone tries to operate on it whereas 0, for example, will likely just cause strange + this.z = Double.NaN; // behaviour - the cause of which may not be immediately obvious. + this.direction = null; + } + + public SpellCastEvent(Source source, Spell spell, World world, double x, double y, double z, EnumFacing direction, SpellModifiers modifiers){ + super(); + this.spell = spell; + this.modifiers = modifiers; + this.source = source; + this.caster = null; + this.world = world; + this.x = x; + this.y = y; + this.z = z; + this.direction = direction; } /** Returns the spell being cast. */ @@ -45,6 +82,39 @@ public abstract class SpellCastEvent extends LivingEvent { public Source getSource(){ return source; } + + /** Returns the entity that cast this spell, or null if it was cast from a dispenser or a command with coordinates. */ + @Nullable + public EntityLivingBase getCaster(){ + return caster; + } + + /** Returns the world in which this spell was cast. If the spell was cast by an entity, this is equivalent to + * {@code getCaster().world}. */ + public World getWorld(){ + return world; + } + + /** Returns the x coordinate at which this spell was cast, or NaN if the spell was not cast from a position. */ + public double getX(){ + return x; + } + + /** Returns the y coordinate at which this spell was cast, or NaN if the spell was not cast from a position. */ + public double getY(){ + return y; + } + + /** Returns the z coordinate at which this spell was cast, or NaN if the spell was not cast from a position. */ + public double getZ(){ + return z; + } + + /** Returns the direction in which this spell was cast, or null if the spell was not cast from a position. */ + @Nullable + public EnumFacing getDirection(){ + return direction; + } public enum Source { /** Signifies that the spell was cast using a wand. */ @@ -55,6 +125,8 @@ public abstract class SpellCastEvent extends LivingEvent { COMMAND, /** Signifies that the spell was cast by an {@link ISpellCaster}. */ NPC, + /** Signifies that the spell was cast from a dispenser. */ + DISPENSER, /** Signifies that the spell was cast by some other means. */ OTHER } @@ -70,6 +142,13 @@ public abstract class SpellCastEvent extends LivingEvent { * right-click action that caused it (if any) returns a result of FAIL, meaning that the right-click is passed to * the block/entity in front of the player, if any.
    *
    + * Priority convention for {@code SpellCastEvent.Pre}:
    + * {@code HIGHEST} - General spell prevention e.g. arcane jammer
    + * {@code HIGH} - Specific spell prevention e.g. spells disabled in config/JSONs
    + * {@code NORMAL} - Everything else e.g. forfeits
    + * {@code LOW} - Changes to modifiers e.g. from potion effects
    + * {@code LOWEST} - Anything that requires modifiers to be at their final values, unused in wizardry
    + *
    * This event does not have a result. {@link HasResult}
    *
    * This event is fired on the {@link MinecraftForge#EVENT_BUS}. @@ -80,10 +159,13 @@ public abstract class SpellCastEvent extends LivingEvent { @Cancelable public static class Pre extends SpellCastEvent { - public Pre(EntityLivingBase caster, Spell spell, SpellModifiers modifiers, Source source){ - super(caster, spell, modifiers, source); + public Pre(Source source, Spell spell, EntityLivingBase caster, SpellModifiers modifiers){ + super(source, spell, caster, modifiers); + } + + public Pre(Source source, Spell spell, World world, double x, double y, double z, EnumFacing direction, SpellModifiers modifiers){ + super(source, spell, world, x, y, z, direction, modifiers); } - } /** @@ -91,7 +173,8 @@ public abstract class SpellCastEvent extends LivingEvent { * whether the spell succeeds, and does not affect the spell itself. For example, wizardry uses this event to keep * track of spellcasting stats. Note that although this event is fired from both sides, it is not fired from common * code; rather, both sides fire it separately, so timing is not guaranteed. Also note that this event is only fired - * once for continuous spells, after the first casting tick.
    + * once for continuous spells, after the first casting tick. Changing the modifiers within this event will likely + * have no effect, with the exception of cooldown modifiers.
    *
    * This event is not {@link Cancelable}.
    *
    @@ -104,8 +187,12 @@ public abstract class SpellCastEvent extends LivingEvent { */ public static class Post extends SpellCastEvent { - public Post(EntityLivingBase caster, Spell spell, SpellModifiers modifiers, Source source){ - super(caster, spell, modifiers, source); + public Post(Source source, Spell spell, EntityLivingBase caster, SpellModifiers modifiers){ + super(source, spell, caster, modifiers); + } + + public Post(Source source, Spell spell, World world, double x, double y, double z, EnumFacing direction, SpellModifiers modifiers){ + super(source, spell, world, x, y, z, direction, modifiers); } } @@ -114,8 +201,9 @@ public abstract class SpellCastEvent extends LivingEvent { * SpellCastEvent.Tick is fired each tick while a continuous spell is being cast.
    *
    * This event is {@link Cancelable}. If this event is canceled, the spell is not cast, mana is not consumed, and the - * spell casting is interrupted. Cancelling this event on the client side will stop particles being spawned, but - * will not interrupt spell casting.
    + * spell casting is interrupted. Cancelling this event on the client side only will stop particles being spawned, but + * will not interrupt spell casting. Cancelling this event on the server side only may have different results + * depending on the source of the spell; as such it is recommended that this event is cancelled on both sides.
    *
    * This event does not have a result. {@link HasResult}
    *
    @@ -129,8 +217,13 @@ public abstract class SpellCastEvent extends LivingEvent { private final int count; - public Tick(EntityLivingBase caster, Spell spell, SpellModifiers modifiers, Source source, int count){ - super(caster, spell, modifiers, source); + public Tick(Source source, Spell spell, EntityLivingBase caster, SpellModifiers modifiers, int count){ + super(source, spell, caster, modifiers); + this.count = count; + } + + public Tick(Source source, Spell spell, World world, double x, double y, double z, EnumFacing direction, SpellModifiers modifiers, int count){ + super(source, spell, world, x, y, z, direction, modifiers); this.count = count; } @@ -141,4 +234,39 @@ public abstract class SpellCastEvent extends LivingEvent { } + /** + * SpellCastEvent.Finish is fired just after a continuous spell stops being cast. Use this event for anything + * that needs to know the total time for which a continuous spell has been cast, or should only happen when the + * spell finishes (as opposed to just after it starts, as in {@link Post}).
    + *
    + * This event is not {@link Cancelable}.
    + *
    + * This event does not have a result. {@link HasResult}
    + *
    + * This event is fired on the {@link MinecraftForge#EVENT_BUS}. + * + * @author Electroblob + * @since Wizardry 2.1 + */ + public static class Finish extends SpellCastEvent { + + private final int count; + + public Finish(Source source, Spell spell, EntityLivingBase caster, SpellModifiers modifiers, int count){ + super(source, spell, caster, modifiers); + this.count = count; + } + + public Finish(Source source, Spell spell, World world, double x, double y, double z, EnumFacing direction, SpellModifiers modifiers, int count){ + super(source, spell, world, x, y, z, direction, modifiers); + this.count = count; + } + + /** Returns the total number of ticks this (continuous) spell was cast for. */ + public int getCount(){ + return count; + } + + } + } diff --git a/src/main/java/electroblob/wizardry/integration/DamageSafetyChecker.java b/src/main/java/electroblob/wizardry/integration/DamageSafetyChecker.java index cb3ea34b..2bbfb421 100644 --- a/src/main/java/electroblob/wizardry/integration/DamageSafetyChecker.java +++ b/src/main/java/electroblob/wizardry/integration/DamageSafetyChecker.java @@ -57,8 +57,8 @@ public final class DamageSafetyChecker { * This allows wizardry to request that users add it to the blacklist. * @param fallback The fallback damage source for when excessive looping is detected. This must not be the * same as the re-applied source, or this method is pointless! Usually it will be more general. - * @param knockback True to apply knockback as normal, false to use the knockback-free methods in WizardryUtilities. - * {@link WizardryUtilities#attackEntityWithoutKnockback(Entity, DamageSource, float)}. + * @param knockback True to apply knockback as normal, false to use the knockback-free methods in WizardryUtilities + * (see {@link WizardryUtilities#attackEntityWithoutKnockback(Entity, DamageSource, float)}). */ public static boolean attackEntitySafely(Entity target, DamageSource source, float damage, String originalSourceName, DamageSource fallback, boolean knockback){ @@ -67,6 +67,7 @@ public final class DamageSafetyChecker { if(originalSourceName.equals(sourceName)){ // Blacklist behaviour // Same as fallback behaviour, but without the log message + // No harm in still incrementing the counter attacksThisTick++; return knockback ? target.attackEntityFrom(fallback, damage) : WizardryUtilities.attackEntityWithoutKnockback(target, fallback, damage); @@ -99,8 +100,9 @@ public final class DamageSafetyChecker { /** * See {@link DamageSafetyChecker#attackEntitySafely(Entity, DamageSource, float, String, DamageSource, boolean)}. - * This version is for when the original source is used as a fallback, i.e. when a damage source is being replaced - * for technical reasons (e.g. summoned creatures) rather than as part of a game mechanic (e.g. shadow ward). + * This version is for when the source being replaced is used as a fallback, i.e. when a damage source is being + * replaced for technical reasons (e.g. summoned creatures) rather than as part of a game mechanic (e.g. shadow ward). + * This means that if excessive looping is detected, the code will work as if the event was never intercepted. */ public static boolean attackEntitySafely(Entity target, DamageSource source, float damage, DamageSource originalSource, boolean knockback){ return attackEntitySafely(target, source, damage, originalSource.getDamageType(), originalSource, knockback); @@ -122,9 +124,9 @@ public final class DamageSafetyChecker { boolean vanillaName = VANILLA_DAMAGE_NAMES.contains(originalSourceName); if(aborted){ - Wizardry.logger.warn("Entity attack excessive call limit exceeded, aborting entity damage entirely!"); + Wizardry.logger.warn("SoundLoopSpellEntity attack excessive call limit reached, aborting entity damage entirely!"); }else{ - Wizardry.logger.warn("Entity attack excessive call threshold exceeded, substituting for non-entity-based " + + Wizardry.logger.warn("SoundLoopSpellEntity attack excessive call threshold reached, substituting for non-entity-based " + "damage to avert a crash."); } diff --git a/src/main/java/electroblob/wizardry/integration/antiqueatlas/WizardryAntiqueAtlasIntegration.java b/src/main/java/electroblob/wizardry/integration/antiqueatlas/WizardryAntiqueAtlasIntegration.java new file mode 100644 index 00000000..8fb48157 --- /dev/null +++ b/src/main/java/electroblob/wizardry/integration/antiqueatlas/WizardryAntiqueAtlasIntegration.java @@ -0,0 +1,71 @@ +package electroblob.wizardry.integration.antiqueatlas; + +import electroblob.wizardry.Wizardry; +import hunternif.mc.atlas.api.AtlasAPI; +import hunternif.mc.atlas.registry.MarkerType; +import net.minecraft.util.ResourceLocation; +import net.minecraft.world.World; +import net.minecraftforge.fml.common.Loader; + +/** + * This class handles all of wizardry's integration with the Antique Atlas mod. This class contains only the code + * that requires Antique Atlas to be loaded in order to run. Conversely, all code that requires Antique Atlas to be + * loaded is located within this class or another class in the package {@code electroblob.wizardry.integration.antiqueatlas}. + * + * @since Wizardry 4.2 + * @author Electroblob + */ +public class WizardryAntiqueAtlasIntegration { + + public static final String ANTIQUE_ATLAS_MOD_ID = "antiqueatlas"; + + private static final ResourceLocation TOWER_MARKER = new ResourceLocation(Wizardry.MODID, "wizard_tower"); + private static final ResourceLocation SHRINE_MARKER = new ResourceLocation(Wizardry.MODID, "shrine"); + private static final ResourceLocation OBELISK_MARKER = new ResourceLocation(Wizardry.MODID, "obelisk"); + + private static boolean antiqueAtlasLoaded; + + public static void init(){ + antiqueAtlasLoaded = Loader.isModLoaded(ANTIQUE_ATLAS_MOD_ID); + Wizardry.proxy.registerAtlasMarkers(); // Needs routing through the proxies to make sure it's only client-side + } + + public static boolean enabled(){ + return Wizardry.settings.antiqueAtlasIntegration && antiqueAtlasLoaded; + } + + /** Places a global wizard tower marker in all antique atlases at the given coordinates in the given world if + * {@link electroblob.wizardry.Settings#autoTowerMarkers} is enabled. Server side only! */ + public static void markTower(World world, int x, int z){ + if(enabled() && Wizardry.settings.autoTowerMarkers){ + AtlasAPI.getMarkerAPI().putGlobalMarker(world, false, TOWER_MARKER.toString(), "integration.antiqueatlas.marker." + TOWER_MARKER.toString(), x, z); + } + } + + /** Places a global obelisk marker in all antique atlases at the given coordinates in the given world if + * {@link electroblob.wizardry.Settings#autoObeliskMarkers} is enabled. Server side only! */ + public static void markObelisk(World world, int x, int z){ + if(enabled() && Wizardry.settings.autoObeliskMarkers){ + AtlasAPI.getMarkerAPI().putGlobalMarker(world, false, OBELISK_MARKER.toString(), "integration.antiqueatlas.marker." + OBELISK_MARKER.toString(), x, z); + } + } + + /** Places a global shrine marker in all antique atlases at the given coordinates in the given world if + * {@link electroblob.wizardry.Settings#autoShrineMarkers} is enabled. Server side only! */ + public static void markShrine(World world, int x, int z){ + if(enabled() && Wizardry.settings.autoShrineMarkers){ + AtlasAPI.getMarkerAPI().putGlobalMarker(world, false, SHRINE_MARKER.toString(), "integration.antiqueatlas.marker." + SHRINE_MARKER.toString(), x, z); + } + } + + /** Registers the marker icons with Antique Atlas. Client side only! */ + public static void registerMarkers(){ + + if(!enabled()) return; + + AtlasAPI.getMarkerAPI().registerMarker(new MarkerType(TOWER_MARKER, new ResourceLocation(Wizardry.MODID, "textures/integration/antiqueatlas/wizard_tower.png"))); + AtlasAPI.getMarkerAPI().registerMarker(new MarkerType(SHRINE_MARKER, new ResourceLocation(Wizardry.MODID, "textures/integration/antiqueatlas/shrine.png"))); + AtlasAPI.getMarkerAPI().registerMarker(new MarkerType(OBELISK_MARKER, new ResourceLocation(Wizardry.MODID, "textures/integration/antiqueatlas/obelisk.png"))); + } + +} diff --git a/src/main/java/electroblob/wizardry/integration/baubles/WizardryBaublesIntegration.java b/src/main/java/electroblob/wizardry/integration/baubles/WizardryBaublesIntegration.java new file mode 100644 index 00000000..11f56ce2 --- /dev/null +++ b/src/main/java/electroblob/wizardry/integration/baubles/WizardryBaublesIntegration.java @@ -0,0 +1,110 @@ +package electroblob.wizardry.integration.baubles; + +import baubles.api.BaubleType; +import baubles.api.BaublesApi; +import baubles.api.IBauble; +import baubles.api.cap.BaublesCapabilities; +import electroblob.wizardry.Wizardry; +import electroblob.wizardry.item.ItemArtefact; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.item.Item; +import net.minecraft.item.ItemStack; +import net.minecraft.util.EnumFacing; +import net.minecraftforge.common.capabilities.Capability; +import net.minecraftforge.common.capabilities.ICapabilityProvider; +import net.minecraftforge.fml.common.Loader; + +import javax.annotation.Nonnull; +import javax.annotation.Nullable; +import java.util.ArrayList; +import java.util.EnumMap; +import java.util.List; +import java.util.Map; + +/** + * This class handles all of wizardry's integration with the Baubles mod. This class contains only the code + * that requires Baubles to be loaded in order to run. Conversely, all code that requires Baubles to be loaded is + * located within this class or another class in the package {@code electroblob.wizardry.integration.baubles}. + * + * @since Wizardry 4.2 + * @author Electroblob + */ +public final class WizardryBaublesIntegration { + + public static final String BAUBLES_MOD_ID = "baubles"; + + private static final Map ARTEFACT_TYPE_MAP = new EnumMap<>(ItemArtefact.Type.class); + + private static boolean baublesLoaded; + + public static void init(){ + + baublesLoaded = Loader.isModLoaded(BAUBLES_MOD_ID); + + if(!enabled()) return; + + ARTEFACT_TYPE_MAP.put(ItemArtefact.Type.RING, BaubleType.RING); + ARTEFACT_TYPE_MAP.put(ItemArtefact.Type.AMULET, BaubleType.AMULET); + ARTEFACT_TYPE_MAP.put(ItemArtefact.Type.CHARM, BaubleType.CHARM); + } + + public static boolean enabled(){ + return Wizardry.settings.baublesIntegration && baublesLoaded; + } + + // Wrappers for BaublesApi methods + + /** + * Return true if the given item is equipped in any bauble slot. + * @param player The player whose inventory is to be checked. + * @param item The item to check for. + * @return True if the given item is equipped in a bauble slot, false otherwise. + */ + public static boolean isBaubleEquipped(EntityPlayer player, Item item){ + return BaublesApi.isBaubleEquipped(player, item) >= 0; + } + + /** + * Returns a list of artefact stacks equipped of the given types. + * @param player The player whose inventory is to be checked. + * @param types Zero or more artefact types to check for. If omitted, searches for all types. + * @return A list of equipped artefact {@code ItemStacks}. + */ + // This could return all ItemStacks, but if an artefact type is given this doesn't really make sense. + public static List getEquippedArtefacts(EntityPlayer player, ItemArtefact.Type... types){ + + List artefacts = new ArrayList<>(); + + for(ItemArtefact.Type type : types){ + for(int slot : ARTEFACT_TYPE_MAP.get(type).getValidSlots()){ + ItemStack stack = BaublesApi.getBaublesHandler(player).getStackInSlot(slot); + if(stack.getItem() instanceof ItemArtefact) artefacts.add((ItemArtefact)stack.getItem()); + } + } + + return artefacts; + } + + // Shamelessly copied from The Twilight Forest, with a few modifications + @SuppressWarnings("unchecked") + public static final class ArtefactBaubleProvider implements ICapabilityProvider { + + private BaubleType type; + + public ArtefactBaubleProvider(ItemArtefact.Type type){ + this.type = ARTEFACT_TYPE_MAP.get(type); + } + + @Override + public boolean hasCapability(@Nonnull Capability capability, @Nullable EnumFacing facing){ + return capability == BaublesCapabilities.CAPABILITY_ITEM_BAUBLE; + } + + @Override + public T getCapability(@Nonnull Capability capability, @Nullable EnumFacing facing){ + // This lambda expression is an implementation of the entire IBauble interface + return capability == BaublesCapabilities.CAPABILITY_ITEM_BAUBLE ? (T)(IBauble)itemStack -> type : null; + } + } + +} diff --git a/src/main/java/electroblob/wizardry/item/IConjuredItem.java b/src/main/java/electroblob/wizardry/item/IConjuredItem.java index 1ab78fe2..eadfe591 100644 --- a/src/main/java/electroblob/wizardry/item/IConjuredItem.java +++ b/src/main/java/electroblob/wizardry/item/IConjuredItem.java @@ -1,59 +1,118 @@ package electroblob.wizardry.item; +import electroblob.wizardry.spell.Spell; +import electroblob.wizardry.spell.SpellConjuration; +import net.minecraft.entity.EntityLivingBase; import net.minecraft.entity.item.EntityItem; +import net.minecraft.item.IItemPropertyGetter; import net.minecraft.item.Item; import net.minecraft.item.ItemStack; import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.util.ResourceLocation; +import net.minecraft.world.World; import net.minecraftforge.event.entity.item.ItemTossEvent; import net.minecraftforge.event.entity.living.LivingDropsEvent; import net.minecraftforge.fml.common.Mod; import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; +import net.minecraftforge.fml.relauncher.Side; +import net.minecraftforge.fml.relauncher.SideOnly; + +import javax.annotation.Nullable; +import java.util.UUID; /** * Allows wizardry to identify items that are conjured (and therefore need destroying if they leave the inventory) - * without explicitly referencing each, thereby allowing for better expandibility. + * without explicitly referencing each, thereby allowing for better expandability. */ @Mod.EventBusSubscriber public interface IConjuredItem { /** The NBT tag key used to store the duration multiplier for conjured items. */ - public static final String DURATION_MULTIPLIER_KEY = "durationMultiplier"; + String DURATION_MULTIPLIER_KEY = "durationMultiplier"; + /** The NBT tag key used to store the damage multiplier for conjured items. */ + String DAMAGE_MULTIPLIER = "damageMultiplier"; + + UUID POTENCY_MODIFIER = UUID.fromString("da067ea6-0b35-4140-8436-5476224de9dd"); /** Helper method for setting the duration multiplier (via NBT) for conjured items. */ - public static void setDurationMultiplier(ItemStack stack, float multiplier){ + static void setDurationMultiplier(ItemStack stack, float multiplier){ if(!stack.hasTagCompound()) stack.setTagCompound(new NBTTagCompound()); stack.getTagCompound().setFloat(DURATION_MULTIPLIER_KEY, multiplier); } + /** Helper method for setting the damage multiplier (via NBT) for conjured items. */ + static void setDamageMultiplier(ItemStack stack, float multiplier){ + if(!stack.hasTagCompound()) stack.setTagCompound(new NBTTagCompound()); + stack.getTagCompound().setFloat(DAMAGE_MULTIPLIER, multiplier); + } + + /** Helper method for getting the damage multiplier (via NBT) for conjured items. */ + static float getDamageMultiplier(ItemStack stack){ + if(!stack.hasTagCompound()) return 1; + return stack.getTagCompound().getFloat(DAMAGE_MULTIPLIER); + } + /** * Helper method for returning the max damage of a conjured item based on its NBT data. Centralises the code. * Implementors will almost certainly want to call this from {@link Item#getMaxDamage(ItemStack stack)}. */ - public default int getMaxDamageFromNBT(ItemStack stack){ + default int getMaxDamageFromNBT(ItemStack stack, Spell spell){ + + float baseDuration = spell.getProperty(SpellConjuration.ITEM_LIFETIME).floatValue(); + if(stack.hasTagCompound() && stack.getTagCompound().hasKey(DURATION_MULTIPLIER_KEY)){ - return (int)(this.getBaseDuration() * stack.getTagCompound().getFloat(DURATION_MULTIPLIER_KEY)); + return (int)(baseDuration * stack.getTagCompound().getFloat(DURATION_MULTIPLIER_KEY)); } - return this.getBaseDuration(); + + return (int)baseDuration; } /** - * Returns the base duration in ticks for this conjured item. Should be a constant (commonly 600). Implementors may - * want to call this when setting an item's max damage in its constructor. + * Adds property overrides to define the conjuring/vanishing animation. Call this from the item's constructor. */ - public int getBaseDuration(); + default void addAnimationPropertyOverrides(){ + + if(!(this instanceof Item)) throw new ClassCastException("Cannot set up conjuring animations for a non-item!"); + + Item item = (Item)this; + + final int frames = getAnimationFrames(); + + item.addPropertyOverride(new ResourceLocation("conjure"), new IItemPropertyGetter(){ + @SideOnly(Side.CLIENT) + public float apply(ItemStack stack, @Nullable World world, @Nullable EntityLivingBase entity){ + return stack.getItemDamage() < frames ? (float)stack.getItemDamage() / frames + : (float)(stack.getMaxDamage() - stack.getItemDamage()) / frames; + } + }); + item.addPropertyOverride(new ResourceLocation("conjuring"), new IItemPropertyGetter(){ + @SideOnly(Side.CLIENT) + public float apply(ItemStack stack, @Nullable World world, @Nullable EntityLivingBase entity){ + return stack.getItemDamage() < frames + || stack.getItemDamage() > stack.getMaxDamage() - frames ? 1.0F : 0.0F; + } + }); + } + + /** Returns the number of frames in the conjuring/vanishing animation. Override to change the number of frames + * set by {@link IConjuredItem#addAnimationPropertyOverrides()}. */ + default int getAnimationFrames(){ + return 8; + } @SubscribeEvent - public static void onLivingDropsEvent(LivingDropsEvent event){ + static void onLivingDropsEvent(LivingDropsEvent event){ // Destroys conjured items if their caster dies. for(EntityItem item : event.getDrops()){ - if(item.getItem().getItem() instanceof IConjuredItem){ + // Apparently some mods don't behave and shove null items in the list, quite why I have no idea + if(item != null && item.getItem() != null && item.getItem().getItem() instanceof IConjuredItem){ item.setDead(); } } } @SubscribeEvent - public static void onItemTossEvent(ItemTossEvent event){ + static void onItemTossEvent(ItemTossEvent event){ // Prevents conjured items being thrown by dragging and dropping outside the inventory. if(event.getEntityItem().getItem().getItem() instanceof IConjuredItem){ event.setCanceled(true); diff --git a/src/main/java/electroblob/wizardry/item/IManaStoringItem.java b/src/main/java/electroblob/wizardry/item/IManaStoringItem.java new file mode 100644 index 00000000..de93846d --- /dev/null +++ b/src/main/java/electroblob/wizardry/item/IManaStoringItem.java @@ -0,0 +1,72 @@ +package electroblob.wizardry.item; + +import net.minecraft.entity.EntityLivingBase; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.item.ItemStack; + +/** + * Interface for any items that store mana. This interface simply specifies methods for setting and getting the amount + * of mana held in the item (plus a few convenience methods); implementations may differ between items. + *

    + * In wizardry itself, mana is still implemented as durability, however, as of wizardry 4.2, the vanilla method + * {@code Item.setDamage()} has been overridden to do nothing. Instead, mana must be interacted with using the methods + * in this interface. This means operating via the item rather than the stack. + *

    + * This change prevents general item repair methods working on mana items (see issues #66 and #153), and also allows + * other items to implement mana differently if they wish. For example, a weapon that can cast spells as an ability + * might want regular durability in addition to mana, so the mana might be stored in NBT instead. Items that do not use + * durability to represent mana may need to do zero-checking themselves, as appropriate. + *

    + * Wizardry's items implement mana as the inverse of item damage; i.e. the more damaged the item, the + * less mana it has. Beware of this when converting to the new system. + *

    + * @author Electroblob + * @since Wizardry 4.2 + */ +public interface IManaStoringItem { + + /** Returns the amount of mana contained in the given item stack. */ + int getMana(ItemStack stack); + + /** Sets the amount of mana contained in the given item stack to the given value. This method does not perform any + * checks for creative mode, etc. */ + void setMana(ItemStack stack, int mana); + + /** Returns the maximum amount of mana that the given item stack can hold. */ + int getManaCapacity(ItemStack stack); + + /** + * Returns whether this item's mana should be displayed in the arcane workbench tooltip. Only called client-side. + * Ignore this method if this item is not an {@link IWorkbenchItem}. + * @param player The player using the workbench. + * @param stack The itemstack to query. + * @return True if the mana should be shown, false if not. Returns true by default. + */ + default boolean showManaInWorkbench(EntityPlayer player, ItemStack stack){ + return true; + } + + /** Convenience method that decreases the amount of mana contained in the given item stack by the given value. This + * method automatically limits the mana to a minimum of 0 and performs the relevant checks for creative mode, etc. */ + default void consumeMana(ItemStack stack, int mana, EntityLivingBase wielder){ + if(wielder instanceof EntityPlayer && ((EntityPlayer)wielder).isCreative()) return; // Mana isn't consumed in creative + setMana(stack, Math.max(getMana(stack) - mana, 0)); + } + + /** Convenience method that increases the amount of mana contained in the given item stack by the given value. + * This method automatically limits the mana to within the item's capacity. */ + // We don't really need to limit this one because Item#setDamage() ultimately limits it anyway, but we may as well + default void rechargeMana(ItemStack stack, int mana){ + setMana(stack, Math.min(getMana(stack) + mana, getManaCapacity(stack))); + } + + /** Convenience method that returns true if the given stack contains the maximum amount of mana, false otherwise. */ + default boolean isManaFull(ItemStack stack){ + return getMana(stack) == getManaCapacity(stack); + } + + /** Convenience method that returns true if the given stack contains no mana, false otherwise. */ + default boolean isManaEmpty(ItemStack stack){ + return getMana(stack) == 0; + } +} diff --git a/src/main/java/electroblob/wizardry/item/IMultiTexturedItem.java b/src/main/java/electroblob/wizardry/item/IMultiTexturedItem.java new file mode 100644 index 00000000..849f9ae8 --- /dev/null +++ b/src/main/java/electroblob/wizardry/item/IMultiTexturedItem.java @@ -0,0 +1,23 @@ +package electroblob.wizardry.item; + +import net.minecraft.item.Item; +import net.minecraft.item.ItemStack; +import net.minecraft.util.ResourceLocation; + +/** + * Interface for items that change their texture depending on their metadata. This is mainly to facilitate use of the + * convenience method {@link electroblob.wizardry.client.model.WizardryModels#registerMultiTexturedModel(Item) WizardryModels.registerMultiTexturedModel(T)}. Also works well for {@code ItemBlock}s! + * @author Electroblob + * @since Wizardry 4.2 + * @see ItemBlockMultiTexturedElemental + */ +public interface IMultiTexturedItem { + + /** + * Returns the appropriate {@code ResourceLocation} for this item's model, based on the given itemstack. + * @param stack The itemstack to return the model name for. + * @return A {@code ResourceLocation} pointing to the appropriate model file. As with any other model, this should + * include the domain (mod ID) and filename, without the rest of the filepath. + */ + ResourceLocation getModelName(ItemStack stack); +} diff --git a/src/main/java/electroblob/wizardry/item/ISpellCastingItem.java b/src/main/java/electroblob/wizardry/item/ISpellCastingItem.java new file mode 100644 index 00000000..0d532200 --- /dev/null +++ b/src/main/java/electroblob/wizardry/item/ISpellCastingItem.java @@ -0,0 +1,129 @@ +package electroblob.wizardry.item; + +import electroblob.wizardry.data.WizardData; +import electroblob.wizardry.spell.Spell; +import electroblob.wizardry.util.SpellModifiers; +import net.minecraft.entity.EntityLivingBase; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.item.ItemStack; +import net.minecraft.util.EnumHand; +import net.minecraft.world.World; + +import javax.annotation.Nonnull; + +/** + * Interface for items that can hold and cast one or more spells. These may be consumables, like scrolls, or they may be + * durability-based, like wands. Custom spell casting items should implement this interface to integrate properly into + * wizardry. It is no longer necessary to extend {@code ItemWand}, but you may still do so instead of implementing + * this interface if appropriate. + *

    + * This interface is used for the following:
    + * - General-purpose detection of continuous spell casting (see {@link electroblob.wizardry.util.WizardryUtilities#isCasting(EntityLivingBase, Spell)})
    + * - Display of the arcane workbench tooltip (in conjunction with {@link IManaStoringItem})
    + * - Spell HUD visibility
    + * - Spell switching controls (they won't do anything unless the player is holding an {@code ISpellCastingItem})
    + * - Artefacts that trigger a player's wands/scrolls to cast spells + * @author Electroblob + * @since Wizardry 4.2 + */ +// This could probably be turned into a capability at some point, but for the moment it's fine like this +// As we've already noted, capabilities are only useful for optional dependencies anyway +public interface ISpellCastingItem { + + /** + * Returns the spell currently equipped on the given itemstack. The given itemstack will be of this item. + * @param stack The itemstack to query. + * @return The currently equipped spell, or {@link electroblob.wizardry.registry.Spells#none Spells.none} if no spell + * is equipped. + */ + @Nonnull + Spell getCurrentSpell(ItemStack stack); + + /** + * Returns all the spells currently bound to the given itemstack. The given itemstack will be of this item. + * @param stack The itemstack to query. + * @return The bound spells, or {@link electroblob.wizardry.registry.Spells#none Spells.none} if no spell + * is equipped. + */ + default Spell[] getSpells(ItemStack stack){ + return new Spell[]{getCurrentSpell(stack)}; // Default implementation for single-spell items, because I'm lazy + } + + /** + * Selects the next spell bound to the given itemstack. The given itemstack will be of this item. + * @param stack The itemstack to query. + */ + default void selectNextSpell(ItemStack stack){ + // If it doesn't need spell-switching then don't bother the implementor with it + } + + /** + * Selects the previous spell bound to the given itemstack. The given itemstack will be of this item. + * @param stack The itemstack to query. + */ + default void selectPreviousSpell(ItemStack stack){ + // Nothing here either + } + + /** + * Returns whether the spell HUD should be shown when a player is holding this item. Only called client-side. + * @param player The player holding the item. + * @param stack The itemstack to query. + * @return True if the spell HUD should be shown, false if not. + */ + boolean showSpellHUD(EntityPlayer player, ItemStack stack); + + /** + * Returns whether this item's spells should be displayed in the arcane workbench tooltip. Only called client-side. + * Ignore this method if this item is not an {@link IWorkbenchItem}. + * @param player The player using the workbench. + * @param stack The itemstack to query. + * @return True if the spells should be shown, false if not. Returns true by default. + */ + default boolean showSpellsInWorkbench(EntityPlayer player, ItemStack stack){ + return true; + } + + // These methods were made with intention of standardising the code for casting spells using items. + // For most external uses there's no reason for them to be separate, however, it makes more sense to do so because + // then we can eliminate a bit of duplicate code from continuous vs. non-continuous spell casting. Otherwise, we'd + // need a separate method for casting continuous spells anyway. + + /** + * Returns whether the given spell can be cast by the given stack in its current state. Does not perform any actual + * spellcasting. + * + * @param stack The stack being queried; will be of this item. + * @param spell The spell to be cast. + * @param caster The player doing the casting. + * @param hand The hand in which the casting item is being held. + * @param castingTick For continuous spells, the number of ticks the spell has already been cast for. For all other + * spells, this will be zero. + * @param modifiers The modifiers with which the spell is being cast. + * @return True if the spell can be cast, false if not. + */ + boolean canCast(ItemStack stack, Spell spell, EntityPlayer caster, EnumHand hand, int castingTick, SpellModifiers modifiers); + + /** + * Casts the given spell using the given item stack. This method does not perform any checks; these are done + * in {@link ISpellCastingItem#canCast(ItemStack, Spell, EntityPlayer, EnumHand, int, SpellModifiers)}. This method + * also performs any post-casting logic, such as mana costs and cooldowns. + *

    + * N.B. Continuous spell casting from outside of the items requires a bit of extra legwork, see + * {@link WizardData} for an example. + * + * @param stack The stack being queried; will be of this item. + * @param spell The spell to be cast. + * @param caster The player doing the casting. + * @param hand The hand in which the casting item is being held. + * @param castingTick For continuous spells, the number of ticks the spell has already been cast for. For all other + * spells, this will be zero. + * @param modifiers The modifiers with which the spell is being cast. + * @return True if the spell succeeded, false if not. This is only really for the purpose of returning a result from + * {@link net.minecraft.item.Item#onItemRightClick(World, EntityPlayer, EnumHand)} and similar methods; mana costs, + * cooldowns and whatever else you might want to do post-spellcasting should be done within this method so that + * external sources don't allow spells to be cast for free, for example. + */ + boolean cast(ItemStack stack, Spell spell, EntityPlayer caster, EnumHand hand, int castingTick, SpellModifiers modifiers); + +} diff --git a/src/main/java/electroblob/wizardry/item/IWorkbenchItem.java b/src/main/java/electroblob/wizardry/item/IWorkbenchItem.java index 704bebec..e85fd314 100644 --- a/src/main/java/electroblob/wizardry/item/IWorkbenchItem.java +++ b/src/main/java/electroblob/wizardry/item/IWorkbenchItem.java @@ -9,7 +9,7 @@ import net.minecraft.item.ItemStack; * Items that implement this interface may be placed in the central slot of the arcane workbench as long as * {@link IWorkbenchItem#canPlace(ItemStack)} returns true. The number of spell book slots displayed is also specified * using {@link IWorkbenchItem#getSpellSlotCount(ItemStack)}. - *

    + *

    * Items that implement this interface define what happens if they are in the central slot of the arcane workbench and * the apply button is pressed, in {@link IWorkbenchItem#onApplyButtonPressed(EntityPlayer, Slot, Slot, Slot, Slot[])}. * This is a core part of the arcane workbench refactoring in version 4.2 and allows for custom spell casting items and @@ -52,5 +52,13 @@ public interface IWorkbenchItem { * @return True if anything changed, false if not. */ boolean onApplyButtonPressed(EntityPlayer player, Slot centre, Slot crystals, Slot upgrade, Slot[] spellBooks); + + /** + * Returns whether the tooltip (dark grey box) should be drawn when this item is in an arcane workbench. Only + * called client-side. + * @param stack The itemstack to query. + * @return True if the workbench tooltip should be shown, false if not. + */ + boolean showTooltip(ItemStack stack); } diff --git a/src/main/java/electroblob/wizardry/item/ItemArcaneTome.java b/src/main/java/electroblob/wizardry/item/ItemArcaneTome.java index bf4b2b25..3e40abd8 100644 --- a/src/main/java/electroblob/wizardry/item/ItemArcaneTome.java +++ b/src/main/java/electroblob/wizardry/item/ItemArcaneTome.java @@ -1,11 +1,8 @@ package electroblob.wizardry.item; -import java.util.List; - import electroblob.wizardry.Wizardry; import electroblob.wizardry.constants.Tier; import electroblob.wizardry.registry.WizardryTabs; -import net.minecraft.client.util.ITooltipFlag; import net.minecraft.creativetab.CreativeTabs; import net.minecraft.item.EnumRarity; import net.minecraft.item.Item; @@ -15,6 +12,8 @@ import net.minecraft.world.World; import net.minecraftforge.fml.relauncher.Side; import net.minecraftforge.fml.relauncher.SideOnly; +import java.util.List; + public class ItemArcaneTome extends Item { public ItemArcaneTome(){ @@ -54,7 +53,12 @@ public class ItemArcaneTome extends Item { @SideOnly(Side.CLIENT) @Override - public void addInformation(ItemStack stack, World world, List tooltip, ITooltipFlag showAdvanced){ + public void addInformation(ItemStack stack, World world, List tooltip, net.minecraft.client.util.ITooltipFlag showAdvanced){ + + if(stack.getItemDamage() < 1){ + return; // If something's up with the metadata it will display a 'generic' tome of arcana with no info + } + Tier tier = Tier.values()[stack.getItemDamage()]; Tier tier2 = Tier.values()[stack.getItemDamage() - 1]; tooltip.add(tier.getDisplayNameWithFormatting()); diff --git a/src/main/java/electroblob/wizardry/item/ItemArmourUpgrade.java b/src/main/java/electroblob/wizardry/item/ItemArmourUpgrade.java index 39eaef6e..b7307b15 100644 --- a/src/main/java/electroblob/wizardry/item/ItemArmourUpgrade.java +++ b/src/main/java/electroblob/wizardry/item/ItemArmourUpgrade.java @@ -1,12 +1,7 @@ package electroblob.wizardry.item; -import java.util.List; - -import javax.annotation.Nullable; - import electroblob.wizardry.Wizardry; import electroblob.wizardry.registry.WizardryTabs; -import net.minecraft.client.util.ITooltipFlag; import net.minecraft.item.EnumRarity; import net.minecraft.item.Item; import net.minecraft.item.ItemStack; @@ -14,6 +9,9 @@ import net.minecraft.world.World; import net.minecraftforge.fml.relauncher.Side; import net.minecraftforge.fml.relauncher.SideOnly; +import javax.annotation.Nullable; +import java.util.List; + public class ItemArmourUpgrade extends Item { public ItemArmourUpgrade(){ @@ -35,7 +33,7 @@ public class ItemArmourUpgrade extends Item { @Override @SideOnly(Side.CLIENT) - public void addInformation(ItemStack stack, @Nullable World worldIn, List tooltip, ITooltipFlag flagIn) { + public void addInformation(ItemStack stack, @Nullable World worldIn, List tooltip, net.minecraft.client.util.ITooltipFlag flagIn) { tooltip.add(net.minecraft.client.resources.I18n.format("item." + Wizardry.MODID + ":armour_upgrade.desc1", "\u00A77")); tooltip.add( net.minecraft.client.resources.I18n.format("item." + Wizardry.MODID + ":armour_upgrade.desc2", "\u00A77", "\u00A7d")); diff --git a/src/main/java/electroblob/wizardry/item/ItemArtefact.java b/src/main/java/electroblob/wizardry/item/ItemArtefact.java new file mode 100644 index 00000000..be1e987c --- /dev/null +++ b/src/main/java/electroblob/wizardry/item/ItemArtefact.java @@ -0,0 +1,875 @@ +package electroblob.wizardry.item; + +import com.google.common.collect.Streams; +import electroblob.wizardry.Wizardry; +import electroblob.wizardry.constants.Element; +import electroblob.wizardry.data.WizardData; +import electroblob.wizardry.entity.construct.EntityFireRing; +import electroblob.wizardry.entity.living.ISummonedCreature; +import electroblob.wizardry.entity.projectile.EntityDart; +import electroblob.wizardry.entity.projectile.EntityForceOrb; +import electroblob.wizardry.entity.projectile.EntityIceShard; +import electroblob.wizardry.event.SpellCastEvent; +import electroblob.wizardry.integration.DamageSafetyChecker; +import electroblob.wizardry.integration.baubles.WizardryBaublesIntegration; +import electroblob.wizardry.registry.*; +import electroblob.wizardry.spell.*; +import electroblob.wizardry.util.*; +import net.minecraft.entity.Entity; +import net.minecraft.entity.EntityLiving; +import net.minecraft.entity.EntityLivingBase; +import net.minecraft.entity.IProjectile; +import net.minecraft.entity.item.EntityItem; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.init.MobEffects; +import net.minecraft.item.EnumRarity; +import net.minecraft.item.Item; +import net.minecraft.item.ItemStack; +import net.minecraft.item.crafting.FurnaceRecipes; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.potion.PotionEffect; +import net.minecraft.util.EnumHand; +import net.minecraft.util.math.Vec3d; +import net.minecraft.world.World; +import net.minecraft.world.biome.Biome; +import net.minecraftforge.common.BiomeDictionary; +import net.minecraftforge.common.capabilities.ICapabilityProvider; +import net.minecraftforge.event.entity.living.LivingDeathEvent; +import net.minecraftforge.event.entity.living.LivingEvent; +import net.minecraftforge.event.entity.living.LivingHurtEvent; +import net.minecraftforge.event.entity.living.PotionEvent; +import net.minecraftforge.event.entity.player.PlayerDropsEvent; +import net.minecraftforge.fml.common.Mod; +import net.minecraftforge.fml.common.eventhandler.Event; +import net.minecraftforge.fml.common.eventhandler.EventPriority; +import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; +import net.minecraftforge.fml.common.gameevent.PlayerEvent; +import net.minecraftforge.fml.common.gameevent.TickEvent; +import net.minecraftforge.fml.relauncher.Side; +import net.minecraftforge.fml.relauncher.SideOnly; + +import javax.annotation.Nullable; +import java.util.*; +import java.util.function.Consumer; +import java.util.stream.Collectors; + +/** + * Base class for all artefact items, which handles effects, textures and so on. The majority of artefacts are + * event-driven so it is unlikely that this class will need to be extended, unless other {@code Item} methods are to be + * overridden. + *

    + * This class contains methods and an enum that mirror those in {@code IBauble} from the Baubles mod. If Baubles is + * loaded, these are called via the bauble capability; otherwise, they are called from regular {@link Item} methods + * or events with appropriate checks. This allows wizardry to run with Baubles as an optional dependency. + *

    + * Do not reference any Baubles classes from subclasses of this, or the dependency will no longer be optional! + * Use {@link ItemArtefact#isArtefactActive(EntityPlayer, Item)} to test if a particular artefact is active. Use + * {@link ItemArtefact#getActiveArtefacts(EntityPlayer, Type...)} to get a list of active artefacts. + *

    + * @author Electroblob + * @since Wizardry 4.2 + * @see electroblob.wizardry.integration.baubles.WizardryBaublesIntegration + */ +@Mod.EventBusSubscriber +public class ItemArtefact extends Item { + + // Artefact checklist: + // - Create and register item, add model and texture + // - Program effect, using events if possible (if it only affects a specific spell or entity, in there is ok) + // - Add name AND description to lang files + // - Add to loot_tables/subsets/[rarity]_artefacts.json + // - Add to advancements/artefact.json and advancements/all_artefacts.json + + public enum Type { + + /** An artefact that improves attacking spells. Two of these can be active at any one time. */ RING(2), + /** An artefact that improves defensive spells. One of these can be active at any one time. */ AMULET(1), + /** An artefact that improves utility spells. One of these can be active at any one time. */ CHARM(1); + + public final int maxAtOnce; + + Type(int maxAtOnce){ + this.maxAtOnce = maxAtOnce; + } + } + + // If Baubles is not installed, artefacts will still work, but must instead be + // on the player's hotbar (and only the first n of a given type will work, where n is the number of baubles slots of that + // artefact's type). + + // Rarity was chosen over Tier here for a couple of reasons: firstly, displaying a tier would add unnecessary clutter + // to a potentially already-long tooltip whereas rarity provides a compact, neat way of displaying it that everyone is + // reasonably familiar with. Secondly, rarity makes more sense for an artefact, since it's something you find rather + // than upgrade to, and artefacts are not tied to tiers of wand/spell/whatever - they can be used whenever. + private final EnumRarity rarity; + private final Type type; + + public ItemArtefact(EnumRarity rarity, Type type){ + setMaxStackSize(1); + setCreativeTab(WizardryTabs.GEAR); + this.rarity = rarity; + this.type = type; + } + + @Override + public EnumRarity getRarity(ItemStack stack){ + return rarity; + } + + public Type getType(){ + return type; + } + + @Override + public boolean hasEffect(ItemStack stack){ + return rarity == EnumRarity.EPIC; + } + + @Override + @SideOnly(Side.CLIENT) + public void addInformation(ItemStack stack, @Nullable World worldIn, List tooltip, net.minecraft.client.util.ITooltipFlag flagIn){ + Wizardry.proxy.addMultiLineDescription(tooltip, "item." + this.getRegistryName() + ".desc"); + } + + @Nullable + @Override + public ICapabilityProvider initCapabilities(ItemStack stack, @Nullable NBTTagCompound nbt){ + return WizardryBaublesIntegration.enabled() ? new WizardryBaublesIntegration.ArtefactBaubleProvider(type) : null; + } + + // IBauble does of course have an onWornTick method. However, because it's an optional dependency, it doesn't really + // make sense to use that method when it's easier to just use the isBaubleEquipped method in the same + // place as the non-baubles check. In other words, most artefacts are event-driven anyway so I'd rather have the + // tick-driven ones use events as well for the sake of consistency. + + /** + * Returns whether the given artefact is active for the given player. If Baubles is loaded, an artefact is active + * when it is equipped in an appropriate bauble slot. If Baubles is not loaded, an artefact is active if it is one + * of the first n of its type on the player's hands/hotbar, where n is the number of bauble slots of that type. + *

    + * N.B. This method is inefficient if you are defining multiple artefact behaviours in the same place. In this use + * case, it is preferable to use {@link ItemArtefact#getActiveArtefacts(EntityPlayer, Type...)}. + * + * @param player The player whose inventory is to be checked. + * @param artefact The artefact to check for. + * @return True if the player has the artefact and it is active, false if not. Always returns false if the given + * item is not an instance of {@code ItemArtefact}. + * @throws IllegalArgumentException If the given item is not an artefact. + */ + // It's cleaner to cast to ItemArtefact here than wherever it is used - items can't be stored as ItemWhatever objects + public static boolean isArtefactActive(EntityPlayer player, Item artefact){ + + if(!(artefact instanceof ItemArtefact)) throw new IllegalArgumentException("Not an artefact!"); + + if(WizardryBaublesIntegration.enabled()){ + return WizardryBaublesIntegration.isBaubleEquipped(player, artefact); + }else{ + // To find out if the given artefact is one of the first n on the player's hotbar (where n is the maximum + // number of that kind of artefact that can be active at once): + return WizardryUtilities.getPrioritisedHotbarAndOffhand(player).stream() // Retrieve the stacks in question + // Filter out all except artefacts of the same type as the given one (preserving order) + .filter(s -> s.getItem() instanceof ItemArtefact && ((ItemArtefact)s.getItem()).type == ((ItemArtefact)artefact).type) + .limit(((ItemArtefact)artefact).type.maxAtOnce) // Ignore all but the first n + .anyMatch(s -> s.getItem() == artefact); // Check if the remaining stacks contain the artefact + // Note that streaming a list DOES retain the order (unless you call unordered(), obviously) + } + } + + /** + * Returns the currently active artefacts for the given player. If Baubles is loaded, an artefact is active + * when it is equipped in an appropriate bauble slot. If Baubles is not loaded, an artefact is active if it is one + * of the first n of its type on the player's hands/hotbar, where n is the number of bauble slots of that type. + *

    + * This method is more efficient for processing multiple artefact behaviours at once. + * + * @param player The player whose inventory is to be checked. + * @param types The artefact types to check for. If omitted, all artefact types will be checked. + * @return True if the player has the artefact and it is active, false if not. Always returns false if the given + * item is not an instance of {@code ItemArtefact}. + */ + public static List getActiveArtefacts(EntityPlayer player, Type... types){ + + if(types.length == 0) types = Type.values(); + + if(WizardryBaublesIntegration.enabled()){ + return WizardryBaublesIntegration.getEquippedArtefacts(player, types); + }else{ + + List artefacts = new ArrayList<>(); + + for(Type type : types){ + artefacts.addAll(WizardryUtilities.getPrioritisedHotbarAndOffhand(player).stream() + .filter(s -> s.getItem() instanceof ItemArtefact) + .map(s -> (ItemArtefact)s.getItem()) + .filter(i -> type == i.type) + .limit(type.maxAtOnce) + .collect(Collectors.toList())); + } + + return artefacts; + } + } + + /** + * Helper method that scans through all wands on the given player's hotbar and offhand and executes the given action + * if any of them have the given spell bound to them. This is a useful code pattern for artefact effects. + * + * @param player The player whose hotbar is to be checked + * @param spell The spell to search for + * @param action A {@link Consumer} specifying the action to be performed if a wand with the given spell is found. + * The stack passed to this consumer will be the wand in question. + * @return True if the action was executed, false otherwise. + */ + public static boolean findMatchingWandAndExecute(EntityPlayer player, Spell spell, Consumer action){ + + List hotbar = WizardryUtilities.getPrioritisedHotbarAndOffhand(player); + + Optional stack = hotbar.stream().filter(s -> s.getItem() instanceof ISpellCastingItem + && Arrays.asList(((ISpellCastingItem)s.getItem()).getSpells(s)).contains(spell)).findFirst(); + + stack.ifPresent(action); + return stack.isPresent(); + } + + /** + * Helper method that scans through all wands on the given player's hotbar and offhand and casts the given spell if + * it is bound to any of them. This is a useful code pattern for artefact effects. + * + * @param player The player whose hotbar is to be checked + * @param spell The spell to search for and cast + * @return True if the spell was cast, false otherwise. + */ + public static boolean findMatchingWandAndCast(EntityPlayer player, Spell spell){ + + return findMatchingWandAndExecute(player, spell, wand -> { + + SpellModifiers modifiers = new SpellModifiers(); + + if(((ISpellCastingItem)wand.getItem()).canCast(wand, spell, player, EnumHand.MAIN_HAND, 0, modifiers)){ + ((ISpellCastingItem)wand.getItem()).cast(wand, spell, player, EnumHand.MAIN_HAND, 0, modifiers); + } + }); + } + + // ================================================ Event Handlers ================================================ + + @SubscribeEvent + public static void onPlayerTickEvent(TickEvent.PlayerTickEvent event){ + + if(event.phase == TickEvent.Phase.START){ + + EntityPlayer player = event.player; + World world = player.world; + + for(ItemArtefact artefact : getActiveArtefacts(player)){ + + if(artefact == WizardryItems.ring_condensing){ + + if(world.isRemote && player.ticksExisted % 150 == 0){ + for(ItemStack stack : WizardryUtilities.getHotbar(player)){ + // Needs to be both of these interfaces because this ring only recharges wands + // (or more accurately, chargeable spellcasting items) + if(stack.getItem() instanceof ISpellCastingItem && stack.getItem() instanceof IManaStoringItem) + ((IManaStoringItem)stack.getItem()).rechargeMana(stack, 1); + } + } + + }else if(artefact == WizardryItems.amulet_arcane_defence){ + + if(world.isRemote && player.ticksExisted % 300 == 0){ + for(ItemStack stack : player.getArmorInventoryList()){ + // IManaStoringItem is sufficient, since anything in the armour slots is probably armour + if(stack.getItem() instanceof IManaStoringItem) + ((IManaStoringItem)stack.getItem()).rechargeMana(stack, 1); + } + } + + }else if(artefact == WizardryItems.amulet_recovery){ + + if(player.shouldHeal() && player.getHealth() < player.getMaxHealth()/2 + && player.ticksExisted % 50 == 0){ + + int totalArmourMana = Streams.stream(player.getArmorInventoryList()) + .filter(s -> s.getItem() instanceof IManaStoringItem) + .mapToInt(s -> ((IManaStoringItem)s.getItem()).getMana(s)) + .sum(); + + if(totalArmourMana >= 2){ + player.heal(1); + // 2 mana per half-heart, randomly distributed + List chargedArmour = Streams.stream(player.getArmorInventoryList()) + .filter(s -> s.getItem() instanceof IManaStoringItem) + .filter(s -> !((IManaStoringItem)s.getItem()).isManaEmpty(s)) + .collect(Collectors.toList()); + + if(chargedArmour.size() == 1){ + ((IManaStoringItem)chargedArmour.get(0).getItem()).consumeMana(chargedArmour.get(0), 2, player); + }else{ + Collections.shuffle(chargedArmour); + ((IManaStoringItem)chargedArmour.get(0).getItem()).consumeMana(chargedArmour.get(0), 1, player); + ((IManaStoringItem)chargedArmour.get(1).getItem()).consumeMana(chargedArmour.get(1), 1, player); + } + } + } + + }else if(artefact == WizardryItems.amulet_glide){ + // This should be a chance per fall, so we can't just check fall distance is greater than 3 each tick + // Based on a stationary start and a gravity acceleration of 0.02 blocks/tick^2, at 3 blocks of fall + // distance the player should be falling at about 0.35b/t, so 0.5 blocks should be enough of a window + if(player.fallDistance > 3f && player.fallDistance < 3.5f && player.world.rand.nextFloat() < 0.5f){ + if(!WizardData.get(player).isCasting()) WizardData.get(player).startCastingContinuousSpell(Spells.glide, new SpellModifiers(), 600); + }else if(player.onGround){ + WizardData data = WizardData.get(player); + if(data.currentlyCasting() == Spells.glide) data.stopCastingContinuousSpell(); + } + + }else if(artefact == WizardryItems.amulet_auto_shield){ + + findMatchingWandAndExecute(player, Spells.shield, wand -> { + + List projectiles = WizardryUtilities.getEntitiesWithinRadius(5, player.posX, player.posY, player.posZ, world, Entity.class); + projectiles.removeIf(e -> !(e instanceof IProjectile)); + Vec3d look = player.getLookVec(); + Vec3d playerPos = player.getPositionVector().add(0, player.height/2, 0); + + for(Entity projectile : projectiles){ + Vec3d vec = playerPos.subtract(projectile.getPositionVector()).normalize(); + double angle = Math.acos(vec.scale(-1).dotProduct(look)); + if(angle > Math.PI * 0.4f) continue; // (Roughly) the angle the shield will protect + Vec3d velocity = new Vec3d(projectile.motionX, projectile.motionY, projectile.motionZ).normalize(); + double angle1 = Math.acos(vec.dotProduct(velocity)); + if(angle1 < Math.PI * 0.2f){ + SpellModifiers modifiers = new SpellModifiers(); + if(((ISpellCastingItem)wand.getItem()).canCast(wand, Spells.shield, player, EnumHand.MAIN_HAND, 0, modifiers)){ + ((ISpellCastingItem)wand.getItem()).cast(wand, Spells.shield, player, EnumHand.MAIN_HAND, 0, modifiers); + } + break; + } + } + }); + + }else if(artefact == WizardryItems.charm_feeding){ + // Every 5 seconds, feed the player if they are near starving + if(player.ticksExisted % 100 == 0 && player.getFoodStats().getFoodLevel() < 2){ + findMatchingWandAndCast(player, Spells.replenish_hunger); + } + } + } + } + } + + @SubscribeEvent(priority = EventPriority.LOW) + public static void onSpellCastPreEvent(SpellCastEvent.Pre event){ + + if(event.getCaster() instanceof EntityPlayer){ + + EntityPlayer player = (EntityPlayer)event.getCaster(); + SpellModifiers modifiers = event.getModifiers(); + + for(ItemArtefact artefact : getActiveArtefacts(player)){ + + float potency = modifiers.get(SpellModifiers.POTENCY); + float cooldown = modifiers.get(WizardryItems.cooldown_upgrade); + Biome biome = player.world.getBiome(player.getPosition()); + + if(artefact == WizardryItems.ring_battlemage){ + + if(player.getHeldItemOffhand().getItem() instanceof ISpellCastingItem + && ImbueWeapon.isSword(player.getHeldItemMainhand().getItem())){ + modifiers.set(SpellModifiers.POTENCY, 1.1f * potency, false); + } + + }else if(artefact == WizardryItems.ring_fire_biome){ + + if(event.getSpell().getElement() == Element.FIRE + && BiomeDictionary.hasType(biome, BiomeDictionary.Type.HOT) + && BiomeDictionary.hasType(biome, BiomeDictionary.Type.DRY)){ + modifiers.set(SpellModifiers.POTENCY, 1.3f * potency, false); + } + + }else if(artefact == WizardryItems.ring_ice_biome){ + + if(event.getSpell().getElement() == Element.ICE + && BiomeDictionary.hasType(biome, BiomeDictionary.Type.SNOWY)){ + modifiers.set(SpellModifiers.POTENCY, 1.3f * potency, false); + } + + }else if(artefact == WizardryItems.ring_earth_biome){ + + if(event.getSpell().getElement() == Element.EARTH + // If it was any forest that would be far too many, so taigas and jungles are excluded + && BiomeDictionary.hasType(biome, BiomeDictionary.Type.FOREST) + && !BiomeDictionary.hasType(biome, BiomeDictionary.Type.CONIFEROUS) + && !BiomeDictionary.hasType(biome, BiomeDictionary.Type.JUNGLE)){ + modifiers.set(SpellModifiers.POTENCY, 1.3f * potency, false); + } + + }else if(artefact == WizardryItems.ring_storm){ + + if(event.getSpell().getElement() == Element.LIGHTNING && player.world.isThundering()){ + modifiers.set(WizardryItems.cooldown_upgrade, cooldown * 0.3f, false); + } + + }else if(artefact == WizardryItems.ring_full_moon){ + + if(event.getSpell().getElement() == Element.EARTH && !player.world.isDaytime() + && player.world.provider.getMoonPhase(player.world.getWorldTime()) == 0){ + modifiers.set(WizardryItems.cooldown_upgrade, cooldown * 0.3f, false); + } + + }else if(artefact == WizardryItems.ring_blockwrangler){ + + if(event.getSpell() == Spells.greater_telekinesis){ + modifiers.set(SpellModifiers.POTENCY, modifiers.get(SpellModifiers.POTENCY) * 2, false); + } + + }else if(artefact == WizardryItems.ring_conjurer){ + + if(event.getSpell() instanceof SpellConjuration){ + modifiers.set(WizardryItems.duration_upgrade, modifiers.get(WizardryItems.duration_upgrade) * 2, false); + } + + }else if(artefact == WizardryItems.charm_minion_health){ + // We COULD check the spell is a SpellMinion here, but there's really no point + modifiers.set(SpellMinion.HEALTH_MODIFIER, 1.25f * modifiers.get(SpellMinion.HEALTH_MODIFIER), true); + + }else if(artefact == WizardryItems.charm_flight){ + + if(event.getSpell() == Spells.flight || event.getSpell() == Spells.glide){ + // FIXME: Does not appear to be working, for some reason + modifiers.set(SpellModifiers.POTENCY, 1.5f * potency, true); + } + + }else if(artefact == WizardryItems.charm_experience_tome){ + + modifiers.set(SpellModifiers.PROGRESSION, modifiers.get(SpellModifiers.PROGRESSION) * 1.5f, false); + } + } + } + } + + @SubscribeEvent + public static void onSpellCastPostEvent(SpellCastEvent.Pre event){ + + if(event.getCaster() instanceof EntityPlayer){ + + EntityPlayer player = (EntityPlayer)event.getCaster(); + + if(isArtefactActive(player, WizardryItems.ring_paladin)){ + + if(event.getSpell() instanceof Heal || event.getSpell() instanceof HealAlly || event.getSpell() instanceof GreaterHeal){ + // Spell properties allow all three of the above spells to be dealt with the same way - neat! + float healthGained = event.getSpell().getProperty(Spell.HEALTH).floatValue() * event.getModifiers().get(SpellModifiers.POTENCY); + + List nearby = WizardryUtilities.getEntitiesWithinRadius(4, player.posX, player.posY, player.posZ, event.getWorld()); + + for(EntityLivingBase entity : nearby){ + if(AllyDesignationSystem.isAllied(player, entity) && entity.getHealth() > 0 && entity.getHealth() < entity.getMaxHealth()){ + entity.heal(healthGained * 0.2f); // 1/5 of the amount healed by the spell itself + if(event.getWorld().isRemote) ParticleBuilder.spawnHealParticles(event.getWorld(), entity); + } + } + } + } + } + } + + @SubscribeEvent + public static void onLivingUpdateEvent(LivingEvent.LivingUpdateEvent event){ + + EntityLivingBase entity = event.getEntityLiving(); + + // No point doing this every tick, every 2.5 seconds should be enough + if(entity.ticksExisted % 50 == 0 && entity.isPotionActive(WizardryPotions.mind_control)){ + + NBTTagCompound entityNBT = entity.getEntityData(); + + if(entityNBT.hasUniqueId(MindControl.NBT_KEY)){ + + Entity caster = WizardryUtilities.getEntityByUUID(entity.world, entityNBT.getUniqueId(MindControl.NBT_KEY)); + + if(caster instanceof EntityPlayer){ + + if(isArtefactActive((EntityPlayer)caster, WizardryItems.ring_mind_control)){ + + WizardryUtilities.getEntitiesWithinRadius(3, entity.posX, entity.posY, entity.posZ, entity.world, EntityLiving.class).stream() + .filter(e -> e.world.rand.nextInt(10) == 0) + .filter(MindControl::canControl) + .filter(e -> AllyDesignationSystem.isValidTarget(caster, e)) + .forEach(target -> MindControl.startControlling(target, (EntityPlayer)caster, + // Control the new target for only the remaining duration, otherwise it could go on forever! + entity.getActivePotionEffect(WizardryPotions.mind_control).getDuration())); + } + } + } + } + } + + @SubscribeEvent + public static void onLivingHurtEvent(LivingHurtEvent event){ + + if(event.getEntity() instanceof EntityPlayer){ + + EntityPlayer player = (EntityPlayer)event.getEntity(); + + for(ItemArtefact artefact : getActiveArtefacts(player)){ + + if(artefact == WizardryItems.amulet_warding){ + + if(!event.getSource().isUnblockable() && event.getSource().isMagicDamage()){ + event.setAmount(event.getAmount() * 0.9f); + } + + }else if(artefact == WizardryItems.amulet_fire_protection){ + + if(event.getSource().isFireDamage()) event.setAmount(event.getAmount() * 0.7f); + + }else if(artefact == WizardryItems.amulet_ice_protection){ + + if(event.getSource() instanceof IElementalDamage + && ((IElementalDamage)event.getSource()).getType() == MagicDamage.DamageType.FROST) + event.setAmount(event.getAmount() * 0.7f); + + }else if(artefact == WizardryItems.amulet_channeling){ + + if(player.world.rand.nextFloat() < 0.3f && event.getSource() instanceof IElementalDamage + && ((IElementalDamage)event.getSource()).getType() == MagicDamage.DamageType.SHOCK){ + event.setCanceled(true); + return; + } + + }else if(artefact == WizardryItems.amulet_fire_cloaking){ + + if(!event.getSource().isUnblockable()){ + + List fireRings = player.world.getEntitiesWithinAABB(EntityFireRing.class, player.getEntityBoundingBox()); + + for(EntityFireRing fireRing : fireRings){ + if(fireRing.getCaster() instanceof EntityPlayer && (fireRing.getCaster() == player + || AllyDesignationSystem.isOwnerAlly(player, fireRing))){ + event.setAmount(event.getAmount() * 0.25f); + } + } + } + + }else if(artefact == WizardryItems.amulet_potential){ + + if(player.world.rand.nextFloat() < 0.2f && WizardryUtilities.isMeleeDamage(event.getSource()) + && event.getSource().getTrueSource() instanceof EntityLivingBase){ + + EntityLivingBase target = (EntityLivingBase)event.getSource().getTrueSource(); + + if(player.world.isRemote){ + + ParticleBuilder.create(ParticleBuilder.Type.LIGHTNING).entity(event.getEntity()) + .pos(0, event.getEntity().height/2, 0).target(target).spawn(player.world); + + ParticleBuilder.spawnShockParticles(player.world, target.posX, + target.getEntityBoundingBox().minY + target.height/2, target.posZ); + } + + DamageSafetyChecker.attackEntitySafely(target, MagicDamage.causeDirectMagicDamage(player, + MagicDamage.DamageType.SHOCK, true), Spells.static_aura.getProperty(Spell.DAMAGE).floatValue(), event.getSource().getDamageType()); + target.playSound(WizardrySounds.SPELL_STATIC_AURA_RETALIATE, 1.0F, player.world.rand.nextFloat() * 0.4F + 1.5F); + + } + + }else if(artefact == WizardryItems.amulet_lich){ + + if(!event.getSource().isUnblockable() && player.world.rand.nextFloat() < 0.15f){ + + List nearbyMobs = WizardryUtilities.getEntitiesWithinRadius(5, player.posX, player.posY, player.posZ, player.world, EntityLiving.class); + nearbyMobs.removeIf(e -> !(e instanceof ISummonedCreature && ((ISummonedCreature)e).getCaster() == player)); + + if(!nearbyMobs.isEmpty()){ + Collections.shuffle(nearbyMobs); + // Even though we're passing the same damage source through, we still need the safety check + DamageSafetyChecker.attackEntitySafely(nearbyMobs.get(0), event.getSource(), event.getAmount(), event.getSource().getDamageType()); + event.setCanceled(true); + return; // Standard practice: stop as soon as the event is canceled + } + } + + }else if(artefact == WizardryItems.amulet_banishing){ + + if(player.world.rand.nextFloat() < 0.2f && WizardryUtilities.isMeleeDamage(event.getSource()) + && event.getSource().getTrueSource() instanceof EntityLivingBase){ + + EntityLivingBase target = (EntityLivingBase)event.getSource().getTrueSource(); + ((Banish)Spells.banish).teleport(target, target.world, 8 + target.world.rand.nextDouble() * 8); + } + + }else if(artefact == WizardryItems.amulet_transience){ + + if(player.getHealth() <= 2 && player.world.rand.nextFloat() < 0.25f){ + player.addPotionEffect(new PotionEffect(WizardryPotions.transience, 300)); + player.addPotionEffect(new PotionEffect(MobEffects.INVISIBILITY, 300, 0, false, false)); + } + } + } + } + + if(event.getSource().getTrueSource() instanceof EntityPlayer){ + + EntityPlayer player = (EntityPlayer)event.getSource().getTrueSource(); + ItemStack mainhandItem = player.getHeldItemMainhand(); + World world = player.world; + + for(ItemArtefact artefact : getActiveArtefacts(player)){ + + if(artefact == WizardryItems.ring_fire_melee){ + // Used ItemWand intentionally because we need the element + // Other mods can always make their own events if they want their own spellcasting items to do this + if(WizardryUtilities.isMeleeDamage(event.getSource()) && mainhandItem.getItem() instanceof ItemWand + && ((ItemWand)mainhandItem.getItem()).element == Element.FIRE){ + event.getEntity().setFire(5); + } + + }else if(artefact == WizardryItems.ring_ice_melee){ + + if(WizardryUtilities.isMeleeDamage(event.getSource()) && mainhandItem.getItem() instanceof ItemWand + && ((ItemWand)mainhandItem.getItem()).element == Element.ICE){ + event.getEntityLiving().addPotionEffect(new PotionEffect(WizardryPotions.frost, 200, 0)); + } + + }else if(artefact == WizardryItems.ring_lightning_melee){ + + if(WizardryUtilities.isMeleeDamage(event.getSource()) && mainhandItem.getItem() instanceof ItemWand + && ((ItemWand)mainhandItem.getItem()).element == Element.LIGHTNING){ + + WizardryUtilities.getEntitiesWithinRadius(3, player.posX, player.posY, player.posZ, world).stream() + .filter(WizardryUtilities::isLiving) + .min(Comparator.comparingDouble(player::getDistanceSq)) + .ifPresent(target -> { + + if(world.isRemote){ + + ParticleBuilder.create(ParticleBuilder.Type.LIGHTNING).entity(event.getEntity()) + .pos(0, event.getEntity().height/2, 0).target(target).spawn(world); + + ParticleBuilder.spawnShockParticles(world, target.posX, + target.getEntityBoundingBox().minY + target.height/2, target.posZ); + } + + DamageSafetyChecker.attackEntitySafely(target, MagicDamage.causeDirectMagicDamage(player, + MagicDamage.DamageType.SHOCK, true), Spells.static_aura.getProperty(Spell.DAMAGE).floatValue(), event.getSource().getDamageType()); + target.playSound(WizardrySounds.SPELL_STATIC_AURA_RETALIATE, 1.0F, world.rand.nextFloat() * 0.4F + 1.5F); + }); + } + + }else if(artefact == WizardryItems.ring_necromancy_melee){ + + if(WizardryUtilities.isMeleeDamage(event.getSource()) && mainhandItem.getItem() instanceof ItemWand + && ((ItemWand)mainhandItem.getItem()).element == Element.NECROMANCY){ + event.getEntityLiving().addPotionEffect(new PotionEffect(MobEffects.WITHER, 200, 0)); + } + + }else if(artefact == WizardryItems.ring_earth_melee){ + + if(WizardryUtilities.isMeleeDamage(event.getSource()) && mainhandItem.getItem() instanceof ItemWand + && ((ItemWand)mainhandItem.getItem()).element == Element.EARTH){ + event.getEntityLiving().addPotionEffect(new PotionEffect(MobEffects.POISON, 200, 0)); + } + + }else if(artefact == WizardryItems.ring_shattering){ + + if(!player.world.isRemote && player.world.rand.nextFloat() < 0.15f + && event.getEntityLiving().getHealth() < 12f // Otherwise it's a bit overpowered! + && event.getEntityLiving().isPotionActive(WizardryPotions.frost) + && WizardryUtilities.isMeleeDamage(event.getSource())){ + + event.setAmount(12f); + + for(int i = 0; i < 8; i++){ + double dx = event.getEntity().world.rand.nextDouble() - 0.5; + double dy = event.getEntity().world.rand.nextDouble() - 0.5; + double dz = event.getEntity().world.rand.nextDouble() - 0.5; + EntityIceShard iceshard = new EntityIceShard(event.getEntity().world); + iceshard.setPosition(event.getEntity().posX + dx + Math.signum(dx) * event.getEntity().width, + event.getEntity().posY + event.getEntity().height/2 + dy, + event.getEntity().posZ + dz + Math.signum(dz) * event.getEntity().width); + iceshard.motionX = dx * 1.5; + iceshard.motionY = dy * 1.5; + iceshard.motionZ = dz * 1.5; + iceshard.setCaster(player); + event.getEntity().world.spawnEntity(iceshard); + } + } + + }else if(artefact == WizardryItems.ring_soulbinding){ + + // Best guess at necromancy spell damage: either it's wither damage... + if((event.getSource() instanceof IElementalDamage + && (((IElementalDamage)event.getSource()).getType() == MagicDamage.DamageType.WITHER)) + // or it's direct, non-melee damage and the player is holding a wand with a necromancy spell selected + || (event.getSource().getImmediateSource() == player && !WizardryUtilities.isMeleeDamage(event.getSource()) + && Streams.stream(player.getHeldEquipment()).anyMatch(s -> s.getItem() instanceof ISpellCastingItem + && ((ISpellCastingItem)s.getItem()).getCurrentSpell(s).getElement() == Element.NECROMANCY))){ + + CurseOfSoulbinding.getSoulboundCreatures(WizardData.get(player)).add(event.getEntity().getUniqueID()); + } + + }else if(artefact == WizardryItems.ring_leeching){ + + // Best guess at necromancy spell damage: either it's wither damage... + if(player.world.rand.nextFloat() < 0.3f && ((event.getSource() instanceof IElementalDamage + && (((IElementalDamage)event.getSource()).getType() == MagicDamage.DamageType.WITHER)) + // ...or it's direct, non-melee damage and the player is holding a wand with a necromancy spell selected + || (event.getSource().getImmediateSource() == player && !WizardryUtilities.isMeleeDamage(event.getSource()) + && Streams.stream(player.getHeldEquipment()).anyMatch(s -> s.getItem() instanceof ISpellCastingItem + && ((ISpellCastingItem)s.getItem()).getCurrentSpell(s).getElement() == Element.NECROMANCY + && ((ISpellCastingItem)s.getItem()).getCurrentSpell(s) != Spells.life_drain)))){ + + if(player.shouldHeal()){ + player.heal(event.getAmount() * Spells.life_drain.getProperty(LifeDrain.HEAL_FACTOR).floatValue()); + } + } + + }else if(artefact == WizardryItems.ring_poison){ + + // Best guess at earth spell damage: either it's poison damage... + if((event.getSource() instanceof IElementalDamage + && (((IElementalDamage)event.getSource()).getType() == MagicDamage.DamageType.POISON)) + // ...or it was from a dart... + || event.getSource().getImmediateSource() instanceof EntityDart + // ...or it's direct, non-melee damage and the player is holding a wand with an earth spell selected + || (event.getSource().getImmediateSource() == player && !WizardryUtilities.isMeleeDamage(event.getSource()) + && Streams.stream(player.getHeldEquipment()).anyMatch(s -> s.getItem() instanceof ISpellCastingItem + && ((ISpellCastingItem)s.getItem()).getCurrentSpell(s).getElement() == Element.EARTH))){ + + event.getEntityLiving().addPotionEffect(new PotionEffect(MobEffects.POISON, 200, 0)); + } + + }else if(artefact == WizardryItems.ring_extraction){ + + // Best guess at sorcery spell damage: either it's force damage... + if((event.getSource() instanceof IElementalDamage + && (((IElementalDamage)event.getSource()).getType() == MagicDamage.DamageType.FORCE)) + // ...or it was from a force orb... + || event.getSource().getImmediateSource() instanceof EntityForceOrb + // ...or it's direct, non-melee damage and the player is holding a wand with a sorcery spell selected + || (event.getSource().getImmediateSource() == player && !WizardryUtilities.isMeleeDamage(event.getSource()) + && Streams.stream(player.getHeldEquipment()).anyMatch(s -> s.getItem() instanceof ISpellCastingItem + && ((ISpellCastingItem)s.getItem()).getCurrentSpell(s).getElement() == Element.SORCERY))){ + + WizardryUtilities.getPrioritisedHotbarAndOffhand(player).stream() + .filter(s -> s.getItem() instanceof ISpellCastingItem && s.getItem() instanceof IManaStoringItem + && !((IManaStoringItem)s.getItem()).isManaFull(s)) + .findFirst() + .ifPresent(s -> ((IManaStoringItem)s.getItem()).rechargeMana(s, 4 + world.rand.nextInt(3))); + } + + } + + } + } + } + + @SubscribeEvent + public static void onLivingDeathEvent(LivingDeathEvent event){ + + if(event.getSource().getTrueSource() instanceof EntityPlayer){ + + EntityPlayer player = (EntityPlayer)event.getSource().getTrueSource(); + + for(ItemArtefact artefact : getActiveArtefacts(player)){ + + if(artefact == WizardryItems.ring_combustion){ + + if(event.getSource() instanceof IElementalDamage && ((IElementalDamage)event.getSource()).getType() == MagicDamage.DamageType.FIRE){ + event.getEntity().world.createExplosion(event.getEntity(), event.getEntity().posX, event.getEntity().posY, + event.getEntity().posZ, 1.5f, false); + } + + }else if(artefact == WizardryItems.ring_disintegration){ + + if(event.getSource() instanceof IElementalDamage && ((IElementalDamage)event.getSource()).getType() == MagicDamage.DamageType.FIRE){ + Disintegration.spawnEmbers(event.getEntity().world, player, event.getEntity(), + Spells.disintegration.getProperty(Disintegration.EMBER_COUNT).intValue()); + } + + }else if(artefact == WizardryItems.ring_arcane_frost){ + + if(!player.world.isRemote && event.getSource() instanceof IElementalDamage + && ((IElementalDamage)event.getSource()).getType() == MagicDamage.DamageType.FROST){ + + for(int i = 0; i < 8; i++){ + double dx = event.getEntity().world.rand.nextDouble() - 0.5; + double dy = event.getEntity().world.rand.nextDouble() - 0.5; + double dz = event.getEntity().world.rand.nextDouble() - 0.5; + EntityIceShard iceshard = new EntityIceShard(event.getEntity().world); + iceshard.setPosition(event.getEntity().posX + dx + Math.signum(dx) * event.getEntity().width, + event.getEntity().posY + event.getEntity().height/2 + dy, + event.getEntity().posZ + dz + Math.signum(dz) * event.getEntity().width); + iceshard.motionX = dx * 1.5; + iceshard.motionY = dy * 1.5; + iceshard.motionZ = dz * 1.5; + iceshard.setCaster(player); + event.getEntity().world.spawnEntity(iceshard); + } + } + } + } + + } + } + + @SubscribeEvent(priority = EventPriority.HIGH) // Needs to happen before gravestones, etc. + public static void onPlayerDropsEvent(PlayerDropsEvent event){ + // Amulet of the immortal allows players to hold onto a wand with resurrection + // This needs to happen or we can't cast the spell with it and use up the mana + if(isArtefactActive(event.getEntityPlayer(), WizardryItems.amulet_resurrection)){ + + EntityItem item = event.getDrops().stream() + .filter(e -> Resurrection.canStackResurrect(e.getItem(), event.getEntityPlayer())) + .findFirst().orElse(null); + + if(item == null) return; // The player didn't have a wand with resurrection on it + if(!WizardryUtilities.getHotbar(event.getEntityPlayer()).contains(ItemStack.EMPTY)) return; // No space on hotbar + + event.getDrops().remove(item); + // At this point the player probably has nothing in their hand, but if not just find a free space somewhere + if(event.getEntityPlayer().getHeldItemMainhand().isEmpty()) event.getEntityPlayer().setHeldItem(EnumHand.MAIN_HAND, item.getItem()); + else event.getEntityPlayer().addItemStackToInventory(item.getItem()); // Always chooses hotbar slots first + } + } + + @SubscribeEvent + public static void onPotionApplicableEvent(PotionEvent.PotionApplicableEvent event){ + + if(event.getEntity() instanceof EntityPlayer){ + + EntityPlayer player = (EntityPlayer)event.getEntity(); + + for(ItemArtefact artefact : getActiveArtefacts(player)){ + + if(artefact == WizardryItems.amulet_ice_immunity){ + + if(event.getPotionEffect().getPotion() == WizardryPotions.frost) event.setResult(Event.Result.DENY); + + }else if(artefact == WizardryItems.amulet_wither_immunity){ + + if(event.getPotionEffect().getPotion() == MobEffects.WITHER) event.setResult(Event.Result.DENY); + } + } + } + } + + @SubscribeEvent + public static void onItemPickupEvent(PlayerEvent.ItemPickupEvent event){ + + // ItemPickupEvent is just a convenient trigger for this; we don't actually care what got picked up + if(isArtefactActive(event.player, WizardryItems.charm_auto_smelt)){ + + // So this doesn't waste mana, only cast pocket furnace when it would smelt the maximum number of items + if(event.player.inventory.mainInventory.stream() + .filter(s -> !FurnaceRecipes.instance().getSmeltingResult(s).isEmpty()) + .mapToInt(ItemStack::getCount) + .sum() >= Spells.pocket_furnace.getProperty(PocketFurnace.ITEMS_SMELTED).intValue()){ + + findMatchingWandAndCast(event.player, Spells.pocket_furnace); + } + } + } + +} diff --git a/src/main/java/electroblob/wizardry/item/ItemBlankScroll.java b/src/main/java/electroblob/wizardry/item/ItemBlankScroll.java index 3e9242d6..dc15754e 100644 --- a/src/main/java/electroblob/wizardry/item/ItemBlankScroll.java +++ b/src/main/java/electroblob/wizardry/item/ItemBlankScroll.java @@ -1,11 +1,12 @@ package electroblob.wizardry.item; -import electroblob.wizardry.WizardData; import electroblob.wizardry.constants.Constants; +import electroblob.wizardry.data.WizardData; import electroblob.wizardry.registry.Spells; import electroblob.wizardry.registry.WizardryItems; import electroblob.wizardry.registry.WizardryTabs; import electroblob.wizardry.spell.Spell; +import electroblob.wizardry.util.SpellProperties; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.inventory.Slot; import net.minecraft.item.Item; @@ -22,28 +23,33 @@ public class ItemBlankScroll extends Item implements IWorkbenchItem { return 1; } + @Override + public boolean showTooltip(ItemStack stack){ + return false; + } + @Override public boolean onApplyButtonPressed(EntityPlayer player, Slot centre, Slot crystals, Slot upgrade, Slot[] spellBooks){ if(!spellBooks[0].getStack().isEmpty() && !crystals.getStack().isEmpty()){ - Spell spell = Spell.get(spellBooks[0].getStack().getItemDamage()); + Spell spell = Spell.byMetadata(spellBooks[0].getStack().getItemDamage()); WizardData data = WizardData.get(player); // Spells can only be bound to scrolls if the player has already cast them (prevents casting of master // spells without getting a master wand) // This restriction does not apply in creative mode - if(spell != Spells.none && player.capabilities.isCreativeMode || (data != null - && data.hasSpellBeenDiscovered(spell))){ + if(spell != Spells.none && player.isCreative() || (data != null + && data.hasSpellBeenDiscovered(spell)) && spell.isEnabled(SpellProperties.Context.SCROLL)){ - int cost = spell.cost; + int cost = spell.getCost() * centre.getStack().getCount(); // Continuous spell scrolls require enough mana to cast them for the duration defined in ItemScroll. if(spell.isContinuous) cost *= ItemScroll.CASTING_TIME / 20; if(crystals.getStack().getCount() * Constants.MANA_PER_CRYSTAL > cost){ // Rounds up to the nearest whole crystal crystals.decrStackSize(cost / Constants.MANA_PER_CRYSTAL + 1); - centre.putStack(new ItemStack(WizardryItems.scroll, 1, spell.id())); + centre.putStack(new ItemStack(WizardryItems.scroll, centre.getStack().getCount(), spell.metadata())); return true; } diff --git a/src/main/java/electroblob/wizardry/item/ItemBlockMultiTexturedElemental.java b/src/main/java/electroblob/wizardry/item/ItemBlockMultiTexturedElemental.java new file mode 100644 index 00000000..0ed575cf --- /dev/null +++ b/src/main/java/electroblob/wizardry/item/ItemBlockMultiTexturedElemental.java @@ -0,0 +1,42 @@ +package electroblob.wizardry.item; + +import electroblob.wizardry.constants.Element; +import net.minecraft.block.Block; +import net.minecraft.item.ItemBlock; +import net.minecraft.item.ItemStack; +import net.minecraft.util.ResourceLocation; + +public class ItemBlockMultiTexturedElemental extends ItemBlock implements IMultiTexturedItem { + + private final boolean separateNames; + + public ItemBlockMultiTexturedElemental(Block block, boolean separateNames){ + super(block); + this.setHasSubtypes(true); + this.setMaxDamage(0); + this.separateNames = separateNames; + } + + @Override + public ResourceLocation getModelName(ItemStack stack){ + int metadata = stack.getMetadata(); + if(metadata >= Element.values().length) metadata = 0; + return getModelName(metadata); + } + + public ResourceLocation getModelName(int metadata){ + return new ResourceLocation(this.block.getRegistryName().getNamespace(), + Element.values()[metadata].getName() + "_" + this.block.getRegistryName().getPath()); + } + + @Override + public String getTranslationKey(ItemStack stack){ + return this.separateNames ? "tile." + this.getModelName(stack).toString() : super.getTranslationKey(stack); + } + + @Override + public int getMetadata(int metadata){ + return metadata; + } + +} diff --git a/src/main/java/electroblob/wizardry/item/ItemCrystal.java b/src/main/java/electroblob/wizardry/item/ItemCrystal.java new file mode 100644 index 00000000..88e4c96d --- /dev/null +++ b/src/main/java/electroblob/wizardry/item/ItemCrystal.java @@ -0,0 +1,44 @@ +package electroblob.wizardry.item; + +import electroblob.wizardry.Wizardry; +import electroblob.wizardry.constants.Element; +import electroblob.wizardry.registry.WizardryTabs; +import net.minecraft.creativetab.CreativeTabs; +import net.minecraft.item.Item; +import net.minecraft.item.ItemStack; +import net.minecraft.util.NonNullList; +import net.minecraft.util.ResourceLocation; + +/** Note that in 1.13, the flattening will make this class redundant, much like ItemCoal, which is probably its + * closest analog in vanilla. */ +public class ItemCrystal extends Item implements IMultiTexturedItem { + + public ItemCrystal(){ + super(); + this.setHasSubtypes(true); + this.setMaxDamage(0); + this.setCreativeTab(WizardryTabs.WIZARDRY); + } + + @Override + public ResourceLocation getModelName(ItemStack stack){ + int metadata = stack.getMetadata(); + if(metadata >= Element.values().length) metadata = 0; + return new ResourceLocation(Wizardry.MODID, "crystal_" + Element.values()[metadata].getName()); + } + + @Override + public String getTranslationKey(ItemStack stack){ + return "item." + this.getModelName(stack).toString(); + } + + @Override + public void getSubItems(CreativeTabs tab, NonNullList items){ + if(tab == WizardryTabs.WIZARDRY){ + for(Element element : Element.values()){ + items.add(new ItemStack(this, 1, element.ordinal())); + } + } + } + +} diff --git a/src/main/java/electroblob/wizardry/item/ItemFirebomb.java b/src/main/java/electroblob/wizardry/item/ItemFirebomb.java index 1a3a6097..c3404136 100644 --- a/src/main/java/electroblob/wizardry/item/ItemFirebomb.java +++ b/src/main/java/electroblob/wizardry/item/ItemFirebomb.java @@ -1,9 +1,9 @@ package electroblob.wizardry.item; import electroblob.wizardry.entity.projectile.EntityFirebomb; +import electroblob.wizardry.registry.WizardrySounds; import electroblob.wizardry.registry.WizardryTabs; import net.minecraft.entity.player.EntityPlayer; -import net.minecraft.init.SoundEvents; import net.minecraft.item.Item; import net.minecraft.item.ItemStack; import net.minecraft.util.ActionResult; @@ -23,15 +23,15 @@ public class ItemFirebomb extends Item { ItemStack stack = player.getHeldItem(hand); - if(!player.capabilities.isCreativeMode){ + if(!player.isCreative()){ stack.shrink(1); } - player.playSound(SoundEvents.ENTITY_SNOWBALL_THROW, 0.5F, 0.4F / (itemRand.nextFloat() * 0.4F + 0.8F)); + player.playSound(WizardrySounds.ENTITY_FIREBOMB_THROW, 0.5F, 0.4F / (itemRand.nextFloat() * 0.4F + 0.8F)); if(!world.isRemote){ EntityFirebomb firebomb = new EntityFirebomb(world); - firebomb.aim(player, 1.5f); + firebomb.aim(player, 1); world.spawnEntity(firebomb); } diff --git a/src/main/java/electroblob/wizardry/item/ItemFlamingAxe.java b/src/main/java/electroblob/wizardry/item/ItemFlamingAxe.java index 23655dd2..dcfe3110 100644 --- a/src/main/java/electroblob/wizardry/item/ItemFlamingAxe.java +++ b/src/main/java/electroblob/wizardry/item/ItemFlamingAxe.java @@ -1,10 +1,19 @@ package electroblob.wizardry.item; +import com.google.common.collect.Multimap; +import electroblob.wizardry.registry.Spells; +import electroblob.wizardry.spell.Spell; import electroblob.wizardry.util.MagicDamage; import electroblob.wizardry.util.MagicDamage.DamageType; +import electroblob.wizardry.util.WizardryUtilities; import net.minecraft.entity.Entity; import net.minecraft.entity.EntityLivingBase; +import net.minecraft.entity.SharedMonsterAttributes; +import net.minecraft.entity.ai.attributes.AttributeModifier; import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.inventory.EntityEquipmentSlot; +import net.minecraft.item.EnumRarity; +import net.minecraft.item.Item; import net.minecraft.item.ItemAxe; import net.minecraft.item.ItemStack; import net.minecraft.world.World; @@ -13,21 +22,42 @@ import net.minecraftforge.fml.relauncher.SideOnly; public class ItemFlamingAxe extends ItemAxe implements IConjuredItem { + private EnumRarity rarity = EnumRarity.COMMON; + public ItemFlamingAxe(ToolMaterial material){ super(material, 8, -3); - setMaxDamage(getBaseDuration()); + setMaxDamage(1200); // Might cause problems if removed, the actual number is irrelevant as long as it's > 0 setNoRepair(); setCreativeTab(null); + addAnimationPropertyOverrides(); } @Override - public int getBaseDuration(){ - return 1200; + public Multimap getAttributeModifiers(EntityEquipmentSlot slot, ItemStack stack){ + + Multimap multimap = super.getItemAttributeModifiers(slot); + + if(slot == EntityEquipmentSlot.MAINHAND){ + multimap.put(SharedMonsterAttributes.ATTACK_DAMAGE.getName(), new AttributeModifier(POTENCY_MODIFIER, + "Potency modifier", IConjuredItem.getDamageMultiplier(stack) - 1, WizardryUtilities.Operations.MULTIPLY_CUMULATIVE)); + } + + return multimap; + } + + public Item setRarity(EnumRarity rarity){ + this.rarity = rarity; + return this; + } + + @Override + public EnumRarity getRarity(ItemStack stack){ + return rarity; } @Override public int getMaxDamage(ItemStack stack){ - return this.getMaxDamageFromNBT(stack); + return this.getMaxDamageFromNBT(stack, Spells.flaming_axe); } @Override @@ -50,9 +80,16 @@ public class ItemFlamingAxe extends ItemAxe implements IConjuredItem { stack.setItemDamage(damage + 1); } + @Override + public Multimap getItemAttributeModifiers(EntityEquipmentSlot equipmentSlot){ + attackDamage = Spells.flaming_axe.getProperty(Spell.DAMAGE).floatValue(); + return super.getItemAttributeModifiers(equipmentSlot); + } + @Override public boolean hitEntity(ItemStack stack, EntityLivingBase target, EntityLivingBase wielder){ - if(!MagicDamage.isEntityImmune(DamageType.FIRE, target)) target.setFire(8); + if(!MagicDamage.isEntityImmune(DamageType.FIRE, target)) + target.setFire(Spells.flaming_axe.getProperty(Spell.BURN_DURATION).intValue()); return false; } @@ -72,6 +109,16 @@ public class ItemFlamingAxe extends ItemAxe implements IConjuredItem { return 0; } + @Override + public boolean isEnchantable(ItemStack stack){ + return false; + } + + @Override + public boolean isBookEnchantable(ItemStack stack, ItemStack book){ + return false; + } + // Cannot be dropped @Override public boolean onDroppedByPlayer(ItemStack item, EntityPlayer player){ diff --git a/src/main/java/electroblob/wizardry/item/ItemFrostAxe.java b/src/main/java/electroblob/wizardry/item/ItemFrostAxe.java index 159d1229..cca0d046 100644 --- a/src/main/java/electroblob/wizardry/item/ItemFrostAxe.java +++ b/src/main/java/electroblob/wizardry/item/ItemFrostAxe.java @@ -1,11 +1,19 @@ package electroblob.wizardry.item; +import com.google.common.collect.Multimap; +import electroblob.wizardry.registry.Spells; import electroblob.wizardry.registry.WizardryPotions; import electroblob.wizardry.util.MagicDamage; import electroblob.wizardry.util.MagicDamage.DamageType; +import electroblob.wizardry.util.WizardryUtilities; import net.minecraft.entity.Entity; import net.minecraft.entity.EntityLivingBase; +import net.minecraft.entity.SharedMonsterAttributes; +import net.minecraft.entity.ai.attributes.AttributeModifier; import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.inventory.EntityEquipmentSlot; +import net.minecraft.item.EnumRarity; +import net.minecraft.item.Item; import net.minecraft.item.ItemAxe; import net.minecraft.item.ItemStack; import net.minecraft.potion.PotionEffect; @@ -15,21 +23,42 @@ import net.minecraftforge.fml.relauncher.SideOnly; public class ItemFrostAxe extends ItemAxe implements IConjuredItem { + private EnumRarity rarity = EnumRarity.COMMON; + public ItemFrostAxe(ToolMaterial material){ super(material, 8, -3); - setMaxDamage(getBaseDuration()); + setMaxDamage(1200); setNoRepair(); setCreativeTab(null); + addAnimationPropertyOverrides(); } @Override - public int getBaseDuration(){ - return 1200; + public Multimap getAttributeModifiers(EntityEquipmentSlot slot, ItemStack stack){ + + Multimap multimap = super.getItemAttributeModifiers(slot); + + if(slot == EntityEquipmentSlot.MAINHAND){ + multimap.put(SharedMonsterAttributes.ATTACK_DAMAGE.getName(), new AttributeModifier(POTENCY_MODIFIER, + "Potency modifier", IConjuredItem.getDamageMultiplier(stack) - 1, WizardryUtilities.Operations.MULTIPLY_CUMULATIVE)); + } + + return multimap; + } + + public Item setRarity(EnumRarity rarity){ + this.rarity = rarity; + return this; + } + + @Override + public EnumRarity getRarity(ItemStack stack){ + return rarity; } @Override public int getMaxDamage(ItemStack stack){ - return this.getMaxDamageFromNBT(stack); + return this.getMaxDamageFromNBT(stack, Spells.frost_axe); } @Override @@ -75,6 +104,16 @@ public class ItemFrostAxe extends ItemAxe implements IConjuredItem { return 0; } + @Override + public boolean isEnchantable(ItemStack stack){ + return false; + } + + @Override + public boolean isBookEnchantable(ItemStack stack, ItemStack book){ + return false; + } + // Cannot be dropped @Override public boolean onDroppedByPlayer(ItemStack item, EntityPlayer player){ diff --git a/src/main/java/electroblob/wizardry/item/ItemIdentificationScroll.java b/src/main/java/electroblob/wizardry/item/ItemIdentificationScroll.java index 8a560c5b..61375b1e 100644 --- a/src/main/java/electroblob/wizardry/item/ItemIdentificationScroll.java +++ b/src/main/java/electroblob/wizardry/item/ItemIdentificationScroll.java @@ -1,19 +1,14 @@ package electroblob.wizardry.item; -import java.util.List; - -import javax.annotation.Nullable; - -import electroblob.wizardry.WizardData; import electroblob.wizardry.Wizardry; +import electroblob.wizardry.data.WizardData; import electroblob.wizardry.event.DiscoverSpellEvent; -import electroblob.wizardry.registry.WizardryAdvancementTriggers; +import electroblob.wizardry.registry.WizardrySounds; import electroblob.wizardry.registry.WizardryTabs; import electroblob.wizardry.spell.Spell; import electroblob.wizardry.util.WizardryUtilities; -import net.minecraft.client.util.ITooltipFlag; import net.minecraft.entity.player.EntityPlayer; -import net.minecraft.init.SoundEvents; +import net.minecraft.item.EnumRarity; import net.minecraft.item.Item; import net.minecraft.item.ItemStack; import net.minecraft.util.ActionResult; @@ -25,6 +20,9 @@ import net.minecraftforge.common.MinecraftForge; import net.minecraftforge.fml.relauncher.Side; import net.minecraftforge.fml.relauncher.SideOnly; +import javax.annotation.Nullable; +import java.util.List; + public class ItemIdentificationScroll extends Item { public ItemIdentificationScroll(){ @@ -38,11 +36,15 @@ public class ItemIdentificationScroll extends Item { return true; } + @Override + public EnumRarity getRarity(ItemStack stack){ + return EnumRarity.UNCOMMON; + } + @Override @SideOnly(Side.CLIENT) - public void addInformation(ItemStack stack, @Nullable World worldIn, List tooltip, ITooltipFlag flagIn) { - tooltip.add(net.minecraft.client.resources.I18n.format("item." + Wizardry.MODID + ":identification_scroll.desc1", "\u00A77")); - tooltip.add(net.minecraft.client.resources.I18n.format("item." + Wizardry.MODID + ":identification_scroll.desc2", "\u00A77")); + public void addInformation(ItemStack stack, @Nullable World world, List tooltip, net.minecraft.client.util.ITooltipFlag flag) { + Wizardry.proxy.addMultiLineDescription(tooltip, "item." + this.getRegistryName() + ".desc"); } @Override @@ -52,27 +54,26 @@ public class ItemIdentificationScroll extends Item { if(WizardData.get(player) != null){ - WizardData properties = WizardData.get(player); + WizardData data = WizardData.get(player); for(ItemStack stack1 : WizardryUtilities.getPrioritisedHotbarAndOffhand(player)){ if(!stack1.isEmpty()){ - Spell spell = Spell.get(stack1.getItemDamage()); + Spell spell = Spell.byMetadata(stack1.getItemDamage()); if((stack1.getItem() instanceof ItemSpellBook || stack1.getItem() instanceof ItemScroll) - && !properties.hasSpellBeenDiscovered(spell)){ + && !data.hasSpellBeenDiscovered(spell)){ if(!MinecraftForge.EVENT_BUS.post(new DiscoverSpellEvent(player, spell, DiscoverSpellEvent.Source.IDENTIFICATION_SCROLL))){ // Identification scrolls give the chat readout in creative mode, otherwise it looks like // nothing happens! - properties.discoverSpell(spell); - WizardryAdvancementTriggers.identify_spell.triggerFor(player); - player.playSound(SoundEvents.ENTITY_PLAYER_LEVELUP, 1.25f, 1); - if(!player.capabilities.isCreativeMode) stack.shrink(1); + data.discoverSpell(spell); + player.playSound(WizardrySounds.MISC_DISCOVER_SPELL, 1.25f, 1); + if(!player.isCreative()) stack.shrink(1); if(!world.isRemote) player.sendMessage(new TextComponentTranslation("spell.discover", spell.getNameForTranslationFormatted())); - return new ActionResult(EnumActionResult.SUCCESS, stack); + return new ActionResult<>(EnumActionResult.SUCCESS, stack); } } } @@ -82,7 +83,7 @@ public class ItemIdentificationScroll extends Item { new TextComponentTranslation("item." + Wizardry.MODID + ":identification_scroll.nothing_to_identify")); } - return new ActionResult(EnumActionResult.FAIL, stack); + return new ActionResult<>(EnumActionResult.FAIL, stack); } } diff --git a/src/main/java/electroblob/wizardry/item/ItemLightningHammer.java b/src/main/java/electroblob/wizardry/item/ItemLightningHammer.java new file mode 100644 index 00000000..0b7d40cd --- /dev/null +++ b/src/main/java/electroblob/wizardry/item/ItemLightningHammer.java @@ -0,0 +1,220 @@ +package electroblob.wizardry.item; + +import com.google.common.collect.Multimap; +import electroblob.wizardry.entity.construct.EntityHammer; +import electroblob.wizardry.registry.Spells; +import electroblob.wizardry.registry.WizardrySounds; +import electroblob.wizardry.spell.LightningHammer; +import electroblob.wizardry.spell.Spell; +import electroblob.wizardry.util.MagicDamage; +import electroblob.wizardry.util.MagicDamage.DamageType; +import electroblob.wizardry.util.ParticleBuilder; +import electroblob.wizardry.util.ParticleBuilder.Type; +import electroblob.wizardry.util.WizardryUtilities; +import net.minecraft.entity.Entity; +import net.minecraft.entity.EntityLivingBase; +import net.minecraft.entity.SharedMonsterAttributes; +import net.minecraft.entity.ai.attributes.AttributeModifier; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.inventory.EntityEquipmentSlot; +import net.minecraft.item.EnumRarity; +import net.minecraft.item.Item; +import net.minecraft.item.ItemStack; +import net.minecraft.util.ActionResult; +import net.minecraft.util.EnumActionResult; +import net.minecraft.util.EnumHand; +import net.minecraft.util.math.Vec3d; +import net.minecraft.world.World; +import net.minecraftforge.event.entity.player.AttackEntityEvent; +import net.minecraftforge.fml.common.Mod; +import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; + +import java.util.List; +import java.util.UUID; + +@Mod.EventBusSubscriber +public class ItemLightningHammer extends Item implements IConjuredItem { + + public static final String DURATION_NBT_KEY = "duration"; + // Annoyingly we can't implement this for attack damage, but at least it gets saved for when the hammer is thrown + public static final String DAMAGE_MULTIPLIER_NBT_KEY = "damageMultiplier"; + + public static final UUID MOVEMENT_SPEED_MODIFIER = UUID.fromString("d4c3bd93-c8e3-49c5-b35b-9356663bad1b"); + + private static final double ATTACK_SPEED = -3.2; + private static final double CHAINING_RANGE = 4; + private static final float CHAINING_DAMAGE = 4; + private static final double THROW_SPEED = 0.75; + private static final double MOVEMENT_SPEED_REDUCTION = -0.25; + + public ItemLightningHammer(){ + super(); + setMaxDamage(600); + setMaxStackSize(1); + setNoRepair(); + setCreativeTab(null); + } + + @Override + public EnumRarity getRarity(ItemStack stack){ + return EnumRarity.EPIC; + } + + @Override + public int getMaxDamage(ItemStack stack){ + if(stack.hasTagCompound() && stack.getTagCompound().hasKey(DURATION_NBT_KEY)){ + return stack.getTagCompound().getInteger(DURATION_NBT_KEY); + } + return super.getMaxDamage(stack); + } + + private float getDamageMultiplier(ItemStack stack){ + if(stack.hasTagCompound() && stack.getTagCompound().hasKey(DAMAGE_MULTIPLIER_NBT_KEY)){ + return stack.getTagCompound().getFloat(DAMAGE_MULTIPLIER_NBT_KEY); + } + return 1; + } + + @Override + public Multimap getItemAttributeModifiers(EntityEquipmentSlot slot){ + + Multimap multimap = super.getItemAttributeModifiers(slot); + + if(slot == EntityEquipmentSlot.MAINHAND){ + multimap.put(SharedMonsterAttributes.ATTACK_DAMAGE.getName(), new AttributeModifier(ATTACK_DAMAGE_MODIFIER, "Weapon modifier", Spells.lightning_hammer.getProperty(Spell.DIRECT_DAMAGE).floatValue(), WizardryUtilities.Operations.ADD)); + multimap.put(SharedMonsterAttributes.ATTACK_SPEED.getName(), new AttributeModifier(ATTACK_SPEED_MODIFIER, "Weapon modifier", ATTACK_SPEED, WizardryUtilities.Operations.ADD)); + multimap.put(SharedMonsterAttributes.MOVEMENT_SPEED.getName(), new AttributeModifier(MOVEMENT_SPEED_MODIFIER, "Weapon modifier", MOVEMENT_SPEED_REDUCTION, WizardryUtilities.Operations.MULTIPLY_FLAT)); + } + + return multimap; + } + + @Override + // This method allows the code for the item's timer to be greatly simplified by damaging it directly from + // onUpdate() and removing the workaround that involved WizardData and all sorts of crazy stuff. + public boolean shouldCauseReequipAnimation(ItemStack oldStack, ItemStack newStack, boolean slotChanged){ + + if(!oldStack.isEmpty() || !newStack.isEmpty()){ + // We only care about the situation where we specifically want the animation NOT to play. + if(oldStack.getItem() == newStack.getItem() && !slotChanged) return false; + } + + return super.shouldCauseReequipAnimation(oldStack, newStack, slotChanged); + } + + @Override + public void onUpdate(ItemStack stack, World world, Entity entity, int slot, boolean selected){ + int damage = stack.getItemDamage(); + if(damage > stack.getMaxDamage()) entity.replaceItemInInventory(slot, ItemStack.EMPTY); + stack.setItemDamage(damage + 1); + } + + @Override + public ActionResult onItemRightClick(World world, EntityPlayer player, EnumHand hand){ + + ItemStack stack = player.getHeldItem(hand); + + if(!world.isRemote){ + EntityHammer hammer = new EntityHammer(world); + Vec3d look = player.getLookVec(); + Vec3d vec = player.getPositionEyes(1).add(look); + hammer.setPositionAndRotation(vec.x, vec.y - hammer.height/2, vec.z, player.rotationYawHead - 90, 0); + // For some reason the above method insists on clamping the pitch to between -90 and 90 + hammer.rotationPitch = 180 + player.rotationPitch; + hammer.prevRotationPitch = hammer.rotationPitch; + + float attackStrength = player.getCooledAttackStrength(0); + double speed = THROW_SPEED * attackStrength; // Throw distance depends on the attack meter + hammer.addVelocity(look.x * speed, look.y * speed, look.z * speed); + hammer.lifetime = stack.getMaxDamage() - stack.getItemDamage(); + hammer.setCaster(player); + hammer.damageMultiplier = getDamageMultiplier(stack); + hammer.spin = true; + world.spawnEntity(hammer); + } + + WizardryUtilities.playSoundAtPlayer(player, WizardrySounds.ENTITY_HAMMER_THROW, 1.0F, 0.8f); + + //player.swingArm(hand); + + // Use this instead of stack.shrink so it works regardless of whether the player is in creative mode or not + player.setHeldItem(hand, ItemStack.EMPTY); + + return ActionResult.newResult(EnumActionResult.SUCCESS, stack); + } + + @Override + public boolean getIsRepairable(ItemStack stack, ItemStack par2ItemStack){ + return false; + } + + @Override + public int getItemEnchantability(){ + return 0; + } + + @Override + public boolean isEnchantable(ItemStack stack){ + return false; + } + + @Override + public boolean isBookEnchantable(ItemStack stack, ItemStack book){ + return false; + } + + // Cannot be dropped + @Override + public boolean onDroppedByPlayer(ItemStack item, EntityPlayer player){ + return false; + } + + // Can't be done in hitEntity because that's only called server-side, and after the cooldown is reset + @SubscribeEvent + public static void onAttackEntityEvent(AttackEntityEvent event){ + + ItemStack stack = event.getEntityPlayer().getHeldItemMainhand(); + + if(stack.getItem() instanceof ItemLightningHammer && event.getTarget() instanceof EntityLivingBase){ + + EntityPlayer wielder = event.getEntityPlayer(); + EntityLivingBase hit = (EntityLivingBase)event.getTarget(); + + float attackStrength = wielder.getCooledAttackStrength(0); + + double dx = wielder.posX - hit.posX; + double dz; + for(dz = wielder.posZ - hit.posZ; dx * dx + dz * dz < 1.0E-4D; dz = (Math.random() - Math.random()) + * 0.01D){ + dx = (Math.random() - Math.random()) * 0.01D; + } + + hit.knockBack(wielder, 2 * attackStrength, dx, dz); + + if(attackStrength == 1){ // Only chains when the attack meter is full + + List nearby = WizardryUtilities.getEntitiesWithinRadius(CHAINING_RANGE, hit.posX, hit.posY, hit.posZ, hit.world); + + nearby.remove(hit); + nearby.remove(wielder); + // When held, the number of chaining targets is halved + int maxTargets = Spells.lightning_hammer.getProperty(LightningHammer.SECONDARY_MAX_TARGETS).intValue() / 2; + while(nearby.size() > maxTargets) nearby.remove(nearby.size() - 1); + + for(EntityLivingBase target : nearby){ + + target.attackEntityFrom(MagicDamage.causeDirectMagicDamage(wielder, DamageType.SHOCK), CHAINING_DAMAGE * ((ItemLightningHammer)stack.getItem()).getDamageMultiplier(stack)); + + if(hit.world.isRemote){ + ParticleBuilder.create(Type.LIGHTNING).pos(hit.getPositionVector().add(0, hit.height / 2, 0)) + .target(target).spawn(hit.world); + ParticleBuilder.spawnShockParticles(hit.world, target.posX, target.getEntityBoundingBox().minY + target.height / 2, target.posZ); + } + + //target.playSound(WizardrySounds.SPELL_SPARK, 1, 1.5f + 0.4f * world.rand.nextFloat()); + } + } + } + } + +} diff --git a/src/main/java/electroblob/wizardry/item/ItemManaFlask.java b/src/main/java/electroblob/wizardry/item/ItemManaFlask.java new file mode 100644 index 00000000..8823b632 --- /dev/null +++ b/src/main/java/electroblob/wizardry/item/ItemManaFlask.java @@ -0,0 +1,37 @@ +package electroblob.wizardry.item; + +import electroblob.wizardry.registry.WizardryTabs; +import net.minecraft.item.EnumRarity; +import net.minecraft.item.Item; +import net.minecraft.item.ItemStack; + +public class ItemManaFlask extends Item { + + public enum Size { + + SMALL(75, EnumRarity.COMMON), + MEDIUM(700, EnumRarity.COMMON), + LARGE(1400, EnumRarity.RARE); + + public int capacity; + public EnumRarity rarity; + + Size(int capacity, EnumRarity rarity){ + this.capacity = capacity; + this.rarity = rarity; + } + } + + public final Size size; + + public ItemManaFlask(Size size){ + super(); + this.size = size; + this.setCreativeTab(WizardryTabs.WIZARDRY); + } + + @Override + public EnumRarity getRarity(ItemStack stack){ + return size.rarity; + } +} diff --git a/src/main/java/electroblob/wizardry/item/ItemPoisonBomb.java b/src/main/java/electroblob/wizardry/item/ItemPoisonBomb.java index 76a9f12a..a68c8aa4 100644 --- a/src/main/java/electroblob/wizardry/item/ItemPoisonBomb.java +++ b/src/main/java/electroblob/wizardry/item/ItemPoisonBomb.java @@ -1,9 +1,9 @@ package electroblob.wizardry.item; import electroblob.wizardry.entity.projectile.EntityPoisonBomb; +import electroblob.wizardry.registry.WizardrySounds; import electroblob.wizardry.registry.WizardryTabs; import net.minecraft.entity.player.EntityPlayer; -import net.minecraft.init.SoundEvents; import net.minecraft.item.Item; import net.minecraft.item.ItemStack; import net.minecraft.util.ActionResult; @@ -23,15 +23,15 @@ public class ItemPoisonBomb extends Item { ItemStack stack = player.getHeldItem(hand); - if(!player.capabilities.isCreativeMode){ + if(!player.isCreative()){ stack.shrink(1); } - player.playSound(SoundEvents.ENTITY_SNOWBALL_THROW, 0.5F, 0.4F / (itemRand.nextFloat() * 0.4F + 0.8F)); + player.playSound(WizardrySounds.ENTITY_POISON_BOMB_THROW, 0.5F, 0.4F / (itemRand.nextFloat() * 0.4F + 0.8F)); if(!world.isRemote){ EntityPoisonBomb poisonbomb = new EntityPoisonBomb(world); - poisonbomb.aim(player, 1.5f); + poisonbomb.aim(player, 1); world.spawnEntity(poisonbomb); } diff --git a/src/main/java/electroblob/wizardry/item/ItemPurifyingElixir.java b/src/main/java/electroblob/wizardry/item/ItemPurifyingElixir.java new file mode 100644 index 00000000..785ed409 --- /dev/null +++ b/src/main/java/electroblob/wizardry/item/ItemPurifyingElixir.java @@ -0,0 +1,99 @@ +package electroblob.wizardry.item; + +import electroblob.wizardry.Wizardry; +import electroblob.wizardry.registry.WizardrySounds; +import electroblob.wizardry.registry.WizardryTabs; +import electroblob.wizardry.util.ParticleBuilder; +import electroblob.wizardry.util.ParticleBuilder.Type; +import net.minecraft.advancements.CriteriaTriggers; +import net.minecraft.entity.EntityLivingBase; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.entity.player.EntityPlayerMP; +import net.minecraft.init.Items; +import net.minecraft.item.EnumAction; +import net.minecraft.item.EnumRarity; +import net.minecraft.item.Item; +import net.minecraft.item.ItemStack; +import net.minecraft.util.ActionResult; +import net.minecraft.util.EnumActionResult; +import net.minecraft.util.EnumHand; +import net.minecraft.util.SoundCategory; +import net.minecraft.world.World; +import net.minecraftforge.fml.relauncher.Side; +import net.minecraftforge.fml.relauncher.SideOnly; + +import javax.annotation.Nullable; +import java.util.List; + +public class ItemPurifyingElixir extends Item { + + public ItemPurifyingElixir(){ + this.setMaxStackSize(1); + this.setCreativeTab(WizardryTabs.WIZARDRY); + } + + @Override + public boolean hasEffect(ItemStack stack){ + return true; + } + + @Override + public EnumRarity getRarity(ItemStack stack){ + return EnumRarity.RARE; + } + + @Override + @SideOnly(Side.CLIENT) + public void addInformation(ItemStack stack, @Nullable World world, List tooltip, net.minecraft.client.util.ITooltipFlag flag) { + Wizardry.proxy.addMultiLineDescription(tooltip, "item." + this.getRegistryName() + ".desc"); + } + + @Override + public ItemStack onItemUseFinish(ItemStack stack, World world, EntityLivingBase entity){ + + if(!world.isRemote){ + entity.curePotionEffects(stack); + }else{ + + ParticleBuilder.spawnHealParticles(world, entity); + + for(int i = 0; i < 20; i++){ + double x = entity.posX + world.rand.nextDouble() * 2 - 1; + double y = entity.getEntityBoundingBox().minY + entity.getEyeHeight() - 0.5 + world.rand.nextDouble(); + double z = entity.posZ + world.rand.nextDouble() * 2 - 1; + ParticleBuilder.create(Type.SPARKLE).pos(x, y, z).vel(0, 0.14, 0).clr(0x0f001b) + .time(20 + world.rand.nextInt(12)).spawn(world); + ParticleBuilder.create(Type.DARK_MAGIC).pos(x, y, z).clr(0x0f001b).spawn(world); + } + } + + world.playSound(entity.posX, entity.posY, entity.posZ, WizardrySounds.ITEM_PURIFYING_ELIXIR_DRINK, SoundCategory.PLAYERS, 1, 1, false); + + if(entity instanceof EntityPlayerMP){ + EntityPlayerMP entityplayermp = (EntityPlayerMP)entity; + CriteriaTriggers.CONSUME_ITEM.trigger(entityplayermp, stack); + } + + if(entity instanceof EntityPlayer && !((EntityPlayer)entity).capabilities.isCreativeMode){ + stack.shrink(1); + } + + return stack.isEmpty() ? new ItemStack(Items.GLASS_BOTTLE) : stack; + } + + @Override + public int getMaxItemUseDuration(ItemStack stack){ + return 32; + } + + @Override + public EnumAction getItemUseAction(ItemStack stack){ + return EnumAction.DRINK; + } + + @Override + public ActionResult onItemRightClick(World worldIn, EntityPlayer playerIn, EnumHand handIn){ + playerIn.setActiveHand(handIn); + return new ActionResult<>(EnumActionResult.SUCCESS, playerIn.getHeldItem(handIn)); + } +} diff --git a/src/main/java/electroblob/wizardry/item/ItemScroll.java b/src/main/java/electroblob/wizardry/item/ItemScroll.java index 6f91757f..d793782b 100644 --- a/src/main/java/electroblob/wizardry/item/ItemScroll.java +++ b/src/main/java/electroblob/wizardry/item/ItemScroll.java @@ -8,7 +8,6 @@ import electroblob.wizardry.packet.WizardryPacketHandler; import electroblob.wizardry.registry.WizardryTabs; import electroblob.wizardry.spell.Spell; import electroblob.wizardry.util.SpellModifiers; -import net.minecraft.client.gui.FontRenderer; import net.minecraft.creativetab.CreativeTabs; import net.minecraft.entity.EntityLivingBase; import net.minecraft.entity.player.EntityPlayer; @@ -24,10 +23,9 @@ import net.minecraftforge.fml.common.network.simpleimpl.IMessage; import net.minecraftforge.fml.relauncher.Side; import net.minecraftforge.fml.relauncher.SideOnly; -public class ItemScroll extends Item { +public class ItemScroll extends Item implements ISpellCastingItem { /** The maximum number of ticks a continuous spell scroll can be cast for (by holding the use item button). */ - // TODO: Make this configurable public static final int CASTING_TIME = 120; public ItemScroll(){ @@ -36,14 +34,24 @@ public class ItemScroll extends Item { setMaxStackSize(16); setCreativeTab(WizardryTabs.SPELLS); } + + @Override + public Spell getCurrentSpell(ItemStack stack){ + return Spell.byMetadata(stack.getItemDamage()); + } + + @Override + public boolean showSpellHUD(EntityPlayer player, ItemStack stack){ + return false; + } @Override public void getSubItems(CreativeTabs tab, NonNullList list){ if(tab == WizardryTabs.SPELLS){ // In this particular case, getTotalSpellCount() is a more efficient way of doing this since the spell instance - // is not required, only the id. + // is not required, only the metadata. for(int i = 0; i < Spell.getTotalSpellCount(); i++){ - // i+1 is used so that the metadata ties up with the id() method. In other words, the none spell has id + // i+1 is used so that the metadata ties up with the metadata() method. In other words, the none spell has metadata // 0 and since this is not used as a spell book the metadata starts at 1. list.add(new ItemStack(this, 1, i + 1)); } @@ -83,54 +91,25 @@ public class ItemScroll extends Item { ItemStack stack = player.getHeldItem(hand); - Spell spell = Spell.get(stack.getItemDamage()); + Spell spell = Spell.byMetadata(stack.getItemDamage()); // By default, scrolls have no modifiers - but with the event system, they could be added. SpellModifiers modifiers = new SpellModifiers(); - // If anything stops the spell working at this point, nothing else happens. - if(MinecraftForge.EVENT_BUS.post(new SpellCastEvent.Pre(player, spell, modifiers, Source.SCROLL))){ - return new ActionResult(EnumActionResult.FAIL, stack); - } - - // Now we can cast continuous spells with scrolls! - if(spell.isContinuous){ - if(!player.isHandActive()){ - player.setActiveHand(hand); - return new ActionResult(EnumActionResult.SUCCESS, stack); - } - }else{ - - if(!world.isRemote){ - - if(spell.cast(world, player, hand, 0, new SpellModifiers())){ - - MinecraftForge.EVENT_BUS.post(new SpellCastEvent.Post(player, spell, modifiers, Source.SCROLL)); - - if(spell.doesSpellRequirePacket()){ - // Sends a packet to all players in dimension to tell them to spawn particles. - IMessage msg = new PacketCastSpell.Message(player.getEntityId(), hand, spell.id(), modifiers); - WizardryPacketHandler.net.sendToDimension(msg, world.provider.getDimension()); - } - - // Scrolls are consumed upon successful use in survival mode - if(!player.capabilities.isCreativeMode) stack.shrink(1); - - return new ActionResult(EnumActionResult.SUCCESS, stack); + if(canCast(stack, spell, player, hand, 0, modifiers)){ + // Now we can cast continuous spells with scrolls! + if(spell.isContinuous){ + if(!player.isHandActive()){ + player.setActiveHand(hand); + return new ActionResult<>(EnumActionResult.SUCCESS, stack); } - - // This else if check was bugging me for AGES! I can't believe I didn't compare to ItemWand before. - }else if(!spell.doesSpellRequirePacket()){ - // Client-inconsistent spell casting. This code only runs client-side. - if(spell.cast(world, player, hand, 0, modifiers)){ - // This is all that needs to happen, because everything above works fine on just the server side. - MinecraftForge.EVENT_BUS.post(new SpellCastEvent.Post(player, spell, modifiers, Source.SCROLL)); - return new ActionResult(EnumActionResult.SUCCESS, stack); + }else{ + if(cast(stack, spell, player, hand, 0, modifiers)){ + return new ActionResult<>(EnumActionResult.SUCCESS, stack); } } } - return new ActionResult(EnumActionResult.FAIL, stack); - + return new ActionResult<>(EnumActionResult.FAIL, stack); } // For continuous spells. The count argument actually decrements by 1 each tick. @@ -141,31 +120,68 @@ public class ItemScroll extends Item { EntityPlayer player = (EntityPlayer)user; - Spell spell = Spell.get(stack.getItemDamage()); + Spell spell = Spell.byMetadata(stack.getItemDamage()); // By default, scrolls have no modifiers - but with the event system, they could be added. SpellModifiers modifiers = new SpellModifiers(); int castingTick = stack.getMaxItemUseDuration() - count; - if(MinecraftForge.EVENT_BUS.post(new SpellCastEvent.Tick(Source.SCROLL, spell, player, modifiers, castingTick))) - return; - // Continuous spells (these must check if they can be cast each tick since the mana changes) - if(spell.isContinuous){ - - if(spell.cast(player.world, player, player.getActiveHand(), castingTick, modifiers)){ - - if(castingTick == 0) - MinecraftForge.EVENT_BUS.post(new SpellCastEvent.Post(Source.SCROLL, spell, player, modifiers)); - } + // In theory the spell is always continuous here but just in case it isn't... + if(spell.isContinuous && canCast(stack, spell, player, player.getActiveHand(), castingTick, modifiers)){ + cast(stack, spell, player, player.getActiveHand(), castingTick, modifiers); + }else{ + // Scrolls normally work on the max use duration so this isn't ever reached by wizardry, but if the + // casting was interrupted by SpellCastEvent.Tick it will be used + player.stopActiveHand(); } } } + + @Override + public boolean canCast(ItemStack stack, Spell spell, EntityPlayer caster, EnumHand hand, int castingTick, SpellModifiers modifiers){ + // Even neater! + if(castingTick == 0){ + return !MinecraftForge.EVENT_BUS.post(new SpellCastEvent.Pre(Source.SCROLL, spell, caster, modifiers)); + }else{ + return !MinecraftForge.EVENT_BUS.post(new SpellCastEvent.Tick(Source.SCROLL, spell, caster, modifiers, castingTick)); + } + } + + @Override + public boolean cast(ItemStack stack, Spell spell, EntityPlayer caster, EnumHand hand, int castingTick, SpellModifiers modifiers){ + + World world = caster.world; + + if(world.isRemote && !spell.isContinuous && spell.requiresPacket()) return false; + + if(spell.cast(world, caster, hand, castingTick, modifiers)){ + + if(castingTick == 0) MinecraftForge.EVENT_BUS.post(new SpellCastEvent.Post(Source.SCROLL, spell, caster, modifiers)); + + if(!world.isRemote){ + + // Continuous spells never require packets so don't rely on the requiresPacket method to specify it + if(!spell.isContinuous && spell.requiresPacket()){ + // Sends a packet to all players in dimension to tell them to spawn particles. + IMessage msg = new PacketCastSpell.Message(caster.getEntityId(), hand, spell, modifiers); + WizardryPacketHandler.net.sendToDimension(msg, world.provider.getDimension()); + } + + // Scrolls are consumed upon successful use in survival mode + if(!spell.isContinuous && !caster.isCreative()) stack.shrink(1); + } + + return true; + } + + return false; + } @Override public void onPlayerStoppedUsing(ItemStack stack, World world, EntityLivingBase user, int timeLeft){ // Consumes a continuous spell scroll when a player in survival mode stops using it. - if(Spell.get(stack.getItemDamage()).isContinuous - && (!(user instanceof EntityPlayer) || !((EntityPlayer)user).capabilities.isCreativeMode)){ + if(Spell.byMetadata(stack.getItemDamage()).isContinuous + && (!(user instanceof EntityPlayer) || !((EntityPlayer)user).isCreative())){ stack.shrink(1); } } @@ -173,8 +189,8 @@ public class ItemScroll extends Item { @Override public ItemStack onItemUseFinish(ItemStack stack, World world, EntityLivingBase user){ // Consumes a continuous spell scroll when the casting elapses whilst in use by a player in survival mode. - if(Spell.get(stack.getItemDamage()).isContinuous - && (!(user instanceof EntityPlayer) || !((EntityPlayer)user).capabilities.isCreativeMode)){ + if(Spell.byMetadata(stack.getItemDamage()).isContinuous + && (!(user instanceof EntityPlayer) || !((EntityPlayer)user).isCreative())){ stack.shrink(1); } @@ -183,7 +199,7 @@ public class ItemScroll extends Item { @Override @SideOnly(Side.CLIENT) - public FontRenderer getFontRenderer(ItemStack stack){ + public net.minecraft.client.gui.FontRenderer getFontRenderer(ItemStack stack){ return Wizardry.proxy.getFontRenderer(stack); } } diff --git a/src/main/java/electroblob/wizardry/item/ItemSmokeBomb.java b/src/main/java/electroblob/wizardry/item/ItemSmokeBomb.java index 880a84c4..a62a1179 100644 --- a/src/main/java/electroblob/wizardry/item/ItemSmokeBomb.java +++ b/src/main/java/electroblob/wizardry/item/ItemSmokeBomb.java @@ -1,9 +1,9 @@ package electroblob.wizardry.item; import electroblob.wizardry.entity.projectile.EntitySmokeBomb; +import electroblob.wizardry.registry.WizardrySounds; import electroblob.wizardry.registry.WizardryTabs; import net.minecraft.entity.player.EntityPlayer; -import net.minecraft.init.SoundEvents; import net.minecraft.item.Item; import net.minecraft.item.ItemStack; import net.minecraft.util.ActionResult; @@ -23,15 +23,15 @@ public class ItemSmokeBomb extends Item { ItemStack stack = player.getHeldItem(hand); - if(!player.capabilities.isCreativeMode){ + if(!player.isCreative()){ stack.shrink(1); } - player.playSound(SoundEvents.ENTITY_SNOWBALL_THROW, 0.5F, 0.4F / (itemRand.nextFloat() * 0.4F + 0.8F)); + player.playSound(WizardrySounds.ENTITY_SMOKE_BOMB_THROW, 0.5F, 0.4F / (itemRand.nextFloat() * 0.4F + 0.8F)); if(!world.isRemote){ EntitySmokeBomb smokebomb = new EntitySmokeBomb(world); - smokebomb.aim(player, 1.5f); + smokebomb.aim(player, 1); world.spawnEntity(smokebomb); } diff --git a/src/main/java/electroblob/wizardry/item/ItemSparkBomb.java b/src/main/java/electroblob/wizardry/item/ItemSparkBomb.java new file mode 100644 index 00000000..319b3dae --- /dev/null +++ b/src/main/java/electroblob/wizardry/item/ItemSparkBomb.java @@ -0,0 +1,41 @@ +package electroblob.wizardry.item; + +import electroblob.wizardry.entity.projectile.EntitySparkBomb; +import electroblob.wizardry.registry.WizardrySounds; +import electroblob.wizardry.registry.WizardryTabs; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.item.Item; +import net.minecraft.item.ItemStack; +import net.minecraft.util.ActionResult; +import net.minecraft.util.EnumActionResult; +import net.minecraft.util.EnumHand; +import net.minecraft.world.World; + +public class ItemSparkBomb extends Item { + + public ItemSparkBomb(){ + setMaxStackSize(16); + setCreativeTab(WizardryTabs.WIZARDRY); + } + + @Override + public ActionResult onItemRightClick(World world, EntityPlayer player, EnumHand hand){ + + ItemStack stack = player.getHeldItem(hand); + + if(!player.isCreative()){ + stack.shrink(1); + } + + player.playSound(WizardrySounds.ENTITY_SPARK_BOMB_THROW, 0.5F, 0.4F / (itemRand.nextFloat() * 0.4F + 0.8F)); + + if(!world.isRemote){ + EntitySparkBomb sparkBomb = new EntitySparkBomb(world); + sparkBomb.aim(player, 1); + world.spawnEntity(sparkBomb); + } + + return ActionResult.newResult(EnumActionResult.SUCCESS, stack); + } + +} \ No newline at end of file diff --git a/src/main/java/electroblob/wizardry/item/ItemSpectralArmour.java b/src/main/java/electroblob/wizardry/item/ItemSpectralArmour.java index e457e2dd..afa653b8 100644 --- a/src/main/java/electroblob/wizardry/item/ItemSpectralArmour.java +++ b/src/main/java/electroblob/wizardry/item/ItemSpectralArmour.java @@ -1,7 +1,6 @@ package electroblob.wizardry.item; -import net.minecraft.client.model.ModelBiped; -import net.minecraft.client.renderer.GlStateManager; +import electroblob.wizardry.registry.Spells; import net.minecraft.entity.Entity; import net.minecraft.entity.EntityLivingBase; import net.minecraft.entity.player.EntityPlayer; @@ -18,17 +17,12 @@ public class ItemSpectralArmour extends ItemArmor implements IConjuredItem { public ItemSpectralArmour(ArmorMaterial material, int renderIndex, EntityEquipmentSlot armourType){ super(material, renderIndex, armourType); setCreativeTab(null); - setMaxDamage(getBaseDuration()); - } - - @Override - public int getBaseDuration(){ - return 1800; + setMaxDamage(1200); } @Override public int getMaxDamage(ItemStack stack){ - return this.getMaxDamageFromNBT(stack); + return this.getMaxDamageFromNBT(stack, Spells.conjure_armour); } // Overridden to stop the enchantment trick making the name turn blue. @@ -73,6 +67,16 @@ public class ItemSpectralArmour extends ItemArmor implements IConjuredItem { return 0; } + @Override + public boolean isEnchantable(ItemStack stack){ + return false; + } + + @Override + public boolean isBookEnchantable(ItemStack stack, ItemStack book){ + return false; + } + // Cannot be dropped @Override public boolean onDroppedByPlayer(ItemStack item, EntityPlayer player){ @@ -89,14 +93,14 @@ public class ItemSpectralArmour extends ItemArmor implements IConjuredItem { @Override @SideOnly(Side.CLIENT) - public ModelBiped getArmorModel(EntityLivingBase entityLiving, ItemStack itemStack, - EntityEquipmentSlot armorSlot, ModelBiped _default){ - GlStateManager.enableBlend(); - GlStateManager.tryBlendFuncSeparate( - GlStateManager.SourceFactor.SRC_ALPHA, - GlStateManager.DestFactor.ONE_MINUS_SRC_ALPHA, - GlStateManager.SourceFactor.ONE, - GlStateManager.DestFactor.ZERO + public net.minecraft.client.model.ModelBiped getArmorModel(EntityLivingBase entityLiving, ItemStack itemStack, + EntityEquipmentSlot armorSlot, net.minecraft.client.model.ModelBiped _default){ + net.minecraft.client.renderer.GlStateManager.enableBlend(); + net.minecraft.client.renderer.GlStateManager.tryBlendFuncSeparate( + net.minecraft.client.renderer.GlStateManager.SourceFactor.SRC_ALPHA, + net.minecraft.client.renderer.GlStateManager.DestFactor.ONE_MINUS_SRC_ALPHA, + net.minecraft.client.renderer.GlStateManager.SourceFactor.ONE, + net.minecraft.client.renderer.GlStateManager.DestFactor.ZERO ); return super.getArmorModel(entityLiving, itemStack, armorSlot, _default); } diff --git a/src/main/java/electroblob/wizardry/item/ItemSpectralBow.java b/src/main/java/electroblob/wizardry/item/ItemSpectralBow.java index 6ebf1cf0..421b5b8c 100644 --- a/src/main/java/electroblob/wizardry/item/ItemSpectralBow.java +++ b/src/main/java/electroblob/wizardry/item/ItemSpectralBow.java @@ -1,9 +1,7 @@ package electroblob.wizardry.item; -import javax.annotation.Nullable; - import electroblob.wizardry.Wizardry; -import net.minecraft.client.Minecraft; +import electroblob.wizardry.registry.Spells; import net.minecraft.enchantment.EnchantmentHelper; import net.minecraft.entity.Entity; import net.minecraft.entity.EntityLivingBase; @@ -17,20 +15,18 @@ import net.minecraft.item.ItemArrow; import net.minecraft.item.ItemBow; import net.minecraft.item.ItemStack; import net.minecraft.stats.StatList; -import net.minecraft.util.ActionResult; -import net.minecraft.util.EnumActionResult; -import net.minecraft.util.EnumHand; -import net.minecraft.util.ResourceLocation; -import net.minecraft.util.SoundCategory; +import net.minecraft.util.*; import net.minecraft.world.World; import net.minecraftforge.fml.relauncher.Side; import net.minecraftforge.fml.relauncher.SideOnly; +import javax.annotation.Nullable; + public class ItemSpectralBow extends ItemBow implements IConjuredItem { public ItemSpectralBow(){ super(); - setMaxDamage(getBaseDuration()); + setMaxDamage(1200); setNoRepair(); setCreativeTab(null); this.addPropertyOverride(new ResourceLocation("pull"), new IItemPropertyGetter(){ @@ -40,7 +36,6 @@ public class ItemSpectralBow extends ItemBow implements IConjuredItem { return 0.0F; }else{ ItemStack itemstack = entityIn.getActiveItemStack(); - // Mojang, observe - hardcoding item references into their own classes is NOT good Java. return itemstack.getItem() == ItemSpectralBow.this ? (float)(stack.getMaxItemUseDuration() - entityIn.getItemInUseCount()) / 20.0F : 0.0F; @@ -54,6 +49,7 @@ public class ItemSpectralBow extends ItemBow implements IConjuredItem { : 0.0F; } }); + addAnimationPropertyOverrides(); } @Override @@ -63,14 +59,9 @@ public class ItemSpectralBow extends ItemBow implements IConjuredItem { return true; } - @Override - public int getBaseDuration(){ - return 1200; - } - @Override public int getMaxDamage(ItemStack stack){ - return this.getMaxDamageFromNBT(stack); + return this.getMaxDamageFromNBT(stack, Spells.conjure_bow); } @Override @@ -78,27 +69,38 @@ public class ItemSpectralBow extends ItemBow implements IConjuredItem { // onUpdate() and removing the workaround that involved WizardData and all sorts of crazy stuff. public boolean shouldCauseReequipAnimation(ItemStack oldStack, ItemStack newStack, boolean slotChanged){ - // TODO: For some reason there used to be an && here instead of an ||, which makes me wonder if there's a weird - // fix I did that needs removing. if(!oldStack.isEmpty() || !newStack.isEmpty()){ // We only care about the situation where we specifically want the animation NOT to play. if(oldStack.getItem() == newStack.getItem() && !slotChanged // This code should only run on the client side, so using Minecraft is ok. - && !Minecraft.getMinecraft().player.isHandActive()) + && !net.minecraft.client.Minecraft.getMinecraft().player.isHandActive()) return false; } return super.shouldCauseReequipAnimation(oldStack, newStack, slotChanged); } + // Copied fixes from ItemWand made possible by recently-added Forge hooks + + @Override + public boolean canContinueUsing(ItemStack oldStack, ItemStack newStack){ + // Ignore durability changes + if(ItemStack.areItemsEqualIgnoreDurability(oldStack, newStack)) return true; + return super.canContinueUsing(oldStack, newStack); + } + + @Override + public boolean shouldCauseBlockBreakReset(ItemStack oldStack, ItemStack newStack){ + // Ignore durability changes + if(ItemStack.areItemsEqualIgnoreDurability(oldStack, newStack)) return false; + return super.shouldCauseBlockBreakReset(oldStack, newStack); + } + @Override public void onUpdate(ItemStack stack, World world, Entity entity, int slot, boolean selected){ int damage = stack.getItemDamage(); if(damage > stack.getMaxDamage()) entity.replaceItemInInventory(slot, ItemStack.EMPTY); - // Can't damage it whilst in use because for some reason it causes the item use to constantly reset. - if(!(entity instanceof EntityLivingBase) || !((EntityLivingBase)entity).isHandActive()){ - stack.setItemDamage(damage + 1); - } + stack.setItemDamage(damage + 1); } // The following two methods re-route the displayed durability through the proxies in order to override the pausing @@ -145,19 +147,29 @@ public class ItemSpectralBow extends ItemBow implements IConjuredItem { return 0; } + @Override + public boolean isEnchantable(ItemStack stack){ + return false; + } + + @Override + public boolean isBookEnchantable(ItemStack stack, ItemStack book){ + return false; + } + // Cannot be dropped @Override public boolean onDroppedByPlayer(ItemStack item, EntityPlayer player){ return false; } - @Override - public void onUsingTick(ItemStack stack, EntityLivingBase player, int count){ - // player.getItemInUseMaxCount() is named incorrectly; you only have to look at the method to see what it really - // does. - if(stack.getItemDamage() + player.getItemInUseMaxCount() > stack.getMaxDamage()) - player.replaceItemInInventory(player.getActiveHand() == EnumHand.MAIN_HAND ? 98 : 99, ItemStack.EMPTY); - } +// @Override +// public void onUsingTick(ItemStack stack, EntityLivingBase player, int count){ +// // player.getItemInUseMaxCount() is named incorrectly; you only have to look at the method to see what it really +// // does. +// if(stack.getItemDamage() + player.getItemInUseMaxCount() > stack.getMaxDamage()) +// player.replaceItemInInventory(player.getActiveHand() == EnumHand.MAIN_HAND ? 98 : 99, ItemStack.EMPTY); +// } @Override public void onPlayerStoppedUsing(ItemStack stack, World world, EntityLivingBase entity, int timeLeft){ @@ -205,10 +217,12 @@ public class ItemSpectralBow extends ItemBow implements IConjuredItem { entityarrow.pickupStatus = EntityArrow.PickupStatus.DISALLOWED; + entityarrow.setDamage(entityarrow.getDamage() * IConjuredItem.getDamageMultiplier(stack)); + world.spawnEntity(entityarrow); } - world.playSound((EntityPlayer)null, entityplayer.posX, entityplayer.posY, entityplayer.posZ, + world.playSound(null, entityplayer.posX, entityplayer.posY, entityplayer.posZ, SoundEvents.ENTITY_ARROW_SHOOT, SoundCategory.NEUTRAL, 1.0F, 1.0F / (itemRand.nextFloat() * 0.4F + 1.2F) + f * 0.5F); diff --git a/src/main/java/electroblob/wizardry/item/ItemSpectralPickaxe.java b/src/main/java/electroblob/wizardry/item/ItemSpectralPickaxe.java index f178d1a3..3f40556e 100644 --- a/src/main/java/electroblob/wizardry/item/ItemSpectralPickaxe.java +++ b/src/main/java/electroblob/wizardry/item/ItemSpectralPickaxe.java @@ -1,30 +1,44 @@ package electroblob.wizardry.item; +import electroblob.wizardry.registry.Spells; +import net.minecraft.block.state.IBlockState; import net.minecraft.entity.Entity; import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.item.EnumRarity; +import net.minecraft.item.Item; import net.minecraft.item.ItemPickaxe; import net.minecraft.item.ItemStack; import net.minecraft.world.World; import net.minecraftforge.fml.relauncher.Side; import net.minecraftforge.fml.relauncher.SideOnly; +import javax.annotation.Nullable; + public class ItemSpectralPickaxe extends ItemPickaxe implements IConjuredItem { + private EnumRarity rarity = EnumRarity.COMMON; + public ItemSpectralPickaxe(ToolMaterial material){ super(material); - setMaxDamage(getBaseDuration()); + setMaxDamage(1200); setNoRepair(); setCreativeTab(null); + addAnimationPropertyOverrides(); + } + + public Item setRarity(EnumRarity rarity){ + this.rarity = rarity; + return this; } @Override - public int getBaseDuration(){ - return 1200; + public EnumRarity getRarity(ItemStack stack){ + return rarity; } @Override public int getMaxDamage(ItemStack stack){ - return this.getMaxDamageFromNBT(stack); + return this.getMaxDamageFromNBT(stack, Spells.conjure_pickaxe); } @Override @@ -47,6 +61,18 @@ public class ItemSpectralPickaxe extends ItemPickaxe implements IConjuredItem { stack.setItemDamage(damage + 1); } + @Override + public float getDestroySpeed(ItemStack stack, IBlockState state){ + float speed = super.getDestroySpeed(stack, state); + return speed > 1 ? speed * IConjuredItem.getDamageMultiplier(stack) : speed; + } + + @Override + public int getHarvestLevel(ItemStack stack, String toolClass, @Nullable EntityPlayer player, @Nullable IBlockState blockState){ + // Reuses the standard bonus amplifier calculation from SpellBuff to increase the mining level at advanced and master tier + return super.getHarvestLevel(stack, toolClass, player, blockState) + (int)((IConjuredItem.getDamageMultiplier(stack) - 1) / 0.4); + } + @Override @SideOnly(Side.CLIENT) public boolean hasEffect(ItemStack stack){ @@ -63,10 +89,19 @@ public class ItemSpectralPickaxe extends ItemPickaxe implements IConjuredItem { return 0; } + @Override + public boolean isEnchantable(ItemStack stack){ + return false; + } + + @Override + public boolean isBookEnchantable(ItemStack stack, ItemStack book){ + return false; + } + // Cannot be dropped @Override public boolean onDroppedByPlayer(ItemStack item, EntityPlayer player){ return false; } - } diff --git a/src/main/java/electroblob/wizardry/item/ItemSpectralSword.java b/src/main/java/electroblob/wizardry/item/ItemSpectralSword.java index 6a960b95..8a14bbab 100644 --- a/src/main/java/electroblob/wizardry/item/ItemSpectralSword.java +++ b/src/main/java/electroblob/wizardry/item/ItemSpectralSword.java @@ -1,7 +1,15 @@ package electroblob.wizardry.item; +import com.google.common.collect.Multimap; +import electroblob.wizardry.registry.Spells; +import electroblob.wizardry.util.WizardryUtilities; import net.minecraft.entity.Entity; +import net.minecraft.entity.SharedMonsterAttributes; +import net.minecraft.entity.ai.attributes.AttributeModifier; import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.inventory.EntityEquipmentSlot; +import net.minecraft.item.EnumRarity; +import net.minecraft.item.Item; import net.minecraft.item.ItemStack; import net.minecraft.item.ItemSword; import net.minecraft.world.World; @@ -10,21 +18,42 @@ import net.minecraftforge.fml.relauncher.SideOnly; public class ItemSpectralSword extends ItemSword implements IConjuredItem { + private EnumRarity rarity = EnumRarity.COMMON; + public ItemSpectralSword(ToolMaterial material){ super(material); - setMaxDamage(getBaseDuration()); + setMaxDamage(1200); setNoRepair(); setCreativeTab(null); + addAnimationPropertyOverrides(); } @Override - public int getBaseDuration(){ - return 1200; + public Multimap getAttributeModifiers(EntityEquipmentSlot slot, ItemStack stack){ + + Multimap multimap = super.getItemAttributeModifiers(slot); + + if(slot == EntityEquipmentSlot.MAINHAND){ + multimap.put(SharedMonsterAttributes.ATTACK_DAMAGE.getName(), new AttributeModifier(POTENCY_MODIFIER, + "Potency modifier", IConjuredItem.getDamageMultiplier(stack) - 1, WizardryUtilities.Operations.MULTIPLY_CUMULATIVE)); + } + + return multimap; + } + + public Item setRarity(EnumRarity rarity){ + this.rarity = rarity; + return this; + } + + @Override + public EnumRarity getRarity(ItemStack stack){ + return rarity; } @Override public int getMaxDamage(ItemStack stack){ - return this.getMaxDamageFromNBT(stack); + return this.getMaxDamageFromNBT(stack, Spells.conjure_sword); } @Override @@ -63,6 +92,16 @@ public class ItemSpectralSword extends ItemSword implements IConjuredItem { return 0; } + @Override + public boolean isEnchantable(ItemStack stack){ + return false; + } + + @Override + public boolean isBookEnchantable(ItemStack stack, ItemStack book){ + return false; + } + // Cannot be dropped @Override public boolean onDroppedByPlayer(ItemStack item, EntityPlayer player){ diff --git a/src/main/java/electroblob/wizardry/item/ItemSpellBook.java b/src/main/java/electroblob/wizardry/item/ItemSpellBook.java index 359e5eac..a99dcd81 100644 --- a/src/main/java/electroblob/wizardry/item/ItemSpellBook.java +++ b/src/main/java/electroblob/wizardry/item/ItemSpellBook.java @@ -1,17 +1,10 @@ package electroblob.wizardry.item; -import java.util.List; - -import electroblob.wizardry.SpellGlyphData; -import electroblob.wizardry.WizardData; import electroblob.wizardry.Wizardry; import electroblob.wizardry.WizardryGuiHandler; +import electroblob.wizardry.data.SpellGlyphData; import electroblob.wizardry.registry.WizardryTabs; import electroblob.wizardry.spell.Spell; -import net.minecraft.client.Minecraft; -import net.minecraft.client.entity.EntityPlayerSP; -import net.minecraft.client.gui.FontRenderer; -import net.minecraft.client.util.ITooltipFlag; import net.minecraft.creativetab.CreativeTabs; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.item.Item; @@ -25,6 +18,8 @@ import net.minecraftforge.fml.relauncher.Side; import net.minecraftforge.fml.relauncher.SideOnly; import net.minecraftforge.oredict.OreDictionary; +import java.util.List; + public class ItemSpellBook extends Item { public ItemSpellBook(){ @@ -38,9 +33,9 @@ public class ItemSpellBook extends Item { public void getSubItems(CreativeTabs tab, NonNullList list){ if(tab == WizardryTabs.SPELLS){ // In this particular case, getTotalSpellCount() is a more efficient way of doing this since the spell instance - // is not required, only the id. + // is not required, only the metadata. for(int i = 0; i < Spell.getTotalSpellCount(); i++){ - // i+1 is used so that the metadata ties up with the id() method. In other words, the none spell has id + // i+1 is used so that the metadata ties up with the metadata() method. In other words, the none spell has metadata // 0 and since this is not used as a spell book the metadata starts at 1. list.add(new ItemStack(this, 1, i + 1)); } @@ -56,23 +51,19 @@ public class ItemSpellBook extends Item { @Override @SideOnly(Side.CLIENT) - public void addInformation(ItemStack itemstack, World world, List tooltip, ITooltipFlag advanced){ + public void addInformation(ItemStack itemstack, World world, List tooltip, net.minecraft.client.util.ITooltipFlag advanced){ // Tooltip is left blank for wizards buying generic spell books. - if(itemstack.getItemDamage() != OreDictionary.WILDCARD_VALUE){ - EntityPlayerSP player = Minecraft.getMinecraft().player; + if(world != null && itemstack.getItemDamage() != OreDictionary.WILDCARD_VALUE){ - Spell spell = Spell.get(itemstack.getItemDamage()); + Spell spell = Spell.byMetadata(itemstack.getItemDamage()); - boolean discovered = true; - if(player != null && Wizardry.settings.discoveryMode && !player.capabilities.isCreativeMode && WizardData.get(player) != null - && !WizardData.get(player).hasSpellBeenDiscovered(spell)){ - discovered = false; - } + boolean discovered = Wizardry.proxy.shouldDisplayDiscovered(spell, itemstack); // Element colour is not given for undiscovered spells tooltip.add(discovered ? "\u00A77" + spell.getDisplayNameWithFormatting() - : "#\u00A79" + SpellGlyphData.getGlyphName(spell, player.world)); - tooltip.add(spell.tier.getDisplayNameWithFormatting()); + : "#\u00A79" + SpellGlyphData.getGlyphName(spell, world)); + + tooltip.add(spell.getTier().getDisplayNameWithFormatting()); } /* Removed to streamline the tooltip a bit. Information is now within the book. if(spell.isContinuous){ * tooltip.add("\u00A79Mana Cost: " + spell.cost + " per second"); }else{ tooltip.add("\u00A79Mana Cost: " + @@ -81,7 +72,7 @@ public class ItemSpellBook extends Item { @Override @SideOnly(Side.CLIENT) - public FontRenderer getFontRenderer(ItemStack stack){ + public net.minecraft.client.gui.FontRenderer getFontRenderer(ItemStack stack){ return Wizardry.proxy.getFontRenderer(stack); } diff --git a/src/main/java/electroblob/wizardry/item/ItemWand.java b/src/main/java/electroblob/wizardry/item/ItemWand.java index 950a5a5d..1f663ff7 100644 --- a/src/main/java/electroblob/wizardry/item/ItemWand.java +++ b/src/main/java/electroblob/wizardry/item/ItemWand.java @@ -1,34 +1,26 @@ package electroblob.wizardry.item; -import java.util.List; - -import electroblob.wizardry.SpellGlyphData; -import electroblob.wizardry.WizardData; +import com.google.common.collect.Multimap; import electroblob.wizardry.Wizardry; import electroblob.wizardry.constants.Constants; import electroblob.wizardry.constants.Element; import electroblob.wizardry.constants.Tier; +import electroblob.wizardry.data.SpellGlyphData; +import electroblob.wizardry.data.WizardData; import electroblob.wizardry.entity.living.ISummonedCreature; import electroblob.wizardry.event.SpellCastEvent; import electroblob.wizardry.event.SpellCastEvent.Source; import electroblob.wizardry.packet.PacketCastSpell; import electroblob.wizardry.packet.WizardryPacketHandler; -import electroblob.wizardry.registry.Spells; -import electroblob.wizardry.registry.WizardryAdvancementTriggers; -import electroblob.wizardry.registry.WizardryItems; -import electroblob.wizardry.registry.WizardryPotions; -import electroblob.wizardry.registry.WizardryTabs; +import electroblob.wizardry.registry.*; import electroblob.wizardry.spell.Spell; -import electroblob.wizardry.util.SpellModifiers; -import electroblob.wizardry.util.WandHelper; -import electroblob.wizardry.util.WizardryUtilities; -import net.minecraft.client.Minecraft; -import net.minecraft.client.entity.EntityPlayerSP; -import net.minecraft.client.gui.FontRenderer; -import net.minecraft.client.util.ITooltipFlag; +import electroblob.wizardry.util.*; +import electroblob.wizardry.util.ParticleBuilder.Type; import net.minecraft.entity.Entity; import net.minecraft.entity.EntityLiving; import net.minecraft.entity.EntityLivingBase; +import net.minecraft.entity.SharedMonsterAttributes; +import net.minecraft.entity.ai.attributes.AttributeModifier; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.inventory.EntityEquipmentSlot; import net.minecraft.inventory.Slot; @@ -38,46 +30,115 @@ import net.minecraft.item.ItemStack; import net.minecraft.util.ActionResult; import net.minecraft.util.EnumActionResult; import net.minecraft.util.EnumHand; +import net.minecraft.util.SoundCategory; +import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.RayTraceResult; +import net.minecraft.util.math.Vec3d; import net.minecraft.util.text.TextComponentTranslation; import net.minecraft.world.World; import net.minecraftforge.common.MinecraftForge; +import net.minecraftforge.event.entity.player.AttackEntityEvent; +import net.minecraftforge.fml.common.Mod; +import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; import net.minecraftforge.fml.common.network.simpleimpl.IMessage; import net.minecraftforge.fml.relauncher.Side; import net.minecraftforge.fml.relauncher.SideOnly; +import java.util.List; +import java.util.Random; + /** - * This class is (literally) where the magic happens! All wand types are single instances of this class. There's a lot - * of quite hard-to-read code in here, but unfortunately there's not much I can do about that. For this reason, I have - * written the {@link WandHelper} class. I strongly recommend you use it for interacting with wand items wherever - * possible. - *

    - * It's unlikely that anything in this class will be of much use externally, but should you wish to use it for whatever - * reason (perhaps if you extend it), it works as follows: - *

    - * - onItemRightClick is where non-continuous spells are cast, and it sets the item in use for continuous spells
    - * - onUsingTick does the casting for continuous spells
    - * - onUpdate deals with the cooldowns for the spells - * + * This class is (literally) where the magic happens! All of wizardry's wand items are instances of this class. As of + * wizardry 4.2, it is no longer necessary to extend {@code ItemWand} thanks to {@link ISpellCastingItem}, though + * extending {@code ItemWand} may still be more appropriate for items using the same casting implementation. + *

    + * This class handles spell casting as follows: + *

    + * - {@code onItemRightClick} is where non-continuous spells are cast, and it sets the item in use for continuous spells
    + * - {@code onUsingTick} does the casting for continuous spells
    + * - {@code onUpdate} deals with the cooldowns for the spells
    + *
    + * See {@link ISpellCastingItem} for more detail on the {@code canCast(...)} and {@code cast(...)} methods.
    + * See {@link WandHelper} for everything related to wand NBT. + * * @since Wizardry 1.0 */ -public class ItemWand extends Item implements IWorkbenchItem { +@Mod.EventBusSubscriber +public class ItemWand extends Item implements IWorkbenchItem, ISpellCastingItem, IManaStoringItem { /** The number of spell slots a wand has with no attunement upgrades applied. */ public static final int BASE_SPELL_SLOTS = 5; + /** The number of ticks between each time a continuous spell is added to the player's recently-cast spells. */ + private static final int CONTINUOUS_TRACKING_INTERVAL = 20; + /** The increase in progression for casting spells of the matching element. */ + private static final float ELEMENTAL_PROGRESSION_MODIFIER = 1.2f; + /** The fraction of progression lost when all recently-cast spells are the same as the one being cast. */ + private static final float MAX_PROGRESSION_REDUCTION = 0.75f; + public Tier tier; public Element element; public ItemWand(Tier tier, Element element){ super(); setMaxStackSize(1); - if(element == null || tier == Tier.BASIC){ - setCreativeTab(WizardryTabs.WIZARDRY); - } + setCreativeTab(WizardryTabs.GEAR); this.tier = tier; this.element = element; setMaxDamage(this.tier.maxCharge); + WizardryRecipes.addToManaFlaskCharging(this); + } + + @Override + public Spell getCurrentSpell(ItemStack stack){ + return WandHelper.getCurrentSpell(stack); + } + + @Override + public Spell[] getSpells(ItemStack stack){ + return WandHelper.getSpells(stack); + } + + @Override + public void selectNextSpell(ItemStack stack){ + WandHelper.selectNextSpell(stack); + } + + @Override + public void selectPreviousSpell(ItemStack stack){ + WandHelper.selectPreviousSpell(stack); + } + + @Override + public boolean showSpellHUD(EntityPlayer player, ItemStack stack){ + return true; + } + + @Override + public boolean showTooltip(ItemStack stack){ + return true; + } + + /** Does nothing, use {@link ItemWand#setMana(ItemStack, int)} to modify wand mana. */ + @Override + public void setDamage(ItemStack stack, int damage){ + // Overridden to do nothing to stop repair things from 'repairing' the mana in a wand + } + + @Override + public void setMana(ItemStack stack, int mana){ + // Using super (which can only be done from in here) bypasses the above override + super.setDamage(stack, getManaCapacity(stack) - mana); + } + + @Override + public int getMana(ItemStack stack){ + return getManaCapacity(stack) - getDamage(stack); + } + + @Override + public int getManaCapacity(ItemStack stack){ + return this.getMaxDamage(stack); } @Override @@ -88,40 +149,111 @@ public class ItemWand extends Item implements IWorkbenchItem { @Override @SideOnly(Side.CLIENT) - public FontRenderer getFontRenderer(ItemStack stack){ + public net.minecraft.client.gui.FontRenderer getFontRenderer(ItemStack stack){ return Wizardry.proxy.getFontRenderer(stack); } + @Override + public boolean isEnchantable(ItemStack stack){ + return false; + } + + @Override + public boolean isBookEnchantable(ItemStack stack, ItemStack book){ + return false; + } + + @Override + public boolean hasEffect(ItemStack stack){ + return !Wizardry.settings.legacyWandLevelling && this.tier.level < Tier.MASTER.level + && WandHelper.getProgression(stack) >= Tier.values()[tier.ordinal() + 1].progression; + } + // Max damage is modifiable with upgrades. @Override - public int getMaxDamage(ItemStack itemstack){ + public int getMaxDamage(ItemStack stack){ // + 0.5f corrects small float errors rounding down - return (int)(super.getMaxDamage(itemstack) * (1.0f + Constants.STORAGE_INCREASE_PER_LEVEL - * WandHelper.getUpgradeLevel(itemstack, WizardryItems.storage_upgrade)) + 0.5f); + return (int)(super.getMaxDamage(stack) * (1.0f + Constants.STORAGE_INCREASE_PER_LEVEL + * WandHelper.getUpgradeLevel(stack, WizardryItems.storage_upgrade)) + 0.5f); } @Override - public void onUpdate(ItemStack itemstack, World world, Entity entity, int slot, boolean isHeld){ + public void onCreated(ItemStack stack, World worldIn, EntityPlayer playerIn){ + setMana(stack, 0); // Wands are empty when first crafted + } - WandHelper.decrementCooldowns(itemstack); + @Override + public void onUpdate(ItemStack stack, World world, Entity entity, int slot, boolean isHeld){ + + WandHelper.decrementCooldowns(stack); // Decrements wand damage (increases mana) every 1.5 seconds if it has a condenser upgrade - if(!world.isRemote && itemstack.isItemDamaged() - && world.getWorldTime() % Constants.CONDENSER_TICK_INTERVAL == 0){ + if(!world.isRemote && !this.isManaFull(stack) && world.getTotalWorldTime() % Constants.CONDENSER_TICK_INTERVAL == 0){ // If the upgrade level is 0, this does nothing anyway. - itemstack.setItemDamage( - itemstack.getItemDamage() - WandHelper.getUpgradeLevel(itemstack, WizardryItems.condenser_upgrade)); - } - - if(entity instanceof EntityPlayer && this.element != null && this.element != Element.MAGIC){ - // As it stands, this will trigger every tick. Not ideal, but I can't find a way to detect if a player - // has a certain achievement. - // TODO: check if this is somehow triggerable via JSON conditions. - WizardryAdvancementTriggers.element_master.triggerFor((EntityPlayer)entity); + this.rechargeMana(stack, WandHelper.getUpgradeLevel(stack, WizardryItems.condenser_upgrade)); } } @Override + public Multimap getAttributeModifiers(EntityEquipmentSlot slot, ItemStack stack){ + + Multimap multimap = super.getAttributeModifiers(slot, stack); + + if(slot == EntityEquipmentSlot.MAINHAND){ + int level = WandHelper.getUpgradeLevel(stack, WizardryItems.melee_upgrade); + // This check doesn't affect the damage output, but it does stop a blank line from appearing in the tooltip. + if(level > 0 && !this.isManaEmpty(stack)){ + multimap.put(SharedMonsterAttributes.ATTACK_DAMAGE.getName(), + new AttributeModifier(ATTACK_DAMAGE_MODIFIER, "Melee upgrade modifier", 2 * level, 0)); + multimap.put(SharedMonsterAttributes.ATTACK_SPEED.getName(), new AttributeModifier(ATTACK_SPEED_MODIFIER, "Melee upgrade modifier", -2.4000000953674316D, 0)); + } + } + + return multimap; + } + + @Override + public boolean hitEntity(ItemStack stack, EntityLivingBase target, EntityLivingBase wielder){ + + int level = WandHelper.getUpgradeLevel(stack, WizardryItems.melee_upgrade); + int mana = this.getMana(stack); + + if(level > 0 && mana > 0) this.consumeMana(stack, level * 4, wielder); + + return true; + } + + @Override + public boolean canDestroyBlockInCreative(World world, BlockPos pos, ItemStack stack, EntityPlayer player){ + return WandHelper.getUpgradeLevel(stack, WizardryItems.melee_upgrade) == 0; + } + + // A proper hook was introduced for this in Forge build 14.23.5.2805 - Hallelujah, finally! + // The discussion about this was quite interesting, see the following: + // https://github.com/TeamTwilight/twilightforest/blob/1.12.x/src/main/java/twilightforest/item/ItemTFScepterLifeDrain.java + // https://github.com/MinecraftForge/MinecraftForge/pull/4834 + // Among the things mentioned were that it can be 'fixed' by doing the exact same hacks that I did, and that + // returning a result of PASS rather than SUCCESS from onItemRightClick also solves the problem (not sure why + // though, and again it's not a perfect solution) + // Edit: It seems that the hacky fix in previous versions actually introduced a wand duplication bug... oops + + @Override + public boolean canContinueUsing(ItemStack oldStack, ItemStack newStack){ + // Ignore durability changes + if(ItemStack.areItemsEqualIgnoreDurability(oldStack, newStack)) return true; + return super.canContinueUsing(oldStack, newStack); + } + + @Override + public boolean shouldCauseBlockBreakReset(ItemStack oldStack, ItemStack newStack){ + // Ignore durability changes + if(ItemStack.areItemsEqualIgnoreDurability(oldStack, newStack)) return false; + return super.shouldCauseBlockBreakReset(oldStack, newStack); + } + + @Override + // Only called client-side + // This method is always called on the item in oldStack, meaning that oldStack.getItem() == this public boolean shouldCauseReequipAnimation(ItemStack oldStack, ItemStack newStack, boolean slotChanged){ // This method does some VERY strange things! Despite its name, it also seems to affect the updating of NBT... @@ -149,18 +281,19 @@ public class ItemWand extends Item implements IWorkbenchItem { @SideOnly(Side.CLIENT) @Override - public void addInformation(ItemStack itemstack, World world, List text, ITooltipFlag advanced){ - EntityPlayerSP player = Minecraft.getMinecraft().player; + public void addInformation(ItemStack stack, World world, List text, net.minecraft.client.util.ITooltipFlag advanced){ + + EntityPlayer player = net.minecraft.client.Minecraft.getMinecraft().player; if (player == null) { return; } // +0.5f is necessary due to the error in the way floats are calculated. if(element != null) text.add("\u00A78" + net.minecraft.client.resources.I18n.format("item." + Wizardry.MODID + ":wand.buff", - (int)((tier.level + 1) * Constants.DAMAGE_INCREASE_PER_TIER * 100 + 0.5f) + "%", + (int)((tier.level + 1) * Constants.POTENCY_INCREASE_PER_TIER * 100 + 0.5f) + "%", element.getDisplayName())); - Spell spell = WandHelper.getCurrentSpell(itemstack); + Spell spell = WandHelper.getCurrentSpell(stack); boolean discovered = true; - if(Wizardry.settings.discoveryMode && !player.capabilities.isCreativeMode && WizardData.get(player) != null + if(Wizardry.settings.discoveryMode && !player.isCreative() && WizardData.get(player) != null && !WizardData.get(player).hasSpellBeenDiscovered(spell)){ discovered = false; } @@ -169,8 +302,19 @@ public class ItemWand extends Item implements IWorkbenchItem { discovered ? "\u00A77" + spell.getDisplayNameWithFormatting() : "#\u00A79" + SpellGlyphData.getGlyphName(spell, player.world))); - text.add("\u00A79" + net.minecraft.client.resources.I18n.format("item." + Wizardry.MODID + ":wand.mana", - (this.getMaxDamage(itemstack) - this.getDamage(itemstack)), this.getMaxDamage(itemstack))); + if(advanced.isAdvanced()){ + // Advanced tooltips for debugging + text.add("\u00A79" + net.minecraft.client.resources.I18n.format("item." + Wizardry.MODID + ":wand.mana", + this.getMana(stack), this.getManaCapacity(stack))); + + text.add("\u00A77" + net.minecraft.client.resources.I18n.format("item." + Wizardry.MODID + ":wand.progression", + WandHelper.getProgression(stack), this.tier.level < Tier.MASTER.level ? Tier.values()[tier.ordinal() + 1].progression : 0)); + +// }else{ +// +// ChargeStatus status = ChargeStatus.getChargeStatus(stack); +// text.add(status.getFormattingCode() + status.getDisplayName()); + } } @Override @@ -188,89 +332,29 @@ public class ItemWand extends Item implements IWorkbenchItem { ItemStack stack = player.getHeldItem(hand); // Alternate right-click function; overrides spell casting. - if(this.selectMinionTarget(player, world)) return new ActionResult(EnumActionResult.SUCCESS, stack); + if(this.selectMinionTarget(player, world)) return new ActionResult<>(EnumActionResult.SUCCESS, stack); Spell spell = WandHelper.getCurrentSpell(stack); - SpellModifiers modifiers = this.calculateModifiers(stack, spell); - - // If anything stops the spell working at this point, nothing else happens. - if(MinecraftForge.EVENT_BUS.post(new SpellCastEvent.Pre(player, spell, modifiers, Source.WAND))){ - return new ActionResult(EnumActionResult.FAIL, stack); - } - - // This is here to start the inUse thing, otherwise the onUsingTick method will not fire. - if(spell.isContinuous && !player.isHandActive()){ - player.setActiveHand(hand); - // Probably ought to be here. (Does it succeed though?) - return new ActionResult(EnumActionResult.SUCCESS, stack); - } - - // Conditions for the spell to be attempted. The tier check is a failsafe; it should never be false unless the - // NBT is modified directly. - if(!spell.isContinuous && spell.tier.level <= this.tier.level - // Checks that the wand has enough mana to cast the spell - && spell.cost <= (stack.getMaxDamage() - stack.getItemDamage()) - // Checks that the spell is not in cooldown or that the player is in creative mode - && (WandHelper.getCurrentCooldown(stack) == 0 || player.capabilities.isCreativeMode)){ - - // If the spell does not require a packet, the code is run in the old client-inconsistent way, since this - // means that swingItem() doesn't need packets in order to work, improving performance. - if(!world.isRemote){ - - if(spell.cast(world, player, hand, 0, modifiers)){ - - MinecraftForge.EVENT_BUS.post(new SpellCastEvent.Post(player, spell, modifiers, Source.WAND)); - - // = Packets = - if(spell.doesSpellRequirePacket()){ - // Sends a packet to all players in dimension to tell them to spawn particles. - // Only sent if the spell succeeded, because if the spell failed, you wouldn't - // need to spawn any particles! - IMessage msg = new PacketCastSpell.Message(player.getEntityId(), hand, spell.id(), modifiers); - WizardryPacketHandler.net.sendToDimension(msg, world.provider.getDimension()); - } + SpellModifiers modifiers = this.calculateModifiers(stack, player, spell); + if(canCast(stack, spell, player, hand, 0, modifiers)){ + // Now we can cast continuous spells with scrolls! + if(spell.isContinuous){ + if(!player.isHandActive()){ player.setActiveHand(hand); - - // = Cooldown = - // Spells only have a cooldown in survival - if(!player.capabilities.isCreativeMode){ - - float cooldownMultiplier = 1.0f - - WandHelper.getUpgradeLevel(stack, WizardryItems.cooldown_upgrade) - * Constants.COOLDOWN_REDUCTION_PER_LEVEL; - - if(player.isPotionActive(WizardryPotions.font_of_mana)){ - // Dividing by this rather than setting it takes upgrades and font of mana into account - // simultaneously - cooldownMultiplier /= 2 - + player.getActivePotionEffect(WizardryPotions.font_of_mana).getAmplifier(); - } - - WandHelper.setCurrentCooldown(stack, (int)(spell.cooldown * cooldownMultiplier)); - } - - // = Mana cost = - // The spell costs 20% less for every armour piece of the matching element. - int armourPieces = getMatchingArmourCount(player, spell); - - stack.damageItem((int)(spell.cost * (1.0f - armourPieces * Constants.COST_REDUCTION_PER_ARMOUR)), - player); - - return new ActionResult(EnumActionResult.SUCCESS, stack); + // Store the modifiers for use each tick + if(WizardData.get(player) != null) WizardData.get(player).itemCastingModifiers = modifiers; + // Return the player's held item so spells can change it if they wish (e.g. possession) + return new ActionResult<>(EnumActionResult.SUCCESS, player.getHeldItem(hand)); } - - }else if(!spell.doesSpellRequirePacket()){ - // Client-inconsistent spell casting. This code only runs client-side. - if(spell.cast(world, player, hand, 0, modifiers)){ - // This is all that needs to happen, because everything above works fine on just the server side. - MinecraftForge.EVENT_BUS.post(new SpellCastEvent.Post(player, spell, modifiers, Source.WAND)); - return new ActionResult(EnumActionResult.SUCCESS, stack); + }else{ + if(cast(stack, spell, player, hand, 0, modifiers)){ + return new ActionResult<>(EnumActionResult.SUCCESS, player.getHeldItem(hand)); } } } - return new ActionResult(EnumActionResult.FAIL, stack); + return new ActionResult<>(EnumActionResult.FAIL, stack); } // For continuous spells. The count argument actually decrements by 1 each tick. @@ -282,72 +366,155 @@ public class ItemWand extends Item implements IWorkbenchItem { EntityPlayer player = (EntityPlayer)user; Spell spell = WandHelper.getCurrentSpell(stack); - SpellModifiers modifiers = this.calculateModifiers(stack, spell); + + SpellModifiers modifiers; + + if(WizardData.get(player) != null){ + modifiers = WizardData.get(player).itemCastingModifiers; + }else{ + modifiers = this.calculateModifiers(stack, (EntityPlayer)user, spell); // Fallback to the old way, should never be used + } + int castingTick = stack.getMaxItemUseDuration() - count; - if(MinecraftForge.EVENT_BUS - .post(new SpellCastEvent.Tick(player, spell, modifiers, Source.WAND, castingTick))) - return; - // Continuous spells (these must check if they can be cast each tick since the mana changes) - if(spell.isContinuous && spell.tier.level <= this.tier.level - && spell.cost / 5 <= (stack.getMaxDamage() - stack.getItemDamage())){ + // Don't call canCast when castingTick == 0 because we already did it in onItemRightClick + if(spell.isContinuous && (castingTick == 0 || canCast(stack, spell, player, player.getActiveHand(), castingTick, modifiers))){ + cast(stack, spell, player, player.getActiveHand(), castingTick, modifiers); + }else{ + // Stops the casting if it was interrupted, either by events or because the wand ran out of mana + player.stopActiveHand(); + } + } + } - if(spell.cast(player.world, player, player.getActiveHand(), castingTick, modifiers)){ + @Override + public boolean canCast(ItemStack stack, Spell spell, EntityPlayer caster, EnumHand hand, int castingTick, SpellModifiers modifiers){ - if(castingTick == 0) - MinecraftForge.EVENT_BUS.post(new SpellCastEvent.Post(player, spell, modifiers, Source.WAND)); + // Spells can only be cast if the casting events aren't cancelled... + if(castingTick == 0){ + if(MinecraftForge.EVENT_BUS.post(new SpellCastEvent.Pre(Source.WAND, spell, caster, modifiers))) return false; + }else{ + if(MinecraftForge.EVENT_BUS.post(new SpellCastEvent.Tick(Source.WAND, spell, caster, modifiers, castingTick))) return false; + } - // = Mana cost = - // Divides the mana cost over a second appropriately; since damage is an integer it cannot - // just be divided by 20. - // Now does five times per second regardless of the spell cost, but each time it does 1/5 of the - // cost per second. - int tickNumber = (count % 20) + 1; - // Tests if the tick counter is a multiple of 4 plus 1, i.e. is true when tickNumber = 1, 5, 9, 13 - // or 17. - // Made a slight adjustment since the counter starts on 1 and not 4. - if(tickNumber % 4 == 1){ + int cost = (int)(spell.getCost() * modifiers.get(SpellModifiers.COST)); - int armourPieces = getMatchingArmourCount(player, spell); + // As of wizardry 4.2 mana cost is only divided over two intervals each second + if(spell.isContinuous) cost = getDistributedCost(cost, castingTick); - switch(armourPieces){ + // ...and the wand has enough mana to cast the spell... + return cost <= this.getMana(stack) // This comes first because it changes over time + // ...and the wand is the same tier as the spell or higher... + && spell.getTier().level <= this.tier.level + // ...and either the spell is not in cooldown or the player is in creative mode + && (WandHelper.getCurrentCooldown(stack) == 0 || caster.isCreative()); + } - case 0: - stack.damageItem(spell.cost / 5, player); - break; + @Override + public boolean cast(ItemStack stack, Spell spell, EntityPlayer caster, EnumHand hand, int castingTick, SpellModifiers modifiers){ - case 1: - if(tickNumber != 17) stack.damageItem(spell.cost / 5, player); - break; + World world = caster.world; - case 2: - if(tickNumber != 9 && tickNumber != 17) stack.damageItem(spell.cost / 5, player); - break; + if(world.isRemote && !spell.isContinuous && spell.requiresPacket()) return false; - case 3: - if(tickNumber != 5 && tickNumber != 13 && tickNumber != 17) - stack.damageItem(spell.cost / 5, player); - break; + if(spell.cast(world, caster, hand, castingTick, modifiers)){ - case 4: - if(tickNumber == 1) stack.damageItem(spell.cost / 5, player); - break; + if(castingTick == 0) MinecraftForge.EVENT_BUS.post(new SpellCastEvent.Post(Source.WAND, spell, caster, modifiers)); - } + if(!world.isRemote){ + + // Continuous spells never require packets so don't rely on the requiresPacket method to specify it + if(!spell.isContinuous && spell.requiresPacket()){ + // Sends a packet to all players in dimension to tell them to spawn particles. + IMessage msg = new PacketCastSpell.Message(caster.getEntityId(), hand, spell, modifiers); + WizardryPacketHandler.net.sendToDimension(msg, world.provider.getDimension()); + } + + caster.setActiveHand(hand); + + // Mana cost + int cost = (int)(spell.getCost() * modifiers.get(SpellModifiers.COST)); + // As of wizardry 4.2 mana cost is only divided over two intervals each second + if(spell.isContinuous) cost = getDistributedCost(cost, castingTick); + + if(cost > 0) this.consumeMana(stack, cost, caster); + + } + + // Cooldown + if(!spell.isContinuous && !caster.isCreative()){ // Spells only have a cooldown in survival + WandHelper.setCurrentCooldown(stack, (int)(spell.getCooldown() * modifiers.get(WizardryItems.cooldown_upgrade))); + } + + // Progression + if(this.tier.level < Tier.MASTER.level && castingTick % CONTINUOUS_TRACKING_INTERVAL == 0){ + + // We don't care about cost modifiers here, otherwise players would be penalised for wearing robes! + int progression = (int)(spell.getCost() * modifiers.get(SpellModifiers.PROGRESSION)); + WandHelper.addProgression(stack, progression); + + if(!Wizardry.settings.legacyWandLevelling){ // Don't display the message if legacy wand levelling is enabled + // If the wand just gained enough progression to be upgraded... + Tier nextTier = Tier.values()[tier.ordinal() + 1]; + int excess = WandHelper.getProgression(stack) - nextTier.progression; + if(excess >= 0 && excess < progression){ + // ...display a message above the player's hotbar + caster.playSound(WizardrySounds.ITEM_WAND_LEVELUP, 1.25f, 1); + if(!world.isRemote) + caster.sendMessage(new TextComponentTranslation("item." + Wizardry.MODID + ":wand.levelup", + this.getItemStackDisplayName(stack), nextTier.getNameForTranslationFormatted())); } } + + WizardData.get(caster).trackRecentSpell(spell); + } + + return true; + } + + return false; + } + + @Override + public void onPlayerStoppedUsing(ItemStack stack, World world, EntityLivingBase user, int timeLeft){ + + if(user instanceof EntityPlayer){ + + EntityPlayer player = (EntityPlayer)user; + + Spell spell = WandHelper.getCurrentSpell(stack); + + SpellModifiers modifiers; + + if(WizardData.get(player) != null){ + modifiers = WizardData.get(player).itemCastingModifiers; + }else{ + modifiers = this.calculateModifiers(stack, (EntityPlayer)user, spell); // Fallback to the old way, should never be used + } + + int castingTick = stack.getMaxItemUseDuration() - timeLeft; // Might as well include this + + int cost = getDistributedCost((int)(spell.getCost() * modifiers.get(SpellModifiers.COST)), castingTick); + + // Still need to check there's enough mana or the spell will finish twice, since running out of mana is + // handled separately. + if(spell.isContinuous && spell.getTier().level <= this.tier.level && cost <= this.getMana(stack)){ + + MinecraftForge.EVENT_BUS.post(new SpellCastEvent.Finish(Source.WAND, spell, player, modifiers, castingTick)); + spell.finishCasting(world, player, Double.NaN, Double.NaN, Double.NaN, null, castingTick, modifiers); + + if(!player.isCreative()){ // Spells only have a cooldown in survival + WandHelper.setCurrentCooldown(stack, (int)(spell.getCooldown() * modifiers.get(WizardryItems.cooldown_upgrade))); + } } } } @Override - public boolean itemInteractionForEntity(ItemStack stack, EntityPlayer player, EntityLivingBase entity, - EnumHand hand){ + public boolean itemInteractionForEntity(ItemStack stack, EntityPlayer player, EntityLivingBase entity, EnumHand hand){ if(player.isSneaking() && entity instanceof EntityPlayer && WizardData.get(player) != null){ - // This is one of those "the method doing the work looks as if it's just returning a value" situations. - // ... I know, right?! I feel very programmer-y. But it's not too confusing here, and it looks neat. String string = WizardData.get(player).toggleAlly((EntityPlayer)entity) ? "item." + Wizardry.MODID + ":wand.addally" : "item." + Wizardry.MODID + ":wand.removeally"; if(!player.world.isRemote) player.sendMessage(new TextComponentTranslation(string, entity.getName())); @@ -357,8 +524,27 @@ public class ItemWand extends Item implements IWorkbenchItem { return false; } + /** Distributes the given cost (which should be the per-second cost of a continuous spell) over a second and + * returns the appropriate cost to be applied for the given tick. Currently the cost is distributed over 2 + * intervals per second, meaning the returned value is 0 unless {@code castingTick} is a multiple of 10.*/ + protected static int getDistributedCost(int cost, int castingTick){ + + int partialCost; + + if(castingTick % 20 == 0){ // Whole number of seconds has elapsed + partialCost = cost / 2 + cost % 2; // Make sure cost adds up to the correct value by adding the remainder here + }else if(castingTick % 10 == 0){ // Something-and-a-half seconds has elapsed + partialCost = cost/2; + }else{ // Some other number of ticks has elapsed + partialCost = 0; // Wands aren't damaged within half-seconds + } + + return partialCost; + } + /** Returns a SpellModifiers object with the appropriate modifiers applied for the given ItemStack and Spell. */ - protected SpellModifiers calculateModifiers(ItemStack stack, Spell spell){ + // This is now public because artefacts use it + public SpellModifiers calculateModifiers(ItemStack stack, EntityPlayer player, Spell spell){ SpellModifiers modifiers = new SpellModifiers(); @@ -375,38 +561,26 @@ public class ItemWand extends Item implements IWorkbenchItem { if(level > 0) modifiers.set(WizardryItems.blast_upgrade, 1.0f + level * Constants.BLAST_RADIUS_INCREASE_PER_LEVEL, true); - // I would have liked to have made potion effects increase in strength according to the damage multiplier, - // but the amplifier level is too discrete to make this work. For example, wither 3 for 10 seconds will kill a - // normal mob on full 20 health, but wither 2 for the same duration only deals about 6 hearts of damage in - // total. - if(this.element == spell.element){ - modifiers.set(SpellModifiers.POTENCY, 1.0f + (this.tier.level + 1) * Constants.DAMAGE_INCREASE_PER_TIER, - true); + level = WandHelper.getUpgradeLevel(stack, WizardryItems.cooldown_upgrade); + if(level > 0) + modifiers.set(WizardryItems.cooldown_upgrade, 1.0f - level * Constants.COOLDOWN_REDUCTION_PER_LEVEL, true); + + float progressionModifier = 1.0f - ((float)WizardData.get(player).countRecentCasts(spell) / WizardData.MAX_RECENT_SPELLS) + * MAX_PROGRESSION_REDUCTION; + + if(this.element == spell.getElement()){ + modifiers.set(SpellModifiers.POTENCY, 1.0f + (this.tier.level + 1) * Constants.POTENCY_INCREASE_PER_TIER, true); + progressionModifier *= ELEMENTAL_PROGRESSION_MODIFIER; } + modifiers.set(SpellModifiers.PROGRESSION, progressionModifier, false); + return modifiers; } - /** Counts the number of armour pieces the given player is wearing that match the given spell's element. */ - private int getMatchingArmourCount(EntityPlayer player, Spell spell){ - - int armourPieces = 0; - - for(EntityEquipmentSlot slot : WizardryUtilities.ARMOUR_SLOTS){ - - ItemStack armour = player.getItemStackFromSlot(slot); - - if(armour != null && armour.getItem() instanceof ItemWizardArmour - && ((ItemWizardArmour)armour.getItem()).element == spell.element) - armourPieces++; - } - - return armourPieces; - } - private boolean selectMinionTarget(EntityPlayer player, World world){ - RayTraceResult rayTrace = WizardryUtilities.standardEntityRayTrace(world, player, 16, false); + RayTraceResult rayTrace = RayTracer.standardEntityRayTrace(world, player, 16, false); if(rayTrace != null && WizardryUtilities.isLiving(rayTrace.entityHit)){ @@ -430,6 +604,8 @@ public class ItemWand extends Item implements IWorkbenchItem { return false; } + // Workbench stuff + @Override public int getSpellSlotCount(ItemStack stack){ return BASE_SPELL_SLOTS + WandHelper.getUpgradeLevel(stack, WizardryItems.attunement_upgrade); @@ -444,24 +620,31 @@ public class ItemWand extends Item implements IWorkbenchItem { // and also the entire NBT tag compound. if(upgrade.getStack().getItem() == WizardryItems.arcane_tome){ - // Checks the wand upgrade is for the tier above the wand's tier. + Tier tier = Tier.values()[upgrade.getStack().getItemDamage()]; + + // Checks the wand upgrade is for the tier above the wand's tier, and that either the wand has enough + // progression or the player is in creative mode. // It is guaranteed that: this == centre.getStack().getItem() - if(upgrade.getStack().getItemDamage() - 1 == this.tier.ordinal()){ - - Tier tier = Tier.values()[upgrade.getStack().getItemDamage()]; - - ItemStack newWand = new ItemStack(WizardryUtilities.getWand(tier, this.element)); + if((player.isCreative() || Wizardry.settings.legacyWandLevelling + || WandHelper.getProgression(centre.getStack()) >= tier.progression) + && tier.ordinal() - 1 == this.tier.ordinal()){ + + // We're not carrying over excess progression for now, but if we do want to, this is how +// if(!Wizardry.settings.legacyWandLevelling){ +// // Easy way to carry excess progression over to the new stack +// WandHelper.setProgression(centre.getStack(), WandHelper.getProgression(centre.getStack()) - tier.progression); +// } + + ItemStack newWand = new ItemStack(WizardryItems.getWand(tier, this.element)); newWand.setTagCompound(centre.getStack().getTagCompound()); - // This needs to be done after copying the tag compound so the max damage for the new wand - // takes storage upgrades into account. - newWand.setItemDamage(newWand.getMaxDamage() - (centre.getStack().getMaxDamage() - centre.getStack().getItemDamage())); - + // This needs to be done after copying the tag compound so the mana capacity for the new wand + // takes storage upgrades into account + // Note the usage of the new wand item and not 'this' to ensure the correct capacity is used + ((IManaStoringItem)newWand.getItem()).setMana(newWand, this.getMana(centre.getStack())); + centre.putStack(newWand); upgrade.decrStackSize(1); - if(tier == Tier.APPRENTICE) WizardryAdvancementTriggers.apprentice.triggerFor(player); - if(tier == Tier.MASTER) WizardryAdvancementTriggers.master.triggerFor(player); - changed = true; } @@ -474,14 +657,14 @@ public class ItemWand extends Item implements IWorkbenchItem { && WandHelper.getUpgradeLevel(centre.getStack(), specialUpgrade) < Constants.UPGRADE_STACK_LIMIT){ // Used to preserve existing mana when upgrading storage rather than creating free mana. - int prevMana = centre.getStack().getMaxDamage() - centre.getStack().getItemDamage(); + int prevMana = this.getMana(centre.getStack()); WandHelper.applyUpgrade(centre.getStack(), specialUpgrade); // Special behaviours for specific upgrades if(specialUpgrade == WizardryItems.storage_upgrade){ - - centre.getStack().setItemDamage(centre.getStack().getMaxDamage() - prevMana); + + this.setMana(centre.getStack(), prevMana); }else if(specialUpgrade == WizardryItems.attunement_upgrade){ @@ -501,9 +684,7 @@ public class ItemWand extends Item implements IWorkbenchItem { int[] newCooldowns = new int[newSlotCount]; if(cooldowns.length > 0){ - for(int i = 0; i < cooldowns.length; i++){ - newCooldowns[i] = cooldowns[i]; - } + System.arraycopy(cooldowns, 0, newCooldowns, 0, cooldowns.length); } WandHelper.setCooldowns(centre.getStack(), newCooldowns); @@ -520,7 +701,7 @@ public class ItemWand extends Item implements IWorkbenchItem { } } - // Reads NBT spell id array to variable, edits this, then writes it back to NBT. + // Reads NBT spell metadata array to variable, edits this, then writes it back to NBT. // Original spells are preserved; if a slot is left empty the existing spell binding will remain. // Accounts for spells which cannot be applied because they are above the wand's tier; these spells // will not bind but the existing spell in that slot will remain and other applicable spells will @@ -535,9 +716,9 @@ public class ItemWand extends Item implements IWorkbenchItem { for(int i = 0; i < spells.length; i++){ if(spellBooks[i].getStack() != ItemStack.EMPTY){ - Spell spell = Spell.get(spellBooks[i].getStack().getItemDamage()); - // If the wand is powerful enough for the spell and it's not already bound to that slot - if(!(spell.tier.level > this.tier.level) && spells[i] != spell){ + Spell spell = Spell.byMetadata(spellBooks[i].getStack().getItemDamage()); + // If the wand is powerful enough for the spell, it's not already bound to that slot and it's enabled for wands + if(!(spell.getTier().level > this.tier.level) && spells[i] != spell && spell.isEnabled(SpellProperties.Context.WANDS)){ spells[i] = spell; changed = true; } @@ -547,24 +728,67 @@ public class ItemWand extends Item implements IWorkbenchItem { WandHelper.setSpells(centre.getStack(), spells); // Charges wand by appropriate amount - if(crystals.getStack() != ItemStack.EMPTY){ + if(crystals.getStack() != ItemStack.EMPTY && !this.isManaFull(centre.getStack())){ - int chargeDepleted = centre.getStack().getItemDamage(); - - if(crystals.getStack().getCount() * Constants.MANA_PER_CRYSTAL < chargeDepleted){ - - centre.getStack().setItemDamage(chargeDepleted - crystals.getStack().getCount() * Constants.MANA_PER_CRYSTAL); - crystals.decrStackSize(crystals.getStack().getCount()); - changed = true; - - }else if(chargeDepleted != 0){ + int chargeDepleted = this.getManaCapacity(centre.getStack()) - this.getMana(centre.getStack()); - centre.getStack().setItemDamage(0); - crystals.decrStackSize((int)Math.ceil(((double)chargeDepleted) / Constants.MANA_PER_CRYSTAL)); - changed = true; + int manaPerItem = Constants.MANA_PER_CRYSTAL; + 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; } return changed; } + + // hitEntity is only called server-side, so we'll have to use events + @SubscribeEvent + public static void onAttackEntityEvent(AttackEntityEvent event){ + + EntityPlayer player = event.getEntityPlayer(); + ItemStack stack = player.getHeldItemMainhand(); // Can't melee with offhand items + + if(stack.getItem() instanceof IManaStoringItem){ + + // Nobody said it had to be a wand, as long as it's got a melee upgrade it counts + int level = WandHelper.getUpgradeLevel(stack, WizardryItems.melee_upgrade); + int mana = ((IManaStoringItem)stack.getItem()).getMana(stack); + + if(level > 0 && mana > 0){ + + Random random = player.world.rand; + + player.world.playSound(player.posX, player.posY, player.posZ, WizardrySounds.ITEM_WAND_MELEE, SoundCategory.PLAYERS, 0.75f, 1, false); + + if(player.world.isRemote){ + + Vec3d origin = new Vec3d(player.posX, player.getEntityBoundingBox().minY + player.getEyeHeight(), player.posZ); + Vec3d hit = origin.add(player.getLookVec().scale(player.getDistance(event.getTarget()))); + // Generate two perpendicular vectors in the plane perpendicular to the look vec + Vec3d vec1 = player.getLookVec().rotatePitch(90); + Vec3d vec2 = player.getLookVec().crossProduct(vec1); + + for(int i = 0; i < 15; i++){ + ParticleBuilder.create(Type.SPARKLE).pos(hit) + .vel(vec1.scale(random.nextFloat() * 0.3f - 0.15f).add(vec2.scale(random.nextFloat() * 0.3f - 0.15f))) + .clr(1f, 1f, 1f).fade(0.3f, 0.5f, 1) + .time(8 + random.nextInt(4)).spawn(player.world); + } + } + } + } + } + } diff --git a/src/main/java/electroblob/wizardry/item/ItemWandUpgrade.java b/src/main/java/electroblob/wizardry/item/ItemWandUpgrade.java new file mode 100644 index 00000000..c9766b10 --- /dev/null +++ b/src/main/java/electroblob/wizardry/item/ItemWandUpgrade.java @@ -0,0 +1,32 @@ +package electroblob.wizardry.item; + +import electroblob.wizardry.Wizardry; +import electroblob.wizardry.registry.WizardryTabs; +import net.minecraft.item.EnumRarity; +import net.minecraft.item.Item; +import net.minecraft.item.ItemStack; +import net.minecraft.world.World; +import net.minecraftforge.fml.relauncher.Side; +import net.minecraftforge.fml.relauncher.SideOnly; + +import javax.annotation.Nullable; +import java.util.List; + +public class ItemWandUpgrade extends Item { + + public ItemWandUpgrade(){ + super(); + this.setCreativeTab(WizardryTabs.WIZARDRY); + } + + @Override + public EnumRarity getRarity(ItemStack stack){ + return EnumRarity.UNCOMMON; + } + + @Override + @SideOnly(Side.CLIENT) + public void addInformation(ItemStack stack, @Nullable World world, List tooltip, net.minecraft.client.util.ITooltipFlag flag) { + Wizardry.proxy.addMultiLineDescription(tooltip, "item." + this.getRegistryName() + ".desc"); + } +} diff --git a/src/main/java/electroblob/wizardry/item/ItemWizardArmour.java b/src/main/java/electroblob/wizardry/item/ItemWizardArmour.java index c3d42872..1e7c2708 100644 --- a/src/main/java/electroblob/wizardry/item/ItemWizardArmour.java +++ b/src/main/java/electroblob/wizardry/item/ItemWizardArmour.java @@ -1,24 +1,24 @@ package electroblob.wizardry.item; -import java.util.List; -import java.util.UUID; - import com.google.common.collect.HashMultimap; import com.google.common.collect.Multimap; - +import com.google.common.collect.Streams; import electroblob.wizardry.Wizardry; -import electroblob.wizardry.block.BlockStatue; import electroblob.wizardry.constants.Constants; import electroblob.wizardry.constants.Element; +import electroblob.wizardry.event.SpellCastEvent; import electroblob.wizardry.registry.WizardryAdvancementTriggers; import electroblob.wizardry.registry.WizardryItems; +import electroblob.wizardry.registry.WizardryRecipes; import electroblob.wizardry.registry.WizardryTabs; -import net.minecraft.client.model.ModelBiped; -import net.minecraft.client.util.ITooltipFlag; +import electroblob.wizardry.util.SpellModifiers; +import electroblob.wizardry.util.WizardryUtilities; import net.minecraft.entity.Entity; +import net.minecraft.entity.EntityLiving; import net.minecraft.entity.EntityLivingBase; import net.minecraft.entity.SharedMonsterAttributes; import net.minecraft.entity.ai.attributes.AttributeModifier; +import net.minecraft.entity.ai.attributes.IAttributeInstance; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.inventory.EntityEquipmentSlot; import net.minecraft.inventory.Slot; @@ -28,14 +28,19 @@ import net.minecraft.item.ItemStack; import net.minecraft.nbt.NBTTagCompound; import net.minecraft.util.EnumHandSide; import net.minecraft.world.World; -import net.minecraftforge.event.entity.living.LivingEvent.LivingUpdateEvent; +import net.minecraftforge.event.entity.living.LivingSetAttackTargetEvent; import net.minecraftforge.fml.common.Mod; +import net.minecraftforge.fml.common.eventhandler.EventPriority; import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; import net.minecraftforge.fml.relauncher.Side; import net.minecraftforge.fml.relauncher.SideOnly; +import java.util.Arrays; +import java.util.List; +import java.util.UUID; + @Mod.EventBusSubscriber -public class ItemWizardArmour extends ItemArmor implements IWorkbenchItem { +public class ItemWizardArmour extends ItemArmor implements IWorkbenchItem, IManaStoringItem { // VanillaCopy, ItemArmor has this set to private for some reason. public static final UUID[] ARMOR_MODIFIERS = new UUID[] {UUID.fromString("845DB27C-C624-495F-8C9F-6020A9A58B6B"), UUID.fromString("D8499B04-0E66-4726-AB29-64469D734E0D"), UUID.fromString("9F3D476D-C118-4544-8365-64846904B48E"), UUID.fromString("2AD3F246-FEE1-4E67-B886-69FD380BB150")}; @@ -47,20 +52,53 @@ public class ItemWizardArmour extends ItemArmor implements IWorkbenchItem { public ItemWizardArmour(ArmorMaterial material, int renderIndex, EntityEquipmentSlot armourType, Element element){ super(material, renderIndex, armourType); this.element = element; - setCreativeTab(WizardryTabs.WIZARDRY); + setCreativeTab(WizardryTabs.GEAR); + WizardryRecipes.addToManaFlaskCharging(this); + } + + /** Should only be used by vanilla's armour damage calculations; use {@link ItemWizardArmour#setMana(ItemStack, int)} + * to modify wand mana from elsewhere. */ + @Override + public void setDamage(ItemStack stack, int damage){ + // Overridden to stop repair things from 'repairing' the mana in wizard armour + // This being armour, it's much easier to let its damage increase normally, but block it from being decreased + if(stack.getItemDamage() < damage) super.setDamage(stack, damage); + } + + @Override + public void setMana(ItemStack stack, int mana){ + // Using super (which can only be done from in here) bypasses the above override + super.setDamage(stack, getManaCapacity(stack) - mana); + } + + @Override + public int getMana(ItemStack stack){ + return getManaCapacity(stack) - getDamage(stack); + } + + @Override + public int getManaCapacity(ItemStack stack){ + return this.getMaxDamage(stack); } @Override @SideOnly(Side.CLIENT) - public void addInformation(ItemStack stack, World world, List tooltip, ITooltipFlag advanced){ + public void addInformation(ItemStack stack, World world, List tooltip, net.minecraft.client.util.ITooltipFlag advanced){ - if(stack.hasTagCompound() && stack.getTagCompound().getBoolean("legendary")) tooltip - .add("\u00A7d" + net.minecraft.client.resources.I18n.format("item." + Wizardry.MODID + ":wizard_armour.legendary")); - if(element != null) + if(stack.hasTagCompound() && stack.getTagCompound().getBoolean("legendary")) + tooltip.add("\u00A7d" + net.minecraft.client.resources.I18n.format("item." + Wizardry.MODID + ":wizard_armour.legendary")); + + if(element != null){ tooltip.add("\u00A78" + net.minecraft.client.resources.I18n.format("item." + Wizardry.MODID + ":wizard_armour.buff", (int)(Constants.COST_REDUCTION_PER_ARMOUR * 100) + "%", element.getDisplayName())); - tooltip.add("\u00A79" + net.minecraft.client.resources.I18n.format("item." + Wizardry.MODID + ":wizard_armour.mana", - (this.getMaxDamage(stack) - this.getDamage(stack)), this.getMaxDamage(stack))); + } + + // tooltip.add("\u00A79" + net.minecraft.client.resources.I18n.format("item." + Wizardry.MODID + ":wizard_armour.mana", +// (this.getMaxDamage(stack) - this.getDamage(stack)), this.getMaxDamage(stack))); + +// ChargeStatus status = ChargeStatus.getChargeStatus(stack); +// +// tooltip.add(status.getFormattingCode() + status.getDisplayName()); } @Override @@ -70,32 +108,23 @@ public class ItemWizardArmour extends ItemArmor implements IWorkbenchItem { @Override @SideOnly(Side.CLIENT) - public boolean hasEffect(ItemStack stack){ - return stack.hasTagCompound() && stack.getTagCompound().getBoolean("legendary"); - } - - @Override - @SideOnly(Side.CLIENT) - public ModelBiped getArmorModel(EntityLivingBase entityLiving, ItemStack itemStack, - EntityEquipmentSlot armourSlot, ModelBiped _default){ - - ModelBiped model = Wizardry.proxy.getWizardArmourModel(); + public net.minecraft.client.model.ModelBiped getArmorModel(EntityLivingBase entityLiving, ItemStack itemStack, + EntityEquipmentSlot armourSlot, net.minecraft.client.model.ModelBiped _default){ // Legs use modelBiped - if(armourSlot == EntityEquipmentSlot.LEGS) return null; + if(armourSlot == EntityEquipmentSlot.LEGS && !entityLiving.isInvisible()) return null; + + net.minecraft.client.model.ModelBiped model = Wizardry.proxy.getWizardArmourModel(); if(model != null){ model.bipedHead.showModel = armourSlot == EntityEquipmentSlot.HEAD; model.bipedHeadwear.showModel = false; - model.bipedBody.showModel = armourSlot == EntityEquipmentSlot.CHEST - || armourSlot == EntityEquipmentSlot.LEGS; + model.bipedBody.showModel = armourSlot == EntityEquipmentSlot.CHEST; model.bipedRightArm.showModel = armourSlot == EntityEquipmentSlot.CHEST; model.bipedLeftArm.showModel = armourSlot == EntityEquipmentSlot.CHEST; - model.bipedRightLeg.showModel = armourSlot == EntityEquipmentSlot.LEGS - || armourSlot == EntityEquipmentSlot.FEET; - model.bipedLeftLeg.showModel = armourSlot == EntityEquipmentSlot.LEGS - || armourSlot == EntityEquipmentSlot.FEET; + model.bipedRightLeg.showModel = armourSlot == EntityEquipmentSlot.FEET; + model.bipedLeftLeg.showModel = armourSlot == EntityEquipmentSlot.FEET; model.isSneak = entityLiving.isSneaking(); model.isRiding = entityLiving.isRiding(); @@ -107,29 +136,29 @@ public class ItemWizardArmour extends ItemArmor implements IWorkbenchItem { ItemStack itemstackL = leftHanded ? entityLiving.getHeldItemMainhand() : entityLiving.getHeldItemOffhand(); if(!itemstackR.isEmpty()){ - model.rightArmPose = ModelBiped.ArmPose.ITEM; + model.rightArmPose = net.minecraft.client.model.ModelBiped.ArmPose.ITEM; if(entityLiving.getItemInUseCount() > 0){ EnumAction enumaction = itemstackR.getItemUseAction(); if(enumaction == EnumAction.BLOCK){ - model.rightArmPose = ModelBiped.ArmPose.BLOCK; + model.rightArmPose = net.minecraft.client.model.ModelBiped.ArmPose.BLOCK; }else if(enumaction == EnumAction.BOW){ - model.rightArmPose = ModelBiped.ArmPose.BOW_AND_ARROW; + model.rightArmPose = net.minecraft.client.model.ModelBiped.ArmPose.BOW_AND_ARROW; } } } if(!itemstackL.isEmpty()){ - model.leftArmPose = ModelBiped.ArmPose.ITEM; + model.leftArmPose = net.minecraft.client.model.ModelBiped.ArmPose.ITEM; if(entityLiving.getItemInUseCount() > 0){ EnumAction enumaction1 = itemstackL.getItemUseAction(); if(enumaction1 == EnumAction.BLOCK){ - model.leftArmPose = ModelBiped.ArmPose.BLOCK; + model.leftArmPose = net.minecraft.client.model.ModelBiped.ArmPose.BLOCK; }else if(enumaction1 == EnumAction.BOW){ - model.leftArmPose = ModelBiped.ArmPose.BOW_AND_ARROW; + model.leftArmPose = net.minecraft.client.model.ModelBiped.ArmPose.BOW_AND_ARROW; } } } @@ -144,33 +173,33 @@ public class ItemWizardArmour extends ItemArmor implements IWorkbenchItem { // Returns a completely transparent texture if the player is invisible. This is such an annoyingly easy // fix, considering how long I spent trying to do this before - a bit of lateral thinking was all it took. // Do note however that a texture pack could override this. - if(entity instanceof EntityLivingBase && ((EntityLivingBase)entity).isInvisible() - && !entity.getEntityData().getBoolean(BlockStatue.NBT_KEY)) - return "ebwizardry:textures/armour/invisible_armour.png"; +// if(entity instanceof EntityLivingBase && entity.isInvisible() && !entity.getEntityData().getBoolean(BlockStatue.PETRIFIED_NBT_KEY)) +// return "ebwizardry:textures/armour/invisible_armour.png"; - if(slot == EntityEquipmentSlot.LEGS) - return this.element == null ? "ebwizardry:textures/armour/wizard_armour_legs.png" - : "ebwizardry:textures/armour/wizard_armour_" + this.element.getUnlocalisedName() + "_legs.png"; + String s = "wizard_armour"; - return this.element == null ? "ebwizardry:textures/armour/wizard_armour.png" - : "ebwizardry:textures/armour/wizard_armour_" + this.element.getUnlocalisedName() + ".png"; + if(this.element != null) s = s + "_" + this.element.getName(); + if(slot == EntityEquipmentSlot.LEGS) s = s + "_legs"; + if(stack.hasTagCompound() && stack.getTagCompound().getBoolean("legendary")) s = "legendary_" + s; + + return "ebwizardry:textures/armour/" + s + ".png"; } @Override - public boolean getIsRepairable(ItemStack stack, ItemStack par2ItemStack){ + public boolean getIsRepairable(ItemStack stack, ItemStack material){ return false; } - /* - * Properly handles the defense value of the armor. This method is responisble for the tooltip on top of - * the armor value. It is also what handles armor toughness, but the wizard armor had a value of 0 for that. + /** + * Properly handles the defence value of the armour. This method is responsible for the tooltip on top of + * the armour value. It is also what handles armour toughness. */ @Override public Multimap getAttributeModifiers(EntityEquipmentSlot slot, ItemStack stack){ Multimap map = HashMultimap.create(); - if(stack.getItemDamage() < stack.getMaxDamage() && this.armorType == slot){ + if(!this.isManaEmpty(stack) && this.armorType == slot){ int defense = reductions[slot.getIndex()]; float toughness = 0f; @@ -189,30 +218,10 @@ public class ItemWizardArmour extends ItemArmor implements IWorkbenchItem { return map; } - // Fixes wizard armor breaking by disallowing setting damage above the max, since damageArmor is not always called. - // Since ISpecialArmor has been removed from this class, this may no longer be necessary, but keeping it won't hurt. + // Workbench stuff + @Override - public void setDamage(ItemStack stack, int damage) { - if(damage <= stack.getMaxDamage()) super.setDamage(stack, damage); - else super.setDamage(stack, stack.getMaxDamage()); - } - - @SubscribeEvent - public static void onLivingUpdateEvent(LivingUpdateEvent event){ - - if(event.getEntityLiving() instanceof EntityPlayer){ - - EntityPlayer player = (EntityPlayer)event.getEntityLiving(); - - for(ItemStack stack : player.getArmorInventoryList()){ - if(!(stack.getItem() instanceof ItemWizardArmour)){ - return; // If any of the armour slots doesn't contain wizard armour, don't trigger the achievement. - } - } - // If it gets this far, then all slots must be wizard armour, so trigger the achievement. - WizardryAdvancementTriggers.armour_set.triggerFor(player); - } - } + public boolean showTooltip(ItemStack stack){ return true; } @Override public int getSpellSlotCount(ItemStack stack){ @@ -241,25 +250,87 @@ public class ItemWizardArmour extends ItemArmor implements IWorkbenchItem { } // Charges armour by appropriate amount - if(crystals.getStack() != ItemStack.EMPTY){ - - int chargeDepleted = centre.getStack().getItemDamage(); - - if(crystals.getStack().getCount() * Constants.MANA_PER_CRYSTAL < chargeDepleted){ - - centre.getStack().setItemDamage(chargeDepleted - crystals.getStack().getCount() * Constants.MANA_PER_CRYSTAL); - crystals.decrStackSize(crystals.getStack().getCount()); - changed = true; - - }else if(chargeDepleted != 0){ + if(crystals.getStack() != ItemStack.EMPTY && !this.isManaFull(centre.getStack())){ - centre.getStack().setItemDamage(0); + int chargeDepleted = this.getManaCapacity(centre.getStack()) - this.getMana(centre.getStack()); + + if(crystals.getStack().getCount() * Constants.MANA_PER_CRYSTAL < chargeDepleted){ + // If there aren't enough crystals to fully charge the armour + this.rechargeMana(centre.getStack(), crystals.getStack().getCount() * Constants.MANA_PER_CRYSTAL); + 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) / Constants.MANA_PER_CRYSTAL)); - changed = true; } + + changed = true; } return changed; } + // Event Handlers + +// @SubscribeEvent +// public static void onLivingUpdateEvent(LivingUpdateEvent event){ +// +// if(event.getEntityLiving() instanceof EntityPlayer){ +// +// EntityPlayer player = (EntityPlayer)event.getEntityLiving(); +// +// for(ItemStack stack : player.getArmorInventoryList()){ +// if(!(stack.getItem() instanceof ItemWizardArmour)){ +// return; // If any of the armour slots doesn't contain wizard armour, don't trigger the achievement. +// } +// } +// // If it gets this far, then all slots must be wizard armour, so trigger the achievement. +// WizardryAdvancementTriggers.armour_set.triggerFor(player); +// } +// } + + @SubscribeEvent(priority = EventPriority.LOW) + public static void onSpellCastPreEvent(SpellCastEvent.Pre event){ + // Armour cost reduction + if(event.getCaster() == null) return; + int armourPieces = getMatchingArmourCount(event.getCaster(), event.getSpell().getElement()); + float multiplier = 1f - armourPieces * Constants.COST_REDUCTION_PER_ARMOUR; + if(armourPieces == WizardryUtilities.ARMOUR_SLOTS.length) multiplier -= Constants.FULL_ARMOUR_SET_BONUS; + event.getModifiers().set(SpellModifiers.COST, event.getModifiers().get(SpellModifiers.COST) * multiplier, false); + } + + /** Counts the number of armour pieces the given entity is wearing that match the given element. */ + public static int getMatchingArmourCount(EntityLivingBase entity, Element element){ + return (int)Arrays.stream(WizardryUtilities.ARMOUR_SLOTS) + .map(s -> entity.getItemStackFromSlot(s).getItem()) + .filter(i -> i instanceof ItemWizardArmour && ((ItemWizardArmour)i).element == element) + .count(); + } + + @SubscribeEvent + public static void onLivingSetAttackTargetEvent(LivingSetAttackTargetEvent event){ + // Undo the mob detection penalty for wearing armour when invisible + // Only bother doing this for players because the penalty only applies to them + if(event.getTarget() instanceof EntityPlayer && event.getEntityLiving() instanceof EntityLiving + && event.getEntityLiving().isInvisible()){ + + int armourPieces = (int)Streams.stream(event.getTarget().getArmorInventoryList()) + .filter(s -> !s.isEmpty() && !(s.getItem() instanceof ItemWizardArmour)) + .count(); + + if(armourPieces == 0) return; + + // Repeat the calculation from EntityAIFindNearestPlayer, but ignoring wizard armour + IAttributeInstance attribute = event.getEntityLiving().getEntityAttribute(SharedMonsterAttributes.FOLLOW_RANGE); + double followRange = attribute == null ? 16 : attribute.getAttributeValue(); + if(event.getTarget().isSneaking()) followRange *= 0.8; + float f = armourPieces / ((EntityPlayer)event.getTarget()).inventory.armorInventory.size(); + if(f < 0.1F) f = 0.1F; + followRange *= (double)(0.7F * f); + // Don't need to worry about the isSuitableTarget check since it must already have been checked to get this far + if(event.getTarget().getDistance(event.getEntity()) > followRange) ((EntityLiving)event.getEntityLiving()).setAttackTarget(null); + } + } + } diff --git a/src/main/java/electroblob/wizardry/item/ItemWizardHandbook.java b/src/main/java/electroblob/wizardry/item/ItemWizardHandbook.java index 67a210c5..e2c6a39b 100644 --- a/src/main/java/electroblob/wizardry/item/ItemWizardHandbook.java +++ b/src/main/java/electroblob/wizardry/item/ItemWizardHandbook.java @@ -1,13 +1,8 @@ package electroblob.wizardry.item; -import java.util.List; - -import javax.annotation.Nullable; - import electroblob.wizardry.Wizardry; import electroblob.wizardry.WizardryGuiHandler; import electroblob.wizardry.registry.WizardryTabs; -import net.minecraft.client.util.ITooltipFlag; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.item.Item; import net.minecraft.item.ItemStack; @@ -16,6 +11,9 @@ import net.minecraft.util.EnumActionResult; import net.minecraft.util.EnumHand; import net.minecraft.world.World; +import javax.annotation.Nullable; +import java.util.List; + public class ItemWizardHandbook extends Item { // Yep, I hardcoded my own name into the mod. Don't want people changing it now, do I? @@ -28,7 +26,7 @@ public class ItemWizardHandbook extends Item { } @Override - public void addInformation(ItemStack stack, @Nullable World worldIn, List tooltip, ITooltipFlag flagIn) { + public void addInformation(ItemStack stack, @Nullable World world, List tooltip, net.minecraft.client.util.ITooltipFlag flag) { tooltip.add( "\u00A77" + net.minecraft.client.resources.I18n.format("item." + Wizardry.MODID + ":wizard_handbook.desc", AUTHOR)); } diff --git a/src/main/java/electroblob/wizardry/loot/RandomSpell.java b/src/main/java/electroblob/wizardry/loot/RandomSpell.java index 9fe703e6..7b9848c0 100644 --- a/src/main/java/electroblob/wizardry/loot/RandomSpell.java +++ b/src/main/java/electroblob/wizardry/loot/RandomSpell.java @@ -1,57 +1,51 @@ package electroblob.wizardry.loot; -import java.util.ArrayList; -import java.util.List; -import java.util.Random; - -import org.apache.commons.lang3.ArrayUtils; - -import com.google.gson.JsonArray; -import com.google.gson.JsonDeserializationContext; -import com.google.gson.JsonElement; -import com.google.gson.JsonObject; -import com.google.gson.JsonPrimitive; -import com.google.gson.JsonSerializationContext; -import com.google.gson.JsonSyntaxException; - +import com.google.gson.*; import electroblob.wizardry.Wizardry; import electroblob.wizardry.constants.Element; import electroblob.wizardry.constants.Tier; +import electroblob.wizardry.data.WizardData; import electroblob.wizardry.item.ItemScroll; import electroblob.wizardry.item.ItemSpellBook; import electroblob.wizardry.spell.Spell; -import electroblob.wizardry.util.WizardryUtilities; +import electroblob.wizardry.util.SpellProperties; +import net.minecraft.entity.player.EntityPlayer; import net.minecraft.item.ItemStack; import net.minecraft.util.JsonUtils; import net.minecraft.util.ResourceLocation; import net.minecraft.world.storage.loot.LootContext; import net.minecraft.world.storage.loot.conditions.LootCondition; import net.minecraft.world.storage.loot.functions.LootFunction; +import org.apache.commons.lang3.ArrayUtils; + +import java.util.ArrayList; +import java.util.List; +import java.util.Random; /** * Loot function that allows spell books and scrolls to select a random spell based on the standard weighting. - * Automatically discounts continuous spells when the item in question is a scroll. Can be used as-is with no - * parameters, but several optional parameters are available for those wishing to customise further: - *

    + * Can be used as-is with no parameters, but several optional parameters are available for those wishing to customise further: + *

    * - spells: A list of spells to choose from. Defaults to all enabled spells.
    * - ignore_weighting: true to ignore the standard weighting and just pick a completely random spell. Defaults to * false.
    + * - undiscovered_bias: A number between 0 and 1 representing the bias towards undiscovered spells, with 0 + * being no bias and 1 meaning spells are guaranteed to be undiscovered.
    * - tiers: A list of tiers to choose from. Defaults to all tiers.
    * - elements: A list of elements to choose from. Defaults to all elements. - *

    + *

    * This class is effectively a loot table-friendly replacement for the standard weighting method in WizardryUtilities * which was the basis of all the old loot systems (not counting wizard trades, which were - and still are - completely * separate). - *

    + *

    * Since spells are stored as metadata, this could be done by having an entry for each tier and letting it pick a * random spell from that tier by setting the metadata to a random value in the range of values that correspond to that * tier. However, this creates a two-fold problem: firstly, not all spells are in tier order, and secondly, if spells * are added via addon mods the entries would have to be updated manually with the new numbers. - *

    + *

    * (This reasoning is similar to that for the enchant_randomly function in vanilla Minecraft, since you can specify NBT * data in loot tables, but using NBT in this way would be incredibly verbose and inflexible, hence the loot function.) - * - * @see WizardryUtilities#getStandardWeightedRandomSpellId(Random, boolean) + * * @author Electroblob * @since Wizardry 1.2 */ @@ -62,14 +56,16 @@ public class RandomSpell extends LootFunction { private final List spells; private final boolean ignoreWeighting; + private final float undiscoveredBias; private final List tiers; private final List elements; - protected RandomSpell(LootCondition[] conditions, List spells, boolean ignoreWeighting, List tiers, - List elements){ + protected RandomSpell(LootCondition[] conditions, List spells, boolean ignoreWeighting, + float undiscoveredBias, List tiers, List elements){ super(conditions); this.spells = spells; this.ignoreWeighting = ignoreWeighting; + this.undiscoveredBias = undiscoveredBias; this.tiers = tiers; this.elements = elements; } @@ -99,8 +95,8 @@ public class RandomSpell extends LootFunction { // Elements aren't weighted if(elements == null || elements.isEmpty()){ - // Element can only be MAGIC if tier is BASIC - if(tier == Tier.BASIC){ + // Element can only be MAGIC if tier is NOVICE + if(tier == Tier.NOVICE){ element = Element.values()[random.nextInt(Element.values().length)]; }else{ Element[] elements = ArrayUtils.removeElement(Element.values(), Element.MAGIC); @@ -114,15 +110,17 @@ public class RandomSpell extends LootFunction { // Here's a thought: does randomly selecting the element beforehand (as opposed to leaving it null and letting // the spell randomiser use any element) change the overall outcome at all? - List spellsList = Spell.getSpells(new Spell.TierElementFilter(tier, element)); - if(stack.getItem() instanceof ItemScroll) spellsList.retainAll(Spell.getSpells(Spell.nonContinuousSpells)); + List spellsList = Spell.getSpells(new Spell.TierElementFilter(tier, element, SpellProperties.Context.TREASURE)); - // Ensures the tier chosen actually has spells in it, and if not uses BASIC instead. BASIC always has at least + if(stack.getItem() instanceof ItemScroll) spellsList.removeIf(s -> !s.isEnabled(SpellProperties.Context.SCROLL)); + if(stack.getItem() instanceof ItemSpellBook) spellsList.removeIf(s -> !s.isEnabled(SpellProperties.Context.BOOK)); + + // Ensures the tier chosen actually has spells in it, and if not uses NOVICE instead. NOVICE always has at least // the NONE spell since this spell cannot be disabled. - // NOTE: Commented out for now because it will interfere with the ability to specify tiers and elements. + // Commented out for now because it will interfere with the ability to specify tiers and elements. // To be honest, I may as well just say that if you disable enough spells to make this important, you deserve // less loot! - /* if(spells.isEmpty()){ spellsList = Spell.getSpells(new Spell.TierElementFilter(EnumTier.BASIC, null)); + /* if(spells.isEmpty()){ spellsList = Spell.getSpells(new Spell.TierElementFilter(EnumTier.NOVICE, null)); * if(stack.getItem() instanceof ItemScroll) spellsList.retainAll(Spell.getSpells(Spell.nonContinuousSpells)); * } */ @@ -130,12 +128,30 @@ public class RandomSpell extends LootFunction { spellsList.retainAll(spells); } + // This method is badly-named, loot chests pass a player through too, not just mobs + // (And WHY does it only return an entity?! The underlying field is always a player so I'm casting it anyway) + EntityPlayer player = (EntityPlayer)context.getKillerPlayer(); + + // Remove either the undiscovered spells or the discovered ones, depending on the bias + if(undiscoveredBias > 0 && player != null){ + + WizardData data = WizardData.get(player); + + int discoveredCount = (int)spellsList.stream().filter(data::hasSpellBeenDiscovered).count(); + // If none have been discovered or they've all been discovered, don't bother! + if(discoveredCount > 0 && discoveredCount < spellsList.size()){ + // Kinda unintuitive but it's very neat! + boolean keepDiscovered = random.nextFloat() < 0.5f + 0.5f * undiscoveredBias; + spellsList.removeIf(s -> keepDiscovered != data.hasSpellBeenDiscovered(s)); + } + } + if(spellsList.isEmpty()){ Wizardry.logger.warn("Tried to apply the random_spell loot function to an item, but no enabled spells" + "matched the criteria specified. Substituting placeholder (metadata 0) item."); stack.setItemDamage(0); }else{ - stack.setItemDamage(spellsList.get(random.nextInt(spellsList.size())).id()); + stack.setItemDamage(spellsList.get(random.nextInt(spellsList.size())).metadata()); } return stack; @@ -162,6 +178,8 @@ public class RandomSpell extends LootFunction { object.addProperty("ignore_weighting", function.ignoreWeighting); + object.addProperty("undiscovered_bias", function.undiscoveredBias); + if(function.tiers != null && !function.tiers.isEmpty()){ JsonArray jsonarray = new JsonArray(); @@ -178,7 +196,7 @@ public class RandomSpell extends LootFunction { JsonArray jsonarray = new JsonArray(); for(Element element : function.elements){ - jsonarray.add(new JsonPrimitive(element.getUnlocalisedName())); + jsonarray.add(new JsonPrimitive(element.getName())); } object.add("elements", jsonarray); @@ -194,8 +212,7 @@ public class RandomSpell extends LootFunction { if(object.has("spells")){ - // Vanilla Minecraft calls Lists.newArrayList() here, which is completely pointless. - spells = new ArrayList(); + spells = new ArrayList<>(); // Importantly, it is necessary to specify a default (the new JsonArray) here because otherwise the // parameter will be mandatory, and the game will crash if it isn't present. @@ -215,50 +232,43 @@ public class RandomSpell extends LootFunction { boolean ignoreWeighting = JsonUtils.getBoolean(object, "ignore_weighting", false); + float undiscoveredBias = JsonUtils.getFloat(object, "undiscovered_bias", 0); + if(object.has("tiers")){ - // Vanilla Minecraft calls Lists.newArrayList() here, which is completely pointless. - tiers = new ArrayList(); + tiers = new ArrayList<>(); - jsonarray: for(JsonElement element : JsonUtils.getJsonArray(object, "tiers", new JsonArray())){ + for(JsonElement element : JsonUtils.getJsonArray(object, "tiers", new JsonArray())){ String string = JsonUtils.getString(element, "tier"); - // IDEA: If it is necessary to get tiers by name elsewhere in the future, move this to EnumTier. - for(Tier tier : Tier.values()){ - if(tier.getUnlocalisedName().equals(string)){ - tiers.add(tier); - continue jsonarray; - } + try { + tiers.add(Tier.fromName(string)); + }catch(IllegalArgumentException e){ + // If the string does not match any of the tiers, throws an exception. + throw new JsonSyntaxException("Unknown tier \'" + string + "\'"); } - // If the string does not match any of the tiers, throws an exception. - throw new JsonSyntaxException("Unknown tier \'" + string + "\'"); } } if(object.has("elements")){ - // Vanilla Minecraft calls Lists.newArrayList() here, which is completely pointless. - elements = new ArrayList(); + elements = new ArrayList<>(); - jsonarray: for(JsonElement jelement : JsonUtils.getJsonArray(object, "elements", new JsonArray())){ + for(JsonElement jelement : JsonUtils.getJsonArray(object, "elements", new JsonArray())){ String string = JsonUtils.getString(jelement, "element"); - // IDEA: If it is necessary to get elements by name elsewhere in the future, move this to - // EnumElement. - for(Element element : Element.values()){ - if(element.getUnlocalisedName().equals(string)){ - elements.add(element); - continue jsonarray; - } + try { + elements.add(Element.fromName(string)); + }catch(IllegalArgumentException e){ + // If the string does not match any of the elements, throws an exception. + throw new JsonSyntaxException("Unknown element \'" + string + "\'"); } - // If the string does not match any of the elements, throws an exception. - throw new JsonSyntaxException("Unknown element \'" + string + "\'"); } } - return new RandomSpell(conditions, spells, ignoreWeighting, tiers, elements); + return new RandomSpell(conditions, spells, ignoreWeighting, undiscoveredBias, tiers, elements); } } diff --git a/src/main/java/electroblob/wizardry/loot/WizardSpell.java b/src/main/java/electroblob/wizardry/loot/WizardSpell.java index 3609926f..72c6d35a 100644 --- a/src/main/java/electroblob/wizardry/loot/WizardSpell.java +++ b/src/main/java/electroblob/wizardry/loot/WizardSpell.java @@ -1,12 +1,8 @@ package electroblob.wizardry.loot; -import java.util.List; -import java.util.Random; - import com.google.gson.JsonDeserializationContext; import com.google.gson.JsonObject; import com.google.gson.JsonSerializationContext; - import electroblob.wizardry.Wizardry; import electroblob.wizardry.entity.living.ISpellCaster; import electroblob.wizardry.item.ItemSpellBook; @@ -18,6 +14,9 @@ import net.minecraft.world.storage.loot.LootContext; import net.minecraft.world.storage.loot.conditions.LootCondition; import net.minecraft.world.storage.loot.functions.LootFunction; +import java.util.List; +import java.util.Random; + /** * Loot function that allows spell books to select a random spell from the spells used by the ISpellCaster that dropped * them. @@ -40,7 +39,7 @@ public class WizardSpell extends LootFunction { if(context.getLootedEntity() instanceof ISpellCaster){ List spells = ((ISpellCaster)context.getLootedEntity()).getSpells(); spells.remove(Spells.magic_missile); // Can't drop magic missile - stack.setItemDamage(spells.get(random.nextInt(spells.size())).id()); + stack.setItemDamage(spells.get(random.nextInt(spells.size())).metadata()); }else{ Wizardry.logger.warn("Applying the wizard_spell loot function to an entity that isn't a spell caster."); } diff --git a/src/main/java/electroblob/wizardry/misc/BehaviourSpellDispense.java b/src/main/java/electroblob/wizardry/misc/BehaviourSpellDispense.java new file mode 100644 index 00000000..cf75f72b --- /dev/null +++ b/src/main/java/electroblob/wizardry/misc/BehaviourSpellDispense.java @@ -0,0 +1,105 @@ +package electroblob.wizardry.misc; + +import electroblob.wizardry.data.DispenserCastingData; +import electroblob.wizardry.event.SpellCastEvent; +import electroblob.wizardry.event.SpellCastEvent.Source; +import electroblob.wizardry.item.ItemScroll; +import electroblob.wizardry.packet.PacketDispenserCastSpell; +import electroblob.wizardry.packet.WizardryPacketHandler; +import electroblob.wizardry.spell.Spell; +import electroblob.wizardry.util.SpellModifiers; +import net.minecraft.block.BlockDispenser; +import net.minecraft.dispenser.IBlockSource; +import net.minecraft.dispenser.IPosition; +import net.minecraft.init.Bootstrap.BehaviorDispenseOptional; +import net.minecraft.item.ItemStack; +import net.minecraft.util.EnumFacing; +import net.minecraft.world.World; +import net.minecraftforge.common.MinecraftForge; +import net.minecraftforge.fml.common.network.simpleimpl.IMessage; + +/** + * Dispenser behaviour for casting spells from dispensers based on the metadata of the dispensed item. This class, along + * with the capability {@link DispenserCastingData DispenserCastingData}, forms the dispenser + * equivalent of {@link electroblob.wizardry.entity.living.EntityAIAttackSpell EntityAIAttackSpell}, which handles spell + * casting for NPCs. + * + * @author Electroblob + * @since Wizardry 4.2 + */ +/* + * The dispenser and NPC casting systems are somewhat comparable in structure: + * + | Dispensers | NPCs | + | -------------------------|---------------------------| + | BehaviourSpellDispense | EntityAIAttackSpell | Handles the actual spell casting. These are slightly different + | | | | | in that EntityAIAttackSpell handles ticking for NPC spells, + | | | | | whereas for dispensers this is handled in DispenserCastingData. + | V | V | + | DispenserCastingData | ISpellCaster | Deals with data storage for spell casting. Of course, being an + | | | interface, ISpellCaster doesn't actually store the data itself. + * + */ +public class BehaviourSpellDispense extends BehaviorDispenseOptional { + + public BehaviourSpellDispense(){} + + @Override + protected ItemStack dispenseStack(IBlockSource source, ItemStack stack){ + + // This is only ever called server-side. + + successful = false; + + World world = source.getWorld(); + // This returns a position that is 0.2 blocks away from the middle of the front face of the dispenser + IPosition position = BlockDispenser.getDispensePosition(source); + EnumFacing direction = source.getBlockState().getValue(BlockDispenser.FACING); + + Spell spell = Spell.byMetadata(stack.getMetadata()); + + // If there's a block in the way, nothing happens + if(world.isSideSolid(source.getBlockPos().offset(direction), direction.getOpposite())) return stack; + + // If the scroll can never be cast by a dispenser, it should be dispensed as an item. + if(!spell.canBeCastByDispensers()) return super.dispenseStack(source, stack); + + SpellModifiers modifiers = new SpellModifiers(); + + double x = position.getX(); + double y = position.getY(); + double z = position.getZ(); + + // For horizontal dispensers, the position is lowered by 0.125 so it actually lines up with the hole. + if(direction.getAxis().isHorizontal()) y -= 0.125; + + // If the scroll can be cast by a dispenser, it should be cast. If this fails, then the scroll should stay in + // the dispenser. + if(MinecraftForge.EVENT_BUS.post(new SpellCastEvent.Pre(Source.DISPENSER, spell, world, x, y, z, direction, modifiers))) + return stack; + + successful = spell.cast(world, x, y, z, direction, 0, -1, modifiers); + + if(successful){ + + MinecraftForge.EVENT_BUS.post(new SpellCastEvent.Post(Source.DISPENSER, spell, world, x, y, z, direction, modifiers)); + + stack.shrink(1); + + if(spell.isContinuous || spell.requiresPacket()){ + // Sends a packet to all players in dimension to tell them to spawn particles. + IMessage msg = new PacketDispenserCastSpell.Message(x, y, z, direction, source.getBlockPos(), spell, + spell.isContinuous ? ItemScroll.CASTING_TIME : 0, modifiers); // Non-continuous spells ignore duration + WizardryPacketHandler.net.sendToDimension(msg, world.provider.getDimension()); + } + + if(spell.isContinuous){ + DispenserCastingData data = DispenserCastingData.get(source.getBlockTileEntity()); + data.startCasting(spell, x, y, z, ItemScroll.CASTING_TIME, modifiers); + } + } + + return stack; + } + +} diff --git a/src/main/java/electroblob/wizardry/misc/Forfeit.java b/src/main/java/electroblob/wizardry/misc/Forfeit.java new file mode 100644 index 00000000..e5782a66 --- /dev/null +++ b/src/main/java/electroblob/wizardry/misc/Forfeit.java @@ -0,0 +1,487 @@ +package electroblob.wizardry.misc; + +import com.google.common.collect.ArrayListMultimap; +import com.google.common.collect.ListMultimap; +import electroblob.wizardry.Wizardry; +import electroblob.wizardry.constants.Element; +import electroblob.wizardry.constants.Tier; +import electroblob.wizardry.data.WizardData; +import electroblob.wizardry.entity.EntityMeteor; +import electroblob.wizardry.entity.construct.*; +import electroblob.wizardry.entity.living.*; +import electroblob.wizardry.entity.projectile.EntityFirebomb; +import electroblob.wizardry.entity.projectile.EntityMagicFireball; +import electroblob.wizardry.event.SpellCastEvent; +import electroblob.wizardry.item.ItemArtefact; +import electroblob.wizardry.registry.*; +import electroblob.wizardry.spell.Banish; +import electroblob.wizardry.util.WizardryUtilities; +import net.minecraft.entity.effect.EntityLightningBolt; +import net.minecraft.entity.item.EntityFallingBlock; +import net.minecraft.entity.passive.EntitySquid; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.init.Blocks; +import net.minecraft.init.MobEffects; +import net.minecraft.item.ItemStack; +import net.minecraft.potion.PotionEffect; +import net.minecraft.util.*; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.Vec3d; +import net.minecraft.util.text.ITextComponent; +import net.minecraft.util.text.TextComponentTranslation; +import net.minecraft.world.World; +import net.minecraftforge.common.IPlantable; +import net.minecraftforge.fml.common.Mod; +import net.minecraftforge.fml.common.eventhandler.EventPriority; +import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; +import org.apache.commons.lang3.tuple.Pair; + +import java.util.Collection; +import java.util.Collections; +import java.util.List; +import java.util.Random; +import java.util.function.BiConsumer; + +/** + * A {@code Forfeit} object represents a negative effect that may happen when a player attempts to cast an + * undiscovered spell. The nature and severity of the forfeit depends on the element and tier of the spell that was + * attempted.
    + *
    + * Adding a new forfeit is as simple as calling {@link Forfeit#add(Tier, Element, Forfeit)} and supplying the + * {@code Forfeit} instance along with a tier and element to associate it with. To create a forfeit, you may extend + * this class and instantiate it, or use {@link Forfeit#create(ResourceLocation, BiConsumer)} to concisely define the + * behaviour (this method is provided since most forfeits' behaviour code is fairly brief and would otherwise result in + * a large number of trivial 'stub' classes - in fact, many of wizardry's forfeits are defined in a single line).
    + *
    + * This class also handles the (event-driven) selection of forfeits and determines when one should be applied. + * + * @author Electroblob + * @since Wizardry 4.2 + */ +// With the exception of sound events, everything forfeit-related is done right here. How about that for modularity? :P +@Mod.EventBusSubscriber +public abstract class Forfeit { + + private static final ListMultimap, Forfeit> forfeits = ArrayListMultimap.create(); + + private static final float TIER_CHANGE_CHANCE = 0.2f; + + private final ResourceLocation name; + + protected final SoundEvent sound; + + public Forfeit(ResourceLocation name){ + this.name = name; + this.sound = WizardrySounds.createSound("forfeit." + name.getPath()); + } + + public abstract void apply(World world, EntityPlayer player); + + /** + * Returns an {@link ITextComponent} for the message displayed when this forfeit is activated. + * @param implementName An {@code ITextComponent} for the name of the implement being used. This is usually + * something generic like 'wand' or 'scroll'. + * @return An {@code ITextComponent} representing this forfeit's message, for use in chat messages. + * @see Forfeit#getMessageForWand() + * @see Forfeit#getMessageForScroll() + */ + public ITextComponent getMessage(ITextComponent implementName){ + return new TextComponentTranslation("forfeit." + name.toString(), implementName); + } + + /** Wrapper for {@link Forfeit#getMessage(ITextComponent)} with {@code implementName} set to the lang file key + * {@code item.ebwizardry:wand.generic} */ + public ITextComponent getMessageForWand(){ + return getMessage(new TextComponentTranslation("item." + Wizardry.MODID + ":wand.generic")); + } + + /** Wrapper for {@link Forfeit#getMessage(ITextComponent)} with {@code implementName} set to the lang file key + * {@code item.ebwizardry:scroll.generic} */ + public ITextComponent getMessageForScroll(){ + return getMessage(new TextComponentTranslation("item." + Wizardry.MODID + ":scroll.generic")); + } + + /** Returns the {@link SoundEvent} played when this forfeit is activated. */ + public SoundEvent getSound(){ + return sound; + } + + public static void add(Tier tier, Element element, Forfeit forfeit){ + forfeits.put(Pair.of(tier, element), forfeit); + } + + public static Forfeit getRandomForfeit(Random random, Tier tier, Element element){ + float f = random.nextFloat(); + if(f < TIER_CHANGE_CHANCE && tier.ordinal() > 0) tier = Tier.values()[tier.ordinal() - 1]; + else if(f > 1 - TIER_CHANGE_CHANCE && tier.ordinal() < Tier.values().length-1) tier = Tier.values()[tier.ordinal() + 1]; + List matches = forfeits.get(Pair.of(tier, element)); + if(matches.isEmpty()){ + Wizardry.logger.warn("No forfeits with tier {} and element {}!", tier, element); + return null; + } + return matches.get(random.nextInt(matches.size())); + } + + public static Collection getForfeits(){ + return Collections.unmodifiableCollection(forfeits.values()); + } + + /** Static helper method that creates a {@code Forfeit} with the given name and an effect specified by the given + * consumer. This allows code to use a neater lambda expression rather than an anonymous class. */ + public static Forfeit create(ResourceLocation name, BiConsumer effect){ + return new Forfeit(name){ + @Override + public void apply(World world, EntityPlayer player){ + effect.accept(world, player); + } + }; + } + + /** Internal wrapper for {@link Forfeit#create(ResourceLocation, BiConsumer)} so I don't have to put wizardry's + * mod ID in every time. */ + private static Forfeit create(String name, BiConsumer effect){ + return create(new ResourceLocation(Wizardry.MODID, name), effect); + } + + @SubscribeEvent(priority = EventPriority.NORMAL) // Forfeits come after spell disabling but before modifiers + public static void onSpellCastPreEvent(SpellCastEvent.Pre event){ + + if(!Wizardry.settings.discoveryMode) return; + + if(event.getCaster() instanceof EntityPlayer && !((EntityPlayer)event.getCaster()).isCreative() + && (event.getSource() == SpellCastEvent.Source.WAND || event.getSource() == SpellCastEvent.Source.SCROLL)){ + + EntityPlayer player = (EntityPlayer)event.getCaster(); + WizardData data = WizardData.get(player); + + float chance = (float)Wizardry.settings.forfeitChance; + if(ItemArtefact.isArtefactActive(player, WizardryItems.amulet_wisdom)) chance *= 0.5; + + // Use the synchronised random to ensure the same outcome on client- and server-side + if(data.synchronisedRandom.nextFloat() < chance && !data.hasSpellBeenDiscovered(event.getSpell())){ + + event.setCanceled(true); + + Forfeit forfeit = getRandomForfeit(event.getWorld().rand, event.getSpell().getTier(), event.getSpell().getElement()); + + if(forfeit == null){ // Should never happen, but just in case... + if(!event.getWorld().isRemote) player.sendMessage(new TextComponentTranslation("forfeit.ebwizardry:do_nothing")); + return; + } + + forfeit.apply(event.getWorld(), player); + + WizardryAdvancementTriggers.spell_failure.triggerFor(player); + + WizardryUtilities.playSoundAtPlayer(player, forfeit.getSound(), WizardrySounds.SPELLS, 1, 1); + + if(!event.getWorld().isRemote) player.sendMessage( + event.getSource() == SpellCastEvent.Source.WAND ? forfeit.getMessageForWand() : forfeit.getMessageForScroll()); + } + } + } + + /** Called from the preInit method in the main mod class to set up all the forfeits. */ + public static void register(){ + + add(Tier.NOVICE, Element.FIRE, create("burn_self", (w, p) -> p.setFire(5))); + + add(Tier.APPRENTICE, Element.FIRE, create("fireball", (w, p) -> { + if(!w.isRemote){ + EntityMagicFireball fireball = new EntityMagicFireball(w); + Vec3d vec = p.getPositionEyes(0).add(p.getLookVec().scale(6)); + fireball.setPosition(vec.x, vec.y, vec.z); + fireball.shoot(p.posX, p.posY + p.getEyeHeight(), p.posZ, 1.5f, 1); + w.spawnEntity(fireball); + } + })); + + add(Tier.APPRENTICE, Element.FIRE, create("firebomb", (w, p) -> { + if(!w.isRemote){ + EntityFirebomb firebomb = new EntityFirebomb(w); + firebomb.setPosition(p.posX, p.posY + 5, p.posZ); + w.spawnEntity(firebomb); + } + })); + + add(Tier.ADVANCED, Element.FIRE, create("explode", (w, p) -> w.createExplosion(null, p.posX, p.posY, p.posZ, 1, false))); + + add(Tier.ADVANCED, Element.FIRE, create("blazes", (w, p) -> { + if(!w.isRemote){ + for(int i = 0; i < 3; i++){ + BlockPos pos = WizardryUtilities.findNearbyFloorSpace(p, 4, 2); + if(pos == null) break; + EntityBlazeMinion blaze = new EntityBlazeMinion(w); + blaze.setPosition(pos.getX() + 0.5, pos.getY(), pos.getZ() + 0.5); + w.spawnEntity(blaze); + } + } + })); + + add(Tier.MASTER, Element.FIRE, create("burn_surroundings", (w, p) -> { + if(!w.isRemote){ + List sphere = WizardryUtilities.getBlockSphere(p.getPosition(), 6); + for(BlockPos pos : sphere){ + if(w.rand.nextBoolean() && w.isAirBlock(pos)) w.setBlockState(pos, Blocks.FIRE.getDefaultState()); + } + } + })); + + add(Tier.MASTER, Element.FIRE, create("meteors", (w, p) -> { + if(!w.isRemote) for(int i=0; i<5; i++) w.spawnEntity(new EntityMeteor(w, p.posX + w.rand.nextDouble() * 16 - 8, + p.posY + 40 + w.rand.nextDouble() * 30, p.posZ + w.rand.nextDouble() * 16 - 8, + 1, WizardryUtilities.canDamageBlocks(p, w))); + })); + + add(Tier.NOVICE, Element.ICE, create("freeze_self", (w, p) -> p.addPotionEffect(new PotionEffect(WizardryPotions.frost, 200)))); + + add(Tier.APPRENTICE, Element.ICE, create("freeze_self_2", (w, p) -> p.addPotionEffect(new PotionEffect(WizardryPotions.frost, 300, 1)))); + + add(Tier.APPRENTICE, Element.ICE, create("ice_spikes", (w, p) -> { + if(!w.isRemote){ + for(int i = 0; i < 5; i++){ + EntityIceSpike iceSpike = new EntityIceSpike(w); + double x = p.posX + 2 - w.rand.nextFloat() * 4; + double z = p.posZ + 2 - w.rand.nextFloat() * 4; + Integer y = WizardryUtilities.getNearestSurface(w, new BlockPos(x, p.posY, z), EnumFacing.UP, 2, true, + WizardryUtilities.SurfaceCriteria.basedOn(World::isBlockFullCube)); + if(y == null) break; + iceSpike.setFacing(EnumFacing.UP); + iceSpike.setPosition(x, y, z); + w.spawnEntity(iceSpike); + } + } + })); + + add(Tier.ADVANCED, Element.ICE, create("blizzard", (w, p) -> { + if(!w.isRemote){ + EntityBlizzard blizzard = new EntityBlizzard(w); + blizzard.setPosition(p.posX, p.posY, p.posZ); + w.spawnEntity(blizzard); + } + })); + + add(Tier.ADVANCED, Element.ICE, create("ice_wraiths", (w, p) -> { + if(!w.isRemote){ + for(int i = 0; i < 3; i++){ + BlockPos pos = WizardryUtilities.findNearbyFloorSpace(p, 4, 2); + if(pos == null) break; + EntityIceWraith iceWraith = new EntityIceWraith(w); + iceWraith.setPosition(pos.getX() + 0.5, pos.getY(), pos.getZ() + 0.5); + w.spawnEntity(iceWraith); + } + } + })); + + add(Tier.MASTER, Element.ICE, create("hailstorm", (w, p) -> { + if(!w.isRemote){ + EntityHailstorm hailstorm = new EntityHailstorm(w); + hailstorm.setPosition(p.posX, p.posY + 5, p.posZ - 3); // Subtract 3 from z because it's facing south (yaw 0) + w.spawnEntity(hailstorm); + } + })); + + add(Tier.MASTER, Element.ICE, create("ice_giant", (w, p) -> { + if(!w.isRemote){ + EntityIceGiant iceGiant = new EntityIceGiant(w); + iceGiant.setPosition(p.posX + p.getLookVec().x * 4, p.posY, p.posZ + p.getLookVec().z * 4); + w.spawnEntity(iceGiant); + } + })); + + add(Tier.NOVICE, Element.LIGHTNING, create("thunder", (w, p) -> { + p.addVelocity(-p.getLookVec().x, 0, -p.getLookVec().z); + if(w.isRemote) w.spawnParticle(EnumParticleTypes.EXPLOSION_LARGE, p.posX, p.posY, p.posZ, 0, 0, 0); + })); + + add(Tier.APPRENTICE, Element.LIGHTNING, create("storm", (w, p) -> { + int standardWeatherTime = (300 + (new Random()).nextInt(600)) * 20; + w.getWorldInfo().setRaining(true); + w.getWorldInfo().setRainTime(standardWeatherTime); + w.getWorldInfo().setThundering(true); + w.getWorldInfo().setThunderTime(standardWeatherTime); + })); + + add(Tier.APPRENTICE, Element.LIGHTNING, create("lightning_sigils", (w, p) -> { + if(!w.isRemote){ + for(EnumFacing direction : EnumFacing.HORIZONTALS){ + BlockPos pos = p.getPosition().offset(direction, 2); + Integer y = WizardryUtilities.getNearestFloor(w, pos, 2); + if(y == null) continue; + EntityLightningSigil sigil = new EntityLightningSigil(w); + sigil.setPosition(pos.getX() + 0.5, y, pos.getZ() + 0.5); + w.spawnEntity(sigil); + } + } + })); + + add(Tier.ADVANCED, Element.LIGHTNING, create("lightning", (w, p) -> w.addWeatherEffect(new EntityLightningBolt(w, p.posX, p.posY, p.posZ, false)))); + + add(Tier.ADVANCED, Element.LIGHTNING, create("paralyse_self", (w, p) -> p.addPotionEffect(new PotionEffect(WizardryPotions.paralysis, 200)))); + + add(Tier.ADVANCED, Element.LIGHTNING, create("lightning_wraiths", (w, p) -> { + if(!w.isRemote){ + for(int i = 0; i < 3; i++){ + BlockPos pos = WizardryUtilities.findNearbyFloorSpace(p, 4, 2); + if(pos == null) break; + EntityLightningWraith lightningWraith = new EntityLightningWraith(w); + lightningWraith.setPosition(pos.getX() + 0.5, pos.getY(), pos.getZ() + 0.5); + w.spawnEntity(lightningWraith); + } + } + })); + + add(Tier.MASTER, Element.LIGHTNING, create("storm_elementals", (w, p) -> { + if(!w.isRemote){ + for(EnumFacing direction : EnumFacing.HORIZONTALS){ + BlockPos pos = p.getPosition().offset(direction, 3); + EntityStormElemental stormElemental = new EntityStormElemental(w); + stormElemental.setPosition(pos.getX() + 0.5, pos.getY(), pos.getZ() + 0.5); + w.spawnEntity(stormElemental); + } + } + })); + + add(Tier.NOVICE, Element.NECROMANCY, create("nausea", (w, p) -> p.addPotionEffect(new PotionEffect(MobEffects.NAUSEA, 400)))); + + add(Tier.APPRENTICE, Element.NECROMANCY, create("zombie_horde", (w, p) -> { + if(!w.isRemote){ + for(int i = 0; i < 3; i++){ + BlockPos pos = WizardryUtilities.findNearbyFloorSpace(p, 4, 2); + if(pos == null) break; + EntityZombieMinion zombie = new EntityZombieMinion(w); + zombie.setPosition(pos.getX() + 0.5, pos.getY(), pos.getZ() + 0.5); + w.spawnEntity(zombie); + } + } + })); + + add(Tier.ADVANCED, Element.NECROMANCY, create("wither_self", (w, p) -> p.addPotionEffect(new PotionEffect(MobEffects.WITHER, 400)))); + + add(Tier.MASTER, Element.NECROMANCY, create("cripple_self", (w, p) -> p.attackEntityFrom(DamageSource.MAGIC, p.getHealth() - 1))); + + add(Tier.MASTER, Element.NECROMANCY, create("shadow_wraiths", (w, p) -> { + if(!w.isRemote){ + for(EnumFacing direction : EnumFacing.HORIZONTALS){ + BlockPos pos = p.getPosition().offset(direction, 3); + EntityShadowWraith wraith = new EntityShadowWraith(w); + wraith.setPosition(pos.getX() + 0.5, pos.getY(), pos.getZ() + 0.5); + w.spawnEntity(wraith); + } + } + })); + + add(Tier.NOVICE, Element.EARTH, create("snares", (w, p) -> { + if(!w.isRemote){ + for(EnumFacing direction : EnumFacing.HORIZONTALS){ + BlockPos pos = p.getPosition().offset(direction); + w.setBlockState(pos, WizardryBlocks.snare.getDefaultState()); + } + } + })); + + add(Tier.NOVICE, Element.EARTH, create("squid", (w, p) -> { + if(!w.isRemote){ + EntitySquid squid = new EntitySquid(w); + squid.setPosition(p.posX, p.posY + 3, p.posZ); + w.spawnEntity(squid); + } + })); + + add(Tier.APPRENTICE, Element.EARTH, create("uproot_plants", (w, p) -> { + if(!w.isRemote){ + List sphere = WizardryUtilities.getBlockSphere(p.getPosition(), 5); + sphere.removeIf(pos -> !(w.getBlockState(pos).getBlock() instanceof IPlantable)); + sphere.forEach(pos -> w.destroyBlock(pos, true)); + } + })); + + add(Tier.APPRENTICE, Element.EARTH, create("poison_self", (w, p) -> p.addPotionEffect(new PotionEffect(MobEffects.POISON, 400, 1)))); + + add(Tier.ADVANCED, Element.EARTH, create("flood", (w, p) -> { + if(!w.isRemote){ + List sphere = WizardryUtilities.getBlockSphere(p.getPosition().up(), 2); + sphere.removeIf(pos -> !WizardryUtilities.canBlockBeReplaced(w, pos, true)); + sphere.forEach(pos -> w.setBlockState(pos, Blocks.WATER.getDefaultState())); + } + })); + + add(Tier.MASTER, Element.EARTH, create("bury_self", (w, p) -> { + if(!w.isRemote){ + List sphere = WizardryUtilities.getBlockSphere(p.getPosition(), 4); + sphere.removeIf(pos -> !w.getBlockState(pos).isFullCube()); + sphere.forEach(pos -> { + EntityFallingBlock block = new EntityFallingBlock(w, pos.getX() + 0.5, pos.getY() + 0.5, + pos.getZ() + 0.5, w.getBlockState(pos)); + block.motionY = 0.3 * (4 - (p.getPosition().getY() - pos.getY())); + w.spawnEntity(block); + }); + } + })); + + add(Tier.NOVICE, Element.SORCERY, create("spill_inventory", (w, p) -> { + for(int i = 0; i < p.inventory.mainInventory.size(); i++){ + ItemStack stack = p.inventory.mainInventory.get(i); + if(!stack.isEmpty()){ + p.dropItem(stack, true, false); + p.inventory.mainInventory.set(i, ItemStack.EMPTY); + } + } + })); + + add(Tier.APPRENTICE, Element.SORCERY, create("teleport_self", (w, p) -> ((Banish)Spells.banish).teleport(p, w, 8 + w.rand.nextDouble() * 8))); + + add(Tier.ADVANCED, Element.SORCERY, create("levitate_self", (w, p) -> p.addPotionEffect(new PotionEffect(MobEffects.LEVITATION, 200)))); + + add(Tier.ADVANCED, Element.SORCERY, create("vex_horde", (w, p) -> { + if(!w.isRemote){ + for(int i = 0; i < 4; i++){ + BlockPos pos = WizardryUtilities.findNearbyFloorSpace(p, 4, 2); + if(pos == null) break; + EntityVexMinion vex = new EntityVexMinion(w); + vex.setPosition(pos.getX() + 0.5, pos.getY() + 1, pos.getZ() + 0.5); + w.spawnEntity(vex); + } + } + })); + + add(Tier.MASTER, Element.SORCERY, create("black_hole", (w, p) -> { + EntityBlackHole blackHole = new EntityBlackHole(w); + Vec3d vec = p.getPositionEyes(1).add(p.getLookVec().scale(4)); + blackHole.setPosition(vec.x, vec.y, vec.z); + w.spawnEntity(blackHole); + })); + + add(Tier.MASTER, Element.SORCERY, create("arrow_rain", (w, p) -> { + if(!w.isRemote){ + EntityArrowRain arrowRain = new EntityArrowRain(w); + arrowRain.setPosition(p.posX, p.posY + 5, p.posZ - 3); // Subtract 3 from z because it's facing south (yaw 0) + w.spawnEntity(arrowRain); + } + })); + + add(Tier.NOVICE, Element.HEALING, create("damage_self", (w, p) -> p.attackEntityFrom(DamageSource.MAGIC, 4))); + + add(Tier.NOVICE, Element.HEALING, create("spill_armour", (w, p) -> { + for(int i = 0; i < p.inventory.armorInventory.size(); i++){ + ItemStack stack = p.inventory.armorInventory.get(i); + if(!stack.isEmpty()){ + p.dropItem(stack, true, false); + p.inventory.armorInventory.set(i, ItemStack.EMPTY); + } + } + })); + + add(Tier.APPRENTICE, Element.HEALING, create("hunger", (w, p) -> p.addPotionEffect(new PotionEffect(MobEffects.HUNGER, 400, 4)))); + + add(Tier.APPRENTICE, Element.HEALING, create("blind_self", (w, p) -> p.addPotionEffect(new PotionEffect(MobEffects.BLINDNESS, 200)))); + + add(Tier.ADVANCED, Element.HEALING, create("weaken_self", (w, p) -> p.addPotionEffect(new PotionEffect(MobEffects.WEAKNESS, 600, 3)))); + + add(Tier.ADVANCED, Element.HEALING, create("jam_self", (w, p) -> p.addPotionEffect(new PotionEffect(WizardryPotions.arcane_jammer, 300)))); + + add(Tier.MASTER, Element.HEALING, create("curse_self", (w, p) -> p.addPotionEffect(new PotionEffect(WizardryPotions.curse_of_undeath, Integer.MAX_VALUE)))); + + } + +} \ No newline at end of file diff --git a/src/main/java/electroblob/wizardry/util/WildcardTradeList.java b/src/main/java/electroblob/wizardry/misc/WildcardTradeList.java similarity index 98% rename from src/main/java/electroblob/wizardry/util/WildcardTradeList.java rename to src/main/java/electroblob/wizardry/misc/WildcardTradeList.java index d7a60a2a..0917bcfa 100644 --- a/src/main/java/electroblob/wizardry/util/WildcardTradeList.java +++ b/src/main/java/electroblob/wizardry/misc/WildcardTradeList.java @@ -1,4 +1,4 @@ -package electroblob.wizardry.util; +package electroblob.wizardry.misc; import net.minecraft.item.ItemStack; import net.minecraft.nbt.NBTTagCompound; diff --git a/src/main/java/electroblob/wizardry/util/WizardryPathFinder.java b/src/main/java/electroblob/wizardry/misc/WizardryPathFinder.java similarity index 99% rename from src/main/java/electroblob/wizardry/util/WizardryPathFinder.java rename to src/main/java/electroblob/wizardry/misc/WizardryPathFinder.java index 898f9b4c..edd4156b 100644 --- a/src/main/java/electroblob/wizardry/util/WizardryPathFinder.java +++ b/src/main/java/electroblob/wizardry/misc/WizardryPathFinder.java @@ -1,11 +1,6 @@ -package electroblob.wizardry.util; - -import java.util.Set; - -import javax.annotation.Nullable; +package electroblob.wizardry.misc; import com.google.common.collect.Sets; - import electroblob.wizardry.spell.Clairvoyance; import net.minecraft.entity.EntityLiving; import net.minecraft.pathfinding.NodeProcessor; @@ -15,6 +10,9 @@ import net.minecraft.pathfinding.PathPoint; import net.minecraft.util.math.BlockPos; import net.minecraft.world.IBlockAccess; +import javax.annotation.Nullable; +import java.util.Set; + /** * Minecraft's pathfinder refused to play nicely, so I 'borrowed' its code and fiddled with it. Currently this is only * used for the {@link Clairvoyance} spell. diff --git a/src/main/java/electroblob/wizardry/packet/PacketCastContinuousSpell.java b/src/main/java/electroblob/wizardry/packet/PacketCastContinuousSpell.java index 35516b63..a4c30b65 100644 --- a/src/main/java/electroblob/wizardry/packet/PacketCastContinuousSpell.java +++ b/src/main/java/electroblob/wizardry/packet/PacketCastContinuousSpell.java @@ -1,16 +1,19 @@ package electroblob.wizardry.packet; import electroblob.wizardry.Wizardry; +import electroblob.wizardry.data.WizardData; import electroblob.wizardry.packet.PacketCastContinuousSpell.Message; +import electroblob.wizardry.spell.Spell; import electroblob.wizardry.util.SpellModifiers; import io.netty.buffer.ByteBuf; +import net.minecraft.entity.player.EntityPlayer; import net.minecraftforge.fml.common.network.simpleimpl.IMessage; import net.minecraftforge.fml.common.network.simpleimpl.IMessageHandler; import net.minecraftforge.fml.common.network.simpleimpl.MessageContext; /** * [Server -> Client] This packet is sent when the /cast command is used with a continuous spell, in order to - * sync the relevant variables in {@link electroblob.wizardry.WizardData WizardData}. + * sync the relevant variables in {@link WizardData WizardData}. */ public class PacketCastContinuousSpell implements IMessageHandler { @@ -21,12 +24,7 @@ public class PacketCastContinuousSpell implements IMessageHandler Wizardry.proxy.handleCastContinuousSpellPacket(message)); } return null; @@ -34,24 +32,23 @@ public class PacketCastContinuousSpell implements IMessageHandler { if(ctx.side.isClient()){ // Using a fully qualified name is a good course of action here; we don't really want to clutter the proxy // methods any more than necessary. - net.minecraft.client.Minecraft.getMinecraft().addScheduledTask(new Runnable(){ - @Override - public void run(){ - Wizardry.proxy.handleCastSpellPacket(message); - } - }); + net.minecraft.client.Minecraft.getMinecraft().addScheduledTask(() -> Wizardry.proxy.handleCastSpellPacket(message)); } return null; @@ -52,10 +48,10 @@ public class PacketCastSpell implements IMessageHandler { public Message(){ } - public Message(int casterID, EnumHand hand, int spellID, SpellModifiers modifiers){ + public Message(int casterID, EnumHand hand, Spell spell, SpellModifiers modifiers){ this.casterID = casterID; - this.spellID = spellID; + this.spellID = spell.networkID(); this.modifiers = modifiers; this.hand = hand == null ? EnumHand.MAIN_HAND : hand; } diff --git a/src/main/java/electroblob/wizardry/packet/PacketCastSpellAtPos.java b/src/main/java/electroblob/wizardry/packet/PacketCastSpellAtPos.java new file mode 100644 index 00000000..bb9047b7 --- /dev/null +++ b/src/main/java/electroblob/wizardry/packet/PacketCastSpellAtPos.java @@ -0,0 +1,85 @@ +package electroblob.wizardry.packet; + +import electroblob.wizardry.Wizardry; +import electroblob.wizardry.spell.Spell; +import electroblob.wizardry.util.SpellModifiers; +import io.netty.buffer.ByteBuf; +import net.minecraft.util.EnumFacing; +import net.minecraft.util.math.Vec3d; +import net.minecraftforge.fml.common.network.simpleimpl.IMessage; +import net.minecraftforge.fml.common.network.simpleimpl.IMessageHandler; +import net.minecraftforge.fml.common.network.simpleimpl.MessageContext; + +/** + * [Server -> Client] This packet is sent when a spell is cast at a position by commands and returns true, and is + * sent to clients so they can spawn the particles themselves. + */ +// Soooo many spell casting packets... +public class PacketCastSpellAtPos implements IMessageHandler { + + @Override + public IMessage onMessage(Message message, MessageContext ctx){ + + // Just to make sure that the side is correct + if(ctx.side.isClient()){ + // Using a fully qualified name is a good course of action here; we don't really want to clutter the proxy + // methods any more than necessary. + net.minecraft.client.Minecraft.getMinecraft().addScheduledTask(() -> Wizardry.proxy.handleCastSpellAtPosPacket(message)); + } + + return null; + } + + public static class Message implements IMessage { + + /** Position for the spell */ + public Vec3d position; + /** Direction for the spell */ + public EnumFacing direction; + /** ID of the spell being cast */ + public int spellID; + /** SpellModifiers for the spell */ + public SpellModifiers modifiers; + /** Number of ticks to cast the spell for, or -1 for non-continuous spells */ + public int duration; + + // This constructor is required otherwise you'll get errors (used somewhere in fml through reflection) + public Message(){} + + public Message(Vec3d position, EnumFacing direction, Spell spell, SpellModifiers modifiers){ + this(position, direction, spell, modifiers, -1); + } + + public Message(Vec3d position, EnumFacing direction, Spell spell, SpellModifiers modifiers, int duration){ + this.spellID = spell.networkID(); + this.modifiers = modifiers; + this.position = position; + this.direction = direction; + this.duration = duration; + } + + @Override + public void fromBytes(ByteBuf buf){ + + // The order is important + position = new Vec3d(buf.readDouble(), buf.readDouble(), buf.readDouble()); + direction = EnumFacing.byIndex(buf.readInt()); + this.spellID = buf.readInt(); + this.modifiers = new SpellModifiers(); + this.modifiers.read(buf); + this.duration = buf.readInt(); + } + + @Override + public void toBytes(ByteBuf buf){ + + buf.writeDouble(position.x); + buf.writeDouble(position.y); + buf.writeDouble(position.z); + buf.writeInt(direction.getIndex()); + buf.writeInt(spellID); + this.modifiers.write(buf); + buf.writeInt(duration); + } + } +} diff --git a/src/main/java/electroblob/wizardry/packet/PacketClairvoyance.java b/src/main/java/electroblob/wizardry/packet/PacketClairvoyance.java index cc3b919b..62a4c7ab 100644 --- a/src/main/java/electroblob/wizardry/packet/PacketClairvoyance.java +++ b/src/main/java/electroblob/wizardry/packet/PacketClairvoyance.java @@ -1,8 +1,5 @@ package electroblob.wizardry.packet; -import java.util.ArrayList; -import java.util.List; - import electroblob.wizardry.Wizardry; import electroblob.wizardry.packet.PacketClairvoyance.Message; import io.netty.buffer.ByteBuf; @@ -12,6 +9,9 @@ import net.minecraftforge.fml.common.network.simpleimpl.IMessage; import net.minecraftforge.fml.common.network.simpleimpl.IMessageHandler; import net.minecraftforge.fml.common.network.simpleimpl.MessageContext; +import java.util.ArrayList; +import java.util.List; + /** * [Server -> Client] This packet is sent when a player casts the clairvoyance spell to allow pathing to chunks * outside the render distance. diff --git a/src/main/java/electroblob/wizardry/packet/PacketConquerShrine.java b/src/main/java/electroblob/wizardry/packet/PacketConquerShrine.java new file mode 100644 index 00000000..7b04362e --- /dev/null +++ b/src/main/java/electroblob/wizardry/packet/PacketConquerShrine.java @@ -0,0 +1,58 @@ +package electroblob.wizardry.packet; + +import electroblob.wizardry.Wizardry; +import io.netty.buffer.ByteBuf; +import net.minecraft.util.math.BlockPos; +import net.minecraftforge.fml.common.network.simpleimpl.IMessage; +import net.minecraftforge.fml.common.network.simpleimpl.IMessageHandler; +import net.minecraftforge.fml.common.network.simpleimpl.MessageContext; + +/** + * [Server -> Client] This packet is sent when a shrine is conquered to update nearby clients and spawn particles. + */ +public class PacketConquerShrine implements IMessageHandler { + + @Override + public IMessage onMessage(Message message, MessageContext ctx){ + + // Just to make sure that the side is correct + if(ctx.side.isClient()){ + // Using a fully qualified name is a good course of action here; we don't really want to clutter the proxy + // methods any more than necessary. + net.minecraft.client.Minecraft.getMinecraft().addScheduledTask(() -> Wizardry.proxy.handleConquerShrinePacket(message)); + } + + return null; + } + + public static class Message implements IMessage { + + public int x; + public int y; + public int z; + + // This constructor is required otherwise you'll get errors (used somewhere in fml through reflection) + public Message(){} + + public Message(BlockPos pos){ + this.x = pos.getX(); + this.y = pos.getY(); + this.z = pos.getZ(); + } + + @Override + public void fromBytes(ByteBuf buf){ + // The order is important + this.x = buf.readInt(); + this.y = buf.readInt(); + this.z = buf.readInt(); + } + + @Override + public void toBytes(ByteBuf buf){ + buf.writeInt(x); + buf.writeInt(y); + buf.writeInt(z); + } + } +} diff --git a/src/main/java/electroblob/wizardry/packet/PacketControlInput.java b/src/main/java/electroblob/wizardry/packet/PacketControlInput.java index c0f3132d..f2a43d39 100644 --- a/src/main/java/electroblob/wizardry/packet/PacketControlInput.java +++ b/src/main/java/electroblob/wizardry/packet/PacketControlInput.java @@ -1,12 +1,18 @@ package electroblob.wizardry.packet; -import electroblob.wizardry.item.ItemWand; +import electroblob.wizardry.Wizardry; +import electroblob.wizardry.item.ISpellCastingItem; import electroblob.wizardry.packet.PacketControlInput.Message; +import electroblob.wizardry.registry.Spells; +import electroblob.wizardry.spell.Possession; +import electroblob.wizardry.spell.Resurrection; import electroblob.wizardry.tileentity.ContainerArcaneWorkbench; -import electroblob.wizardry.util.WandHelper; +import electroblob.wizardry.util.SpellModifiers; +import electroblob.wizardry.util.WizardryUtilities; import io.netty.buffer.ByteBuf; import net.minecraft.entity.player.EntityPlayerMP; import net.minecraft.item.ItemStack; +import net.minecraft.util.EnumHand; import net.minecraftforge.fml.common.network.simpleimpl.IMessage; import net.minecraftforge.fml.common.network.simpleimpl.IMessageHandler; import net.minecraftforge.fml.common.network.simpleimpl.MessageContext; @@ -22,45 +28,100 @@ public class PacketControlInput implements IMessageHandler { final EntityPlayerMP player = ctx.getServerHandler().player; - player.getServerWorld().addScheduledTask(new Runnable(){ + player.getServerWorld().addScheduledTask(() -> { - public void run(){ + ItemStack wand = player.getHeldItemMainhand(); - ItemStack wand = player.getHeldItemMainhand(); + if(!(wand.getItem() instanceof ISpellCastingItem)){ + wand = player.getHeldItemOffhand(); + } - if(!(wand.getItem() instanceof ItemWand)){ - wand = player.getHeldItemOffhand(); - } + switch(message.controlType){ - switch(message.controlType){ - - case APPLY_BUTTON: + case APPLY_BUTTON: + if(!(player.openContainer instanceof ContainerArcaneWorkbench)){ + Wizardry.logger.warn("Received a PacketControlInput, but the player that sent it was not " + + "currently using an arcane workbench. This should not happen!"); + }else{ ((ContainerArcaneWorkbench)player.openContainer).onApplyButtonPressed(player); - break; - - case NEXT_SPELL_KEY: - - if(wand.getItem() instanceof ItemWand){ - - WandHelper.selectNextSpell(wand); - // This line fixes the bug with continuous spells casting when they shouldn't be - player.stopActiveHand(); - } - - break; - - case PREVIOUS_SPELL_KEY: - - if(wand.getItem() instanceof ItemWand){ - - WandHelper.selectPreviousSpell(wand); - // This line fixes the bug with continuous spells casting when they shouldn't be - player.stopActiveHand(); - } - - break; } + + break; + + case NEXT_SPELL_KEY: + + if(wand.getItem() instanceof ISpellCastingItem){ + + ((ISpellCastingItem)wand.getItem()).selectNextSpell(wand); + // This line fixes the bug with continuous spells casting when they shouldn't be + player.stopActiveHand(); + } + + break; + + case PREVIOUS_SPELL_KEY: + + if(wand.getItem() instanceof ISpellCastingItem){ + + ((ISpellCastingItem)wand.getItem()).selectPreviousSpell(wand); + // This line fixes the bug with continuous spells casting when they shouldn't be + player.stopActiveHand(); + } + + break; + + case RESURRECT_BUTTON: + + if(player.isDead && Resurrection.getRemainingWaitTime(player.deathTime) == 0){ + + ItemStack stack = WizardryUtilities.getHotbar(player).stream() + .filter(s -> Resurrection.canStackResurrect(s, player)).findFirst().orElse(null); + + if(stack != null){ + // This should suffice, since this is the only way a player can cast resurrection when dead! + ((ISpellCastingItem)stack.getItem()).cast(stack, Spells.resurrection, player, EnumHand.MAIN_HAND, 0, new SpellModifiers()); + break; + } + } + + Wizardry.logger.warn("Received a resurrect button packet, but the player that sent it was not" + + " currently able to resurrect. This should not happen!"); + + break; + + case CANCEL_RESURRECT: + + if(player.world.getGameRules().getBoolean("keepInventory")) break; // Shouldn't even receive this + + if(player.isDead){ + + ItemStack stack = WizardryUtilities.getHotbar(player).stream() + .filter(s -> Resurrection.canStackResurrect(s, player)).findFirst().orElse(null); + + if(stack != null){ + player.dropItem(stack, true, false); + player.inventory.deleteStack(stack); // Might as well + break; + } + + Wizardry.logger.warn("Received a cancel resurrect packet, but the player that sent it was not" + + " holding a wand with the resurrection spell. This should not happen!"); + } + + Wizardry.logger.warn("Received a cancel resurrect packet, but the player that sent it was not" + + " currently dead. This should not happen!"); + + break; + + case POSSESSION_PROJECTILE: + + if(!Possession.isPossessing(player)) Wizardry.logger.warn("Received a possession projectile packet, " + + "but the player that sent it is not currently possessing anything!"); + + Possession.shootProjectile(player); + + break; } }); } @@ -68,8 +129,8 @@ public class PacketControlInput implements IMessageHandler { return null; } - public static enum ControlType { - APPLY_BUTTON, NEXT_SPELL_KEY, PREVIOUS_SPELL_KEY; + public enum ControlType { + APPLY_BUTTON, NEXT_SPELL_KEY, PREVIOUS_SPELL_KEY, RESURRECT_BUTTON, CANCEL_RESURRECT, POSSESSION_PROJECTILE } public static class Message implements IMessage { diff --git a/src/main/java/electroblob/wizardry/packet/PacketDispenserCastSpell.java b/src/main/java/electroblob/wizardry/packet/PacketDispenserCastSpell.java new file mode 100644 index 00000000..3975bd14 --- /dev/null +++ b/src/main/java/electroblob/wizardry/packet/PacketDispenserCastSpell.java @@ -0,0 +1,94 @@ +package electroblob.wizardry.packet; + +import electroblob.wizardry.Wizardry; +import electroblob.wizardry.packet.PacketDispenserCastSpell.Message; +import electroblob.wizardry.spell.Spell; +import electroblob.wizardry.util.SpellModifiers; +import io.netty.buffer.ByteBuf; +import net.minecraft.util.EnumFacing; +import net.minecraft.util.math.BlockPos; +import net.minecraftforge.fml.common.network.simpleimpl.IMessage; +import net.minecraftforge.fml.common.network.simpleimpl.IMessageHandler; +import net.minecraftforge.fml.common.network.simpleimpl.MessageContext; + +/** + * [Server -> Client] This packet is sent when a spell is cast by a dispenser and returns true, and is sent to + * clients so they can spawn the particles. Unlike the player packets, this is for both continuous and + * non-continuous spells. + */ +public class PacketDispenserCastSpell implements IMessageHandler { + + @Override + public IMessage onMessage(Message message, MessageContext ctx){ + + // Just to make sure that the side is correct + if(ctx.side.isClient()){ + // Using a fully qualified name is a good course of action here; we don't really want to clutter the proxy + // methods any more than necessary. + net.minecraft.client.Minecraft.getMinecraft().addScheduledTask(() -> Wizardry.proxy.handleDispenserCastSpellPacket(message)); + } + + return null; + } + + public static class Message implements IMessage { + + /** ID of the spell being cast */ + public int spellID; + /** Coordinates of the spell origin */ + public double x, y, z; + /** Spell casting direction */ + public EnumFacing direction; + /** BlockPos of the block that cast this spell. Not necessarily the same as the (x, y, z) coordinates. */ + public BlockPos pos; + /** The number of ticks to cast the spell for, or -1 if the spell should be cast until stopped. */ + public int duration; + /** SpellModifiers for the spell */ + public SpellModifiers modifiers; + + // This constructor is required otherwise you'll get errors (used somewhere in fml through reflection) + public Message(){ + } + + public Message(double x, double y, double z, EnumFacing direction, BlockPos pos, Spell spell, int duration, SpellModifiers modifiers){ + + this.x = x; + this.y = y; + this.z = z; + this.direction = direction; + this.pos = pos; + this.spellID = spell.networkID(); + this.duration = duration; + this.modifiers = modifiers; + + } + + @Override + public void fromBytes(ByteBuf buf){ + + // The order is important + this.x = buf.readDouble(); + this.y = buf.readDouble(); + this.z = buf.readDouble(); + this.direction = EnumFacing.values()[buf.readInt()]; + this.pos = BlockPos.fromLong(buf.readLong()); + this.spellID = buf.readInt(); + this.duration = buf.readInt(); + this.modifiers = new SpellModifiers(); + this.modifiers.read(buf); + } + + @Override + public void toBytes(ByteBuf buf){ + + buf.writeDouble(x); + buf.writeDouble(y); + buf.writeDouble(z); + buf.writeInt(direction.ordinal()); + buf.writeLong(pos.toLong()); + buf.writeInt(spellID); + buf.writeInt(duration); + this.modifiers.write(buf); + } + } +} diff --git a/src/main/java/electroblob/wizardry/packet/PacketEmitterData.java b/src/main/java/electroblob/wizardry/packet/PacketEmitterData.java new file mode 100644 index 00000000..4fe8c704 --- /dev/null +++ b/src/main/java/electroblob/wizardry/packet/PacketEmitterData.java @@ -0,0 +1,55 @@ +package electroblob.wizardry.packet; + +import electroblob.wizardry.Wizardry; +import electroblob.wizardry.command.SpellEmitter; +import io.netty.buffer.ByteBuf; +import net.minecraftforge.fml.common.network.simpleimpl.IMessage; +import net.minecraftforge.fml.common.network.simpleimpl.IMessageHandler; +import net.minecraftforge.fml.common.network.simpleimpl.MessageContext; + +import java.util.ArrayList; +import java.util.List; + +/** + * [Server -> Client] This packet is sent each time a player joins a world to synchronise the client-side spell + * emitters with the server-side ones. + */ +public class PacketEmitterData implements IMessageHandler { + + @Override + public IMessage onMessage(Message message, MessageContext ctx){ + // Just to make sure that the side is correct + if(ctx.side.isClient()){ + // Using a fully qualified name is a good course of action here; we don't really want to clutter the proxy + // methods any more than necessary. + net.minecraft.client.Minecraft.getMinecraft().addScheduledTask(() -> Wizardry.proxy.handleEmitterDataPacket(message)); + } + + return null; + } + + public static class Message implements IMessage { + + public List emitters; + + // This constructor is required otherwise you'll get errors (used somewhere in fml through reflection) + public Message(){} + + public Message(List emitters){ + this.emitters = emitters; + } + + @Override + public void fromBytes(ByteBuf buf){ + emitters = new ArrayList<>(); + while(buf.isReadable()){ + emitters.add(SpellEmitter.read(buf)); + } + } + + @Override + public void toBytes(ByteBuf buf){ + emitters.forEach(s -> s.write(buf)); + } + } +} diff --git a/src/main/java/electroblob/wizardry/packet/PacketEndSlowTime.java b/src/main/java/electroblob/wizardry/packet/PacketEndSlowTime.java new file mode 100644 index 00000000..e4d276f8 --- /dev/null +++ b/src/main/java/electroblob/wizardry/packet/PacketEndSlowTime.java @@ -0,0 +1,47 @@ +package electroblob.wizardry.packet; + +import electroblob.wizardry.Wizardry; +import io.netty.buffer.ByteBuf; +import net.minecraft.entity.Entity; +import net.minecraftforge.fml.common.network.simpleimpl.IMessage; +import net.minecraftforge.fml.common.network.simpleimpl.IMessageHandler; +import net.minecraftforge.fml.common.network.simpleimpl.MessageContext; + +/** [Server -> Client] This packet is sent when the slow time potion effect expires or is removed from an + * entity to unblock all nearby entities' updates. */ +public class PacketEndSlowTime implements IMessageHandler { + + @Override + public IMessage onMessage(Message message, MessageContext ctx){ + + // Just to make sure that the side is correct + if(ctx.side.isClient()){ + net.minecraft.client.Minecraft.getMinecraft().addScheduledTask(() -> Wizardry.proxy.handleEndSlowTimePacket(message)); + } + + return null; + } + + public static class Message implements IMessage { + + public int hostID; + + // This constructor is required otherwise you'll get errors (used somewhere in fml through reflection) + public Message(){ + } + + public Message(Entity host){ + this.hostID = host.getEntityId(); + } + + @Override + public void fromBytes(ByteBuf buf){ + this.hostID = buf.readInt(); + } + + @Override + public void toBytes(ByteBuf buf){ + buf.writeInt(hostID); + } + } +} diff --git a/src/main/java/electroblob/wizardry/packet/PacketGlyphData.java b/src/main/java/electroblob/wizardry/packet/PacketGlyphData.java index 883794d1..23e4b7c3 100644 --- a/src/main/java/electroblob/wizardry/packet/PacketGlyphData.java +++ b/src/main/java/electroblob/wizardry/packet/PacketGlyphData.java @@ -1,8 +1,5 @@ package electroblob.wizardry.packet; -import java.util.ArrayList; -import java.util.List; - import electroblob.wizardry.Wizardry; import electroblob.wizardry.packet.PacketGlyphData.Message; import io.netty.buffer.ByteBuf; @@ -11,6 +8,9 @@ import net.minecraftforge.fml.common.network.simpleimpl.IMessage; import net.minecraftforge.fml.common.network.simpleimpl.IMessageHandler; import net.minecraftforge.fml.common.network.simpleimpl.MessageContext; +import java.util.ArrayList; +import java.util.List; + /** * [Server -> Client] This packet is sent each time a player joins a world to synchronise the client-side spell * glyph names with the server-side ones. @@ -23,12 +23,7 @@ public class PacketGlyphData implements IMessageHandler { if(ctx.side.isClient()){ // Using a fully qualified name is a good course of action here; we don't really want to clutter the proxy // methods any more than necessary. - net.minecraft.client.Minecraft.getMinecraft().addScheduledTask(new Runnable(){ - @Override - public void run(){ - Wizardry.proxy.handleGlyphDataPacket(message); - } - }); + net.minecraft.client.Minecraft.getMinecraft().addScheduledTask(() -> Wizardry.proxy.handleGlyphDataPacket(message)); } return null; @@ -52,8 +47,8 @@ public class PacketGlyphData implements IMessageHandler { @Override public void fromBytes(ByteBuf buf){ - names = new ArrayList(); - descriptions = new ArrayList(); + names = new ArrayList<>(); + descriptions = new ArrayList<>(); while(buf.isReadable()){ names.add(ByteBufUtils.readUTF8String(buf)); descriptions.add(ByteBufUtils.readUTF8String(buf)); diff --git a/src/main/java/electroblob/wizardry/packet/PacketNPCCastSpell.java b/src/main/java/electroblob/wizardry/packet/PacketNPCCastSpell.java index 4151d9a3..a25b308d 100644 --- a/src/main/java/electroblob/wizardry/packet/PacketNPCCastSpell.java +++ b/src/main/java/electroblob/wizardry/packet/PacketNPCCastSpell.java @@ -3,6 +3,7 @@ package electroblob.wizardry.packet; import electroblob.wizardry.Wizardry; import electroblob.wizardry.entity.living.ISpellCaster; import electroblob.wizardry.packet.PacketNPCCastSpell.Message; +import electroblob.wizardry.spell.Spell; import electroblob.wizardry.util.SpellModifiers; import io.netty.buffer.ByteBuf; import net.minecraft.util.EnumHand; @@ -52,10 +53,10 @@ public class PacketNPCCastSpell implements IMessageHandler { public Message(){ } - public Message(int casterID, int targetID, EnumHand hand, int spellID, SpellModifiers modifiers){ + public Message(int casterID, int targetID, EnumHand hand, Spell spell, SpellModifiers modifiers){ this.casterID = casterID; this.targetID = targetID; - this.spellID = spellID; + this.spellID = spell.networkID(); this.modifiers = modifiers; this.hand = hand == null ? EnumHand.MAIN_HAND : hand; } diff --git a/src/main/java/electroblob/wizardry/packet/PacketPlayerSync.java b/src/main/java/electroblob/wizardry/packet/PacketPlayerSync.java index 879db01e..6fca18bc 100644 --- a/src/main/java/electroblob/wizardry/packet/PacketPlayerSync.java +++ b/src/main/java/electroblob/wizardry/packet/PacketPlayerSync.java @@ -1,9 +1,8 @@ package electroblob.wizardry.packet; -import java.util.HashSet; -import java.util.Set; - import electroblob.wizardry.Wizardry; +import electroblob.wizardry.data.IVariable; +import electroblob.wizardry.data.WizardData; import electroblob.wizardry.packet.PacketPlayerSync.Message; import electroblob.wizardry.spell.Spell; import io.netty.buffer.ByteBuf; @@ -11,9 +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.MessageContext; +import java.util.*; + /** * [Server -> Client] This packet is sent to synchronise any fields that need synchronising in - * {@link electroblob.wizardry.WizardData WizardData}. This packet is not sent often enough and is too small to warrant + * {@link WizardData WizardData}. This packet is not sent often enough and is too small to warrant * having separate packets for each field that needs synchronising. */ public class PacketPlayerSync implements IMessageHandler { @@ -24,12 +25,7 @@ public class PacketPlayerSync implements IMessageHandler { if(ctx.side.isClient()){ // Using a fully qualified name is a good course of action here; we don't really want to clutter the proxy // methods any more than necessary. - net.minecraft.client.Minecraft.getMinecraft().addScheduledTask(new Runnable(){ - @Override - public void run(){ - Wizardry.proxy.handlePlayerSyncPacket(message); - } - }); + net.minecraft.client.Minecraft.getMinecraft().addScheduledTask(() -> Wizardry.proxy.handlePlayerSyncPacket(message)); } return null; @@ -37,36 +33,51 @@ public class PacketPlayerSync implements IMessageHandler { public static class Message implements IMessage { + public long seed; public Set spellsDiscovered; public int selectedMinionID; + public Map spellData; // This constructor is required otherwise you'll get errors (used somewhere in fml through reflection) public Message(){ } - public Message(Set spellsDiscovered2, int selectedMinionID){ - this.spellsDiscovered = spellsDiscovered2; + public Message(long seed, Set spellsDiscovered, int selectedMinionID, Map spellData){ + this.seed = seed; + this.spellsDiscovered = spellsDiscovered; this.selectedMinionID = selectedMinionID; + this.spellData = spellData; } @Override public void fromBytes(ByteBuf buf){ + + this.seed = buf.readLong(); this.selectedMinionID = buf.readInt(); - this.spellsDiscovered = new HashSet(); + + this.spellData = new HashMap<>(); + WizardData.getSyncedVariables().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 + spellData.values().removeIf(Objects::isNull); + + this.spellsDiscovered = new HashSet<>(); while(buf.isReadable()){ - this.spellsDiscovered.add(Spell.get(buf.readInt())); + this.spellsDiscovered.add(Spell.byNetworkID(buf.readInt())); } } @Override + @SuppressWarnings("unchecked") // We know it's ok public void toBytes(ByteBuf buf){ + buf.writeLong(seed); buf.writeInt(selectedMinionID); - if(this.spellsDiscovered == null) return; + WizardData.getSyncedVariables().forEach(v -> v.write(buf, spellData.get(v))); + if(this.spellsDiscovered == null) return; for(Spell spell : this.spellsDiscovered){ - buf.writeInt(spell.id()); + buf.writeInt(spell.networkID()); } } } diff --git a/src/main/java/electroblob/wizardry/packet/PacketPossession.java b/src/main/java/electroblob/wizardry/packet/PacketPossession.java new file mode 100644 index 00000000..34c5e3e3 --- /dev/null +++ b/src/main/java/electroblob/wizardry/packet/PacketPossession.java @@ -0,0 +1,58 @@ +package electroblob.wizardry.packet; + +import electroblob.wizardry.Wizardry; +import io.netty.buffer.ByteBuf; +import net.minecraft.entity.EntityLiving; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraftforge.fml.common.network.simpleimpl.IMessage; +import net.minecraftforge.fml.common.network.simpleimpl.IMessageHandler; +import net.minecraftforge.fml.common.network.simpleimpl.MessageContext; + +import javax.annotation.Nullable; + +/** [Server -> Client] This packet is sent when a player possesses an entity or when a player stops possessing + * to update all clients. */ +public class PacketPossession implements IMessageHandler { + + @Override + public IMessage onMessage(Message message, MessageContext ctx){ + + // Just to make sure that the side is correct + if(ctx.side.isClient()){ + net.minecraft.client.Minecraft.getMinecraft().addScheduledTask(() -> Wizardry.proxy.handlePossessionPacket(message)); + } + + return null; + } + + public static class Message implements IMessage { + + public int playerID; + public int targetID; + public int duration; + + // This constructor is required otherwise you'll get errors (used somewhere in fml through reflection) + public Message(){ + } + + public Message(EntityPlayer host, @Nullable EntityLiving target, int duration){ + this.playerID = host.getEntityId(); + this.targetID = target == null ? -1 : target.getEntityId(); + this.duration = duration; + } + + @Override + public void fromBytes(ByteBuf buf){ + this.playerID = buf.readInt(); + this.targetID = buf.readInt(); + this.duration = buf.readInt(); + } + + @Override + public void toBytes(ByteBuf buf){ + buf.writeInt(playerID); + buf.writeInt(targetID); + buf.writeInt(duration); + } + } +} diff --git a/src/main/java/electroblob/wizardry/packet/PacketRequestAdvancementSync.java b/src/main/java/electroblob/wizardry/packet/PacketRequestAdvancementSync.java new file mode 100644 index 00000000..a4d7fc9c --- /dev/null +++ b/src/main/java/electroblob/wizardry/packet/PacketRequestAdvancementSync.java @@ -0,0 +1,50 @@ +package electroblob.wizardry.packet; + +import io.netty.buffer.ByteBuf; +import net.minecraft.advancements.Advancement; +import net.minecraft.entity.player.EntityPlayerMP; +import net.minecraft.util.ResourceLocation; +import net.minecraftforge.fml.common.network.simpleimpl.IMessage; +import net.minecraftforge.fml.common.network.simpleimpl.IMessageHandler; +import net.minecraftforge.fml.common.network.simpleimpl.MessageContext; + +import java.util.ArrayList; + +/** [Client -> Server] Fired on resource reload to request that the server re-sync the player's advancements. */ +public class PacketRequestAdvancementSync implements IMessageHandler { + + @Override + public PacketSyncAdvancements.Message onMessage(Message message, MessageContext ctx){ + + // Just to make sure that the side is correct + if(ctx.side.isServer()){ + + final EntityPlayerMP player = ctx.getServerHandler().player; + + ArrayList advancements = new ArrayList<>(); + + for(Advancement advancement : player.getServer().getAdvancementManager().getAdvancements()){ + if(player.getAdvancements().getProgress(advancement).isDone()) advancements.add(advancement.getId()); + } + + return new PacketSyncAdvancements.Message(false, advancements.toArray(new ResourceLocation[0])); + } + + return null; + } + + + public static class Message implements IMessage { + + // This constructor is required otherwise you'll get errors (used somewhere in fml through reflection) + public Message(){} + + // Don't need to put anything in here! + + @Override + public void fromBytes(ByteBuf buf){} + + @Override + public void toBytes(ByteBuf buf){} + } +} diff --git a/src/main/java/electroblob/wizardry/packet/PacketResurrection.java b/src/main/java/electroblob/wizardry/packet/PacketResurrection.java new file mode 100644 index 00000000..5526489e --- /dev/null +++ b/src/main/java/electroblob/wizardry/packet/PacketResurrection.java @@ -0,0 +1,47 @@ +package electroblob.wizardry.packet; + +import electroblob.wizardry.Wizardry; +import io.netty.buffer.ByteBuf; +import net.minecraftforge.fml.common.network.simpleimpl.IMessage; +import net.minecraftforge.fml.common.network.simpleimpl.IMessageHandler; +import net.minecraftforge.fml.common.network.simpleimpl.MessageContext; + +/** + * [Server -> Client] This packet is sent to clients in the same dimension when a player is resurrected. + */ +public class PacketResurrection implements IMessageHandler { + + @Override + public IMessage onMessage(Message message, MessageContext ctx){ + // Just to make sure that the side is correct + if(ctx.side.isClient()){ + // Using a fully qualified name is a good course of action here; we don't really want to clutter the proxy + // methods any more than necessary. + net.minecraft.client.Minecraft.getMinecraft().addScheduledTask(() -> Wizardry.proxy.handleResurrectionPacket(message)); + } + + return null; + } + + public static class Message implements IMessage { + + public int playerID; + + // This constructor is required otherwise you'll get errors (used somewhere in fml through reflection) + public Message(){} + + public Message(int playerID){ + this.playerID = playerID; + } + + @Override + public void fromBytes(ByteBuf buf){ + this.playerID = buf.readInt(); + } + + @Override + public void toBytes(ByteBuf buf){ + buf.writeInt(playerID); + } + } +} diff --git a/src/main/java/electroblob/wizardry/packet/PacketSpellProperties.java b/src/main/java/electroblob/wizardry/packet/PacketSpellProperties.java new file mode 100644 index 00000000..acacde6a --- /dev/null +++ b/src/main/java/electroblob/wizardry/packet/PacketSpellProperties.java @@ -0,0 +1,64 @@ +package electroblob.wizardry.packet; + +import electroblob.wizardry.spell.Spell; +import electroblob.wizardry.util.SpellProperties; +import io.netty.buffer.ByteBuf; +import net.minecraft.entity.player.EntityPlayerMP; +import net.minecraftforge.fml.common.network.simpleimpl.IMessage; +import net.minecraftforge.fml.common.network.simpleimpl.IMessageHandler; +import net.minecraftforge.fml.common.network.simpleimpl.MessageContext; + +import java.util.ArrayList; +import java.util.List; + +/** [Server -> Client] This packet is sent to sync server-side spell properties with clients on login. */ +public class PacketSpellProperties implements IMessageHandler { + + @Override + public IMessage onMessage(Message message, MessageContext ctx){ + + // Just to make sure that the side is correct + if(ctx.side.isServer()){ + + final EntityPlayerMP player = ctx.getServerHandler().player; + + player.getServerWorld().addScheduledTask(() -> { + for(int i=0; i propertiesList = new ArrayList<>(); + int i = 0; + + while(buf.isReadable()){ + propertiesList.add(new SpellProperties(Spell.byNetworkID(i++), buf)); + } + + propertiesArray = propertiesList.toArray(new SpellProperties[0]); + } + + @Override + public void toBytes(ByteBuf buf){ + for(SpellProperties properties : propertiesArray) properties.write(buf); + } + } +} diff --git a/src/main/java/electroblob/wizardry/packet/PacketSyncAdvancements.java b/src/main/java/electroblob/wizardry/packet/PacketSyncAdvancements.java new file mode 100644 index 00000000..f5fc1d78 --- /dev/null +++ b/src/main/java/electroblob/wizardry/packet/PacketSyncAdvancements.java @@ -0,0 +1,61 @@ +package electroblob.wizardry.packet; + +import electroblob.wizardry.Wizardry; +import io.netty.buffer.ByteBuf; +import net.minecraft.util.ResourceLocation; +import net.minecraftforge.fml.common.network.ByteBufUtils; +import net.minecraftforge.fml.common.network.simpleimpl.IMessage; +import net.minecraftforge.fml.common.network.simpleimpl.IMessageHandler; +import net.minecraftforge.fml.common.network.simpleimpl.MessageContext; + +import java.util.ArrayList; + +/** [Server -> Client] This packet is fired on login and on advancement gain to update the handbook progress. */ +public class PacketSyncAdvancements implements IMessageHandler { + + @Override + public IMessage onMessage(Message message, MessageContext ctx){ + + // Just to make sure that the side is correct + if(ctx.side.isClient()){ + // Using a fully qualified name is a good course of action here; we don't really want to clutter the proxy + // methods any more than necessary. + net.minecraft.client.Minecraft.getMinecraft().addScheduledTask(() -> Wizardry.proxy.handleAdvancementSyncPacket(message)); + } + + return null; + } + + public static class Message implements IMessage { + + public boolean showToasts; + public ResourceLocation[] completedAdvancements; + + // This constructor is required otherwise you'll get errors (used somewhere in fml through reflection) + public Message(){ + } + + public Message(boolean showToasts, ResourceLocation... completed){ + this.showToasts = showToasts; + this.completedAdvancements = completed; + } + + @Override + public void fromBytes(ByteBuf buf){ + showToasts = buf.readBoolean(); + ArrayList advancements = new ArrayList<>(); + while(buf.isReadable()){ + advancements.add(new ResourceLocation(ByteBufUtils.readUTF8String(buf))); + } + this.completedAdvancements = advancements.toArray(new ResourceLocation[0]); + } + + @Override + public void toBytes(ByteBuf buf){ + buf.writeBoolean(showToasts); + for(ResourceLocation advancement : completedAdvancements){ + ByteBufUtils.writeUTF8String(buf, advancement.toString()); + } + } + } +} diff --git a/src/main/java/electroblob/wizardry/packet/PacketSyncSettings.java b/src/main/java/electroblob/wizardry/packet/PacketSyncSettings.java index c8afb156..9fc16ac5 100644 --- a/src/main/java/electroblob/wizardry/packet/PacketSyncSettings.java +++ b/src/main/java/electroblob/wizardry/packet/PacketSyncSettings.java @@ -21,13 +21,7 @@ public class PacketSyncSettings implements IMessageHandler { if(ctx.side.isClient()){ // Using a fully qualified name is a good course of action here; we don't really want to clutter the proxy // any more than necessary. - net.minecraft.client.Minecraft.getMinecraft().addScheduledTask(new Runnable(){ - @Override - public void run(){ - copySettings(message); - } - }); - + net.minecraft.client.Minecraft.getMinecraft().addScheduledTask(() -> copySettings(message)); } return null; @@ -35,16 +29,14 @@ public class PacketSyncSettings implements IMessageHandler { private static void copySettings(Message message){ Wizardry.settings.discoveryMode = message.settings.discoveryMode; - // Wizardry.settings.maxSpellCommandMultiplier = message.settings.maxSpellCommandMultiplier; - // Wizardry.settings.castCommandName = message.settings.castCommandName; - // Wizardry.settings.discoverspellCommandName = message.settings.discoverspellCommandName; - // Wizardry.settings.allyCommandName = message.settings.allyCommandName; - // Wizardry.settings.alliesCommandName = message.settings.alliesCommandName; + Wizardry.settings.creativeBypassesArcaneLock = message.settings.creativeBypassesArcaneLock; + Wizardry.settings.slowTimeAffectsPlayers = message.settings.slowTimeAffectsPlayers; + Wizardry.settings.forfeitChance = message.settings.forfeitChance; } public static class Message implements IMessage { - /** EntityID of the caster */ + /** Instance of wizardry's settings object */ public Settings settings; // This constructor is required otherwise you'll get errors (used somewhere in fml through reflection) @@ -62,21 +54,17 @@ public class PacketSyncSettings implements IMessageHandler { settings = new Settings(); // The order is important settings.discoveryMode = buf.readBoolean(); - // settings.maxSpellCommandMultiplier = buf.readDouble(); - // settings.castCommandName = ByteBufUtils.readUTF8String(buf); - // settings.discoverspellCommandName = ByteBufUtils.readUTF8String(buf); - // settings.allyCommandName = ByteBufUtils.readUTF8String(buf); - // settings.alliesCommandName = ByteBufUtils.readUTF8String(buf); + settings.creativeBypassesArcaneLock = buf.readBoolean(); + settings.slowTimeAffectsPlayers = buf.readBoolean(); + settings.forfeitChance = buf.readFloat(); } @Override public void toBytes(ByteBuf buf){ buf.writeBoolean(settings.discoveryMode); - // buf.writeDouble(settings.maxSpellCommandMultiplier); - // ByteBufUtils.writeUTF8String(buf, settings.castCommandName); - // ByteBufUtils.writeUTF8String(buf, settings.discoverspellCommandName); - // ByteBufUtils.writeUTF8String(buf, settings.allyCommandName); - // ByteBufUtils.writeUTF8String(buf, settings.alliesCommandName); + buf.writeBoolean(settings.creativeBypassesArcaneLock); + buf.writeBoolean(settings.slowTimeAffectsPlayers); + buf.writeFloat((float)settings.forfeitChance); // Configs don't have floats but this can only be 0-1 anyway } } } diff --git a/src/main/java/electroblob/wizardry/packet/PacketTransportation.java b/src/main/java/electroblob/wizardry/packet/PacketTransportation.java index 8f6e5a0e..afb07f7d 100644 --- a/src/main/java/electroblob/wizardry/packet/PacketTransportation.java +++ b/src/main/java/electroblob/wizardry/packet/PacketTransportation.java @@ -19,12 +19,7 @@ public class PacketTransportation implements IMessageHandler if(ctx.side.isClient()){ // Using a fully qualified name is a good course of action here; we don't really want to clutter the proxy // methods any more than necessary. - net.minecraft.client.Minecraft.getMinecraft().addScheduledTask(new Runnable(){ - @Override - public void run(){ - Wizardry.proxy.handleTransportationPacket(message); - } - }); + net.minecraft.client.Minecraft.getMinecraft().addScheduledTask(() -> Wizardry.proxy.handleTransportationPacket(message)); } return null; diff --git a/src/main/java/electroblob/wizardry/packet/WizardryPacketHandler.java b/src/main/java/electroblob/wizardry/packet/WizardryPacketHandler.java index ed40e136..41d12d0d 100644 --- a/src/main/java/electroblob/wizardry/packet/WizardryPacketHandler.java +++ b/src/main/java/electroblob/wizardry/packet/WizardryPacketHandler.java @@ -22,6 +22,16 @@ public class WizardryPacketHandler { registerMessage(PacketClairvoyance.class, PacketClairvoyance.Message.class); registerMessage(PacketSyncSettings.class, PacketSyncSettings.Message.class); registerMessage(PacketNPCCastSpell.class, PacketNPCCastSpell.Message.class); + registerMessage(PacketDispenserCastSpell.class, PacketDispenserCastSpell.Message.class); + registerMessage(PacketSpellProperties.class, PacketSpellProperties.Message.class); + registerMessage(PacketSyncAdvancements.class, PacketSyncAdvancements.Message.class); + registerMessage(PacketRequestAdvancementSync.class, PacketRequestAdvancementSync.Message.class); + registerMessage(PacketEndSlowTime.class, PacketEndSlowTime.Message.class); + registerMessage(PacketResurrection.class, PacketResurrection.Message.class); + registerMessage(PacketCastSpellAtPos.class, PacketCastSpellAtPos.Message.class); + registerMessage(PacketEmitterData.class, PacketEmitterData.Message.class); + registerMessage(PacketPossession.class, PacketPossession.Message.class); + registerMessage(PacketConquerShrine.class, PacketConquerShrine.Message.class); } private static int nextPacketId = 0; diff --git a/src/main/java/electroblob/wizardry/potion/Curse.java b/src/main/java/electroblob/wizardry/potion/Curse.java new file mode 100644 index 00000000..09b9e8ab --- /dev/null +++ b/src/main/java/electroblob/wizardry/potion/Curse.java @@ -0,0 +1,70 @@ +package electroblob.wizardry.potion; + +import electroblob.wizardry.Wizardry; +import net.minecraft.item.ItemStack; +import net.minecraft.potion.PotionEffect; +import net.minecraft.util.ResourceLocation; +import net.minecraftforge.fml.relauncher.Side; +import net.minecraftforge.fml.relauncher.SideOnly; + +import java.util.ArrayList; +import java.util.List; + +/** A curse is a permanent potion effect, which is displayed in the inventory with a special background and + * no timer. It also allows for longer potion effect names by wrapping them onto two lines. */ +public class Curse extends PotionMagicEffect { + + private static final ResourceLocation BACKGROUND = new ResourceLocation(Wizardry.MODID, "textures/gui/curse_background.png"); + + public Curse(boolean isBadEffect, int liquidColour, ResourceLocation texture){ + super(isBadEffect, liquidColour, texture); + } + + @Override + public boolean shouldRenderInvText(PotionEffect effect){ + return false; + } + + @Override + public List getCurativeItems(){ + return new ArrayList<>(); // Cannot be cured! + } + + @Override + @SideOnly(Side.CLIENT) + public void renderInventoryEffect(int x, int y, PotionEffect effect, net.minecraft.client.Minecraft mc){ + + mc.renderEngine.bindTexture(BACKGROUND); + electroblob.wizardry.client.DrawingUtils.drawTexturedRect(x, y, 0, 0, 140, 32, 256, 256); + + super.renderInventoryEffect(x, y, effect, mc); + + String name = net.minecraft.client.resources.I18n.format(this.getName()); + + // Amplifier 0 (which would be I) is not rendered and the tooltips only go up to X (amplifier 9) + // The vanilla implementation uses elseifs and only goes up to 4... how lazy. + if(effect.getAmplifier() > 0 && effect.getAmplifier() < 10){ + name = name + " " + net.minecraft.client.resources.I18n.format("enchantment.level." + (effect.getAmplifier() + 1)); + } + + List lines = mc.fontRenderer.listFormattedStringToWidth(name, 100); + + int i=0; + for(String line : lines){ + int h = lines.size() == 1 ? 5 : i * (mc.fontRenderer.FONT_HEIGHT + 1); + mc.fontRenderer.drawStringWithShadow(line, (float)(x + 10 + 18), (float)(y + 6 + h), 0xbf00ee); + i++; + } + } + + @Override + @SideOnly(Side.CLIENT) + public void renderHUDEffect(int x, int y, PotionEffect effect, net.minecraft.client.Minecraft mc, float alpha){ + + net.minecraft.client.renderer.GlStateManager.color(1, 1, 1, 1); + mc.renderEngine.bindTexture(BACKGROUND); + electroblob.wizardry.client.DrawingUtils.drawTexturedRect(x, y, 141, 0, 24, 24, 256, 256); + super.renderHUDEffect(x, y, effect, mc, alpha); + } + +} diff --git a/src/main/java/electroblob/wizardry/potion/CurseEnfeeblement.java b/src/main/java/electroblob/wizardry/potion/CurseEnfeeblement.java new file mode 100644 index 00000000..69daa132 --- /dev/null +++ b/src/main/java/electroblob/wizardry/potion/CurseEnfeeblement.java @@ -0,0 +1,49 @@ +package electroblob.wizardry.potion; + +import electroblob.wizardry.Wizardry; +import electroblob.wizardry.registry.WizardryPotions; +import net.minecraft.entity.SharedMonsterAttributes; +import net.minecraft.util.FoodStats; +import net.minecraft.util.ResourceLocation; +import net.minecraftforge.fml.common.Mod; +import net.minecraftforge.fml.common.ObfuscationReflectionHelper; +import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; +import net.minecraftforge.fml.common.gameevent.TickEvent; + +import java.lang.reflect.Field; + +@Mod.EventBusSubscriber +public class CurseEnfeeblement extends Curse { + + // Yay more reflection + private static final Field foodTimer; + + static { + foodTimer = ObfuscationReflectionHelper.findField(FoodStats.class, "field_75123_d"); + foodTimer.setAccessible(true); + } + + public CurseEnfeeblement(boolean isBadEffect, int liquiidColour){ + super(isBadEffect, liquiidColour, new ResourceLocation(Wizardry.MODID, "textures/gui/potion_icon_curse_of_enfeeblement.png")); + // This needs to be here because registerPotionAttributeModifier doesn't like it if the potion has no name yet. + this.setPotionName("potion." + Wizardry.MODID + ":curse_of_enfeeblement"); + this.registerPotionAttributeModifier(SharedMonsterAttributes.MAX_HEALTH, + "2e8c378e-3d51-4ba1-b02c-591b5d968a05", -0.2, 1); + } + + @SubscribeEvent + public static void onPlayerTickEvent(TickEvent.PlayerTickEvent event){ + // Players are the only entities with natural regeneration + // This can't be done in performEffect as that method only gets called every 20 ticks or so + // Don't bother trying to prevent it unless the player is full enough + if(event.player.isPotionActive(WizardryPotions.curse_of_enfeeblement) && event.player.getFoodStats().getFoodLevel() > 17){ + try{ + // Constantly setting this to zero prevents natural regeneration + foodTimer.set(event.player.getFoodStats(), 0); + }catch(IllegalAccessException e){ + Wizardry.logger.error("Error setting player food timer: ", e); + } + } + } + +} diff --git a/src/main/java/electroblob/wizardry/potion/CurseUndeath.java b/src/main/java/electroblob/wizardry/potion/CurseUndeath.java new file mode 100644 index 00000000..6f2d0a9f --- /dev/null +++ b/src/main/java/electroblob/wizardry/potion/CurseUndeath.java @@ -0,0 +1,58 @@ +package electroblob.wizardry.potion; + +import electroblob.wizardry.Wizardry; +import net.minecraft.entity.EntityLivingBase; +import net.minecraft.inventory.EntityEquipmentSlot; +import net.minecraft.item.ItemStack; +import net.minecraft.util.ResourceLocation; +import net.minecraft.util.math.BlockPos; + +public class CurseUndeath extends Curse { + + public CurseUndeath(boolean isBadEffect, int liquiidColour){ + super(isBadEffect, liquiidColour, new ResourceLocation(Wizardry.MODID, "textures/gui/potion_icon_curse_of_undeath.png")); + // This needs to be here because registerPotionAttributeModifier doesn't like it if the potion has no name yet. + this.setPotionName("potion." + Wizardry.MODID + ":curse_of_undeath"); + } + + @Override + public boolean isReady(int duration, int amplifier){ + return true; + } + + @Override + public void performEffect(EntityLivingBase entitylivingbase, int strength){ + + // Adapted from EntityZombie + if(entitylivingbase.world.isDaytime() && !entitylivingbase.world.isRemote){ + + float f = entitylivingbase.getBrightness(); + + if(f > 0.5F && entitylivingbase.world.rand.nextFloat() * 30.0F < (f - 0.4F) * 2.0F + && entitylivingbase.world.canSeeSky(new BlockPos(entitylivingbase.posX, + entitylivingbase.posY + (double)entitylivingbase.getEyeHeight(), entitylivingbase.posZ))){ + + boolean flag = true; + ItemStack itemstack = entitylivingbase.getItemStackFromSlot(EntityEquipmentSlot.HEAD); + + if(!itemstack.isEmpty()){ + if(itemstack.isItemStackDamageable()){ + + itemstack.setItemDamage(itemstack.getItemDamage() + entitylivingbase.world.rand.nextInt(2)); + + if(itemstack.getItemDamage() >= itemstack.getMaxDamage()){ + entitylivingbase.renderBrokenItemStack(itemstack); + entitylivingbase.setItemStackToSlot(EntityEquipmentSlot.HEAD, ItemStack.EMPTY); + } + } + + flag = false; + } + + if(flag){ + entitylivingbase.setFire(8); + } + } + } + } +} diff --git a/src/main/java/electroblob/wizardry/potion/ICustomPotionParticles.java b/src/main/java/electroblob/wizardry/potion/ICustomPotionParticles.java index c1c565ff..ab0ec6e0 100644 --- a/src/main/java/electroblob/wizardry/potion/ICustomPotionParticles.java +++ b/src/main/java/electroblob/wizardry/potion/ICustomPotionParticles.java @@ -1,7 +1,6 @@ package electroblob.wizardry.potion; -import java.util.stream.Collectors; - +import net.minecraft.entity.EntityLivingBase; import net.minecraft.potion.PotionEffect; import net.minecraft.potion.PotionUtils; import net.minecraft.world.World; @@ -10,16 +9,23 @@ import net.minecraftforge.event.entity.living.PotionColorCalculationEvent; import net.minecraftforge.fml.common.Mod; import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; +import java.util.stream.Collectors; + /** - * Interface for potion effects that spawn custom particles instead of (or as well as) the vanilla 'swirly' particles. - * To hide the vanilla 'swirly' particles, set the potion's liquid colour to 0 (black). By default, potions that implement - * this interface no longer mix their colour with other potions. + * Interface for potion effects that spawn custom particles instead of (or as well as) the vanilla 'swirly' particles.
    + *
    + * To hide the vanilla 'swirly' particles, set the potion's liquid colour to 0 (black). By default, potions that + * implement this interface do not mix their colour with other potions.
    + *
    + * Potions that implement this interface also implement {@link ISyncedPotion} since any custom particles require syncing + * to disappear correctly when the effect ends; if syncing is not required, override + * {@link ISyncedPotion#shouldSync(EntityLivingBase)} to return false. * * @author Electroblob * @since Wizardry 1.2 */ @Mod.EventBusSubscriber -public interface ICustomPotionParticles { +public interface ICustomPotionParticles extends ISyncedPotion { /** * Called from the event handler to spawn a single custom potion particle. To get an instance of @@ -65,4 +71,5 @@ public interface ICustomPotionParticles { p -> !(p instanceof ICustomPotionParticles && !((ICustomPotionParticles)p).shouldMixColour())) .collect(Collectors.toList()))); } + } diff --git a/src/main/java/electroblob/wizardry/potion/ISyncedPotion.java b/src/main/java/electroblob/wizardry/potion/ISyncedPotion.java new file mode 100644 index 00000000..76741001 --- /dev/null +++ b/src/main/java/electroblob/wizardry/potion/ISyncedPotion.java @@ -0,0 +1,81 @@ +package electroblob.wizardry.potion; + +import net.minecraft.entity.EntityLivingBase; +import net.minecraft.entity.player.EntityPlayerMP; +import net.minecraft.network.play.server.SPacketEntityEffect; +import net.minecraft.network.play.server.SPacketRemoveEntityEffect; +import net.minecraftforge.event.entity.living.PotionEvent; +import net.minecraftforge.fml.common.Mod; +import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; + +/** + * Interface for potion effects that need syncing to ensure client and server side are consistent. Simply implement + * this interface and the potion will be synced automatically. + * + * @author Electroblob + * @since Wizardry 1.2 + */ +@Mod.EventBusSubscriber +public interface ISyncedPotion { + + /** The distance from an entity with this effect within which players will receive potion update packets. */ + double SYNC_RADIUS = 64; + + /** Returns true if this potion should sync with nearby clients when added to / removed from an entity and on + * expiry, false if not. The host entity is provided in case syncing is entity-dependent. Defaults to true. */ + default boolean shouldSync(EntityLivingBase host){ + return true; + } + + // The following event handlers fix the inconsistencies caused by clients not syncing correctly + // These packets are only sent for players with potion effects in vanilla, and only to that player's client + + // This one is only actually necessary if the effect gets added via a server-side method e.g. commands + // Unfortunately there's no way of checking that, so we'll just have to live with the extra packets + @SubscribeEvent + public static void onPotionAddedEvent(PotionEvent.PotionAddedEvent event){ + + if(event.getPotionEffect().getPotion() instanceof ISyncedPotion + && ((ISyncedPotion)event.getPotionEffect().getPotion()).shouldSync(event.getEntityLiving())){ + + if(!event.getEntityLiving().world.isRemote){ + event.getEntityLiving().world.playerEntities.stream() + .filter(p -> p.getDistanceSq(event.getEntityLiving()) < SYNC_RADIUS * SYNC_RADIUS) + // Apparently unchecked casting in a lambda expression doesn't generate a warning. Who knew? + // (We know this cast is safe though) + .forEach(p -> ((EntityPlayerMP)p).connection.sendPacket(new SPacketEntityEffect( + event.getEntity().getEntityId(), event.getPotionEffect()))); + } + } + } + + @SubscribeEvent + public static void onPotionExpiryEvent(PotionEvent.PotionExpiryEvent event){ + + if(event.getPotionEffect().getPotion() instanceof ISyncedPotion + && ((ISyncedPotion)event.getPotionEffect().getPotion()).shouldSync(event.getEntityLiving())){ + + if(!event.getEntityLiving().world.isRemote){ + event.getEntityLiving().world.playerEntities.stream() + .filter(p -> p.getDistanceSq(event.getEntityLiving()) < SYNC_RADIUS * SYNC_RADIUS) + .forEach(p -> ((EntityPlayerMP)p).connection.sendPacket(new SPacketRemoveEntityEffect( + event.getEntity().getEntityId(), event.getPotionEffect().getPotion()))); + } + } + } + + @SubscribeEvent + public static void onPotionRemoveEvent(PotionEvent.PotionRemoveEvent event){ + + if(event.getPotionEffect().getPotion() instanceof ISyncedPotion + && ((ISyncedPotion)event.getPotionEffect().getPotion()).shouldSync(event.getEntityLiving())){ + + if(!event.getEntityLiving().world.isRemote){ + event.getEntityLiving().world.playerEntities.stream() + .filter(p -> p.getDistanceSq(event.getEntityLiving()) < SYNC_RADIUS * SYNC_RADIUS) + .forEach(p -> ((EntityPlayerMP)p).connection.sendPacket(new SPacketRemoveEntityEffect( + event.getEntity().getEntityId(), event.getPotionEffect().getPotion()))); + } + } + } +} diff --git a/src/main/java/electroblob/wizardry/potion/PotionContainment.java b/src/main/java/electroblob/wizardry/potion/PotionContainment.java new file mode 100644 index 00000000..672d6ba6 --- /dev/null +++ b/src/main/java/electroblob/wizardry/potion/PotionContainment.java @@ -0,0 +1,121 @@ +package electroblob.wizardry.potion; + +import electroblob.wizardry.Wizardry; +import electroblob.wizardry.registry.WizardryPotions; +import electroblob.wizardry.util.WizardryUtilities; +import net.minecraft.entity.EntityLivingBase; +import net.minecraft.entity.player.EntityPlayerMP; +import net.minecraft.nbt.NBTUtil; +import net.minecraft.network.play.server.SPacketEntityVelocity; +import net.minecraft.util.ResourceLocation; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.Vec3d; +import net.minecraftforge.event.entity.living.LivingEvent.LivingUpdateEvent; +import net.minecraftforge.fml.common.Mod; +import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; + +@Mod.EventBusSubscriber +public class PotionContainment extends PotionMagicEffect { + + public static final String ENTITY_TAG = "containmentPos"; + + public PotionContainment(boolean isBadEffect, int liquidColour){ + super(isBadEffect, liquidColour, new ResourceLocation(Wizardry.MODID, "textures/gui/potion_icon_containment.png")); + this.setPotionName("potion." + Wizardry.MODID + ":containment"); + } + + @Override + public boolean isReady(int duration, int amplifier){ + return true; // Execute the effect every tick + } + + public static float getContainmentDistance(int effectStrength){ + return 15 - effectStrength * 4; + } + + @Override + public void performEffect(EntityLivingBase target, int strength){ + + float maxDistance = getContainmentDistance(strength); + + // Initialise the containment position to the entity's position if it wasn't set already + if(!target.getEntityData().hasKey(ENTITY_TAG)){ + target.getEntityData().setTag(ENTITY_TAG, NBTUtil.createPosTag(new BlockPos(target.getPositionVector().subtract(0.5, 0.5, 0.5)))); + } + + Vec3d origin = WizardryUtilities.getCentre(NBTUtil.getPosFromTag(target.getEntityData().getCompoundTag(ENTITY_TAG))); + + double x = target.posX, y = target.posY, z = target.posZ; + + // Containment fields are cubes so we're dealing with each axis separately + if(target.getEntityBoundingBox().maxX > origin.x + maxDistance) x = origin.x + maxDistance - target.width/2; + if(target.getEntityBoundingBox().minX < origin.x - maxDistance) x = origin.x - maxDistance + target.width/2; + + if(target.getEntityBoundingBox().maxY > origin.y + maxDistance) y = origin.y + maxDistance - target.height; + if(target.getEntityBoundingBox().minY < origin.y - maxDistance) y = origin.y - maxDistance; + + if(target.getEntityBoundingBox().maxZ > origin.z + maxDistance) z = origin.z + maxDistance - target.width/2; + if(target.getEntityBoundingBox().minZ < origin.z - maxDistance) z = origin.z - maxDistance + target.width/2; + + if(x != target.posX || y != target.posY || z != target.posZ){ + +// if(target.world.isRemote){ +// +// if(x != target.posX){ +// for(int i = 0; i < 20; i++){ +// ParticleBuilder.create(ParticleBuilder.Type.DUST).pos( +// x, +// target.getEntityBoundingBox().minY + target.height * target.world.rand.nextFloat(), +// target.posZ + target.width * (target.world.rand.nextFloat() - 0.5f)) +// .face(EnumFacing.EAST).clr(0.8f, 0.9f, 1).spawn(target.world); +// } +// } +// +// if(y != target.posY){ +// for(int i = 0; i < 20; i++){ +// ParticleBuilder.create(ParticleBuilder.Type.DUST).pos( +// target.posX + target.width * (target.world.rand.nextFloat() - 0.5f), +// y, +// target.posZ + target.width * (target.world.rand.nextFloat() - 0.5f)) +// .face(EnumFacing.UP).clr(0.8f, 0.9f, 1).spawn(target.world); +// } +// } +// +// if(z != target.posZ){ +// for(int i = 0; i < 20; i++){ +// ParticleBuilder.create(ParticleBuilder.Type.DUST).pos( +// target.posX + target.width * (target.world.rand.nextFloat() - 0.5f), +// target.getEntityBoundingBox().minY + target.height * target.world.rand.nextFloat(), +// z) +// .face(EnumFacing.SOUTH).clr(0.8f, 0.9f, 1).spawn(target.world); +// } +// } +// } + + WizardryUtilities.undoGravity(target); + target.addVelocity(0.35 * Math.signum(x - target.posX), 0.35 * Math.signum(y - target.posY), 0.35 * Math.signum(z - target.posZ)); + target.setPositionAndUpdate(x, y, z); + // Player motion is handled on that player's client so needs packets + if(target instanceof EntityPlayerMP){ + ((EntityPlayerMP)target).connection.sendPacket(new SPacketEntityVelocity(target)); + } +// +// target.world.playSound(target.posX, target.posY, target.posZ, WizardrySounds.ENTITY_FORCEFIELD_DEFLECT, +// WizardrySounds.SPELLS, 0.3f, 1f, false); + + } + + // Need to do this here because it's the only way to hook into potion ending both client- and server-side + if(target.getActivePotionEffect(this).getDuration() <= 1) target.getEntityData().removeTag(ENTITY_TAG); + + } + + @SubscribeEvent + public static void onLivingUpdateEvent(LivingUpdateEvent event){ + if(event.getEntityLiving().getEntityData().hasKey(ENTITY_TAG) + && !event.getEntityLiving().isPotionActive(WizardryPotions.containment)){ + event.getEntityLiving().getEntityData().removeTag(ENTITY_TAG); + } + } + +} diff --git a/src/main/java/electroblob/wizardry/potion/PotionDecay.java b/src/main/java/electroblob/wizardry/potion/PotionDecay.java index 025c9e16..c4562d3c 100644 --- a/src/main/java/electroblob/wizardry/potion/PotionDecay.java +++ b/src/main/java/electroblob/wizardry/potion/PotionDecay.java @@ -1,24 +1,19 @@ package electroblob.wizardry.potion; -import java.util.List; - import electroblob.wizardry.Wizardry; -import electroblob.wizardry.client.DrawingUtils; import electroblob.wizardry.constants.Constants; import electroblob.wizardry.entity.construct.EntityDecay; import electroblob.wizardry.registry.WizardryPotions; import net.minecraft.entity.Entity; import net.minecraft.entity.EntityLivingBase; import net.minecraft.entity.SharedMonsterAttributes; -import net.minecraft.potion.Potion; -import net.minecraft.potion.PotionEffect; import net.minecraft.util.DamageSource; import net.minecraft.util.ResourceLocation; import net.minecraftforge.event.entity.living.LivingEvent.LivingUpdateEvent; import net.minecraftforge.fml.common.Mod; import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; -import net.minecraftforge.fml.relauncher.Side; -import net.minecraftforge.fml.relauncher.SideOnly; + +import java.util.List; @Mod.EventBusSubscriber public class PotionDecay extends PotionMagicEffect { @@ -40,8 +35,8 @@ public class PotionDecay extends PotionMagicEffect { } @Override - public void performEffect(EntityLivingBase target, int strength){ - target.attackEntityFrom(DamageSource.WITHER, 1); + public void performEffect(EntityLivingBase host, int strength){ + host.attackEntityFrom(DamageSource.WITHER, 1); } @SubscribeEvent diff --git a/src/main/java/electroblob/wizardry/potion/PotionFrost.java b/src/main/java/electroblob/wizardry/potion/PotionFrost.java index cba91fd6..28b89553 100644 --- a/src/main/java/electroblob/wizardry/potion/PotionFrost.java +++ b/src/main/java/electroblob/wizardry/potion/PotionFrost.java @@ -1,21 +1,16 @@ package electroblob.wizardry.potion; import electroblob.wizardry.Wizardry; -import electroblob.wizardry.client.DrawingUtils; import electroblob.wizardry.constants.Constants; import electroblob.wizardry.registry.WizardryPotions; import electroblob.wizardry.util.ParticleBuilder; import electroblob.wizardry.util.ParticleBuilder.Type; -import net.minecraft.entity.EntityLivingBase; import net.minecraft.entity.SharedMonsterAttributes; -import net.minecraft.potion.PotionEffect; import net.minecraft.util.ResourceLocation; import net.minecraft.world.World; import net.minecraftforge.event.entity.player.PlayerEvent.BreakSpeed; import net.minecraftforge.fml.common.Mod; import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; -import net.minecraftforge.fml.relauncher.Side; -import net.minecraftforge.fml.relauncher.SideOnly; @Mod.EventBusSubscriber public class PotionFrost extends PotionMagicEffect implements ICustomPotionParticles { diff --git a/src/main/java/electroblob/wizardry/potion/PotionFrostStep.java b/src/main/java/electroblob/wizardry/potion/PotionFrostStep.java new file mode 100644 index 00000000..4c369526 --- /dev/null +++ b/src/main/java/electroblob/wizardry/potion/PotionFrostStep.java @@ -0,0 +1,116 @@ +package electroblob.wizardry.potion; + +import electroblob.wizardry.Wizardry; +import electroblob.wizardry.item.ItemArtefact; +import electroblob.wizardry.registry.WizardryBlocks; +import electroblob.wizardry.registry.WizardryItems; +import electroblob.wizardry.registry.WizardryPotions; +import electroblob.wizardry.util.ParticleBuilder; +import electroblob.wizardry.util.ParticleBuilder.Type; +import net.minecraft.block.BlockLiquid; +import net.minecraft.block.material.Material; +import net.minecraft.block.state.IBlockState; +import net.minecraft.enchantment.EnchantmentFrostWalker; +import net.minecraft.entity.EntityLivingBase; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.init.Blocks; +import net.minecraft.util.EnumFacing; +import net.minecraft.util.ResourceLocation; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.MathHelper; +import net.minecraft.world.World; +import net.minecraftforge.event.entity.living.LivingEvent.LivingUpdateEvent; +import net.minecraftforge.fml.common.Mod; +import net.minecraftforge.fml.common.ObfuscationReflectionHelper; +import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; + +import java.lang.reflect.Field; + +@Mod.EventBusSubscriber +public class PotionFrostStep extends PotionMagicEffect implements ICustomPotionParticles { + + private static final Field prevBlockPos = ObfuscationReflectionHelper.findField(EntityLivingBase.class, "field_184620_bC"); + + public PotionFrostStep(boolean isBadEffect, int liquidColour){ + super(isBadEffect, liquidColour, new ResourceLocation(Wizardry.MODID, "textures/gui/potion_icon_frost_step.png")); + this.setPotionName("potion." + Wizardry.MODID + ":frost_step"); + } + +// @Override +// public boolean isReady(int duration, int amplifier){ +// return true; // Execute the effect every tick +// } + + @Override + public void spawnCustomParticle(World world, double x, double y, double z){ + ParticleBuilder.create(Type.SNOW).pos(x, y, z).time(15 + world.rand.nextInt(5)).spawn(world); + } + + // Use LivingUpdateEvent instead of performEffect because it gets called before the actual frost walker processing + // performEffect is called afterwards, at which point prevBlockPos has already been set to the current position + // regardless of whether the player is wearing frost walker boots or not + + @SubscribeEvent + public static void onLivingUpdateEvent(LivingUpdateEvent event){ + + EntityLivingBase host = event.getEntityLiving(); + + if(host.isPotionActive(WizardryPotions.frost_step)){ + // Mimics the behaviour of the frost walker enchantment itself + if(!host.world.isRemote){ + + BlockPos currentPos = new BlockPos(host); + + try{ + + if(!currentPos.equals(prevBlockPos.get(host))){ + + prevBlockPos.set(host, currentPos); + + int strength = host.getActivePotionEffect(WizardryPotions.frost_step).getAmplifier(); + + EnchantmentFrostWalker.freezeNearby(host, host.world, currentPos, strength); + + if(host instanceof EntityPlayer && ItemArtefact.isArtefactActive((EntityPlayer)host, WizardryItems.charm_lava_walking)){ + freezeNearbyLava(host, host.world, currentPos, strength); + } + } + + }catch(IllegalAccessException e){ + Wizardry.logger.error("Error accessing living entity previous block pos:", e); + } + } + } + } + + /** Copied from {@link EnchantmentFrostWalker#freezeNearby(EntityLivingBase, World, BlockPos, int)} and modified + * to turn lava to obsidian crust blocks instead. */ + private static void freezeNearbyLava(EntityLivingBase living, World world, BlockPos pos, int level){ + + if(living.onGround){ + + float f = (float)Math.min(16, 2 + level); + BlockPos.MutableBlockPos pos1 = new BlockPos.MutableBlockPos(0, 0, 0); + + for(BlockPos.MutableBlockPos pos2 : BlockPos.getAllInBoxMutable(pos.add((double)(-f), -1.0D, (double)(-f)), pos.add((double)f, -1.0D, (double)f))){ + + if(pos2.distanceSqToCenter(living.posX, living.posY, living.posZ) <= (double)(f * f)){ + + pos1.setPos(pos2.getX(), pos2.getY() + 1, pos2.getZ()); + IBlockState state1 = world.getBlockState(pos1); + + if(state1.getMaterial() == Material.AIR){ + + IBlockState state2 = world.getBlockState(pos2); + + if(state2.getMaterial() == Material.LAVA && (state2.getBlock() == Blocks.LAVA || state2.getBlock() == Blocks.FLOWING_LAVA) && state2.getValue(BlockLiquid.LEVEL) == 0 && world.mayPlace(WizardryBlocks.obsidian_crust, pos2, false, EnumFacing.DOWN, null)){ + world.setBlockState(pos2, WizardryBlocks.obsidian_crust.getDefaultState()); + world.scheduleUpdate(pos2.toImmutable(), WizardryBlocks.obsidian_crust, MathHelper.getInt(living.getRNG(), 60, 120)); + } + } + } + } + } + } + +} diff --git a/src/main/java/electroblob/wizardry/potion/PotionMagicEffect.java b/src/main/java/electroblob/wizardry/potion/PotionMagicEffect.java index cf7f5820..72b2f747 100644 --- a/src/main/java/electroblob/wizardry/potion/PotionMagicEffect.java +++ b/src/main/java/electroblob/wizardry/potion/PotionMagicEffect.java @@ -1,6 +1,5 @@ package electroblob.wizardry.potion; -import electroblob.wizardry.client.DrawingUtils; import net.minecraft.entity.EntityLivingBase; import net.minecraft.potion.Potion; import net.minecraft.potion.PotionEffect; @@ -42,7 +41,7 @@ public class PotionMagicEffect extends Potion { @SideOnly(Side.CLIENT) protected void drawIcon(int x, int y, PotionEffect effect, net.minecraft.client.Minecraft mc){ mc.renderEngine.bindTexture(texture); - DrawingUtils.drawTexturedRect(x, y, 0, 0, 18, 18, 18, 18); + electroblob.wizardry.client.DrawingUtils.drawTexturedRect(x, y, 0, 0, 18, 18, 18, 18); } } diff --git a/src/main/java/electroblob/wizardry/potion/PotionSlowTime.java b/src/main/java/electroblob/wizardry/potion/PotionSlowTime.java new file mode 100644 index 00000000..b6e1f51d --- /dev/null +++ b/src/main/java/electroblob/wizardry/potion/PotionSlowTime.java @@ -0,0 +1,172 @@ +package electroblob.wizardry.potion; + +import electroblob.wizardry.Wizardry; +import electroblob.wizardry.item.ItemArtefact; +import electroblob.wizardry.packet.PacketEndSlowTime; +import electroblob.wizardry.packet.WizardryPacketHandler; +import electroblob.wizardry.registry.Spells; +import electroblob.wizardry.registry.WizardryItems; +import electroblob.wizardry.registry.WizardryPotions; +import electroblob.wizardry.spell.SlowTime; +import electroblob.wizardry.spell.Spell; +import electroblob.wizardry.util.ParticleBuilder; +import electroblob.wizardry.util.WizardryUtilities; +import net.minecraft.entity.Entity; +import net.minecraft.entity.EntityLivingBase; +import net.minecraft.entity.IProjectile; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.entity.projectile.EntityArrow; +import net.minecraft.util.ResourceLocation; +import net.minecraftforge.event.entity.living.LivingEvent.LivingUpdateEvent; +import net.minecraftforge.event.entity.living.PotionEvent; +import net.minecraftforge.fml.common.Mod; +import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; + +import java.util.List; + +@Mod.EventBusSubscriber +public class PotionSlowTime extends PotionMagicEffect implements ISyncedPotion { + + // FIXME: Minecarts with entities in them (and, I suspect, any other ridden entities) go crazy when time-slowed + + public PotionSlowTime(boolean isBadEffect, int liquidColour){ + super(isBadEffect, liquidColour, new ResourceLocation(Wizardry.MODID, "textures/gui/potion_icon_slow_time.png")); + this.setPotionName("potion." + Wizardry.MODID + ":slow_time"); + } + + private static double getEffectRadius(){ + return Spells.slow_time.getProperty(Spell.EFFECT_RADIUS).doubleValue(); + } + + public static void unblockNearbyEntities(EntityLivingBase host){ + List targetsBeyondRange = WizardryUtilities.getEntitiesWithinRadius(getEffectRadius() + 3, host.posX, host.posY, host.posZ, host.world, Entity.class); + targetsBeyondRange.forEach(e -> e.updateBlocked = false); + } + + // Not done in performEffect because it's client-inconsistent; it only fires on the client of the player with the + // potion effect, and doesn't fire on the client at all for non-players + private static void performEffectConsistent(EntityLivingBase host, int strength){ + + boolean stopTime = host instanceof EntityPlayer && ItemArtefact.isArtefactActive((EntityPlayer)host, WizardryItems.charm_stop_time); + + int interval = strength * 4 + 6; + + // Mark all entities within range + List targetsInRange = WizardryUtilities.getEntitiesWithinRadius(getEffectRadius(), host.posX, host.posY, host.posZ, host.world, Entity.class); + targetsInRange.remove(host); + // Other entities with the slow time effect are unaffected + targetsInRange.removeIf(t -> t instanceof EntityLivingBase && ((EntityLivingBase)t).isPotionActive(WizardryPotions.slow_time)); + if(!Wizardry.settings.slowTimeAffectsPlayers) targetsInRange.removeIf(t -> t instanceof EntityPlayer); + targetsInRange.removeIf(t -> t instanceof EntityArrow && t.isEntityInsideOpaqueBlock()); + + for(Entity entity : targetsInRange){ + + // If time is stopped, block all updates; otherwise block all updates except every [interval] ticks + entity.updateBlocked = stopTime || host.ticksExisted % interval != 0; + + if(!stopTime && entity.world.isRemote){ + + // Client-side movement interpolation (smoothing) + + if(entity.onGround) entity.motionY = 0; // Don't ask. It just works. + +// if(entity instanceof EntityLivingBase){ +// ((EntityLivingBase)entity).prevLimbSwingAmount = ((EntityLivingBase)entity).limbSwingAmount; +// ((EntityLivingBase)entity).swingProgress = ((EntityLivingBase)entity).prevSwingProgress; +// ((EntityLivingBase)entity).renderYawOffset = ((EntityLivingBase)entity).prevRenderYawOffset; +// ((EntityLivingBase)entity).rotationYawHead = ((EntityLivingBase)entity).prevRotationYawHead; +// } + + if(entity.updateBlocked){ + // When the update is blocked, the entity is moved 1/interval times the distance it would have moved + double x = entity.posX + entity.motionX * 1d / (double)interval; + double y = entity.posY + entity.motionY * 1d / (double)interval; + double z = entity.posZ + entity.motionZ * 1d / (double)interval; + + entity.prevPosX = entity.posX; + entity.prevPosY = entity.posY; + entity.prevPosZ = entity.posZ; + + entity.posX = x; + entity.posY = y; + entity.posZ = z; + + }else{ + // When the update is not blocked, the entity is moved BACK 1-1/interval times the distance it moved + // This is because the entity already covered most of that distance when its update was blocked + entity.posX += entity.motionX * 1d / (double)interval; + entity.posY += entity.motionY * 1d / (double)interval; + entity.posZ += entity.motionZ * 1d / (double)interval; + + double x = entity.posX - entity.motionX * 1d / (double)interval; + double y = entity.posY - entity.motionY * 1d / (double)interval; + double z = entity.posZ - entity.motionZ * 1d / (double)interval; + + entity.prevPosX = x; + entity.prevPosY = y; + entity.prevPosZ = z; + } + } + + if(entity.world.isRemote && host.ticksExisted % 2 == 0){ + int lifetime = 15; + double dx = (entity.world.rand.nextDouble() - 0.5D) * 2 * (double)entity.width; + double dy = (entity.world.rand.nextDouble() - 0.5D) * 2 * (double)entity.width; + double dz = (entity.world.rand.nextDouble() - 0.5D) * 2 * (double)entity.width; + double x = entity.posX + dx; + double y = entity instanceof IProjectile ? entity.posY + dy : entity.posY + entity.height/2 + dy; + double z = entity.posZ + dz; + ParticleBuilder.create(ParticleBuilder.Type.DUST) + .pos(x, y, z) + .vel(-dx/lifetime, -dy/lifetime, -dz/lifetime) + .clr(0x5be3bb).time(15).spawn(entity.world); + } + } + + // Un-mark all entities that have just left range + List targetsBeyondRange = WizardryUtilities.getEntitiesWithinRadius(getEffectRadius() + 3, host.posX, host.posY, host.posZ, host.world, Entity.class); + targetsBeyondRange.removeAll(targetsInRange); + targetsBeyondRange.forEach(e -> e.updateBlocked = false); + + } + + @SubscribeEvent + public static void onLivingUpdateEvent(LivingUpdateEvent event){ + + EntityLivingBase entity = event.getEntityLiving(); + + if(entity.isPotionActive(WizardryPotions.slow_time)){ + performEffectConsistent(entity, entity.getActivePotionEffect(WizardryPotions.slow_time).getAmplifier()); + } + } + + @SubscribeEvent + public static void onPotionAddedEvent(PotionEvent.PotionAddedEvent event){ + if(event.getEntity().world.isRemote && event.getPotionEffect().getPotion() == WizardryPotions.slow_time + && event.getEntity() == net.minecraft.client.Minecraft.getMinecraft().player){ + if(Wizardry.settings.useShaders) net.minecraft.client.Minecraft.getMinecraft().entityRenderer.loadShader(SlowTime.SHADER); + electroblob.wizardry.client.WizardryClientEventHandler.playBlinkEffect(); + } + } + + @SubscribeEvent + public static void onPotionExpiryEvent(PotionEvent.PotionExpiryEvent event){ + if(event.getPotionEffect() != null && event.getPotionEffect().getPotion() == WizardryPotions.slow_time){ + unblockNearbyEntities(event.getEntityLiving()); + if(!event.getEntity().world.isRemote){ + WizardryPacketHandler.net.sendToDimension(new PacketEndSlowTime.Message(event.getEntityLiving()), event.getEntity().dimension); + } + } + } + + @SubscribeEvent + public static void onPotionRemoveEvent(PotionEvent.PotionRemoveEvent event){ + if(event.getPotionEffect() != null && event.getPotionEffect().getPotion() == WizardryPotions.slow_time){ + unblockNearbyEntities(event.getEntityLiving()); + if(!event.getEntity().world.isRemote){ + WizardryPacketHandler.net.sendToDimension(new PacketEndSlowTime.Message(event.getEntityLiving()), event.getEntity().dimension); + } + } + } + +} diff --git a/src/main/java/electroblob/wizardry/registry/Spells.java b/src/main/java/electroblob/wizardry/registry/Spells.java index eb775f1e..5398da75 100644 --- a/src/main/java/electroblob/wizardry/registry/Spells.java +++ b/src/main/java/electroblob/wizardry/registry/Spells.java @@ -1,49 +1,11 @@ package electroblob.wizardry.registry; -import org.apache.commons.lang3.tuple.Triple; - import electroblob.wizardry.Wizardry; -import electroblob.wizardry.constants.Element; -import electroblob.wizardry.constants.SpellType; -import electroblob.wizardry.constants.Tier; -import electroblob.wizardry.entity.construct.EntityBlackHole; -import electroblob.wizardry.entity.construct.EntityBlizzard; -import electroblob.wizardry.entity.construct.EntityFireRing; -import electroblob.wizardry.entity.construct.EntityFireSigil; -import electroblob.wizardry.entity.construct.EntityForcefield; -import electroblob.wizardry.entity.construct.EntityFrostSigil; -import electroblob.wizardry.entity.construct.EntityHealAura; -import electroblob.wizardry.entity.construct.EntityLightningSigil; -import electroblob.wizardry.entity.living.EntityBlazeMinion; -import electroblob.wizardry.entity.living.EntityIceGiant; -import electroblob.wizardry.entity.living.EntityIceWraith; -import electroblob.wizardry.entity.living.EntityLightningWraith; -import electroblob.wizardry.entity.living.EntityPhoenix; -import electroblob.wizardry.entity.living.EntitySilverfishMinion; -import electroblob.wizardry.entity.living.EntitySpiderMinion; -import electroblob.wizardry.entity.living.EntityStormElemental; -import electroblob.wizardry.entity.living.EntityWitherSkeletonMinion; -import electroblob.wizardry.entity.living.EntityZombieMinion; -import electroblob.wizardry.entity.projectile.EntityDarknessOrb; -import electroblob.wizardry.entity.projectile.EntityDart; -import electroblob.wizardry.entity.projectile.EntityFirebolt; -import electroblob.wizardry.entity.projectile.EntityFirebomb; -import electroblob.wizardry.entity.projectile.EntityForceArrow; -import electroblob.wizardry.entity.projectile.EntityForceOrb; -import electroblob.wizardry.entity.projectile.EntityIceCharge; -import electroblob.wizardry.entity.projectile.EntityIceLance; -import electroblob.wizardry.entity.projectile.EntityIceShard; -import electroblob.wizardry.entity.projectile.EntityLightningArrow; -import electroblob.wizardry.entity.projectile.EntityLightningDisc; -import electroblob.wizardry.entity.projectile.EntityMagicMissile; -import electroblob.wizardry.entity.projectile.EntityPoisonBomb; -import electroblob.wizardry.entity.projectile.EntitySmokeBomb; -import electroblob.wizardry.entity.projectile.EntitySpark; -import electroblob.wizardry.entity.projectile.EntitySparkBomb; -import electroblob.wizardry.entity.projectile.EntityThunderbolt; +import electroblob.wizardry.entity.construct.*; +import electroblob.wizardry.entity.living.*; +import electroblob.wizardry.entity.projectile.*; import electroblob.wizardry.spell.*; import net.minecraft.init.MobEffects; -import net.minecraft.init.SoundEvents; import net.minecraft.item.EnumAction; import net.minecraft.util.ResourceLocation; import net.minecraftforge.event.RegistryEvent; @@ -53,6 +15,8 @@ import net.minecraftforge.fml.common.registry.GameRegistry.ObjectHolder; import net.minecraftforge.registries.IForgeRegistry; import net.minecraftforge.registries.RegistryBuilder; +import javax.annotation.Nonnull; + /** * Class responsible for defining, storing and registering all of wizardry's spells. Use this to access individual * spell instances, similar to the {@code Blocks} and {@code Items} classes. @@ -60,23 +24,16 @@ import net.minecraftforge.registries.RegistryBuilder; * @author Electroblob * @since Wizardry 2.1 */ -// In case anyone was wondering, the reason @ObjectHolder is useful within one mod is that it allows you to initialise -// stuff during the registry events (or whenever), whilst still having a final field (which is important, not only -// because it makes the text go bold, but also because it stops anyone fiddling with your fields). "Why would I want to -// initialise things within the registry events?", I hear you ask - well, for one, custom registries don't like it if -// you haven't created the registry before you start calling constructors of classes extending IForgeRegistryEntry.Impl, -// and secondly, you might want to initialise objects based on certain conditions - perhaps a config option, or whether -// another mod is installed. This, presumably, is why everyone at forge is encouraging us to use @ObjectHolder. @ObjectHolder(Wizardry.MODID) @Mod.EventBusSubscriber public final class Spells { + private Spells(){} // No instances! + // This is here because this class is already an event handler. @SubscribeEvent public static void createRegistry(RegistryEvent.NewRegistry event){ - // Beats me why we need both of these. Surely the type parameter means it already knows? - // EDIT: It's probably because of type erasure, thinking about it. RegistryBuilder builder = new RegistryBuilder<>(); builder.setType(Spell.class); builder.setName(new ResourceLocation(Wizardry.MODID, "spells")); @@ -85,158 +42,200 @@ public final class Spells { Spell.registry = builder.create(); } + @Nonnull + @SuppressWarnings("ConstantConditions") + private static T placeholder(){ return null; } + // Wizardry 1.0 spells - public static final Spell none = null; - public static final Spell magic_missile = null; - public static final Spell ignite = null; - public static final Spell freeze = null; - public static final Spell snowball = null; - public static final Spell arc = null; - public static final Spell thunderbolt = null; - public static final Spell summon_zombie = null; - public static final Spell snare = null; - public static final Spell dart = null; - public static final Spell light = null; - public static final Spell telekinesis = null; - public static final Spell heal = null; + public static final Spell none = placeholder(); + public static final Spell magic_missile = placeholder(); + public static final Spell ignite = placeholder(); + public static final Spell freeze = placeholder(); + public static final Spell snowball = placeholder(); + public static final Spell arc = placeholder(); + public static final Spell thunderbolt = placeholder(); + public static final Spell summon_zombie = placeholder(); + public static final Spell snare = placeholder(); + public static final Spell dart = placeholder(); + public static final Spell light = placeholder(); + public static final Spell telekinesis = placeholder(); + public static final Spell heal = placeholder(); - public static final Spell fireball = null; - public static final Spell flame_ray = null; - public static final Spell firebomb = null; - public static final Spell fire_sigil = null; - public static final Spell firebolt = null; - public static final Spell frost_ray = null; - public static final Spell summon_snow_golem = null; - public static final Spell ice_shard = null; - public static final Spell ice_statue = null; - public static final Spell frost_sigil = null; - public static final Spell lightning_ray = null; - public static final Spell spark_bomb = null; - public static final Spell homing_spark = null; - public static final Spell lightning_sigil = null; - public static final Spell lightning_arrow = null; - public static final Spell life_drain = null; - public static final Spell summon_skeleton = null; - public static final Spell metamorphosis = null; - public static final Spell wither = null; - public static final Spell poison = null; - public static final Spell growth_aura = null; - public static final Spell bubble = null; - public static final Spell whirlwind = null; - public static final Spell poison_bomb = null; - public static final Spell summon_spirit_wolf = null; - public static final Spell blink = null; - public static final Spell agility = null; - public static final Spell conjure_sword = null; - public static final Spell conjure_pickaxe = null; - public static final Spell conjure_bow = null; - public static final Spell force_arrow = null; - public static final Spell shield = null; - public static final Spell replenish_hunger = null; - public static final Spell cure_effects = null; - public static final Spell heal_ally = null; + public static final Spell fireball = placeholder(); + public static final Spell flame_ray = placeholder(); + public static final Spell firebomb = placeholder(); + public static final Spell fire_sigil = placeholder(); + public static final Spell firebolt = placeholder(); + public static final Spell frost_ray = placeholder(); + public static final Spell summon_snow_golem = placeholder(); + public static final Spell ice_shard = placeholder(); + public static final Spell ice_statue = placeholder(); + public static final Spell frost_sigil = placeholder(); + public static final Spell lightning_ray = placeholder(); + public static final Spell spark_bomb = placeholder(); + public static final Spell homing_spark = placeholder(); + public static final Spell lightning_sigil = placeholder(); + public static final Spell lightning_arrow = placeholder(); + public static final Spell life_drain = placeholder(); + public static final Spell summon_skeleton = placeholder(); + public static final Spell metamorphosis = placeholder(); + public static final Spell wither = placeholder(); + public static final Spell poison = placeholder(); + public static final Spell growth_aura = placeholder(); + public static final Spell bubble = placeholder(); + public static final Spell whirlwind = placeholder(); + public static final Spell poison_bomb = placeholder(); + public static final Spell summon_spirit_wolf = placeholder(); + public static final Spell blink = placeholder(); + public static final Spell agility = placeholder(); + public static final Spell conjure_sword = placeholder(); + public static final Spell conjure_pickaxe = placeholder(); + public static final Spell conjure_bow = placeholder(); + public static final Spell force_arrow = placeholder(); + public static final Spell shield = placeholder(); + public static final Spell replenish_hunger = placeholder(); + public static final Spell cure_effects = placeholder(); + public static final Spell heal_ally = placeholder(); - public static final Spell summon_blaze = null; - public static final Spell ring_of_fire = null; - public static final Spell detonate = null; - public static final Spell fire_resistance = null; - public static final Spell fireskin = null; - public static final Spell flaming_axe = null; - public static final Spell blizzard = null; - public static final Spell summon_ice_wraith = null; - public static final Spell ice_shroud = null; - public static final Spell ice_charge = null; - public static final Spell frost_axe = null; - public static final Spell invoke_weather = null; - public static final Spell chain_lightning = null; - public static final Spell lightning_bolt = null; - public static final Spell summon_lightning_wraith = null; - public static final Spell static_aura = null; - public static final Spell lightning_disc = null; - public static final Spell mind_control = null; - public static final Spell summon_wither_skeleton = null; - public static final Spell entrapment = null; - public static final Spell wither_skull = null; - public static final Spell darkness_orb = null; - public static final Spell shadow_ward = null; - public static final Spell decay = null; - public static final Spell water_breathing = null; - public static final Spell tornado = null; - public static final Spell glide = null; - public static final Spell summon_spirit_horse = null; - public static final Spell spider_swarm = null; - public static final Spell slime = null; - public static final Spell petrify = null; - public static final Spell invisibility = null; - public static final Spell levitation = null; - public static final Spell force_orb = null; - public static final Spell transportation = null; - public static final Spell spectral_pathway = null; - public static final Spell phase_step = null; - public static final Spell vanishing_box = null; - public static final Spell greater_heal = null; - public static final Spell healing_aura = null; - public static final Spell forcefield = null; - public static final Spell ironflesh = null; - public static final Spell transience = null; + public static final Spell summon_blaze = placeholder(); + public static final Spell ring_of_fire = placeholder(); + public static final Spell detonate = placeholder(); + public static final Spell fire_resistance = placeholder(); + public static final Spell fireskin = placeholder(); + public static final Spell flaming_axe = placeholder(); + public static final Spell blizzard = placeholder(); + public static final Spell summon_ice_wraith = placeholder(); + public static final Spell ice_shroud = placeholder(); + public static final Spell ice_charge = placeholder(); + public static final Spell frost_axe = placeholder(); + public static final Spell invoke_weather = placeholder(); + public static final Spell chain_lightning = placeholder(); + public static final Spell lightning_bolt = placeholder(); + public static final Spell summon_lightning_wraith = placeholder(); + public static final Spell static_aura = placeholder(); + public static final Spell lightning_disc = placeholder(); + public static final Spell mind_control = placeholder(); + public static final Spell summon_wither_skeleton = placeholder(); + public static final Spell entrapment = placeholder(); + public static final Spell wither_skull = placeholder(); + public static final Spell darkness_orb = placeholder(); + public static final Spell shadow_ward = placeholder(); + public static final Spell decay = placeholder(); + public static final Spell water_breathing = placeholder(); + public static final Spell tornado = placeholder(); + public static final Spell glide = placeholder(); + public static final Spell summon_spirit_horse = placeholder(); + public static final Spell spider_swarm = placeholder(); + public static final Spell slime = placeholder(); + public static final Spell petrify = placeholder(); + public static final Spell invisibility = placeholder(); + public static final Spell levitation = placeholder(); + public static final Spell force_orb = placeholder(); + public static final Spell transportation = placeholder(); + public static final Spell spectral_pathway = placeholder(); + public static final Spell phase_step = placeholder(); + public static final Spell vanishing_box = placeholder(); + public static final Spell greater_heal = placeholder(); + public static final Spell healing_aura = placeholder(); + public static final Spell forcefield = placeholder(); + public static final Spell ironflesh = placeholder(); + public static final Spell transience = placeholder(); - public static final Spell meteor = null; - public static final Spell firestorm = null; - public static final Spell summon_phoenix = null; - public static final Spell ice_age = null; - public static final Spell wall_of_frost = null; - public static final Spell summon_ice_giant = null; - public static final Spell thunderstorm = null; - public static final Spell lightning_hammer = null; - public static final Spell plague_of_darkness = null; - public static final Spell summon_skeleton_legion = null; - public static final Spell summon_shadow_wraith = null; - public static final Spell forests_curse = null; - public static final Spell flight = null; - public static final Spell silverfish_swarm = null; - public static final Spell black_hole = null; - public static final Spell shockwave = null; - public static final Spell summon_iron_golem = null; - public static final Spell arrow_rain = null; - public static final Spell diamondflesh = null; - public static final Spell font_of_vitality = null; + public static final Spell meteor = placeholder(); + public static final Spell fire_breath = placeholder(); + public static final Spell summon_phoenix = placeholder(); + public static final Spell ice_age = placeholder(); + public static final Spell wall_of_frost = placeholder(); + public static final Spell summon_ice_giant = placeholder(); + public static final Spell thunderstorm = placeholder(); + public static final Spell lightning_hammer = placeholder(); + public static final Spell plague_of_darkness = placeholder(); + public static final Spell summon_skeleton_legion = placeholder(); + public static final Spell summon_shadow_wraith = placeholder(); + public static final Spell forests_curse = placeholder(); + public static final Spell flight = placeholder(); + public static final Spell silverfish_swarm = placeholder(); + public static final Spell black_hole = placeholder(); + public static final Spell shockwave = placeholder(); + public static final Spell summon_iron_golem = placeholder(); + public static final Spell arrow_rain = placeholder(); + public static final Spell diamondflesh = placeholder(); + public static final Spell font_of_vitality = placeholder(); // Wizardry 1.1 spells - public static final Spell smoke_bomb = null; - public static final Spell mind_trick = null; - public static final Spell leap = null; + public static final Spell smoke_bomb = placeholder(); + public static final Spell mind_trick = placeholder(); + public static final Spell leap = placeholder(); - public static final Spell pocket_furnace = null; - public static final Spell intimidate = null; - public static final Spell banish = null; - public static final Spell sixth_sense = null; - public static final Spell darkvision = null; - public static final Spell clairvoyance = null; - public static final Spell pocket_workbench = null; - public static final Spell imbue_weapon = null; - public static final Spell invigorating_presence = null; - public static final Spell oakflesh = null; + public static final Spell pocket_furnace = placeholder(); + public static final Spell intimidate = placeholder(); + public static final Spell banish = placeholder(); + public static final Spell sixth_sense = placeholder(); + public static final Spell darkvision = placeholder(); + public static final Spell clairvoyance = placeholder(); + public static final Spell pocket_workbench = placeholder(); + public static final Spell imbue_weapon = placeholder(); + public static final Spell invigorating_presence = placeholder(); + public static final Spell oakflesh = placeholder(); - public static final Spell greater_fireball = null; - public static final Spell flaming_weapon = null; - public static final Spell ice_lance = null; - public static final Spell freezing_weapon = null; - public static final Spell ice_spikes = null; - public static final Spell lightning_pulse = null; - public static final Spell curse_of_soulbinding = null; - public static final Spell cobwebs = null; - public static final Spell decoy = null; - public static final Spell arcane_jammer = null; - public static final Spell conjure_armour = null; - public static final Spell group_heal = null; + public static final Spell greater_fireball = placeholder(); + public static final Spell flaming_weapon = placeholder(); + public static final Spell ice_lance = placeholder(); + public static final Spell freezing_weapon = placeholder(); + public static final Spell ice_spikes = placeholder(); + public static final Spell lightning_pulse = placeholder(); + public static final Spell curse_of_soulbinding = placeholder(); + public static final Spell cobwebs = placeholder(); + public static final Spell decoy = placeholder(); + public static final Spell arcane_jammer = placeholder(); + public static final Spell conjure_armour = placeholder(); + public static final Spell group_heal = placeholder(); - public static final Spell hailstorm = null; - public static final Spell lightning_web = null; - public static final Spell summon_storm_elemental = null; - public static final Spell earthquake = null; - public static final Spell font_of_mana = null; + public static final Spell hailstorm = placeholder(); + public static final Spell lightning_web = placeholder(); + public static final Spell summon_storm_elemental = placeholder(); + public static final Spell earthquake = placeholder(); + public static final Spell font_of_mana = placeholder(); + + // Wizardry 4.2 spells + + public static final Spell mine = placeholder(); + public static final Spell conjure_block = placeholder(); + public static final Spell muffle = placeholder(); + public static final Spell ward = placeholder(); + public static final Spell evade = placeholder(); + + public static final Spell iceball = placeholder(); + public static final Spell charge = placeholder(); + public static final Spell reversal = placeholder(); + public static final Spell grapple = placeholder(); + public static final Spell divination = placeholder(); + public static final Spell empowering_presence = placeholder(); + + public static final Spell disintegration = placeholder(); + public static final Spell combustion_rune = placeholder(); + public static final Spell frost_step = placeholder(); + public static final Spell paralysis = placeholder(); + public static final Spell shulker_bullet = placeholder(); + public static final Spell curse_of_undeath = placeholder(); + public static final Spell dragon_fireball = placeholder(); + public static final Spell greater_telekinesis = placeholder(); + public static final Spell vex_swarm = placeholder(); + public static final Spell arcane_lock = placeholder(); + public static final Spell containment = placeholder(); + public static final Spell satiety = placeholder(); + public static final Spell greater_ward = placeholder(); + public static final Spell ray_of_purification = placeholder(); + public static final Spell remove_curse = placeholder(); + + public static final Spell possession = placeholder(); + public static final Spell curse_of_enfeeblement = placeholder(); + public static final Spell forest_of_thorns = placeholder(); + public static final Spell speed_time = placeholder(); + public static final Spell slow_time = placeholder(); + public static final Spell resurrection = placeholder(); @SubscribeEvent public static void register(RegistryEvent.Register event){ @@ -244,34 +243,34 @@ public final class Spells { IForgeRegistry registry = event.getRegistry(); registry.register(new None()); - registry.register(new SpellArrow("magic_missile", Tier.BASIC, Element.MAGIC, 5, 10, EntityMagicMissile::new, 2, WizardrySounds.SPELL_MAGIC).soundValues(1, 1.4f, 0.4f)); + registry.register(new SpellArrow<>("magic_missile", EntityMagicMissile::new).addProperties(Spell.DAMAGE).soundValues(1, 1.4f, 0.4f)); registry.register(new Ignite()); registry.register(new Freeze()); registry.register(new Snowball()); registry.register(new Arc()); - registry.register(new SpellProjectile("thunderbolt", Tier.BASIC, Element.LIGHTNING, 10, 15, EntityThunderbolt::new, 2.5f, WizardrySounds.SPELL_ICE).soundValues(0.8f, 0.9f, 0.2f)); - registry.register(new SpellMinion<>("summon_zombie", Tier.BASIC, Element.NECROMANCY, 10, 40, EntityZombieMinion::new, 600, WizardrySounds.SPELL_SUMMONING).soundValues(7, 0.6f, 0)); + registry.register(new SpellProjectile<>("thunderbolt", EntityThunderbolt::new).addProperties(Spell.DAMAGE, EntityThunderbolt.KNOCKBACK_STRENGTH).soundValues(0.8f, 0.9f, 0.2f)); + registry.register(new SummonZombie()); registry.register(new Snare()); - registry.register(new SpellArrow("dart", Tier.BASIC, Element.EARTH, 5, 10, EntityDart::new, 2, SoundEvents.ENTITY_ARROW_SHOOT).soundValues(0.5f, 0.4f, 0.2f)); + registry.register(new SpellArrow<>("dart", EntityDart::new).addProperties(Spell.DAMAGE, Spell.EFFECT_DURATION, Spell.EFFECT_STRENGTH).soundValues(0.5f, 0.4f, 0.2f)); registry.register(new Light()); registry.register(new Telekinesis()); registry.register(new Heal()); - registry.register(new Fireball()); + registry.register(new SpellProjectile<>("fireball", EntityMagicFireball::new).addProperties(Spell.DAMAGE, Spell.BURN_DURATION));//new Fireball()); registry.register(new FlameRay()); - registry.register(new SpellProjectile("firebomb", Tier.APPRENTICE, Element.FIRE, 15, 25, EntityFirebomb::new, 1.5f, SoundEvents.ENTITY_SNOWBALL_THROW).soundValues(0.5f, 0.4f, 0.2f)); - registry.register(new SpellConstructRanged<>("fire_sigil", Tier.APPRENTICE, Element.FIRE, SpellType.CONSTRUCT, 10, 20, EntityFireSigil::new, -1, 10, SoundEvents.ITEM_FLINTANDSTEEL_USE).floor(true)); - registry.register(new SpellProjectile("firebolt", Tier.APPRENTICE, Element.FIRE, 10, 10, EntityFirebolt::new, 2.5f, SoundEvents.ENTITY_BLAZE_SHOOT)); + registry.register(new SpellProjectile<>("firebomb", EntityFirebomb::new).addProperties(Spell.DIRECT_DAMAGE, Spell.SPLASH_DAMAGE, Spell.BLAST_RADIUS, Spell.BURN_DURATION).soundValues(0.5f, 0.4f, 0.2f)); + registry.register(new SpellConstructRanged<>("fire_sigil", EntityFireSigil::new, true).floor(true).addProperties(Spell.DAMAGE, Spell.BURN_DURATION)); + registry.register(new SpellProjectile<>("firebolt", EntityFirebolt::new).addProperties(Spell.DAMAGE, Spell.BURN_DURATION)); registry.register(new FrostRay()); registry.register(new SummonSnowGolem()); - registry.register(new SpellArrow("ice_shard", Tier.APPRENTICE, Element.ICE, 10, 10, EntityIceShard::new, 2, WizardrySounds.SPELL_ICE).soundValues(1, 1.6f, 0.4f)); + registry.register(new SpellArrow<>("ice_shard", EntityIceShard::new).addProperties(Spell.DAMAGE, Spell.EFFECT_DURATION, Spell.EFFECT_STRENGTH).soundValues(1, 1.6f, 0.4f)); registry.register(new IceStatue()); - registry.register(new SpellConstructRanged<>("frost_sigil", Tier.APPRENTICE, Element.ICE, SpellType.CONSTRUCT, 10, 20, EntityFrostSigil::new, -1, 10, WizardrySounds.SPELL_ICE).floor(true)); + registry.register(new SpellConstructRanged<>("frost_sigil", EntityFrostSigil::new, true).floor(true).addProperties(Spell.DAMAGE, Spell.EFFECT_DURATION, Spell.EFFECT_STRENGTH)); registry.register(new LightningRay()); - registry.register(new SpellProjectile("spark_bomb", Tier.APPRENTICE, Element.LIGHTNING, 15, 25, EntitySparkBomb::new, 1.5f, SoundEvents.ENTITY_SNOWBALL_THROW).soundValues(0.5f, 0.4f, 0.2f)); - registry.register(new SpellProjectile("homing_spark", Tier.APPRENTICE, Element.LIGHTNING, 10, 20, EntitySpark::new, 0.5f, WizardrySounds.SPELL_CONJURATION).soundValues(1.0f, 0.4f, 0.2f)); - registry.register(new SpellConstructRanged<>("lightning_sigil", Tier.APPRENTICE, Element.LIGHTNING, SpellType.CONSTRUCT, 10, 20, EntityLightningSigil::new, -1, 10, WizardrySounds.SPELL_CONJURATION).floor(true)); - registry.register(new SpellArrow("lightning_arrow", Tier.APPRENTICE, Element.LIGHTNING, 15, 20, EntityLightningArrow::new, 2, WizardrySounds.SPELL_LIGHTNING).soundValues(1, 1.45f, 0.3f)); + registry.register(new SpellProjectile<>("spark_bomb", EntitySparkBomb::new).addProperties(Spell.DIRECT_DAMAGE, Spell.EFFECT_RADIUS, EntitySparkBomb.SECONDARY_MAX_TARGETS, Spell.SPLASH_DAMAGE).soundValues(0.5f, 0.4f, 0.2f)); + registry.register(new SpellProjectile<>("homing_spark", EntitySpark::new).addProperties(Spell.DAMAGE, Spell.SEEKING_STRENGTH).soundValues(1.0f, 0.4f, 0.2f)); + registry.register(new SpellConstructRanged<>("lightning_sigil", EntityLightningSigil::new, true).floor(true).addProperties(Spell.DIRECT_DAMAGE, Spell.EFFECT_RADIUS, EntityLightningSigil.SECONDARY_MAX_TARGETS, Spell.SPLASH_DAMAGE)); + registry.register(new SpellArrow<>("lightning_arrow", EntityLightningArrow::new).addProperties(Spell.DAMAGE).soundValues(1, 1.45f, 0.3f)); registry.register(new LifeDrain()); registry.register(new SummonSkeleton()); registry.register(new Metamorphosis()); @@ -280,69 +279,69 @@ public final class Spells { registry.register(new GrowthAura()); registry.register(new Bubble()); registry.register(new Whirlwind()); - registry.register(new SpellProjectile("poison_bomb", Tier.APPRENTICE, Element.EARTH, 15, 25, EntityPoisonBomb::new, 1.5f, SoundEvents.ENTITY_SNOWBALL_THROW).soundValues(0.5f, 0.4f, 0.2f)); + registry.register(new SpellProjectile<>("poison_bomb", EntityPoisonBomb::new).addProperties(Spell.DIRECT_DAMAGE, Spell.EFFECT_RADIUS, Spell.DIRECT_EFFECT_DURATION, Spell.DIRECT_EFFECT_STRENGTH, Spell.SPLASH_DAMAGE, Spell.SPLASH_EFFECT_DURATION, Spell.SPLASH_EFFECT_STRENGTH).soundValues(0.5f, 0.4f, 0.2f)); registry.register(new SummonSpiritWolf()); registry.register(new Blink()); - registry.register(new SpellBuff("agility", Tier.APPRENTICE, Element.SORCERY, SpellType.BUFF, 20, 40, WizardrySounds.SPELL_HEAL, 0.4f, 1.0f, 0.8f, Triple.of(MobEffects.SPEED, 600, 1), Triple.of(MobEffects.JUMP_BOOST, 600, 1)).soundValues(0.7f, 1.2f, 0.4f)); - registry.register(new SpellConjuration("conjure_sword", Tier.APPRENTICE, Element.SORCERY, SpellType.UTILITY, 25, 50, WizardryItems.spectral_sword, WizardrySounds.SPELL_CONJURATION)); - registry.register(new SpellConjuration("conjure_pickaxe", Tier.APPRENTICE, Element.SORCERY, SpellType.UTILITY, 25, 50, WizardryItems.spectral_pickaxe, WizardrySounds.SPELL_CONJURATION)); - registry.register(new SpellConjuration("conjure_bow", Tier.APPRENTICE, Element.SORCERY, SpellType.UTILITY, 40, 50, WizardryItems.spectral_bow, WizardrySounds.SPELL_CONJURATION)); - registry.register(new SpellArrow("force_arrow", Tier.APPRENTICE, Element.SORCERY, 15, 20, EntityForceArrow::new, 1, WizardrySounds.SPELL_FORCE).soundValues(1, 1.3f, 0.2f)); + registry.register(new SpellBuff("agility", 0.4f, 1.0f, 0.8f, () -> MobEffects.SPEED, () -> MobEffects.JUMP_BOOST).soundValues(0.7f, 1.2f, 0.4f)); + registry.register(new SpellConjuration("conjure_sword", WizardryItems.spectral_sword)); + registry.register(new SpellConjuration("conjure_pickaxe", WizardryItems.spectral_pickaxe)); + registry.register(new SpellConjuration("conjure_bow", WizardryItems.spectral_bow)); + registry.register(new ForceArrow()); registry.register(new Shield()); registry.register(new ReplenishHunger()); registry.register(new CureEffects()); registry.register(new HealAlly()); - registry.register(new SpellMinion<>("summon_blaze", Tier.ADVANCED, Element.FIRE, 40, 200, EntityBlazeMinion::new, 600, SoundEvents.ENTITY_WITHER_AMBIENT).soundValues(1, 1.1f, 0.2f)); - registry.register(new SpellConstruct<>("ring_of_fire", Tier.ADVANCED, Element.FIRE, SpellType.CONSTRUCT, 30, 100, EnumAction.BOW, EntityFireRing::new, 600, SoundEvents.ENTITY_BLAZE_SHOOT)); + registry.register(new SpellMinion<>("summon_blaze", EntityBlazeMinion::new).soundValues(1, 1.1f, 0.2f)); + registry.register(new SpellConstruct<>("ring_of_fire", EnumAction.BOW, EntityFireRing::new, false).floor(true).addProperties(Spell.DAMAGE, Spell.BURN_DURATION)); registry.register(new Detonate()); - registry.register(new SpellBuff("fire_resistance", Tier.ADVANCED, Element.FIRE, SpellType.DEFENCE, 20, 80, WizardrySounds.SPELL_HEAL, 1, 0.5f, 0, Triple.of(MobEffects.FIRE_RESISTANCE, 600, 0)).soundValues(0.7f, 1.2f, 0.4f)); - registry.register(new SpellBuff("fireskin", Tier.ADVANCED, Element.FIRE, SpellType.DEFENCE, 40, 250, SoundEvents.ENTITY_BLAZE_SHOOT, 1, 0.5f, 0, Triple.of(WizardryPotions.fireskin, 600, 0))); + registry.register(new SpellBuff("fire_resistance", 1, 0.5f, 0, () -> MobEffects.FIRE_RESISTANCE).soundValues(0.7f, 1.2f, 0.4f)); + registry.register(new SpellBuff("fireskin", 1, 0.5f, 0, () -> WizardryPotions.fireskin).addProperties(Spell.BURN_DURATION)); registry.register(new FlamingAxe()); - registry.register(new SpellConstructRanged<>("blizzard", Tier.ADVANCED, Element.ICE, SpellType.CONSTRUCT, 40, 100, EntityBlizzard::new, 600, 20, WizardrySounds.SPELL_ICE)); - registry.register(new SpellMinion<>("summon_ice_wraith", Tier.ADVANCED, Element.ICE, 40, 200, EntityIceWraith::new, 600, SoundEvents.ENTITY_WITHER_AMBIENT).soundValues(1, 1.1f, 0.2f)); - registry.register(new SpellBuff("ice_shroud", Tier.ADVANCED, Element.ICE, SpellType.DEFENCE, 40, 250, WizardrySounds.SPELL_ICE, 0.3f, 0.5f, 1, Triple.of(WizardryPotions.ice_shroud, 600, 0)).soundValues(1, 1.6f, 0.4f)); - registry.register(new SpellProjectile("ice_charge", Tier.ADVANCED, Element.ICE, 20, 30, EntityIceCharge::new, 1.5f, WizardrySounds.SPELL_ICE).soundValues(1, 1.6f, 0.4f)); + registry.register(new SpellConstructRanged<>("blizzard", EntityBlizzard::new, false).addProperties(Spell.EFFECT_RADIUS)); + registry.register(new SpellMinion<>("summon_ice_wraith", EntityIceWraith::new).soundValues(1, 1.1f, 0.2f)); + registry.register(new SpellBuff("ice_shroud", 0.3f, 0.5f, 1, () -> WizardryPotions.ice_shroud).addProperties(Spell.EFFECT_DURATION, Spell.EFFECT_STRENGTH).soundValues(1, 1.6f, 0.4f)); + registry.register(new SpellProjectile<>("ice_charge", EntityIceCharge::new).addProperties(Spell.DAMAGE, Spell.EFFECT_RADIUS, Spell.DIRECT_EFFECT_DURATION, Spell.DIRECT_EFFECT_STRENGTH, Spell.SPLASH_EFFECT_DURATION, Spell.SPLASH_EFFECT_STRENGTH, EntityIceCharge.ICE_SHARDS).soundValues(1, 1.6f, 0.4f)); registry.register(new FrostAxe()); registry.register(new InvokeWeather()); registry.register(new ChainLightning()); registry.register(new LightningBolt()); - registry.register(new SpellMinion<>("summon_lightning_wraith", Tier.ADVANCED, Element.LIGHTNING, 40, 200, EntityLightningWraith::new, 600, SoundEvents.ENTITY_WITHER_AMBIENT).soundValues(1, 1.1f, 0.2f)); - registry.register(new SpellBuff("static_aura", Tier.ADVANCED, Element.LIGHTNING, SpellType.DEFENCE, 40, 250, WizardrySounds.SPELL_SPARK, 0, 0.5f, 0.7f, Triple.of(WizardryPotions.static_aura, 600, 0)).soundValues(1, 1.6f, 0.4f)); - registry.register(new SpellProjectile("lightning_disc", Tier.ADVANCED, Element.LIGHTNING, 25, 60, EntityLightningDisc::new, 1.2f, WizardrySounds.SPELL_LIGHTNING).soundValues(1, 0.95f, 0.3f)); + registry.register(new SpellMinion<>("summon_lightning_wraith", EntityLightningWraith::new).soundValues(1, 1.1f, 0.2f)); + registry.register(new SpellBuff("static_aura", 0, 0.5f, 0.7f, () -> WizardryPotions.static_aura).addProperties(Spell.DAMAGE).soundValues(1, 1.6f, 0.4f)); + registry.register(new SpellProjectile<>("lightning_disc", EntityLightningDisc::new).addProperties(Spell.DAMAGE, Spell.SEEKING_STRENGTH).soundValues(1, 0.95f, 0.3f)); registry.register(new MindControl()); - registry.register(new SpellMinion<>("summon_wither_skeleton", Tier.ADVANCED, Element.NECROMANCY, 35, 150, EntityWitherSkeletonMinion::new, 600, WizardrySounds.SPELL_SUMMONING).soundValues(7, 0.6f, 0)); + registry.register(new SummonWitherSkeleton()); registry.register(new Entrapment()); registry.register(new WitherSkull()); - registry.register(new SpellProjectile("darkness_orb", Tier.ADVANCED, Element.NECROMANCY, 20, 20, EntityDarknessOrb::new, 0.5f, SoundEvents.ENTITY_WITHER_SHOOT).soundValues(0.5f, 0.4f, 0.2f)); + registry.register(new SpellProjectile<>("darkness_orb", EntityDarknessOrb::new).addProperties(Spell.DAMAGE, Spell.EFFECT_DURATION, Spell.EFFECT_STRENGTH).soundValues(0.5f, 0.4f, 0.2f)); registry.register(new ShadowWard()); registry.register(new Decay()); - registry.register(new SpellBuff("water_breathing", Tier.ADVANCED, Element.EARTH, SpellType.BUFF, 30, 250, WizardrySounds.SPELL_HEAL, 0.3f, 0.3f, 1, Triple.of(MobEffects.WATER_BREATHING, 1200, 0)){ @Override public boolean canBeCastByNPCs(){ return false; } }.soundValues(0.7f, 1.2f, 0.4f)); + registry.register(new SpellBuff("water_breathing", 0.3f, 0.3f, 1, () -> MobEffects.WATER_BREATHING){ @Override public boolean canBeCastByNPCs(){ return false; } }.soundValues(0.7f, 1.2f, 0.4f)); registry.register(new Tornado()); registry.register(new Glide()); registry.register(new SummonSpiritHorse()); - registry.register(new SpellMinion<>("spider_swarm", Tier.ADVANCED, Element.EARTH, 45, 200, EntitySpiderMinion::new, 600, SoundEvents.BLOCK_FIRE_EXTINGUISH).soundValues(1, 1.1f, 0.1f).quantity(5).range(3)); + registry.register(new SpellMinion<>("spider_swarm", EntitySpiderMinion::new).soundValues(1, 1.1f, 0.1f)); registry.register(new Slime()); registry.register(new Petrify()); - registry.register(new SpellBuff("invisibility", Tier.ADVANCED, Element.SORCERY, SpellType.BUFF, 35, 200, WizardrySounds.SPELL_HEAL, 0.7f, 1, 1, Triple.of(MobEffects.INVISIBILITY, 600, 0)).soundValues(0.7f, 1.2f, 0.4f)); + registry.register(new SpellBuff("invisibility", 0.7f, 1, 1, () -> MobEffects.INVISIBILITY).soundValues(0.7f, 1.2f, 0.4f)); registry.register(new Levitation()); - registry.register(new SpellProjectile("force_orb", Tier.ADVANCED, Element.SORCERY, 20, 20, EntityForceOrb::new, 1.5f, SoundEvents.ENTITY_SNOWBALL_THROW).soundValues(0.5f, 0.4f, 0.2f)); + registry.register(new SpellProjectile<>("force_orb", EntityForceOrb::new).addProperties(Spell.DAMAGE, Spell.BLAST_RADIUS).soundValues(0.5f, 0.4f, 0.2f)); registry.register(new Transportation()); registry.register(new SpectralPathway()); registry.register(new PhaseStep()); registry.register(new VanishingBox()); registry.register(new GreaterHeal()); - registry.register(new SpellConstruct<>("healing_aura", Tier.ADVANCED, Element.HEALING, SpellType.CONSTRUCT, 35, 150, EnumAction.BOW, EntityHealAura::new, 600, null)); - registry.register(new SpellConstruct<>("forcefield", Tier.ADVANCED, Element.HEALING, SpellType.DEFENCE, 45, 200, EnumAction.BOW, EntityForcefield::new, 600, WizardrySounds.SPELL_CONJURATION_LARGE)); - registry.register(new SpellBuff("ironflesh", Tier.ADVANCED, Element.HEALING, SpellType.DEFENCE, 30, 100, WizardrySounds.SPELL_HEAL, 0.4f, 0.5f, 0.6f, Triple.of(MobEffects.RESISTANCE, 600, 2)).soundValues(0.7f, 1.2f, 0.4f)); + registry.register(new SpellConstruct<>("healing_aura", EnumAction.BOW, EntityHealAura::new, false).addProperties(Spell.DAMAGE, Spell.HEALTH)); + registry.register(new Forcefield()); + registry.register(new SpellBuff("ironflesh", 0.4f, 0.5f, 0.6f, () -> MobEffects.RESISTANCE).soundValues(0.7f, 1.2f, 0.4f)); registry.register(new Transience()); registry.register(new Meteor()); - registry.register(new Firestorm()); - registry.register(new SpellMinion<>("summon_phoenix", Tier.MASTER, Element.FIRE, 150, 400, EntityPhoenix::new, 600, SoundEvents.ENTITY_WITHER_AMBIENT).soundValues(1, 1.1f, 0.1f)); + registry.register(new FireBreath()); + registry.register(new SpellMinion<>("summon_phoenix", EntityPhoenix::new).flying(true).soundValues(1, 1.1f, 0.1f)); registry.register(new IceAge()); registry.register(new WallOfFrost()); - registry.register(new SpellMinion<>("summon_ice_giant", Tier.MASTER, Element.ICE, 100, 400, EntityIceGiant::new, 600, WizardrySounds.SPELL_ICE).soundValues(1, 0.15f, 0.1f)); + registry.register(new SpellMinion<>("summon_ice_giant", EntityIceGiant::new).soundValues(1, 0.15f, 0.1f)); registry.register(new Thunderstorm()); registry.register(new LightningHammer()); registry.register(new PlagueOfDarkness()); @@ -350,17 +349,17 @@ public final class Spells { registry.register(new SummonShadowWraith()); registry.register(new ForestsCurse()); registry.register(new Flight()); - registry.register(new SpellMinion<>("silverfish_swarm", Tier.MASTER, Element.EARTH, 80, 300, EntitySilverfishMinion::new, 600, SoundEvents.BLOCK_FIRE_EXTINGUISH).soundValues(1, 1.1f, 0.1f).quantity(20).range(3)); - registry.register(new SpellConstructRanged<>("black_hole", Tier.MASTER, Element.SORCERY, SpellType.CONSTRUCT, 150, 400, EntityBlackHole::new, 600, 10, SoundEvents.ENTITY_WITHER_SPAWN).soundValues(2, 0.7f, 0)); + registry.register(new SpellMinion<>("silverfish_swarm", EntitySilverfishMinion::new).soundValues(1, 1.1f, 0.1f)); + registry.register(new SpellConstructRanged<>("black_hole", EntityBlackHole::new, false).soundValues(2, 0.7f, 0)); registry.register(new Shockwave()); registry.register(new SummonIronGolem()); registry.register(new ArrowRain()); - registry.register(new SpellBuff("diamondflesh", Tier.MASTER, Element.HEALING, SpellType.DEFENCE, 100, 300, WizardrySounds.SPELL_HEAL, 0.1f, 0.7f, 1, Triple.of(MobEffects.RESISTANCE, 600, 5)).soundValues(0.7f, 1.2f, 0.4f)); - registry.register(new SpellBuff("font_of_vitality", Tier.MASTER, Element.HEALING, SpellType.DEFENCE, 75, 300, WizardrySounds.SPELL_HEAL, 1, 0.8f, 0.3f, Triple.of(MobEffects.ABSORPTION, 1200, 1), Triple.of(MobEffects.REGENERATION, 300, 1)).soundValues(0.7f, 1.2f, 0.4f)); + registry.register(new SpellBuff("diamondflesh", 0.1f, 0.7f, 1, () -> MobEffects.RESISTANCE).soundValues(0.7f, 1.2f, 0.4f)); + registry.register(new SpellBuff("font_of_vitality", 1, 0.8f, 0.3f, () -> MobEffects.ABSORPTION, () -> MobEffects.REGENERATION).soundValues(0.7f, 1.2f, 0.4f)); // Wizardry 1.1 spells - registry.register(new SpellProjectile("smoke_bomb", Tier.BASIC, Element.FIRE, 10, 20, EntitySmokeBomb::new, 1.5f, SoundEvents.ENTITY_SNOWBALL_THROW).soundValues(0.5f, 0.4f, 0.2f)); + registry.register(new SpellProjectile<>("smoke_bomb", EntitySmokeBomb::new).addProperties(Spell.BLAST_RADIUS, Spell.EFFECT_DURATION).soundValues(0.5f, 0.4f, 0.2f)); registry.register(new MindTrick()); registry.register(new Leap()); @@ -368,16 +367,16 @@ public final class Spells { registry.register(new Intimidate()); registry.register(new Banish()); registry.register(new SixthSense()); - registry.register(new SpellBuff("darkvision", Tier.APPRENTICE, Element.EARTH, SpellType.BUFF, 20, 40, WizardrySounds.SPELL_HEAL, 0, 0.4f, 0.7f, Triple.of(MobEffects.NIGHT_VISION, 900, 0)){ @Override public boolean canBeCastByNPCs(){ return false; } }.soundValues(0.7f, 1.2f, 0.4f)); + registry.register(new SpellBuff("darkvision", 0, 0.4f, 0.7f, () -> MobEffects.NIGHT_VISION){ @Override public boolean canBeCastByNPCs(){ return false; } }.soundValues(0.7f, 1.2f, 0.4f)); registry.register(new Clairvoyance()); registry.register(new PocketWorkbench()); registry.register(new ImbueWeapon()); registry.register(new InvigoratingPresence()); - registry.register(new SpellBuff("oakflesh", Tier.ADVANCED, Element.HEALING, SpellType.DEFENCE, 20, 50, WizardrySounds.SPELL_HEAL, 0.6f, 0.5f, 0.4f, Triple.of(MobEffects.RESISTANCE, 600, 1)).soundValues(0.7f, 1.2f, 0.4f)); + registry.register(new SpellBuff("oakflesh", 0.6f, 0.5f, 0.4f, () -> MobEffects.RESISTANCE).soundValues(0.7f, 1.2f, 0.4f)); - registry.register(new GreaterFireball()); + registry.register(new SpellProjectile<>("greater_fireball", EntityLargeMagicFireball::new).addProperties(Spell.DAMAGE, EntityLargeMagicFireball.EXPLOSION_POWER));//new GreaterFireball()); registry.register(new FlamingWeapon()); - registry.register(new SpellArrow("ice_lance", Tier.ADVANCED, Element.ICE, 20, 20, EntityIceLance::new, 2, WizardrySounds.SPELL_ICE).soundValues(1, 1, 0.4f)); + registry.register(new SpellArrow<>("ice_lance", EntityIceLance::new).addProperties(Spell.DAMAGE, Spell.EFFECT_DURATION, Spell.EFFECT_STRENGTH).soundValues(1, 1, 0.4f)); registry.register(new FreezingWeapon()); registry.register(new IceSpikes()); registry.register(new LightningPulse()); @@ -390,9 +389,47 @@ public final class Spells { registry.register(new Hailstorm()); registry.register(new LightningWeb()); - registry.register(new SpellMinion<>("summon_storm_elemental", Tier.MASTER, Element.LIGHTNING, 100, 400, EntityStormElemental::new, 600, SoundEvents.ENTITY_WITHER_AMBIENT).soundValues(1, 1.1f, 0.1f)); + registry.register(new SpellMinion<>("summon_storm_elemental", EntityStormElemental::new).soundValues(1, 1.1f, 0.1f)); registry.register(new Earthquake()); registry.register(new FontOfMana()); + + // Wizardry 4.2 spells + + registry.register(new Mine()); + registry.register(new ConjureBlock()); + registry.register(new SpellBuff("muffle", 0.3f, 0.4f, 0.8f, () -> WizardryPotions.muffle).soundValues(0.7f, 1.2f, 0.4f)); + registry.register(new SpellBuff("ward", 0.75f, 0.6f, 0.8f, () -> WizardryPotions.ward).soundValues(0.7f, 1.2f, 0.4f)); + registry.register(new Evade()); + + registry.register(new SpellProjectile<>("iceball", EntityIceball::new).addProperties(Spell.DAMAGE, Spell.EFFECT_DURATION, Spell.EFFECT_STRENGTH)); + registry.register(new Charge()); + registry.register(new Reversal()); + registry.register(new Grapple()); + registry.register(new Divination()); + registry.register(new EmpoweringPresence()); + + registry.register(new Disintegration()); + registry.register(new SpellConstructRanged<>("combustion_rune", EntityCombustionRune::new, true).floor(true).addProperties(Spell.BLAST_RADIUS)); + registry.register(new SpellBuff("frost_step", 0.3f, 0.4f, 0.8f, () -> WizardryPotions.frost_step).soundValues(0.7f, 1.2f, 0.4f)); + registry.register(new Paralysis()); + registry.register(new ShulkerBullet()); + registry.register(new CurseOfUndeath()); + registry.register(new DragonFireball()); + registry.register(new GreaterTelekinesis()); + registry.register(new SpellMinion<>("vex_swarm", EntityVexMinion::new).flying(true).soundValues(1, 1.1f, 0.1f)); + registry.register(new ArcaneLock()); + registry.register(new Containment()); + registry.register(new Satiety()); + registry.register(new SpellBuff("greater_ward", 0.75f, 0.6f, 0.8f, () -> WizardryPotions.ward).soundValues(0.7f, 1.2f, 0.4f)); + registry.register(new RayOfPurification()); + registry.register(new RemoveCurse()); + + registry.register(new Possession()); + registry.register(new CurseOfEnfeeblement()); + registry.register(new ForestOfThorns()); + registry.register(new SpeedTime()); + registry.register(new SlowTime()); + registry.register(new Resurrection()); } } \ No newline at end of file diff --git a/src/main/java/electroblob/wizardry/registry/WizardryAdvancementTriggers.java b/src/main/java/electroblob/wizardry/registry/WizardryAdvancementTriggers.java index 5d50f2ba..f5cc4aef 100644 --- a/src/main/java/electroblob/wizardry/registry/WizardryAdvancementTriggers.java +++ b/src/main/java/electroblob/wizardry/registry/WizardryAdvancementTriggers.java @@ -1,59 +1,48 @@ package electroblob.wizardry.registry; -import electroblob.wizardry.util.CustomAdvancementTrigger; +import electroblob.wizardry.Wizardry; +import electroblob.wizardry.advancement.*; import net.minecraft.advancements.CriteriaTriggers; +import net.minecraft.util.ResourceLocation; /** - * This class stores a collection of custom advancement triggers, for advancements that cannot be triggered - * from plain vanilla JSON definitions. It replaces the old WizardryAchievements class. + * Class responsible for defining, storing and registering all of wizardry's advancement triggers. As of wizardry 4.2, + * the 'dummy' advancement triggers are being phased out in favour of proper custom triggers with JSON parameters, or + * where possible, existing triggers in Minecraft. * - * @author 12foo + * @author 12foo, Electroblob * @since Wizardry 4.1.0 */ public final class WizardryAdvancementTriggers { - - public static final CustomAdvancementTrigger armour_set = new CustomAdvancementTrigger("trigger_armour_set"); - public static final CustomAdvancementTrigger jam_wizard = new CustomAdvancementTrigger("trigger_jam_wizard"); - public static final CustomAdvancementTrigger self_destruct = new CustomAdvancementTrigger("trigger_self_destruct"); - public static final CustomAdvancementTrigger all_spells = new CustomAdvancementTrigger("trigger_all_spells"); - public static final CustomAdvancementTrigger element_master = new CustomAdvancementTrigger("trigger_element_master"); - public static final CustomAdvancementTrigger identify_spell = new CustomAdvancementTrigger("trigger_identify_spell"); - public static final CustomAdvancementTrigger elemental = new CustomAdvancementTrigger("trigger_elemental"); + + private WizardryAdvancementTriggers(){} // No instances! + public static final CustomAdvancementTrigger legendary = new CustomAdvancementTrigger("trigger_legendary"); public static final CustomAdvancementTrigger max_out_wand = new CustomAdvancementTrigger("trigger_max_out_wand"); public static final CustomAdvancementTrigger special_upgrade = new CustomAdvancementTrigger("trigger_special_upgrade"); - public static final CustomAdvancementTrigger pig_tornado = new CustomAdvancementTrigger("trigger_pig_tornado"); - public static final CustomAdvancementTrigger master = new CustomAdvancementTrigger("trigger_master"); - public static final CustomAdvancementTrigger apprentice = new CustomAdvancementTrigger("trigger_apprentice"); public static final CustomAdvancementTrigger anger_wizard = new CustomAdvancementTrigger("trigger_anger_wizard"); public static final CustomAdvancementTrigger buy_master_spell = new CustomAdvancementTrigger("trigger_buy_master_spell"); - public static final CustomAdvancementTrigger wizard_trade = new CustomAdvancementTrigger("trigger_wizard_trade"); - public static final CustomAdvancementTrigger slime_skeleton = new CustomAdvancementTrigger("trigger_slime_skeleton"); - public static final CustomAdvancementTrigger freeze_blaze = new CustomAdvancementTrigger("trigger_freeze_blaze"); - public static final CustomAdvancementTrigger frankenstein = new CustomAdvancementTrigger("trigger_frankenstein"); - public static final CustomAdvancementTrigger charge_creeper = new CustomAdvancementTrigger("trigger_charge_creeper"); + public static final CustomAdvancementTrigger wizard_trade = new CustomAdvancementTrigger("trigger_wizard_trade"); + public static final CustomAdvancementTrigger spell_failure = new CustomAdvancementTrigger("trigger_spell_failure"); + + public static final StructureTrigger visit_structure = new StructureTrigger(new ResourceLocation(Wizardry.MODID, "visit_structure")); + public static final ArcaneWorkbenchTrigger arcane_workbench = new ArcaneWorkbenchTrigger(new ResourceLocation(Wizardry.MODID, "arcane_workbench")); + public static final SpellCastTrigger cast_spell = new SpellCastTrigger(new ResourceLocation(Wizardry.MODID, "cast_spell")); + public static final SpellDiscoveryTrigger discover_spell = new SpellDiscoveryTrigger(new ResourceLocation(Wizardry.MODID, "discover_spell")); public static void register(){ - - CriteriaTriggers.register(armour_set); - CriteriaTriggers.register(jam_wizard); - CriteriaTriggers.register(self_destruct); - CriteriaTriggers.register(all_spells); - CriteriaTriggers.register(element_master); - CriteriaTriggers.register(identify_spell); - CriteriaTriggers.register(elemental); + CriteriaTriggers.register(legendary); CriteriaTriggers.register(max_out_wand); CriteriaTriggers.register(special_upgrade); - CriteriaTriggers.register(pig_tornado); - CriteriaTriggers.register(master); - CriteriaTriggers.register(apprentice); CriteriaTriggers.register(anger_wizard); CriteriaTriggers.register(buy_master_spell); CriteriaTriggers.register(wizard_trade); - CriteriaTriggers.register(slime_skeleton); - CriteriaTriggers.register(freeze_blaze); - CriteriaTriggers.register(frankenstein); - CriteriaTriggers.register(charge_creeper); + CriteriaTriggers.register(spell_failure); + + CriteriaTriggers.register(visit_structure); + CriteriaTriggers.register(arcane_workbench); + CriteriaTriggers.register(cast_spell); + CriteriaTriggers.register(discover_spell); } } \ No newline at end of file diff --git a/src/main/java/electroblob/wizardry/registry/WizardryBlocks.java b/src/main/java/electroblob/wizardry/registry/WizardryBlocks.java index c1d79e48..8772e212 100644 --- a/src/main/java/electroblob/wizardry/registry/WizardryBlocks.java +++ b/src/main/java/electroblob/wizardry/registry/WizardryBlocks.java @@ -2,16 +2,22 @@ package electroblob.wizardry.registry; import electroblob.wizardry.Wizardry; import electroblob.wizardry.block.*; +import electroblob.wizardry.tileentity.*; import net.minecraft.block.Block; import net.minecraft.block.material.Material; +import net.minecraft.util.ResourceLocation; import net.minecraftforge.event.RegistryEvent; import net.minecraftforge.fml.common.Mod; import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; +import net.minecraftforge.fml.common.registry.GameRegistry; import net.minecraftforge.fml.common.registry.GameRegistry.ObjectHolder; import net.minecraftforge.registries.IForgeRegistry; +import javax.annotation.Nonnull; + /** - * Class responsible for defining, storing and registering all of wizardry's blocks. + * Class responsible for defining, storing and registering all of wizardry's blocks. Also handles registry of the + * tile entities. * * @author Electroblob * @since Wizardry 2.1 @@ -20,6 +26,8 @@ import net.minecraftforge.registries.IForgeRegistry; @Mod.EventBusSubscriber public final class WizardryBlocks { + private WizardryBlocks(){} // No instances! + // Found a very nice way of registering things using arrays, which might make @ObjectHolder actually useful. // http://www.minecraftforge.net/forum/topic/49497-1112-is-using-registryevent-this-way-ok/ @@ -27,29 +35,37 @@ public final class WizardryBlocks { // setSoundType should be public, but in this particular version it isn't... which is a bit of a pain. - public static final Block arcane_workbench = null; - public static final Block crystal_ore = null; - public static final Block petrified_stone = null; - public static final Block ice_statue = null; - public static final Block magic_light = null; - public static final Block crystal_flower = null; - public static final Block snare = null; - public static final Block transportation_stone = null; - public static final Block spectral_block = null; - public static final Block crystal_block = null; - public static final Block meteor = null; - public static final Block vanishing_cobweb = null; - public static final Block runestone = null; + @Nonnull + @SuppressWarnings("ConstantConditions") + private static T placeholder(){ return null; } + + public static final Block arcane_workbench = placeholder(); + public static final Block crystal_ore = placeholder(); + public static final Block petrified_stone = placeholder(); + public static final Block ice_statue = placeholder(); + public static final Block magic_light = placeholder(); + public static final Block crystal_flower = placeholder(); + public static final Block snare = placeholder(); + public static final Block transportation_stone = placeholder(); + public static final Block spectral_block = placeholder(); + public static final Block crystal_block = placeholder(); + public static final Block meteor = placeholder(); + public static final Block vanishing_cobweb = placeholder(); + public static final Block runestone = placeholder(); + public static final Block runestone_pedestal = placeholder(); + public static final Block thorns = placeholder(); + public static final Block obsidian_crust = placeholder(); + public static final Block dry_frosted_ice = placeholder(); /** * Sets both the registry and unlocalised names of the given block, then registers it with the given registry. Use - * this instead of {@link Block#setRegistryName(String)} and {@link Block#setUnlocalizedName(String)} during + * this instead of {@link Block#setRegistryName(String)} and {@link Block#setTranslationKey(String)} during * construction, for convenience and consistency. * * @param registry The registry to register the given block to. * @param name The name of the block, without the mod ID or the .name stuff. The registry name will be * {@code ebwizardry:[name]}. The unlocalised name will be {@code tile.ebwizardry:[name].name}. - * @param item The block to register. + * @param block The block to register. */ public static void registerBlock(IForgeRegistry registry, String name, Block block){ block.setRegistryName(Wizardry.MODID, name); @@ -62,19 +78,35 @@ public final class WizardryBlocks { IForgeRegistry registry = event.getRegistry(); - registerBlock(registry, "arcane_workbench", new BlockArcaneWorkbench().setHardness(1.0F).setCreativeTab(WizardryTabs.WIZARDRY)); + registerBlock(registry, "arcane_workbench", new BlockArcaneWorkbench().setHardness(1.0F).setCreativeTab(WizardryTabs.WIZARDRY)); registerBlock(registry, "crystal_ore", new BlockCrystalOre(Material.ROCK).setHardness(3.0F).setCreativeTab(WizardryTabs.WIZARDRY)); registerBlock(registry, "petrified_stone", new BlockStatue(Material.ROCK).setHardness(1.5F).setResistance(10.0F)); - registerBlock(registry, "ice_statue", new BlockStatue(Material.ICE).setHardness(0.5F).setLightOpacity(3)); + registerBlock(registry, "ice_statue", new BlockStatue(Material.ICE).setHardness(0.5F).setLightOpacity(3)); registerBlock(registry, "magic_light", new BlockMagicLight(Material.CIRCUITS)); - registerBlock(registry, "crystal_flower", new BlockCrystalFlower(Material.PLANTS).setHardness(0.0F).setCreativeTab(WizardryTabs.WIZARDRY)); - registerBlock(registry, "snare", new BlockSnare(Material.PLANTS).setHardness(0.0F)); - registerBlock(registry, "transportation_stone", new BlockTransportationStone(Material.ROCK).setHardness(0.3F).setLightLevel(0.5f).setLightOpacity(0).setCreativeTab(WizardryTabs.WIZARDRY)); - registerBlock(registry, "spectral_block", new BlockSpectral(Material.GLASS).setLightLevel(0.7f).setLightOpacity(0).setBlockUnbreakable().setResistance(6000000.0F)); - registerBlock(registry, "crystal_block", new BlockCrystal(Material.IRON).setHardness(5.0F).setResistance(10.0F).setCreativeTab(WizardryTabs.WIZARDRY)); - registerBlock(registry, "meteor", new Block(Material.ROCK).setLightLevel(1)); - registerBlock(registry, "vanishing_cobweb", new BlockVanishingCobweb(Material.WEB).setLightOpacity(1).setHardness(4.0F)); - registerBlock(registry, "runestone", new BlockRunestone(Material.ROCK)); + registerBlock(registry, "crystal_flower", new BlockCrystalFlower(Material.PLANTS).setHardness(0.0F).setCreativeTab(WizardryTabs.WIZARDRY)); + registerBlock(registry, "snare", new BlockSnare(Material.PLANTS).setHardness(0.0F)); + registerBlock(registry, "transportation_stone", new BlockTransportationStone(Material.ROCK).setHardness(0.3F).setLightLevel(0.5f).setLightOpacity(0).setCreativeTab(WizardryTabs.WIZARDRY)); + registerBlock(registry, "spectral_block", new BlockSpectral(Material.GLASS).setLightLevel(0.7f).setLightOpacity(0).setBlockUnbreakable().setResistance(6000000.0F)); + registerBlock(registry, "crystal_block", new BlockCrystal(Material.IRON).setHardness(5.0F).setResistance(10.0F).setCreativeTab(WizardryTabs.WIZARDRY)); + registerBlock(registry, "meteor", new Block(Material.ROCK).setLightLevel(1)); + registerBlock(registry, "vanishing_cobweb", new BlockVanishingCobweb(Material.WEB).setLightOpacity(1).setHardness(4.0F)); + registerBlock(registry, "runestone", new BlockRunestone(Material.ROCK)); + registerBlock(registry, "runestone_pedestal", new BlockPedestal(Material.ROCK)); + registerBlock(registry, "thorns", new BlockThorns()); + registerBlock(registry, "obsidian_crust", new BlockObsidianCrust()); + registerBlock(registry, "dry_frosted_ice", new BlockDryFrostedIce()); } + + /** Called from the preInit method in the main mod class to register all the tile entities. */ + public static void registerTileEntities(){ + // Nope, these still don't have their own registry... + GameRegistry.registerTileEntity(TileEntityArcaneWorkbench.class, new ResourceLocation(Wizardry.MODID, "arcane_workbench")); + GameRegistry.registerTileEntity(TileEntityStatue.class, new ResourceLocation(Wizardry.MODID, "petrified_stone")); + GameRegistry.registerTileEntity(TileEntityMagicLight.class, new ResourceLocation(Wizardry.MODID, "magic_light")); + GameRegistry.registerTileEntity(TileEntityTimer.class, new ResourceLocation(Wizardry.MODID, "timer")); + GameRegistry.registerTileEntity(TileEntityPlayerSave.class, new ResourceLocation(Wizardry.MODID, "player_save")); + GameRegistry.registerTileEntity(TileEntityPlayerSaveTimed.class, new ResourceLocation(Wizardry.MODID, "player_save_timed")); + GameRegistry.registerTileEntity(TileEntityShrineCore.class, new ResourceLocation(Wizardry.MODID, "shrine_core")); + } } \ No newline at end of file diff --git a/src/main/java/electroblob/wizardry/registry/WizardryEnchantments.java b/src/main/java/electroblob/wizardry/registry/WizardryEnchantments.java index 66c8789c..b8a767f2 100644 --- a/src/main/java/electroblob/wizardry/registry/WizardryEnchantments.java +++ b/src/main/java/electroblob/wizardry/registry/WizardryEnchantments.java @@ -1,13 +1,17 @@ package electroblob.wizardry.registry; import electroblob.wizardry.Wizardry; +import electroblob.wizardry.enchantment.EnchantmentMagicProtection; import electroblob.wizardry.enchantment.EnchantmentMagicSword; import electroblob.wizardry.enchantment.EnchantmentTimed; +import electroblob.wizardry.util.WizardryUtilities; import net.minecraft.enchantment.Enchantment; import net.minecraftforge.event.RegistryEvent; import net.minecraftforge.fml.common.Mod; import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; +import javax.annotation.Nonnull; + /** * Class responsible for defining, storing and registering all of wizardry's enchantments. * @@ -17,6 +21,8 @@ import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; @Mod.EventBusSubscriber public final class WizardryEnchantments { + private WizardryEnchantments(){} // No instances! + // At the moment these enchantments generate on books in dungeon chests due to a bad bit of code (EnchantRandomly:49). // No idea how to fix this because I have no way of hooking into that code... removing the enchantments from the // registry works, but breaks everything else! @@ -26,17 +32,31 @@ public final class WizardryEnchantments { // All of these have custom classes, so the unlocalised name (referred to simply as 'name' for enchantments) is // dealt with inside those classes. - public static final Enchantment magic_sword = null; - public static final Enchantment magic_bow = null; - public static final Enchantment flaming_weapon = null; - public static final Enchantment freezing_weapon = null; + + @Nonnull + @SuppressWarnings("ConstantConditions") + private static T placeholder(){ return null; } + + public static final Enchantment magic_sword = placeholder(); + public static final Enchantment magic_bow = placeholder(); + public static final Enchantment flaming_weapon = placeholder(); + public static final Enchantment freezing_weapon = placeholder(); + + public static final Enchantment magic_protection = placeholder(); + public static final Enchantment frost_protection = placeholder(); + public static final Enchantment shock_protection = placeholder(); @SubscribeEvent public static void register(RegistryEvent.Register event){ + event.getRegistry().register(new EnchantmentMagicSword().setRegistryName(Wizardry.MODID, "magic_sword")); event.getRegistry().register(new EnchantmentTimed().setRegistryName(Wizardry.MODID, "magic_bow")); event.getRegistry().register(new EnchantmentTimed().setRegistryName(Wizardry.MODID, "flaming_weapon")); event.getRegistry().register(new EnchantmentTimed().setRegistryName(Wizardry.MODID, "freezing_weapon")); + + event.getRegistry().register(new EnchantmentMagicProtection(Enchantment.Rarity.UNCOMMON, EnchantmentMagicProtection.Type.MAGIC, WizardryUtilities.ARMOUR_SLOTS).setRegistryName(Wizardry.MODID, "magic_protection")); + event.getRegistry().register(new EnchantmentMagicProtection(Enchantment.Rarity.RARE, EnchantmentMagicProtection.Type.FROST, WizardryUtilities.ARMOUR_SLOTS).setRegistryName(Wizardry.MODID, "frost_protection")); + event.getRegistry().register(new EnchantmentMagicProtection(Enchantment.Rarity.RARE, EnchantmentMagicProtection.Type.SHOCK, WizardryUtilities.ARMOUR_SLOTS).setRegistryName(Wizardry.MODID, "shock_protection")); } } diff --git a/src/main/java/electroblob/wizardry/registry/WizardryEntities.java b/src/main/java/electroblob/wizardry/registry/WizardryEntities.java new file mode 100644 index 00000000..b7bf9839 --- /dev/null +++ b/src/main/java/electroblob/wizardry/registry/WizardryEntities.java @@ -0,0 +1,190 @@ +package electroblob.wizardry.registry; + +import electroblob.wizardry.Wizardry; +import electroblob.wizardry.entity.EntityLevitatingBlock; +import electroblob.wizardry.entity.EntityMeteor; +import electroblob.wizardry.entity.EntityShield; +import electroblob.wizardry.entity.construct.*; +import electroblob.wizardry.entity.living.*; +import electroblob.wizardry.entity.projectile.*; +import net.minecraft.entity.Entity; +import net.minecraft.entity.EnumCreatureType; +import net.minecraft.util.ResourceLocation; +import net.minecraftforge.common.BiomeDictionary; +import net.minecraftforge.event.RegistryEvent; +import net.minecraftforge.fml.common.Mod; +import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; +import net.minecraftforge.fml.common.registry.EntityEntry; +import net.minecraftforge.fml.common.registry.EntityEntryBuilder; +import net.minecraftforge.fml.common.registry.ForgeRegistries; +import net.minecraftforge.registries.IForgeRegistry; + +import java.util.Arrays; +import java.util.stream.Collectors; + +/** + * Class responsible for registering all of wizardry's entities and their spawning conditions. + * + * @author Electroblob + * @since Wizardry 4.2 + */ +@Mod.EventBusSubscriber +public class WizardryEntities { + + private WizardryEntities(){} // No instances! + + /** Most entity trackers fall into one of a few categories, so they are defined here for convenience. This + * generally follows the values used in vanilla for each entity type. */ + enum TrackingType { + + LIVING(80, 3, true), + PROJECTILE(64, 10, true), + CONSTRUCT(160, 10, false); + + int range; + int interval; + boolean trackVelocity; + + TrackingType(int range, int interval, boolean trackVelocity){ + this.range = range; + this.interval = interval; + this.trackVelocity = trackVelocity; + } + } + + /** Incrementing index for the mod-specific entity network ID. */ + private static int id = 0; + + @SubscribeEvent + public static void register(RegistryEvent.Register event){ + + IForgeRegistry registry = event.getRegistry(); + + // Vanilla summoned creatures + registry.register(createEntry(EntityZombieMinion.class, "zombie_minion", TrackingType.LIVING).build()); + registry.register(createEntry(EntityHuskMinion.class, "husk_minion", TrackingType.LIVING).build()); + registry.register(createEntry(EntitySkeletonMinion.class, "skeleton_minion", TrackingType.LIVING).build()); + registry.register(createEntry(EntityStrayMinion.class, "stray_minion", TrackingType.LIVING).build()); + registry.register(createEntry(EntitySpiderMinion.class, "spider_minion", TrackingType.LIVING).build()); + registry.register(createEntry(EntityBlazeMinion.class, "blaze_minion", TrackingType.LIVING).build()); + registry.register(createEntry(EntityWitherSkeletonMinion.class, "wither_skeleton_minion", TrackingType.LIVING).build()); + registry.register(createEntry(EntitySilverfishMinion.class, "silverfish_minion", TrackingType.LIVING).build()); + registry.register(createEntry(EntityVexMinion.class, "vex_minion", TrackingType.LIVING).build()); + + // Custom summoned creatures + registry.register(createEntry(EntityIceWraith.class, "ice_wraith", TrackingType.LIVING).egg(0xaafaff, 0x001ce1) + .spawn(EnumCreatureType.MONSTER, Wizardry.settings.iceWraithSpawnRate, 1, 1, ForgeRegistries.BIOMES.getValuesCollection().stream() + .filter(b -> !Arrays.asList(Wizardry.settings.mobSpawnBiomeBlacklist).contains(b.getRegistryName()) + && BiomeDictionary.hasType(b, BiomeDictionary.Type.SNOWY) + && !BiomeDictionary.hasType(b, BiomeDictionary.Type.FOREST)) + .collect(Collectors.toSet())).build()); + + registry.register(createEntry(EntityLightningWraith.class, "lightning_wraith", TrackingType.LIVING).egg(0x35424b, 0x27b9d9) + .spawn(EnumCreatureType.MONSTER, Wizardry.settings.lightningWraithSpawnRate, 1, 1, ForgeRegistries.BIOMES.getValuesCollection().stream() + .filter(b -> !Arrays.asList(Wizardry.settings.mobSpawnBiomeBlacklist).contains(b.getRegistryName())) + .collect(Collectors.toSet())).build()); + + registry.register(createEntry(EntitySpiritWolf.class, "spirit_wolf", TrackingType.LIVING).egg(0xbcc2e8, 0x5464c6).build()); + registry.register(createEntry(EntitySpiritHorse.class, "spirit_horse", TrackingType.LIVING).egg(0x5464c6, 0xbcc2e8).build()); + registry.register(createEntry(EntityPhoenix.class, "phoenix", TrackingType.LIVING).egg(0xff4900, 0xfde535).build()); + registry.register(createEntry(EntityIceGiant.class, "ice_giant", TrackingType.LIVING).egg(0x5bacd9, 0xeffaff).build()); + + registry.register(createEntry(EntityMagicSlime.class, "magic_slime", TrackingType.LIVING).build()); + registry.register(createEntry(EntityDecoy.class, "decoy", TrackingType.LIVING).build()); + + // These two are only made of particles, so we can afford a lower update frequency + registry.register(createEntry(EntityShadowWraith.class, "shadow_wraith") .tracker(80, 10, true).egg(0x11071c, 0x421384).build()); + registry.register(createEntry(EntityStormElemental.class, "storm_elemental") .tracker(80, 10, true).egg(0x162128, 0x135279).build()); + + // Other living entities + registry.register(createEntry(EntityWizard.class, "wizard", TrackingType.LIVING).egg(0x19295e, 0xee9312).build()); + registry.register(createEntry(EntityEvilWizard.class, "evil_wizard", TrackingType.LIVING).egg(0x290404, 0xee9312) + // For reference: 5, 1, 1 are the parameters for the witch in vanilla + .spawn(EnumCreatureType.MONSTER, Wizardry.settings.evilWizardSpawnRate, 1, 1, ForgeRegistries.BIOMES.getValuesCollection().stream() + .filter(b -> !Arrays.asList(Wizardry.settings.mobSpawnBiomeBlacklist).contains(b.getRegistryName())) + .collect(Collectors.toSet())).build()); + + // Directed projectiles + registry.register(createEntry(EntityMagicMissile.class, "magic_missile", TrackingType.PROJECTILE).build()); + registry.register(createEntry(EntityIceShard.class, "ice_shard", TrackingType.PROJECTILE).build()); + registry.register(createEntry(EntityLightningArrow.class, "lightning_arrow", TrackingType.PROJECTILE).build()); + registry.register(createEntry(EntityForceArrow.class, "force_arrow", TrackingType.PROJECTILE).build()); + registry.register(createEntry(EntityDart.class, "dart", TrackingType.PROJECTILE).build()); + registry.register(createEntry(EntityIceLance.class, "ice_lance", TrackingType.PROJECTILE).build()); + + // Directionless projectiles + registry.register(createEntry(EntityFirebomb.class, "firebomb", TrackingType.PROJECTILE).build()); + registry.register(createEntry(EntityPoisonBomb.class, "poison_bomb", TrackingType.PROJECTILE).build()); + registry.register(createEntry(EntitySparkBomb.class, "spark_bomb", TrackingType.PROJECTILE).build()); + registry.register(createEntry(EntitySmokeBomb.class, "smoke_bomb", TrackingType.PROJECTILE).build()); + registry.register(createEntry(EntityIceCharge.class, "ice_charge", TrackingType.PROJECTILE).build()); + registry.register(createEntry(EntityForceOrb.class, "force_orb", TrackingType.PROJECTILE).build()); + registry.register(createEntry(EntitySpark.class, "spark", TrackingType.PROJECTILE).build()); + registry.register(createEntry(EntityDarknessOrb.class, "darkness_orb", TrackingType.PROJECTILE).build()); + registry.register(createEntry(EntityFirebolt.class, "firebolt", TrackingType.PROJECTILE).build()); + registry.register(createEntry(EntityThunderbolt.class, "thunderbolt", TrackingType.PROJECTILE).build()); + registry.register(createEntry(EntityLightningDisc.class, "lightning_disc", TrackingType.PROJECTILE).build()); + registry.register(createEntry(EntityEmber.class, "ember", TrackingType.PROJECTILE).build()); + registry.register(createEntry(EntityMagicFireball.class, "magic_fireball", TrackingType.PROJECTILE).build()); + registry.register(createEntry(EntityLargeMagicFireball.class, "large_magic_fireball", TrackingType.PROJECTILE).build()); + registry.register(createEntry(EntityIceball.class, "iceball", TrackingType.PROJECTILE).build()); + + // These are effectively projectiles, but since they're bigger and start high up they need updating from further away + registry.register(createEntry(EntityMeteor.class, "meteor") .tracker(160, 3, true).build()); + registry.register(createEntry(EntityHammer.class, "lightning_hammer") .tracker(160, 3, true).build()); + registry.register(createEntry(EntityLevitatingBlock.class, "levitating_block") .tracker(160, 3, true).build()); + + // Constructs + registry.register(createEntry(EntityBlackHole.class, "black_hole", TrackingType.CONSTRUCT).build()); + registry.register(createEntry(EntityBlizzard.class, "blizzard", TrackingType.CONSTRUCT).build()); + registry.register(createEntry(EntityForcefield.class, "forcefield", TrackingType.CONSTRUCT).build()); + registry.register(createEntry(EntityFireSigil.class, "fire_sigil", TrackingType.CONSTRUCT).build()); + registry.register(createEntry(EntityFrostSigil.class, "frost_sigil", TrackingType.CONSTRUCT).build()); + registry.register(createEntry(EntityLightningSigil.class, "lightning_sigil", TrackingType.CONSTRUCT).build()); + registry.register(createEntry(EntityCombustionRune.class, "combustion_rune", TrackingType.CONSTRUCT).build()); + registry.register(createEntry(EntityFireRing.class, "ring_of_fire", TrackingType.CONSTRUCT).build()); + registry.register(createEntry(EntityHealAura.class, "healing_aura", TrackingType.CONSTRUCT).build()); + registry.register(createEntry(EntityDecay.class, "decay", TrackingType.CONSTRUCT).build()); + + // These ones don't render, currently that makes no difference here but we might as well separate them + registry.register(createEntry(EntityArrowRain.class, "arrow_rain", TrackingType.CONSTRUCT).build()); + registry.register(createEntry(EntityEarthquake.class, "earthquake", TrackingType.CONSTRUCT).build()); + registry.register(createEntry(EntityHailstorm.class, "hailstorm", TrackingType.CONSTRUCT).build()); + + // These ones move, velocity updates are sent if that's not at constant velocity + registry.register(createEntry(EntityShield.class, "shield") .tracker(160, 10, true).build()); + registry.register(createEntry(EntityBubble.class, "bubble") .tracker(160, 3, false).build()); + registry.register(createEntry(EntityTornado.class, "tornado") .tracker(160, 3, false).build()); + registry.register(createEntry(EntityIceSpike.class, "ice_spike") .tracker(160, 1, true).build()); + + } + + /** + * Private helper method that simplifies the parts of an {@link EntityEntry} that are common to all entities. + * This automatically assigns a network id, and accepts a {@link TrackingType} for automatic tracker assignment. + * @param entityClass The entity class to use. + * @param name The name of the entity. This will form the path of a {@code ResourceLocation} with domain + * {@code ebwizardry}, which in turn will be used as both the registry name and the 'command' name. + * @param tracking The {@link TrackingType} to use for this entity. + * @param The type of entity. + * @return The (part-built) builder instance, allowing other builder methods to be added as necessary. + */ + private static EntityEntryBuilder createEntry(Class entityClass, String name, TrackingType tracking){ + return createEntry(entityClass, name).tracker(tracking.range, tracking.interval, tracking.trackVelocity); + } + + /** + * Private helper method that simplifies the parts of an {@link EntityEntry} that are common to all entities. + * This automatically assigns a network id. + * @param entityClass The entity class to use. + * @param name The name of the entity. This will form the path of a {@code ResourceLocation} with domain + * {@code ebwizardry}, which in turn will be used as both the registry name and the 'command' name. + * @param The type of entity. + * @return The (part-built) builder instance, allowing other builder methods to be added as necessary. + */ + private static EntityEntryBuilder createEntry(Class entityClass, String name){ + ResourceLocation registryName = new ResourceLocation(Wizardry.MODID, name); + return EntityEntryBuilder.create().entity(entityClass).id(registryName, id++).name(registryName.toString()); + } + +} diff --git a/src/main/java/electroblob/wizardry/registry/WizardryItems.java b/src/main/java/electroblob/wizardry/registry/WizardryItems.java index c43699a2..56777325 100644 --- a/src/main/java/electroblob/wizardry/registry/WizardryItems.java +++ b/src/main/java/electroblob/wizardry/registry/WizardryItems.java @@ -1,47 +1,42 @@ package electroblob.wizardry.registry; -import java.util.HashMap; -import java.util.Map; - -import org.apache.commons.lang3.tuple.ImmutablePair; -import org.apache.commons.lang3.tuple.Pair; - -import com.google.common.collect.ImmutableMap; - import electroblob.wizardry.Wizardry; import electroblob.wizardry.constants.Element; import electroblob.wizardry.constants.Tier; -import electroblob.wizardry.item.ItemArcaneTome; -import electroblob.wizardry.item.ItemArmourUpgrade; -import electroblob.wizardry.item.ItemBlankScroll; -import electroblob.wizardry.item.ItemFirebomb; -import electroblob.wizardry.item.ItemFlamingAxe; -import electroblob.wizardry.item.ItemFrostAxe; -import electroblob.wizardry.item.ItemIdentificationScroll; -import electroblob.wizardry.item.ItemPoisonBomb; -import electroblob.wizardry.item.ItemScroll; -import electroblob.wizardry.item.ItemSmokeBomb; -import electroblob.wizardry.item.ItemSpectralArmour; -import electroblob.wizardry.item.ItemSpectralBow; -import electroblob.wizardry.item.ItemSpectralPickaxe; -import electroblob.wizardry.item.ItemSpectralSword; -import electroblob.wizardry.item.ItemSpellBook; -import electroblob.wizardry.item.ItemWand; -import electroblob.wizardry.item.ItemWizardArmour; -import electroblob.wizardry.item.ItemWizardHandbook; +import electroblob.wizardry.entity.projectile.EntityFirebomb; +import electroblob.wizardry.entity.projectile.EntityPoisonBomb; +import electroblob.wizardry.entity.projectile.EntitySmokeBomb; +import electroblob.wizardry.entity.projectile.EntitySparkBomb; +import electroblob.wizardry.item.*; +import electroblob.wizardry.misc.BehaviourSpellDispense; +import electroblob.wizardry.registry.WizardryTabs.CreativeTabListed; +import electroblob.wizardry.registry.WizardryTabs.CreativeTabSorted; import net.minecraft.block.Block; -import net.minecraft.init.SoundEvents; +import net.minecraft.block.BlockDispenser; +import net.minecraft.dispenser.BehaviorProjectileDispense; +import net.minecraft.dispenser.IPosition; +import net.minecraft.entity.IProjectile; import net.minecraft.inventory.EntityEquipmentSlot; +import net.minecraft.inventory.EntityEquipmentSlot.Type; +import net.minecraft.item.EnumRarity; import net.minecraft.item.Item; import net.minecraft.item.Item.ToolMaterial; import net.minecraft.item.ItemArmor.ArmorMaterial; import net.minecraft.item.ItemBlock; +import net.minecraft.item.ItemStack; +import net.minecraft.world.World; import net.minecraftforge.common.util.EnumHelper; import net.minecraftforge.event.RegistryEvent; import net.minecraftforge.fml.common.Mod; import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; import net.minecraftforge.fml.common.registry.GameRegistry.ObjectHolder; import net.minecraftforge.registries.IForgeRegistry; +import org.apache.commons.lang3.tuple.ImmutablePair; +import org.apache.commons.lang3.tuple.Pair; + +import javax.annotation.Nonnull; +import java.util.HashMap; +import java.util.Map; /** * Class responsible for defining, storing and registering all of wizardry's items. Also registers the ItemBlocks for @@ -53,7 +48,9 @@ import net.minecraftforge.registries.IForgeRegistry; @ObjectHolder(Wizardry.MODID) @Mod.EventBusSubscriber public final class WizardryItems { - + + private WizardryItems(){} // No instances! + /** Keeping the material fields in here means {@code @ObjectHolder} ignores them. In actual fact, I could have just * made them private since wizardry only uses them within this class, but in case someone needs them elsewhere I've * used this trick instead to keep them public. */ @@ -62,223 +59,228 @@ public final class WizardryItems { public static final ToolMaterial MAGICAL = EnumHelper.addToolMaterial("MAGICAL", 3, 1000, 8.0f, 4.0f, 0); public static final ArmorMaterial SILK = EnumHelper.addArmorMaterial("SILK", "wizardry/textures/armour/wizard_armour", - 15, new int[]{0, 0, 0, 0}, 0, WizardrySounds.ITEM_ARMOUR_EQUIP_SILK, 0.0F); + 15, new int[]{0, 0, 0, 0}, 15, WizardrySounds.ITEM_ARMOUR_EQUIP_SILK, 0.0F); } + + @Nonnull + @SuppressWarnings("ConstantConditions") + private static T placeholder(){ return null; } // This is the most concise way I can think of to register the items. Really, I'd prefer it if there was only one // point where all the items were listed, but that's not possible within the current system unless you use an array, // which means you lose the individual fields... - public static final Item magic_crystal = null; + public static final Item magic_crystal = placeholder(); - public static final Item magic_wand = null; - public static final Item apprentice_wand = null; - public static final Item advanced_wand = null; - public static final Item master_wand = null; + public static final Item grand_crystal = placeholder(); + public static final Item crystal_shard = placeholder(); - public static final Item arcane_tome = null; - public static final Item wizard_handbook = null; - public static final Item spell_book = null; + public static final Item wizard_handbook = placeholder(); + public static final Item arcane_tome = placeholder(); + public static final Item spell_book = placeholder(); + public static final Item scroll = placeholder(); - public static final Item basic_fire_wand = null; - public static final Item basic_ice_wand = null; - public static final Item basic_lightning_wand = null; - public static final Item basic_necromancy_wand = null; - public static final Item basic_earth_wand = null; - public static final Item basic_sorcery_wand = null; - public static final Item basic_healing_wand = null; + public static final Item magic_wand = placeholder(); + public static final Item apprentice_wand = placeholder(); + public static final Item advanced_wand = placeholder(); + public static final Item master_wand = placeholder(); - public static final Item apprentice_fire_wand = null; - public static final Item apprentice_ice_wand = null; - public static final Item apprentice_lightning_wand = null; - public static final Item apprentice_necromancy_wand = null; - public static final Item apprentice_earth_wand = null; - public static final Item apprentice_sorcery_wand = null; - public static final Item apprentice_healing_wand = null; + public static final Item novice_fire_wand = placeholder(); + public static final Item novice_ice_wand = placeholder(); + public static final Item novice_lightning_wand = placeholder(); + public static final Item novice_necromancy_wand = placeholder(); + public static final Item novice_earth_wand = placeholder(); + public static final Item novice_sorcery_wand = placeholder(); + public static final Item novice_healing_wand = placeholder(); - public static final Item advanced_fire_wand = null; - public static final Item advanced_ice_wand = null; - public static final Item advanced_lightning_wand = null; - public static final Item advanced_necromancy_wand = null; - public static final Item advanced_earth_wand = null; - public static final Item advanced_sorcery_wand = null; - public static final Item advanced_healing_wand = null; + public static final Item apprentice_fire_wand = placeholder(); + public static final Item apprentice_ice_wand = placeholder(); + public static final Item apprentice_lightning_wand = placeholder(); + public static final Item apprentice_necromancy_wand = placeholder(); + public static final Item apprentice_earth_wand = placeholder(); + public static final Item apprentice_sorcery_wand = placeholder(); + public static final Item apprentice_healing_wand = placeholder(); - public static final Item master_fire_wand = null; - public static final Item master_ice_wand = null; - public static final Item master_lightning_wand = null; - public static final Item master_necromancy_wand = null; - public static final Item master_earth_wand = null; - public static final Item master_sorcery_wand = null; - public static final Item master_healing_wand = null; + public static final Item advanced_fire_wand = placeholder(); + public static final Item advanced_ice_wand = placeholder(); + public static final Item advanced_lightning_wand = placeholder(); + public static final Item advanced_necromancy_wand = placeholder(); + public static final Item advanced_earth_wand = placeholder(); + public static final Item advanced_sorcery_wand = placeholder(); + public static final Item advanced_healing_wand = placeholder(); - public static final Item spectral_sword = null; - public static final Item spectral_pickaxe = null; - public static final Item spectral_bow = null; + public static final Item master_fire_wand = placeholder(); + public static final Item master_ice_wand = placeholder(); + public static final Item master_lightning_wand = placeholder(); + public static final Item master_necromancy_wand = placeholder(); + public static final Item master_earth_wand = placeholder(); + public static final Item master_sorcery_wand = placeholder(); + public static final Item master_healing_wand = placeholder(); - public static final Item medium_mana_flask = null; + public static final Item spectral_sword = placeholder(); + public static final Item spectral_pickaxe = placeholder(); + public static final Item spectral_bow = placeholder(); - public static final Item storage_upgrade = null; - public static final Item siphon_upgrade = null; - public static final Item condenser_upgrade = null; - public static final Item range_upgrade = null; - public static final Item duration_upgrade = null; - public static final Item cooldown_upgrade = null; - public static final Item blast_upgrade = null; - public static final Item attunement_upgrade = null; + public static final Item blank_scroll = placeholder(); + public static final Item magic_silk = placeholder(); - public static final Item magic_silk = null; + public static final Item small_mana_flask = placeholder(); + public static final Item medium_mana_flask = placeholder(); + public static final Item large_mana_flask = placeholder(); - public static final Item flaming_axe = null; - public static final Item frost_axe = null; + public static final Item storage_upgrade = placeholder(); + public static final Item siphon_upgrade = placeholder(); + public static final Item condenser_upgrade = placeholder(); + public static final Item range_upgrade = placeholder(); + public static final Item duration_upgrade = placeholder(); + public static final Item cooldown_upgrade = placeholder(); + public static final Item blast_upgrade = placeholder(); + public static final Item attunement_upgrade = placeholder(); + public static final Item melee_upgrade = placeholder(); - public static final Item firebomb = null; - public static final Item poison_bomb = null; + public static final Item flaming_axe = placeholder(); + public static final Item frost_axe = placeholder(); - public static final Item blank_scroll = null; - public static final Item scroll = null; - - public static final Item armour_upgrade = null; - - public static final Item wizard_hat = null; - public static final Item wizard_robe = null; - public static final Item wizard_leggings = null; - public static final Item wizard_boots = null; + public static final Item identification_scroll = placeholder(); + public static final Item armour_upgrade = placeholder(); + public static final Item astral_diamond = placeholder(); + public static final Item purifying_elixir = placeholder(); - public static final Item wizard_hat_fire = null; - public static final Item wizard_robe_fire = null; - public static final Item wizard_leggings_fire = null; - public static final Item wizard_boots_fire = null; + public static final Item firebomb = placeholder(); + public static final Item poison_bomb = placeholder(); + public static final Item smoke_bomb = placeholder(); + public static final Item spark_bomb = placeholder(); - public static final Item wizard_hat_ice = null; - public static final Item wizard_robe_ice = null; - public static final Item wizard_leggings_ice = null; - public static final Item wizard_boots_ice = null; + public static final Item wizard_hat = placeholder(); + public static final Item wizard_robe = placeholder(); + public static final Item wizard_leggings = placeholder(); + public static final Item wizard_boots = placeholder(); - public static final Item wizard_hat_lightning = null; - public static final Item wizard_robe_lightning = null; - public static final Item wizard_leggings_lightning = null; - public static final Item wizard_boots_lightning = null; + public static final Item wizard_hat_fire = placeholder(); + public static final Item wizard_robe_fire = placeholder(); + public static final Item wizard_leggings_fire = placeholder(); + public static final Item wizard_boots_fire = placeholder(); - public static final Item wizard_hat_necromancy = null; - public static final Item wizard_robe_necromancy = null; - public static final Item wizard_leggings_necromancy = null; - public static final Item wizard_boots_necromancy = null; + public static final Item wizard_hat_ice = placeholder(); + public static final Item wizard_robe_ice = placeholder(); + public static final Item wizard_leggings_ice = placeholder(); + public static final Item wizard_boots_ice = placeholder(); - public static final Item wizard_hat_earth = null; - public static final Item wizard_robe_earth = null; - public static final Item wizard_leggings_earth = null; - public static final Item wizard_boots_earth = null; + public static final Item wizard_hat_lightning = placeholder(); + public static final Item wizard_robe_lightning = placeholder(); + public static final Item wizard_leggings_lightning = placeholder(); + public static final Item wizard_boots_lightning = placeholder(); - public static final Item wizard_hat_sorcery = null; - public static final Item wizard_robe_sorcery = null; - public static final Item wizard_leggings_sorcery = null; - public static final Item wizard_boots_sorcery = null; + public static final Item wizard_hat_necromancy = placeholder(); + public static final Item wizard_robe_necromancy = placeholder(); + public static final Item wizard_leggings_necromancy = placeholder(); + public static final Item wizard_boots_necromancy = placeholder(); - public static final Item wizard_hat_healing = null; - public static final Item wizard_robe_healing = null; - public static final Item wizard_leggings_healing = null; - public static final Item wizard_boots_healing = null; + public static final Item wizard_hat_earth = placeholder(); + public static final Item wizard_robe_earth = placeholder(); + public static final Item wizard_leggings_earth = placeholder(); + public static final Item wizard_boots_earth = placeholder(); - public static final Item spectral_helmet = null; - public static final Item spectral_chestplate = null; - public static final Item spectral_leggings = null; - public static final Item spectral_boots = null; - - public static final Item smoke_bomb = null; + public static final Item wizard_hat_sorcery = placeholder(); + public static final Item wizard_robe_sorcery = placeholder(); + public static final Item wizard_leggings_sorcery = placeholder(); + public static final Item wizard_boots_sorcery = placeholder(); - public static final Item identification_scroll = null; + public static final Item wizard_hat_healing = placeholder(); + public static final Item wizard_robe_healing = placeholder(); + public static final Item wizard_leggings_healing = placeholder(); + public static final Item wizard_boots_healing = placeholder(); + + public static final Item spectral_helmet = placeholder(); + public static final Item spectral_chestplate = placeholder(); + public static final Item spectral_leggings = placeholder(); + public static final Item spectral_boots = placeholder(); + + public static final Item lightning_hammer = placeholder(); + + public static final Item ring_condensing = placeholder(); + public static final Item ring_siphoning = placeholder(); + public static final Item ring_battlemage = placeholder(); + public static final Item ring_combustion = placeholder(); + public static final Item ring_fire_melee = placeholder(); + public static final Item ring_fire_biome = placeholder(); + public static final Item ring_disintegration = placeholder(); + public static final Item ring_ice_melee = placeholder(); + public static final Item ring_ice_biome = placeholder(); + public static final Item ring_arcane_frost = placeholder(); + public static final Item ring_shattering = placeholder(); + public static final Item ring_lightning_melee = placeholder(); + public static final Item ring_storm = placeholder(); + public static final Item ring_seeking = placeholder(); + public static final Item ring_hammer = placeholder(); + public static final Item ring_soulbinding = placeholder(); + public static final Item ring_leeching = placeholder(); + public static final Item ring_necromancy_melee = placeholder(); + public static final Item ring_mind_control = placeholder(); + public static final Item ring_poison = placeholder(); + public static final Item ring_earth_melee = placeholder(); + public static final Item ring_earth_biome = placeholder(); + public static final Item ring_full_moon = placeholder(); + public static final Item ring_extraction = placeholder(); + public static final Item ring_mana_return = placeholder(); + public static final Item ring_blockwrangler = placeholder(); + public static final Item ring_conjurer = placeholder(); + public static final Item ring_defender = placeholder(); + public static final Item ring_paladin = placeholder(); + public static final Item ring_interdiction = placeholder(); + + public static final Item amulet_arcane_defence = placeholder(); + public static final Item amulet_warding = placeholder(); + public static final Item amulet_wisdom = placeholder(); + public static final Item amulet_fire_protection = placeholder(); + public static final Item amulet_fire_cloaking = placeholder(); + public static final Item amulet_ice_immunity = placeholder(); + public static final Item amulet_ice_protection = placeholder(); + public static final Item amulet_potential = placeholder(); + public static final Item amulet_channeling = placeholder(); + public static final Item amulet_lich = placeholder(); + public static final Item amulet_wither_immunity = placeholder(); + public static final Item amulet_glide = placeholder(); + public static final Item amulet_banishing = placeholder(); + public static final Item amulet_anchoring = placeholder(); + public static final Item amulet_recovery = placeholder(); + public static final Item amulet_transience = placeholder(); + public static final Item amulet_resurrection = placeholder(); + public static final Item amulet_auto_shield = placeholder(); + + public static final Item charm_haggler = placeholder(); + public static final Item charm_experience_tome = placeholder(); + public static final Item charm_auto_smelt = placeholder(); + public static final Item charm_lava_walking = placeholder(); + public static final Item charm_storm = placeholder(); + public static final Item charm_minion_health = placeholder(); + public static final Item charm_minion_variants = placeholder(); + public static final Item charm_flight = placeholder(); + public static final Item charm_growth = placeholder(); + public static final Item charm_abseiling = placeholder(); + public static final Item charm_silk_touch = placeholder(); + public static final Item charm_stop_time = placeholder(); + public static final Item charm_light = placeholder(); + public static final Item charm_transportation = placeholder(); + public static final Item charm_feeding = placeholder(); private static final Map, Item> WAND_MAP = new HashMap<>(); private static final Map, Item> ARMOUR_MAP = new HashMap<>(); - static { - - WAND_MAP.put(ImmutablePair.of(Tier.BASIC, Element.MAGIC), magic_wand); - WAND_MAP.put(ImmutablePair.of(Tier.BASIC, Element.FIRE), basic_fire_wand); - WAND_MAP.put(ImmutablePair.of(Tier.BASIC, Element.ICE), basic_ice_wand); - WAND_MAP.put(ImmutablePair.of(Tier.BASIC, Element.LIGHTNING), basic_lightning_wand); - WAND_MAP.put(ImmutablePair.of(Tier.BASIC, Element.NECROMANCY), basic_necromancy_wand); - WAND_MAP.put(ImmutablePair.of(Tier.BASIC, Element.EARTH), basic_earth_wand); - WAND_MAP.put(ImmutablePair.of(Tier.BASIC, Element.SORCERY), basic_sorcery_wand); - WAND_MAP.put(ImmutablePair.of(Tier.BASIC, Element.HEALING), basic_healing_wand); - WAND_MAP.put(ImmutablePair.of(Tier.APPRENTICE, Element.MAGIC), apprentice_wand); - WAND_MAP.put(ImmutablePair.of(Tier.APPRENTICE, Element.FIRE), apprentice_fire_wand); - WAND_MAP.put(ImmutablePair.of(Tier.APPRENTICE, Element.ICE), apprentice_ice_wand); - WAND_MAP.put(ImmutablePair.of(Tier.APPRENTICE, Element.LIGHTNING), apprentice_lightning_wand); - WAND_MAP.put(ImmutablePair.of(Tier.APPRENTICE, Element.NECROMANCY), apprentice_necromancy_wand); - WAND_MAP.put(ImmutablePair.of(Tier.APPRENTICE, Element.EARTH), apprentice_earth_wand); - WAND_MAP.put(ImmutablePair.of(Tier.APPRENTICE, Element.SORCERY), apprentice_sorcery_wand); - WAND_MAP.put(ImmutablePair.of(Tier.APPRENTICE, Element.HEALING), apprentice_healing_wand); - WAND_MAP.put(ImmutablePair.of(Tier.ADVANCED, Element.MAGIC), advanced_wand); - WAND_MAP.put(ImmutablePair.of(Tier.ADVANCED, Element.FIRE), advanced_fire_wand); - WAND_MAP.put(ImmutablePair.of(Tier.ADVANCED, Element.ICE), advanced_ice_wand); - WAND_MAP.put(ImmutablePair.of(Tier.ADVANCED, Element.LIGHTNING), advanced_lightning_wand); - WAND_MAP.put(ImmutablePair.of(Tier.ADVANCED, Element.NECROMANCY), advanced_necromancy_wand); - WAND_MAP.put(ImmutablePair.of(Tier.ADVANCED, Element.EARTH), advanced_earth_wand); - WAND_MAP.put(ImmutablePair.of(Tier.ADVANCED, Element.SORCERY), advanced_sorcery_wand); - WAND_MAP.put(ImmutablePair.of(Tier.ADVANCED, Element.HEALING), advanced_healing_wand); - WAND_MAP.put(ImmutablePair.of(Tier.MASTER, Element.MAGIC), master_wand); - WAND_MAP.put(ImmutablePair.of(Tier.MASTER, Element.FIRE), master_fire_wand); - WAND_MAP.put(ImmutablePair.of(Tier.MASTER, Element.ICE), master_ice_wand); - WAND_MAP.put(ImmutablePair.of(Tier.MASTER, Element.LIGHTNING), master_lightning_wand); - WAND_MAP.put(ImmutablePair.of(Tier.MASTER, Element.NECROMANCY), master_necromancy_wand); - WAND_MAP.put(ImmutablePair.of(Tier.MASTER, Element.EARTH), master_earth_wand); - WAND_MAP.put(ImmutablePair.of(Tier.MASTER, Element.SORCERY), master_sorcery_wand); - WAND_MAP.put(ImmutablePair.of(Tier.MASTER, Element.HEALING), master_healing_wand); - - ARMOUR_MAP.put(ImmutablePair.of(EntityEquipmentSlot.HEAD, Element.MAGIC), wizard_hat); - ARMOUR_MAP.put(ImmutablePair.of(EntityEquipmentSlot.HEAD, Element.FIRE), wizard_hat_fire); - ARMOUR_MAP.put(ImmutablePair.of(EntityEquipmentSlot.HEAD, Element.ICE), wizard_hat_ice); - ARMOUR_MAP.put(ImmutablePair.of(EntityEquipmentSlot.HEAD, Element.LIGHTNING), wizard_hat_lightning); - ARMOUR_MAP.put(ImmutablePair.of(EntityEquipmentSlot.HEAD, Element.NECROMANCY), wizard_hat_necromancy); - ARMOUR_MAP.put(ImmutablePair.of(EntityEquipmentSlot.HEAD, Element.EARTH), wizard_hat_earth); - ARMOUR_MAP.put(ImmutablePair.of(EntityEquipmentSlot.HEAD, Element.SORCERY), wizard_hat_sorcery); - ARMOUR_MAP.put(ImmutablePair.of(EntityEquipmentSlot.HEAD, Element.HEALING), wizard_hat_healing); - ARMOUR_MAP.put(ImmutablePair.of(EntityEquipmentSlot.CHEST, Element.MAGIC), wizard_robe); - ARMOUR_MAP.put(ImmutablePair.of(EntityEquipmentSlot.CHEST, Element.FIRE), wizard_robe_fire); - ARMOUR_MAP.put(ImmutablePair.of(EntityEquipmentSlot.CHEST, Element.ICE), wizard_robe_ice); - ARMOUR_MAP.put(ImmutablePair.of(EntityEquipmentSlot.CHEST, Element.LIGHTNING), wizard_robe_lightning); - ARMOUR_MAP.put(ImmutablePair.of(EntityEquipmentSlot.CHEST, Element.NECROMANCY), wizard_robe_necromancy); - ARMOUR_MAP.put(ImmutablePair.of(EntityEquipmentSlot.CHEST, Element.EARTH), wizard_robe_earth); - ARMOUR_MAP.put(ImmutablePair.of(EntityEquipmentSlot.CHEST, Element.SORCERY), wizard_robe_sorcery); - ARMOUR_MAP.put(ImmutablePair.of(EntityEquipmentSlot.CHEST, Element.HEALING), wizard_robe_healing); - ARMOUR_MAP.put(ImmutablePair.of(EntityEquipmentSlot.LEGS, Element.MAGIC), wizard_leggings); - ARMOUR_MAP.put(ImmutablePair.of(EntityEquipmentSlot.LEGS, Element.FIRE), wizard_leggings_fire); - ARMOUR_MAP.put(ImmutablePair.of(EntityEquipmentSlot.LEGS, Element.ICE), wizard_leggings_ice); - ARMOUR_MAP.put(ImmutablePair.of(EntityEquipmentSlot.LEGS, Element.LIGHTNING), wizard_leggings_lightning); - ARMOUR_MAP.put(ImmutablePair.of(EntityEquipmentSlot.LEGS, Element.NECROMANCY), wizard_leggings_necromancy); - ARMOUR_MAP.put(ImmutablePair.of(EntityEquipmentSlot.LEGS, Element.EARTH), wizard_leggings_earth); - ARMOUR_MAP.put(ImmutablePair.of(EntityEquipmentSlot.LEGS, Element.SORCERY), wizard_leggings_sorcery); - ARMOUR_MAP.put(ImmutablePair.of(EntityEquipmentSlot.LEGS, Element.HEALING), wizard_leggings_healing); - ARMOUR_MAP.put(ImmutablePair.of(EntityEquipmentSlot.FEET, Element.MAGIC), wizard_boots); - ARMOUR_MAP.put(ImmutablePair.of(EntityEquipmentSlot.FEET, Element.FIRE), wizard_boots_fire); - ARMOUR_MAP.put(ImmutablePair.of(EntityEquipmentSlot.FEET, Element.ICE), wizard_boots_ice); - ARMOUR_MAP.put(ImmutablePair.of(EntityEquipmentSlot.FEET, Element.LIGHTNING), wizard_boots_lightning); - ARMOUR_MAP.put(ImmutablePair.of(EntityEquipmentSlot.FEET, Element.NECROMANCY), wizard_boots_necromancy); - ARMOUR_MAP.put(ImmutablePair.of(EntityEquipmentSlot.FEET, Element.EARTH), wizard_boots_earth); - ARMOUR_MAP.put(ImmutablePair.of(EntityEquipmentSlot.FEET, Element.SORCERY), wizard_boots_sorcery); - ARMOUR_MAP.put(ImmutablePair.of(EntityEquipmentSlot.FEET, Element.HEALING), wizard_boots_healing); - } - - // TODO: These methods need a rethink. What are we trying to achieve with them? Should each use case look in the - // same pool of items? For example, might we (or someone else) want to have a wand which can generate in chests, but - // is not used by wizards? - - // I reckon this should be strictly for cases where we only ever want the standard wand set, i.e. wizards' gear, - // etc. - /** * Helper method to return the appropriate wand based on tier and element. As of Wizardry 2.1, this uses the * immutable map stored in {@link WizardryItems#WAND_MAP}. Currently used for upgrading wands, for chest generation * and to iterate through wands for charging recipes. - * + * * @param tier The tier of the wand required. * @param element The element of the wand required. Null will be converted to {@link Element#MAGIC}. - * @return The wand item which corresponds to the given element and slot, or null if no such item exists. + * @return The wand item which corresponds to the given tier and element, or null if no such item exists. * @throws NullPointerException if the given tier is null. + * @deprecated This is being phased out; it is now only used for wizard gear and trades. To add an item to + * charging recipes, use {@link WizardryRecipes#addToManaFlaskCharging(Item)}. */ + @Deprecated public static Item getWand(Tier tier, Element element){ if(tier == null) throw new NullPointerException("The given tier cannot be null."); if(element == null) element = Element.MAGIC; @@ -289,26 +291,29 @@ public final class WizardryItems { * Helper method to return the appropriate armour item based on element and slot. As of Wizardry 2.1, this uses the * immutable map stored in {@link WizardryItems#ARMOUR_MAP}. Currently used to iterate through armour for * registering charging recipes and for chest generation. - * + * * @param element The EnumElement of the armour required. Null will be converted to {@link Element#MAGIC}. * @param slot EntityEquipmentSlot of the armour piece required * @return The armour item which corresponds to the given element and slot, or null if no such item exists. * @throws IllegalArgumentException if the given slot is not an armour slot. + * @deprecated This is being phased out; it is now only used for wizard gear and trades. To add an item to + * charging recipes, use {@link WizardryRecipes#addToManaFlaskCharging(Item)}. */ + @Deprecated public static Item getArmour(Element element, EntityEquipmentSlot slot){ if(slot == null || slot.getSlotType() != Type.ARMOR) throw new IllegalArgumentException("Must be a valid armour slot"); if(element == null) element = Element.MAGIC; return ARMOUR_MAP.get(ImmutablePair.of(slot, element)); } - + /** * Sets both the registry and unlocalised names of the given item, then registers it with the given registry. Use - * this instead of {@link Item#setRegistryName(String)} and {@link Item#setUnlocalizedName(String)} during + * this instead of {@link Item#setRegistryName(String)} and {@link Item#setTranslationKey(String)} during * construction, for convenience and consistency. As of wizardry 4.2, this also automatically adds it to the order * list for its creative tab if that tab is a {@link CreativeTabListed}, meaning the order can be defined simply * by the order in which the items are registered in this class. - * + * * @param registry The registry to register the given item to. * @param name The name of the item, without the mod ID or the .name stuff. The registry name will be * {@code ebwizardry:[name]}. The unlocalised name will be {@code item.ebwizardry:[name].name}. @@ -321,11 +326,11 @@ public final class WizardryItems { /** * Sets both the registry and unlocalised names of the given item, then registers it with the given registry. Use - * this instead of {@link Item#setRegistryName(String)} and {@link Item#setUnlocalizedName(String)} during + * this instead of {@link Item#setRegistryName(String)} and {@link Item#setTranslationKey(String)} during * construction, for convenience and consistency. As of wizardry 4.2, this also automatically adds it to the order * list for its creative tab if that tab is a {@link CreativeTabListed}, meaning the order can be defined simply * by the order in which the items are registered in this class. - * + * * @param registry The registry to register the given item to. * @param name The name of the item, without the mod ID or the .name stuff. The registry name will be * {@code ebwizardry:[name]}. The unlocalised name will be {@code item.ebwizardry:[name].name}. @@ -334,6 +339,7 @@ public final class WizardryItems { */ // It now makes sense to have the name first, since it's shorter than an entire item declaration. public static void registerItem(IForgeRegistry registry, String name, Item item, boolean setTabIcon){ + item.setRegistryName(Wizardry.MODID, name); item.setTranslationKey(item.getRegistryName().toString()); registry.register(item); @@ -341,7 +347,7 @@ public final class WizardryItems { if(setTabIcon && item.getCreativeTab() instanceof CreativeTabSorted){ ((CreativeTabSorted)item.getCreativeTab()).setIconItem(new ItemStack(item)); } - + if(item.getCreativeTab() instanceof CreativeTabListed){ ((CreativeTabListed)item.getCreativeTab()).order.add(item); } @@ -354,15 +360,26 @@ public final class WizardryItems { // We don't need to keep a reference to the ItemBlock Item itemblock = new ItemBlock(block).setRegistryName(block.getRegistryName()); registry.register(itemblock); - - if(block.getCreativeTabToDisplayOn() instanceof CreativeTabListed){ - ((CreativeTabListed)block.getCreativeTabToDisplayOn()).order.add(itemblock); + + if(block.getCreativeTab() instanceof CreativeTabListed){ + ((CreativeTabListed)block.getCreativeTab()).order.add(itemblock); } } + + private static void registerMultiTexturedItemBlock(IForgeRegistry registry, Block block, boolean separateNames){ + // We don't need to keep a reference to the ItemBlock + Item itemblock = new ItemBlockMultiTexturedElemental(block, separateNames).setRegistryName(block.getRegistryName()); + registry.register(itemblock); + + if(block.getCreativeTab() instanceof CreativeTabListed){ + ((CreativeTabListed)block.getCreativeTab()).order.add(itemblock); + } } + @SubscribeEvent public static void register(RegistryEvent.Register event){ + IForgeRegistry registry = event.getRegistry(); // ItemBlocks @@ -372,52 +389,58 @@ public final class WizardryItems { registerItemBlock(registry, WizardryBlocks.crystal_ore); registerItemBlock(registry, WizardryBlocks.crystal_flower); registerItemBlock(registry, WizardryBlocks.transportation_stone); - registerItemBlock(registry, WizardryBlocks.crystal_block); + registerMultiTexturedItemBlock(registry, WizardryBlocks.crystal_block, true); + registerMultiTexturedItemBlock(registry, WizardryBlocks.runestone, false); + registerMultiTexturedItemBlock(registry, WizardryBlocks.runestone_pedestal, false); // Items - + registerItem(registry, "magic_crystal", new ItemCrystal()); - registerItem(registry, "magic_wand", new ItemWand(Tier.BASIC, null)); + registerItem(registry, "crystal_shard", new Item().setCreativeTab(WizardryTabs.WIZARDRY)); + registerItem(registry, "grand_crystal", new Item().setCreativeTab(WizardryTabs.WIZARDRY)); + + registerItem(registry, "wizard_handbook", new ItemWizardHandbook(), true); + registerItem(registry, "arcane_tome", new ItemArcaneTome()); + registerItem(registry, "spell_book", new ItemSpellBook(), true); + registerItem(registry, "scroll", new ItemScroll()); + + registerItem(registry, "magic_wand", new ItemWand(Tier.NOVICE, null)); registerItem(registry, "apprentice_wand", new ItemWand(Tier.APPRENTICE, null)); registerItem(registry, "advanced_wand", new ItemWand(Tier.ADVANCED, null)); registerItem(registry, "master_wand", new ItemWand(Tier.MASTER, null)); - registerItem(registry, "arcane_tome", new ItemArcaneTome()); - registerItem(registry, "wizard_handbook", new ItemWizardHandbook(), true); - registerItem(registry, "spell_book", new ItemSpellBook(), true); - - registerItem(registry, "basic_fire_wand", new ItemWand(Tier.BASIC, Element.FIRE)); + registerItem(registry, "novice_fire_wand", new ItemWand(Tier.NOVICE, Element.FIRE)); registerItem(registry, "apprentice_fire_wand", new ItemWand(Tier.APPRENTICE, Element.FIRE)); registerItem(registry, "advanced_fire_wand", new ItemWand(Tier.ADVANCED, Element.FIRE)); registerItem(registry, "master_fire_wand", new ItemWand(Tier.MASTER, Element.FIRE)); - - registerItem(registry, "basic_ice_wand", new ItemWand(Tier.BASIC, Element.ICE)); + + registerItem(registry, "novice_ice_wand", new ItemWand(Tier.NOVICE, Element.ICE)); registerItem(registry, "apprentice_ice_wand", new ItemWand(Tier.APPRENTICE, Element.ICE)); registerItem(registry, "advanced_ice_wand", new ItemWand(Tier.ADVANCED, Element.ICE)); registerItem(registry, "master_ice_wand", new ItemWand(Tier.MASTER, Element.ICE)); - - registerItem(registry, "basic_lightning_wand", new ItemWand(Tier.BASIC, Element.LIGHTNING)); + + registerItem(registry, "novice_lightning_wand", new ItemWand(Tier.NOVICE, Element.LIGHTNING)); registerItem(registry, "apprentice_lightning_wand", new ItemWand(Tier.APPRENTICE, Element.LIGHTNING)); registerItem(registry, "advanced_lightning_wand", new ItemWand(Tier.ADVANCED, Element.LIGHTNING)); registerItem(registry, "master_lightning_wand", new ItemWand(Tier.MASTER, Element.LIGHTNING)); - - registerItem(registry, "basic_necromancy_wand", new ItemWand(Tier.BASIC, Element.NECROMANCY)); + + registerItem(registry, "novice_necromancy_wand", new ItemWand(Tier.NOVICE, Element.NECROMANCY)); registerItem(registry, "apprentice_necromancy_wand", new ItemWand(Tier.APPRENTICE, Element.NECROMANCY)); registerItem(registry, "advanced_necromancy_wand", new ItemWand(Tier.ADVANCED, Element.NECROMANCY)); registerItem(registry, "master_necromancy_wand", new ItemWand(Tier.MASTER, Element.NECROMANCY)); - - registerItem(registry, "basic_earth_wand", new ItemWand(Tier.BASIC, Element.EARTH)); + + registerItem(registry, "novice_earth_wand", new ItemWand(Tier.NOVICE, Element.EARTH)); registerItem(registry, "apprentice_earth_wand", new ItemWand(Tier.APPRENTICE, Element.EARTH)); registerItem(registry, "advanced_earth_wand", new ItemWand(Tier.ADVANCED, Element.EARTH)); registerItem(registry, "master_earth_wand", new ItemWand(Tier.MASTER, Element.EARTH)); - - registerItem(registry, "basic_sorcery_wand", new ItemWand(Tier.BASIC, Element.SORCERY)); + + registerItem(registry, "novice_sorcery_wand", new ItemWand(Tier.NOVICE, Element.SORCERY)); registerItem(registry, "apprentice_sorcery_wand", new ItemWand(Tier.APPRENTICE, Element.SORCERY)); registerItem(registry, "advanced_sorcery_wand", new ItemWand(Tier.ADVANCED, Element.SORCERY)); registerItem(registry, "master_sorcery_wand", new ItemWand(Tier.MASTER, Element.SORCERY)); - - registerItem(registry, "basic_healing_wand", new ItemWand(Tier.BASIC, Element.HEALING)); + + registerItem(registry, "novice_healing_wand", new ItemWand(Tier.NOVICE, Element.HEALING)); registerItem(registry, "apprentice_healing_wand", new ItemWand(Tier.APPRENTICE, Element.HEALING)); registerItem(registry, "advanced_healing_wand", new ItemWand(Tier.ADVANCED, Element.HEALING)); registerItem(registry, "master_healing_wand", new ItemWand(Tier.MASTER, Element.HEALING)); @@ -426,31 +449,35 @@ public final class WizardryItems { registerItem(registry, "spectral_pickaxe", new ItemSpectralPickaxe(ToolMaterial.IRON)); registerItem(registry, "spectral_bow", new ItemSpectralBow()); - registerItem(registry, "medium_mana_flask", new Item().setCreativeTab(WizardryTabs.WIZARDRY)); - - registerItem(registry, "storage_upgrade", new Item().setCreativeTab(WizardryTabs.WIZARDRY)); - registerItem(registry, "siphon_upgrade", new Item().setCreativeTab(WizardryTabs.WIZARDRY)); - registerItem(registry, "condenser_upgrade", new Item().setCreativeTab(WizardryTabs.WIZARDRY)); - registerItem(registry, "range_upgrade", new Item().setCreativeTab(WizardryTabs.WIZARDRY)); - registerItem(registry, "duration_upgrade", new Item().setCreativeTab(WizardryTabs.WIZARDRY)); - registerItem(registry, "cooldown_upgrade", new Item().setCreativeTab(WizardryTabs.WIZARDRY)); - registerItem(registry, "blast_upgrade", new Item().setCreativeTab(WizardryTabs.WIZARDRY)); - registerItem(registry, "attunement_upgrade", new Item().setCreativeTab(WizardryTabs.WIZARDRY)); - + registerItem(registry, "blank_scroll", new ItemBlankScroll()); registerItem(registry, "magic_silk", new Item().setCreativeTab(WizardryTabs.WIZARDRY)); + registerItem(registry, "small_mana_flask", new ItemManaFlask(ItemManaFlask.Size.SMALL)); + registerItem(registry, "medium_mana_flask", new ItemManaFlask(ItemManaFlask.Size.MEDIUM)); + registerItem(registry, "large_mana_flask", new ItemManaFlask(ItemManaFlask.Size.LARGE)); + + registerItem(registry, "storage_upgrade", new ItemWandUpgrade()); + registerItem(registry, "siphon_upgrade", new ItemWandUpgrade()); + registerItem(registry, "condenser_upgrade", new ItemWandUpgrade()); + registerItem(registry, "range_upgrade", new ItemWandUpgrade()); + registerItem(registry, "duration_upgrade", new ItemWandUpgrade()); + registerItem(registry, "cooldown_upgrade", new ItemWandUpgrade()); + registerItem(registry, "blast_upgrade", new ItemWandUpgrade()); + registerItem(registry, "attunement_upgrade", new ItemWandUpgrade()); + registerItem(registry, "melee_upgrade", new ItemWandUpgrade()); + registerItem(registry, "flaming_axe", new ItemFlamingAxe(Materials.MAGICAL)); registerItem(registry, "frost_axe", new ItemFrostAxe(Materials.MAGICAL)); + registerItem(registry, "identification_scroll", new ItemIdentificationScroll()); + registerItem(registry, "armour_upgrade", new ItemArmourUpgrade()); + registerItem(registry, "astral_diamond", new Item(){ @Override public EnumRarity getRarity(ItemStack stack){ return EnumRarity.RARE; }}.setCreativeTab(WizardryTabs.WIZARDRY)); + registerItem(registry, "purifying_elixir", new ItemPurifyingElixir()); + registerItem(registry, "firebomb", new ItemFirebomb()); registerItem(registry, "poison_bomb", new ItemPoisonBomb()); - - registerItem(registry, "blank_scroll", new ItemBlankScroll()); - registerItem(registry, "scroll", new ItemScroll()); - - // The only way to get these is in dungeon chests (They are legendary, after all. Wizards don't just have them. - // Also if they were sold you could buy four from the same wizard - and that's no fun at all!) - registerItem(registry, "armour_upgrade", new ItemArmourUpgrade()); + registerItem(registry, "smoke_bomb", new ItemSmokeBomb()); + registerItem(registry, "spark_bomb", new ItemSparkBomb()); registerItem(registry, "wizard_hat", new ItemWizardArmour(Materials.SILK, 1, EntityEquipmentSlot.HEAD, null), true); registerItem(registry, "wizard_robe", new ItemWizardArmour(Materials.SILK, 1, EntityEquipmentSlot.CHEST, null)); @@ -496,13 +523,198 @@ public final class WizardryItems { registerItem(registry, "spectral_chestplate", new ItemSpectralArmour(ArmorMaterial.IRON, 1, EntityEquipmentSlot.CHEST)); registerItem(registry, "spectral_leggings", new ItemSpectralArmour(ArmorMaterial.IRON, 1, EntityEquipmentSlot.LEGS)); registerItem(registry, "spectral_boots", new ItemSpectralArmour(ArmorMaterial.IRON, 1, EntityEquipmentSlot.FEET)); - - registerItem(registry, "smoke_bomb", new ItemSmokeBomb()); - registerItem(registry, "identification_scroll", new ItemIdentificationScroll()); - - registerItem(registry, "test_artefact", new ItemArtefact(EnumRarity.UNCOMMON)); + registerItem(registry, "lightning_hammer", new ItemLightningHammer()); + + registerItem(registry, "ring_condensing", new ItemArtefact(EnumRarity.RARE, ItemArtefact.Type.RING)); + registerItem(registry, "ring_siphoning", new ItemArtefact(EnumRarity.UNCOMMON, ItemArtefact.Type.RING)); + registerItem(registry, "ring_battlemage", new ItemArtefact(EnumRarity.UNCOMMON, ItemArtefact.Type.RING)); + registerItem(registry, "ring_combustion", new ItemArtefact(EnumRarity.EPIC, ItemArtefact.Type.RING)); + registerItem(registry, "ring_fire_melee", new ItemArtefact(EnumRarity.UNCOMMON, ItemArtefact.Type.RING)); + registerItem(registry, "ring_fire_biome", new ItemArtefact(EnumRarity.UNCOMMON, ItemArtefact.Type.RING)); + registerItem(registry, "ring_disintegration", new ItemArtefact(EnumRarity.RARE, ItemArtefact.Type.RING)); + registerItem(registry, "ring_ice_melee", new ItemArtefact(EnumRarity.UNCOMMON, ItemArtefact.Type.RING)); + registerItem(registry, "ring_ice_biome", new ItemArtefact(EnumRarity.UNCOMMON, ItemArtefact.Type.RING)); + registerItem(registry, "ring_arcane_frost", new ItemArtefact(EnumRarity.EPIC, ItemArtefact.Type.RING)); + registerItem(registry, "ring_shattering", new ItemArtefact(EnumRarity.RARE, ItemArtefact.Type.RING)); + registerItem(registry, "ring_lightning_melee", new ItemArtefact(EnumRarity.UNCOMMON, ItemArtefact.Type.RING)); + registerItem(registry, "ring_storm", new ItemArtefact(EnumRarity.RARE, ItemArtefact.Type.RING)); + registerItem(registry, "ring_seeking", new ItemArtefact(EnumRarity.EPIC, ItemArtefact.Type.RING)); + registerItem(registry, "ring_hammer", new ItemArtefact(EnumRarity.EPIC, ItemArtefact.Type.RING)); + registerItem(registry, "ring_soulbinding", new ItemArtefact(EnumRarity.EPIC, ItemArtefact.Type.RING)); + registerItem(registry, "ring_leeching", new ItemArtefact(EnumRarity.RARE, ItemArtefact.Type.RING)); + registerItem(registry, "ring_necromancy_melee", new ItemArtefact(EnumRarity.UNCOMMON, ItemArtefact.Type.RING)); + registerItem(registry, "ring_mind_control", new ItemArtefact(EnumRarity.RARE, ItemArtefact.Type.RING)); + registerItem(registry, "ring_poison", new ItemArtefact(EnumRarity.RARE, ItemArtefact.Type.RING)); + registerItem(registry, "ring_earth_melee", new ItemArtefact(EnumRarity.UNCOMMON, ItemArtefact.Type.RING)); + registerItem(registry, "ring_earth_biome", new ItemArtefact(EnumRarity.UNCOMMON, ItemArtefact.Type.RING)); + registerItem(registry, "ring_full_moon", new ItemArtefact(EnumRarity.RARE, ItemArtefact.Type.RING)); + registerItem(registry, "ring_extraction", new ItemArtefact(EnumRarity.UNCOMMON, ItemArtefact.Type.RING)); + registerItem(registry, "ring_mana_return", new ItemArtefact(EnumRarity.EPIC, ItemArtefact.Type.RING)); + registerItem(registry, "ring_blockwrangler", new ItemArtefact(EnumRarity.RARE, ItemArtefact.Type.RING)); + registerItem(registry, "ring_conjurer", new ItemArtefact(EnumRarity.RARE, ItemArtefact.Type.RING)); + registerItem(registry, "ring_defender", new ItemArtefact(EnumRarity.RARE, ItemArtefact.Type.RING)); + registerItem(registry, "ring_paladin", new ItemArtefact(EnumRarity.UNCOMMON, ItemArtefact.Type.RING)); + registerItem(registry, "ring_interdiction", new ItemArtefact(EnumRarity.EPIC, ItemArtefact.Type.RING)); + + registerItem(registry, "amulet_arcane_defence", new ItemArtefact(EnumRarity.RARE, ItemArtefact.Type.AMULET)); + registerItem(registry, "amulet_warding", new ItemArtefact(EnumRarity.UNCOMMON, ItemArtefact.Type.AMULET)); + registerItem(registry, "amulet_wisdom", new ItemArtefact(EnumRarity.RARE, ItemArtefact.Type.AMULET)); + registerItem(registry, "amulet_fire_protection", new ItemArtefact(EnumRarity.UNCOMMON, ItemArtefact.Type.AMULET)); + registerItem(registry, "amulet_fire_cloaking", new ItemArtefact(EnumRarity.RARE, ItemArtefact.Type.AMULET)); + registerItem(registry, "amulet_ice_immunity", new ItemArtefact(EnumRarity.EPIC, ItemArtefact.Type.AMULET)); + registerItem(registry, "amulet_ice_protection", new ItemArtefact(EnumRarity.UNCOMMON, ItemArtefact.Type.AMULET)); + registerItem(registry, "amulet_potential", new ItemArtefact(EnumRarity.RARE, ItemArtefact.Type.AMULET)); + registerItem(registry, "amulet_channeling", new ItemArtefact(EnumRarity.UNCOMMON, ItemArtefact.Type.AMULET)); + registerItem(registry, "amulet_lich", new ItemArtefact(EnumRarity.UNCOMMON, ItemArtefact.Type.AMULET)); + registerItem(registry, "amulet_wither_immunity", new ItemArtefact(EnumRarity.EPIC, ItemArtefact.Type.AMULET)); + registerItem(registry, "amulet_glide", new ItemArtefact(EnumRarity.EPIC, ItemArtefact.Type.AMULET)); + registerItem(registry, "amulet_banishing", new ItemArtefact(EnumRarity.UNCOMMON, ItemArtefact.Type.AMULET)); + registerItem(registry, "amulet_anchoring", new ItemArtefact(EnumRarity.RARE, ItemArtefact.Type.AMULET)); + registerItem(registry, "amulet_recovery", new ItemArtefact(EnumRarity.UNCOMMON, ItemArtefact.Type.AMULET)); + registerItem(registry, "amulet_transience", new ItemArtefact(EnumRarity.RARE, ItemArtefact.Type.AMULET)); + registerItem(registry, "amulet_resurrection", new ItemArtefact(EnumRarity.EPIC, ItemArtefact.Type.AMULET)); + registerItem(registry, "amulet_auto_shield", new ItemArtefact(EnumRarity.RARE, ItemArtefact.Type.AMULET)); + + registerItem(registry, "charm_haggler", new ItemArtefact(EnumRarity.RARE, ItemArtefact.Type.CHARM)); + registerItem(registry, "charm_experience_tome", new ItemArtefact(EnumRarity.EPIC, ItemArtefact.Type.CHARM)); + registerItem(registry, "charm_auto_smelt", new ItemArtefact(EnumRarity.RARE, ItemArtefact.Type.CHARM)); + registerItem(registry, "charm_lava_walking", new ItemArtefact(EnumRarity.EPIC, ItemArtefact.Type.CHARM)); + registerItem(registry, "charm_storm", new ItemArtefact(EnumRarity.RARE, ItemArtefact.Type.CHARM)); + registerItem(registry, "charm_minion_health", new ItemArtefact(EnumRarity.UNCOMMON, ItemArtefact.Type.CHARM)); + registerItem(registry, "charm_minion_variants", new ItemArtefact(EnumRarity.RARE, ItemArtefact.Type.CHARM)); + registerItem(registry, "charm_flight", new ItemArtefact(EnumRarity.RARE, ItemArtefact.Type.CHARM)); + registerItem(registry, "charm_growth", new ItemArtefact(EnumRarity.UNCOMMON, ItemArtefact.Type.CHARM)); + registerItem(registry, "charm_abseiling", new ItemArtefact(EnumRarity.RARE, ItemArtefact.Type.CHARM)); + registerItem(registry, "charm_silk_touch", new ItemArtefact(EnumRarity.EPIC, ItemArtefact.Type.CHARM)); + registerItem(registry, "charm_stop_time", new ItemArtefact(EnumRarity.EPIC, ItemArtefact.Type.CHARM)); + registerItem(registry, "charm_light", new ItemArtefact(EnumRarity.RARE, ItemArtefact.Type.CHARM)); + registerItem(registry, "charm_transportation", new ItemArtefact(EnumRarity.RARE, ItemArtefact.Type.CHARM)); + registerItem(registry, "charm_feeding", new ItemArtefact(EnumRarity.UNCOMMON, ItemArtefact.Type.CHARM)); + } + + /** Called from init() in the main mod class to register wizardry's dispenser behaviours. */ + public static void registerDispenseBehaviours(){ + + BlockDispenser.DISPENSE_BEHAVIOR_REGISTRY.putObject(firebomb, new BehaviorProjectileDispense(){ + + @Override + protected IProjectile getProjectileEntity(World world, IPosition position, ItemStack stack){ + EntityFirebomb entity = new EntityFirebomb(world); + entity.setPosition(position.getX(), position.getY(), position.getZ()); + return entity; + } + + }); + + BlockDispenser.DISPENSE_BEHAVIOR_REGISTRY.putObject(poison_bomb, new BehaviorProjectileDispense(){ + + @Override + protected IProjectile getProjectileEntity(World world, IPosition position, ItemStack stack){ + EntityPoisonBomb entity = new EntityPoisonBomb(world); + entity.setPosition(position.getX(), position.getY(), position.getZ()); + return entity; + } + + }); + + BlockDispenser.DISPENSE_BEHAVIOR_REGISTRY.putObject(smoke_bomb, new BehaviorProjectileDispense(){ + + @Override + protected IProjectile getProjectileEntity(World world, IPosition position, ItemStack stack){ + EntitySmokeBomb entity = new EntitySmokeBomb(world); + entity.setPosition(position.getX(), position.getY(), position.getZ()); + return entity; + } + + }); + + BlockDispenser.DISPENSE_BEHAVIOR_REGISTRY.putObject(spark_bomb, new BehaviorProjectileDispense(){ + + @Override + protected IProjectile getProjectileEntity(World world, IPosition position, ItemStack stack){ + EntitySparkBomb entity = new EntitySparkBomb(world); + entity.setPosition(position.getX(), position.getY(), position.getZ()); + return entity; + } + + }); + + BlockDispenser.DISPENSE_BEHAVIOR_REGISTRY.putObject(scroll, new BehaviourSpellDispense()); + + } + + public static void populateWandMap(){ + + WAND_MAP.put(ImmutablePair.of(Tier.NOVICE, Element.MAGIC), magic_wand); + WAND_MAP.put(ImmutablePair.of(Tier.NOVICE, Element.FIRE), novice_fire_wand); + WAND_MAP.put(ImmutablePair.of(Tier.NOVICE, Element.ICE), novice_ice_wand); + WAND_MAP.put(ImmutablePair.of(Tier.NOVICE, Element.LIGHTNING), novice_lightning_wand); + WAND_MAP.put(ImmutablePair.of(Tier.NOVICE, Element.NECROMANCY), novice_necromancy_wand); + WAND_MAP.put(ImmutablePair.of(Tier.NOVICE, Element.EARTH), novice_earth_wand); + WAND_MAP.put(ImmutablePair.of(Tier.NOVICE, Element.SORCERY), novice_sorcery_wand); + WAND_MAP.put(ImmutablePair.of(Tier.NOVICE, Element.HEALING), novice_healing_wand); + WAND_MAP.put(ImmutablePair.of(Tier.APPRENTICE, Element.MAGIC), apprentice_wand); + WAND_MAP.put(ImmutablePair.of(Tier.APPRENTICE, Element.FIRE), apprentice_fire_wand); + WAND_MAP.put(ImmutablePair.of(Tier.APPRENTICE, Element.ICE), apprentice_ice_wand); + WAND_MAP.put(ImmutablePair.of(Tier.APPRENTICE, Element.LIGHTNING), apprentice_lightning_wand); + WAND_MAP.put(ImmutablePair.of(Tier.APPRENTICE, Element.NECROMANCY), apprentice_necromancy_wand); + WAND_MAP.put(ImmutablePair.of(Tier.APPRENTICE, Element.EARTH), apprentice_earth_wand); + WAND_MAP.put(ImmutablePair.of(Tier.APPRENTICE, Element.SORCERY), apprentice_sorcery_wand); + WAND_MAP.put(ImmutablePair.of(Tier.APPRENTICE, Element.HEALING), apprentice_healing_wand); + WAND_MAP.put(ImmutablePair.of(Tier.ADVANCED, Element.MAGIC), advanced_wand); + WAND_MAP.put(ImmutablePair.of(Tier.ADVANCED, Element.FIRE), advanced_fire_wand); + WAND_MAP.put(ImmutablePair.of(Tier.ADVANCED, Element.ICE), advanced_ice_wand); + WAND_MAP.put(ImmutablePair.of(Tier.ADVANCED, Element.LIGHTNING), advanced_lightning_wand); + WAND_MAP.put(ImmutablePair.of(Tier.ADVANCED, Element.NECROMANCY), advanced_necromancy_wand); + WAND_MAP.put(ImmutablePair.of(Tier.ADVANCED, Element.EARTH), advanced_earth_wand); + WAND_MAP.put(ImmutablePair.of(Tier.ADVANCED, Element.SORCERY), advanced_sorcery_wand); + WAND_MAP.put(ImmutablePair.of(Tier.ADVANCED, Element.HEALING), advanced_healing_wand); + WAND_MAP.put(ImmutablePair.of(Tier.MASTER, Element.MAGIC), master_wand); + WAND_MAP.put(ImmutablePair.of(Tier.MASTER, Element.FIRE), master_fire_wand); + WAND_MAP.put(ImmutablePair.of(Tier.MASTER, Element.ICE), master_ice_wand); + WAND_MAP.put(ImmutablePair.of(Tier.MASTER, Element.LIGHTNING), master_lightning_wand); + WAND_MAP.put(ImmutablePair.of(Tier.MASTER, Element.NECROMANCY), master_necromancy_wand); + WAND_MAP.put(ImmutablePair.of(Tier.MASTER, Element.EARTH), master_earth_wand); + WAND_MAP.put(ImmutablePair.of(Tier.MASTER, Element.SORCERY), master_sorcery_wand); + WAND_MAP.put(ImmutablePair.of(Tier.MASTER, Element.HEALING), master_healing_wand); + } + + public static void populateArmourMap(){ + + ARMOUR_MAP.put(ImmutablePair.of(EntityEquipmentSlot.HEAD, Element.MAGIC), wizard_hat); + ARMOUR_MAP.put(ImmutablePair.of(EntityEquipmentSlot.HEAD, Element.FIRE), wizard_hat_fire); + ARMOUR_MAP.put(ImmutablePair.of(EntityEquipmentSlot.HEAD, Element.ICE), wizard_hat_ice); + ARMOUR_MAP.put(ImmutablePair.of(EntityEquipmentSlot.HEAD, Element.LIGHTNING), wizard_hat_lightning); + ARMOUR_MAP.put(ImmutablePair.of(EntityEquipmentSlot.HEAD, Element.NECROMANCY), wizard_hat_necromancy); + ARMOUR_MAP.put(ImmutablePair.of(EntityEquipmentSlot.HEAD, Element.EARTH), wizard_hat_earth); + ARMOUR_MAP.put(ImmutablePair.of(EntityEquipmentSlot.HEAD, Element.SORCERY), wizard_hat_sorcery); + ARMOUR_MAP.put(ImmutablePair.of(EntityEquipmentSlot.HEAD, Element.HEALING), wizard_hat_healing); + ARMOUR_MAP.put(ImmutablePair.of(EntityEquipmentSlot.CHEST, Element.MAGIC), wizard_robe); + ARMOUR_MAP.put(ImmutablePair.of(EntityEquipmentSlot.CHEST, Element.FIRE), wizard_robe_fire); + ARMOUR_MAP.put(ImmutablePair.of(EntityEquipmentSlot.CHEST, Element.ICE), wizard_robe_ice); + ARMOUR_MAP.put(ImmutablePair.of(EntityEquipmentSlot.CHEST, Element.LIGHTNING), wizard_robe_lightning); + ARMOUR_MAP.put(ImmutablePair.of(EntityEquipmentSlot.CHEST, Element.NECROMANCY), wizard_robe_necromancy); + ARMOUR_MAP.put(ImmutablePair.of(EntityEquipmentSlot.CHEST, Element.EARTH), wizard_robe_earth); + ARMOUR_MAP.put(ImmutablePair.of(EntityEquipmentSlot.CHEST, Element.SORCERY), wizard_robe_sorcery); + ARMOUR_MAP.put(ImmutablePair.of(EntityEquipmentSlot.CHEST, Element.HEALING), wizard_robe_healing); + ARMOUR_MAP.put(ImmutablePair.of(EntityEquipmentSlot.LEGS, Element.MAGIC), wizard_leggings); + ARMOUR_MAP.put(ImmutablePair.of(EntityEquipmentSlot.LEGS, Element.FIRE), wizard_leggings_fire); + ARMOUR_MAP.put(ImmutablePair.of(EntityEquipmentSlot.LEGS, Element.ICE), wizard_leggings_ice); + ARMOUR_MAP.put(ImmutablePair.of(EntityEquipmentSlot.LEGS, Element.LIGHTNING), wizard_leggings_lightning); + ARMOUR_MAP.put(ImmutablePair.of(EntityEquipmentSlot.LEGS, Element.NECROMANCY), wizard_leggings_necromancy); + ARMOUR_MAP.put(ImmutablePair.of(EntityEquipmentSlot.LEGS, Element.EARTH), wizard_leggings_earth); + ARMOUR_MAP.put(ImmutablePair.of(EntityEquipmentSlot.LEGS, Element.SORCERY), wizard_leggings_sorcery); + ARMOUR_MAP.put(ImmutablePair.of(EntityEquipmentSlot.LEGS, Element.HEALING), wizard_leggings_healing); + ARMOUR_MAP.put(ImmutablePair.of(EntityEquipmentSlot.FEET, Element.MAGIC), wizard_boots); + ARMOUR_MAP.put(ImmutablePair.of(EntityEquipmentSlot.FEET, Element.FIRE), wizard_boots_fire); + ARMOUR_MAP.put(ImmutablePair.of(EntityEquipmentSlot.FEET, Element.ICE), wizard_boots_ice); + ARMOUR_MAP.put(ImmutablePair.of(EntityEquipmentSlot.FEET, Element.LIGHTNING), wizard_boots_lightning); + ARMOUR_MAP.put(ImmutablePair.of(EntityEquipmentSlot.FEET, Element.NECROMANCY), wizard_boots_necromancy); + ARMOUR_MAP.put(ImmutablePair.of(EntityEquipmentSlot.FEET, Element.EARTH), wizard_boots_earth); + ARMOUR_MAP.put(ImmutablePair.of(EntityEquipmentSlot.FEET, Element.SORCERY), wizard_boots_sorcery); + ARMOUR_MAP.put(ImmutablePair.of(EntityEquipmentSlot.FEET, Element.HEALING), wizard_boots_healing); } } \ No newline at end of file diff --git a/src/main/java/electroblob/wizardry/registry/WizardryLoot.java b/src/main/java/electroblob/wizardry/registry/WizardryLoot.java new file mode 100644 index 00000000..551e11e0 --- /dev/null +++ b/src/main/java/electroblob/wizardry/registry/WizardryLoot.java @@ -0,0 +1,156 @@ +package electroblob.wizardry.registry; + +import electroblob.wizardry.Wizardry; +import electroblob.wizardry.constants.Tier; +import electroblob.wizardry.loot.RandomSpell; +import electroblob.wizardry.loot.WizardSpell; +import electroblob.wizardry.spell.Spell; +import net.minecraft.entity.EntityList; +import net.minecraft.entity.EnumCreatureType; +import net.minecraft.util.ResourceLocation; +import net.minecraft.world.storage.loot.*; +import net.minecraft.world.storage.loot.conditions.LootCondition; +import net.minecraft.world.storage.loot.functions.LootFunctionManager; +import net.minecraftforge.event.LootTableLoadEvent; +import net.minecraftforge.fml.common.Mod; +import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; +import net.minecraftforge.fml.common.registry.EntityEntry; +import net.minecraftforge.fml.common.registry.ForgeRegistries; + +import java.util.Arrays; +import java.util.List; +import java.util.Random; +import java.util.function.Predicate; + +/** + * Class responsible for registering wizardry's loot functions and loot tables. Also handles loot injection and the + * standard weighting. + * + * @author Electroblob + * @since Wizardry 1.0 + */ +@Mod.EventBusSubscriber +public final class WizardryLoot { + + //public static final String FROM_SPAWNER_NBT_FLAG = "fromSpawner"; + + private WizardryLoot(){} // No instances! + + /** Called from the preInit method in the main mod class to register the custom dungeon loot. */ + public static void register(){ + + /* Loot tables work as follows: Minecraft goes through each pool in turn. For each pool, it does a certain + * number of rolls, which can either be set to always be one number or a random number from a range. Each roll, + * it generates one stack of a single random entry in that pool, weighted according to the weights of the + * entries. Functions allow properties of that stack (stack size, damage, nbt) to be set, and even allow it to + * be replaced dynamically with a completely different item (though there's very little point in doing that as + * it could be achieved just as easily with more entries, which makes me think it would be bad practice). You + * can also use conditions to control whether an entry or pool is used at all, which is mostly for mob drops + * under specific conditions, but one of them is simply a random chance, meaning you could use it to make a pool + * that only gets rolled sometimes. All in all, this can get rather confusing, because stackable items can have + * 5 stages of randomness applied to them at once: a random chance for the pool, a random number of rolls for + * the pool, the weighted random chance of choosing that particular entry, a random chance for that entry, and a + * random stack size, and that's before you take functions into account. + * + * ...oh, and entries can be entire loot tables in themselves, allowing for potentially infinite levels of + * randomness. Yeah. */ + + // Always registers the loot tables, but only injects the additions into vanilla if the appropriate option is + // enabled in the config (see WizardryEventHandler). + LootFunctionManager.registerFunction(new RandomSpell.Serializer()); + LootFunctionManager.registerFunction(new WizardSpell.Serializer()); + LootTableList.register(new ResourceLocation(Wizardry.MODID, "chests/wizard_tower")); + LootTableList.register(new ResourceLocation(Wizardry.MODID, "chests/obelisk")); + LootTableList.register(new ResourceLocation(Wizardry.MODID, "chests/shrine")); + LootTableList.register(new ResourceLocation(Wizardry.MODID, "chests/dungeon_additions")); + LootTableList.register(new ResourceLocation(Wizardry.MODID, "chests/jungle_dispenser_additions")); + LootTableList.register(new ResourceLocation(Wizardry.MODID, "subsets/elemental_crystals")); + LootTableList.register(new ResourceLocation(Wizardry.MODID, "subsets/wizard_armour")); + LootTableList.register(new ResourceLocation(Wizardry.MODID, "subsets/arcane_tomes")); + LootTableList.register(new ResourceLocation(Wizardry.MODID, "subsets/wand_upgrades")); + LootTableList.register(new ResourceLocation(Wizardry.MODID, "entities/evil_wizard")); + LootTableList.register(new ResourceLocation(Wizardry.MODID, "entities/mob_additions")); + + } + + /** + * Helper method which gets a spell id according to the standard weighting. The tier is a weighted random value; the + * actual spell within that tier is completely random. Will not return the id of a spell which has been disabled in + * the config. This is for simple stuff like chests and drops; more complex generators like wizard trades don't use + * this method. + *

    + * For reference, the standard weighting is as follows: Novice: 60%, Apprentice: 25%, Advanced: 10%, Master: 5% + * + * @param random An instance of {@link Random} to use for RNG + * @param filter A {@link Predicate} specifying any requirements the chosen spell must fulfil + * @return A random spell id number, or -1 if no spell exists that satisfies the given filter + * @deprecated Everything uses loot tables now, I may remove this as some point + */ + @Deprecated + public static int getStandardWeightedRandomSpellId(Random random, Predicate filter){ + + Tier tier = Tier.getWeightedRandomTier(random); + + List spells = Spell.getSpells(new Spell.TierElementFilter(tier, null)); + spells.removeIf(filter.negate()); + + // Ensures the tier chosen actually has spells in it, and if not uses NOVICE instead. + if(spells.isEmpty()){ + spells = Spell.getSpells(new Spell.TierElementFilter(Tier.NOVICE, null)); + spells.removeIf(filter.negate()); + } + + if(spells.isEmpty()) return -1; + + // Finds a random spell in the list and returns its id. + return spells.get(random.nextInt(spells.size())).metadata(); + } + + @SubscribeEvent + public static void onLootTableLoadEvent(LootTableLoadEvent event){ + // General dungeon loot + if(Arrays.asList(Wizardry.settings.lootInjectionLocations).contains(event.getName())){ + event.getTable().addPool(getAdditive(Wizardry.MODID + ":chests/dungeon_additions", Wizardry.MODID + "_additional_dungeon_loot")); + } + // Jungle temple dispensers + if(event.getName().toString().matches("minecraft:chests/jungle_temple_dispenser")){ + event.getTable().addPool(getAdditive(Wizardry.MODID + ":chests/jungle_dispenser_additions", Wizardry.MODID + "_additional_dispenser_loot")); + } + // Mob drops + // Let's hope mods will play nice and store their entity loot tables under 'entities' or 'entity' + // If not, packmakers will have to sort it out themselves using the whitelist/blacklist + if(Arrays.asList(Wizardry.settings.mobLootTableWhitelist).contains(event.getName())){ + event.getTable().addPool(getAdditive(Wizardry.MODID + ":entities/mob_additions", Wizardry.MODID + "_additional_mob_drops")); + + }else if(!Arrays.asList(Wizardry.settings.mobLootTableBlacklist).contains(event.getName()) + && event.getName().getPath().contains("entities") || event.getName().getPath().contains("entity")){ + // Get the filename of the loot table json, for well-behaved mods this will be the entity name + String[] split = event.getName().getPath().split("/"); + String entityName = split[split.length - 1]; + + EntityEntry entry = ForgeRegistries.ENTITIES.getValue(new ResourceLocation(entityName)); + if(entry == null) return; // If this is true it didn't work :( + Class entityClass = entry.getEntityClass(); + + if(EnumCreatureType.MONSTER.getCreatureClass().isAssignableFrom(entityClass)){ + event.getTable().addPool(getAdditive(Wizardry.MODID + ":entities/mob_additions", Wizardry.MODID + "_additional_mob_drops")); + } + } + } + + private static LootPool getAdditive(String entryName, String poolName){ + return new LootPool(new LootEntry[]{getAdditiveEntry(entryName, 1)}, new LootCondition[0], + new RandomValueRange(1), new RandomValueRange(0, 1), Wizardry.MODID + "_" + poolName); + } + + private static LootEntryTable getAdditiveEntry(String name, int weight){ + return new LootEntryTable(new ResourceLocation(name), weight, 0, new LootCondition[0], + Wizardry.MODID + "_additive_entry"); + } + +// @SubscribeEvent +// public static void onLivingSpawnEvent(LivingSpawnEvent.SpecialSpawn event){ +// if(event.getSpawner() != null) event.getEntityLiving().getEntityData().setBoolean(FROM_SPAWNER_NBT_FLAG, true); +// } + +} diff --git a/src/main/java/electroblob/wizardry/registry/WizardryPotions.java b/src/main/java/electroblob/wizardry/registry/WizardryPotions.java index a39a99d7..3f799f6a 100644 --- a/src/main/java/electroblob/wizardry/registry/WizardryPotions.java +++ b/src/main/java/electroblob/wizardry/registry/WizardryPotions.java @@ -5,7 +5,6 @@ import electroblob.wizardry.potion.*; import electroblob.wizardry.util.ParticleBuilder; import electroblob.wizardry.util.ParticleBuilder.Type; import net.minecraft.entity.EntityLivingBase; -import net.minecraft.entity.ai.attributes.AbstractAttributeMap; import net.minecraft.potion.Potion; import net.minecraft.util.EnumParticleTypes; import net.minecraft.util.ResourceLocation; @@ -16,6 +15,8 @@ import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; import net.minecraftforge.fml.common.registry.GameRegistry.ObjectHolder; import net.minecraftforge.registries.IForgeRegistry; +import javax.annotation.Nonnull; + /** * Class responsible for defining, storing and registering all of wizardry's potion effects. * @@ -26,23 +27,34 @@ import net.minecraftforge.registries.IForgeRegistry; @Mod.EventBusSubscriber public final class WizardryPotions { - public static final Potion frost = null; - public static final Potion transience = null; - public static final Potion fireskin = null; - public static final Potion ice_shroud = null; - public static final Potion static_aura = null; - public static final Potion decay = null; - public static final Potion sixth_sense = null; - public static final Potion arcane_jammer = null; - public static final Potion mind_trick = null; - public static final Potion mind_control = null; - public static final Potion font_of_mana = null; - public static final Potion fear = null; - public static final Potion curse_of_soulbinding = null; - public static final Potion paralysis = null; - public static final Potion muffle = null; - public static final Potion ward = null; - public static final Potion slow_time = null; + private WizardryPotions(){} // No instances! + + @Nonnull + @SuppressWarnings("ConstantConditions") + private static T placeholder(){ return null; } + + public static final Potion frost = placeholder(); + public static final Potion transience = placeholder(); + public static final Potion fireskin = placeholder(); + public static final Potion ice_shroud = placeholder(); + public static final Potion static_aura = placeholder(); + public static final Potion decay = placeholder(); + public static final Potion sixth_sense = placeholder(); + public static final Potion arcane_jammer = placeholder(); + public static final Potion mind_trick = placeholder(); + public static final Potion mind_control = placeholder(); + public static final Potion font_of_mana = placeholder(); + public static final Potion fear = placeholder(); + public static final Potion curse_of_soulbinding = placeholder(); + public static final Potion paralysis = placeholder(); + public static final Potion muffle = placeholder(); + public static final Potion ward = placeholder(); + public static final Potion slow_time = placeholder(); + public static final Potion empowerment = placeholder(); + public static final Potion curse_of_enfeeblement = placeholder(); + public static final Potion curse_of_undeath = placeholder(); + public static final Potion containment = placeholder(); + public static final Potion frost_step = placeholder(); /** * Sets both the registry and unlocalised names of the given potion, then registers it with the given registry. Use @@ -71,7 +83,7 @@ public final class WizardryPotions { registerPotion(registry, "frost", new PotionFrost(true, 0)); // Colour was 0x38ddec (was arbitrary anyway) registerPotion(registry, "transience", new PotionMagicEffectParticles(false, 0, - new ResourceLocation(Wizardry.MODID, "potion_icon_transience")){ + new ResourceLocation(Wizardry.MODID, "textures/gui/potion_icon_transience.png")){ @Override public void spawnCustomParticle(World world, double x, double y, double z){ ParticleBuilder.create(Type.DUST).pos(x, y, z).clr(0.8f, 0.8f, 1.0f).shaded(true).spawn(world); @@ -79,7 +91,7 @@ public final class WizardryPotions { }.setBeneficial()); // 0xffe89b registerPotion(registry, "fireskin", new PotionMagicEffectParticles(false, 0, - new ResourceLocation(Wizardry.MODID, "potion_icon_fireskin")){ + new ResourceLocation(Wizardry.MODID, "textures/gui/potion_icon_fireskin.png")){ @Override public void spawnCustomParticle(World world, double x, double y, double z){ world.spawnParticle(EnumParticleTypes.FLAME, x, y, z, 0, 0, 0); @@ -89,11 +101,11 @@ public final class WizardryPotions { public void performEffect(EntityLivingBase entitylivingbase, int strength){ entitylivingbase.extinguish(); // Stops melee mobs that are on fire from setting the player on fire, // without allowing the player to actually stand in fire or swim in lava without taking damage. - }; + } }.setBeneficial()); // 0xff2f02 registerPotion(registry, "ice_shroud", new PotionMagicEffectParticles(false, 0, - new ResourceLocation(Wizardry.MODID, "potion_icon_ice_shroud")){ + new ResourceLocation(Wizardry.MODID, "textures/gui/potion_icon_ice_shroud.png")){ @Override public void spawnCustomParticle(World world, double x, double y, double z){ float brightness = 0.5f + (world.rand.nextFloat() / 2); @@ -103,7 +115,7 @@ public final class WizardryPotions { }.setBeneficial()); // 0x52f1ff registerPotion(registry, "static_aura", new PotionMagicEffectParticles(false, 0, - new ResourceLocation(Wizardry.MODID, "potion_icon_static_aura")){ + new ResourceLocation(Wizardry.MODID, "textures/gui/potion_icon_static_aura.png")){ @Override public void spawnCustomParticle(World world, double x, double y, double z){ ParticleBuilder.create(Type.SPARK).pos(x, y, z).spawn(world); @@ -113,33 +125,35 @@ public final class WizardryPotions { registerPotion(registry, "decay", new PotionDecay(true, 0x3c006c)); registerPotion(registry, "sixth_sense", new PotionMagicEffect(false, 0xc6ff01, - new ResourceLocation(Wizardry.MODID, "potion_icon_sixth_sense")){ + new ResourceLocation(Wizardry.MODID, "textures/gui/potion_icon_sixth_sense.png")){ @Override - public void removeAttributesModifiersFromEntity(EntityLivingBase target, AbstractAttributeMap attributeMapIn, int amplifier){ - // Reset the shader - if(target.world.isRemote && target == net.minecraft.client.Minecraft.getMinecraft().player){ + public void performEffect(EntityLivingBase target, int strength){ + // Reset the shader (a bit dirty but both the potion expiry hooks are only fired server-side, and + // there's no point sending packets unnecessarily if we can just do this instead) + if(target.getActivePotionEffect(this).getDuration() <= 1 && target.world.isRemote + && target == net.minecraft.client.Minecraft.getMinecraft().player){ net.minecraft.client.Minecraft.getMinecraft().entityRenderer.stopUseShader(); } } }.setBeneficial()); registerPotion(registry, "arcane_jammer", new PotionMagicEffect(true, 0xcf4aa2, - new ResourceLocation(Wizardry.MODID, "potion_icon_arcane_jammer"))); + new ResourceLocation(Wizardry.MODID, "textures/gui/potion_icon_arcane_jammer.png"))); registerPotion(registry, "mind_trick", new PotionMagicEffect(true, 0x601683, - new ResourceLocation(Wizardry.MODID, "potion_icon_mind_trick"))); + new ResourceLocation(Wizardry.MODID, "textures/gui/potion_icon_mind_trick.png"))); registerPotion(registry, "mind_control", new PotionMagicEffect(true, 0x320b44, - new ResourceLocation(Wizardry.MODID, "potion_icon_mind_control"))); + new ResourceLocation(Wizardry.MODID, "textures/gui/potion_icon_mind_control.png"))); registerPotion(registry, "font_of_mana", new PotionMagicEffect(false, 0xffe5bb, - new ResourceLocation(Wizardry.MODID, "potion_icon_font_of_mana")).setBeneficial()); + new ResourceLocation(Wizardry.MODID, "textures/gui/potion_icon_font_of_mana.png")).setBeneficial()); registerPotion(registry, "fear", new PotionMagicEffect(true, 0xbd0100, - new ResourceLocation(Wizardry.MODID, "potion_icon_fear"))); + new ResourceLocation(Wizardry.MODID, "textures/gui/potion_icon_fear.png"))); registerPotion(registry, "curse_of_soulbinding", new Curse(true, 0x0f000f, - new ResourceLocation(Wizardry.MODID, "potion_icon_curse_of_soulbinding")){ + new ResourceLocation(Wizardry.MODID, "textures/gui/potion_icon_curse_of_soulbinding.png")){ @Override // We're not removing any attributes, but it's called when we want it to be so... public void removeAttributesModifiersFromEntity(EntityLivingBase entity, net.minecraft.entity.ai.attributes.AbstractAttributeMap attributeMapIn, int amplifier){ // TODO: Hmmmm... @@ -147,7 +161,7 @@ public final class WizardryPotions { }); registerPotion(registry, "paralysis", new PotionMagicEffectParticles(true, 0, - new ResourceLocation(Wizardry.MODID, "potion_icon_paralysis")){ + new ResourceLocation(Wizardry.MODID, "textures/gui/potion_icon_paralysis.png")){ @Override public void spawnCustomParticle(World world, double x, double y, double z){ ParticleBuilder.create(Type.SPARK).pos(x, y, z).spawn(world); @@ -155,12 +169,24 @@ public final class WizardryPotions { }); registerPotion(registry, "muffle", new PotionMagicEffect(false, 0x4464d9, - new ResourceLocation(Wizardry.MODID, "potion_icon_muffle")).setBeneficial()); + new ResourceLocation(Wizardry.MODID, "textures/gui/potion_icon_muffle.png")).setBeneficial()); registerPotion(registry, "ward", new PotionMagicEffect(false, 0xc991d0, - new ResourceLocation(Wizardry.MODID, "potion_icon_ward")).setBeneficial()); + new ResourceLocation(Wizardry.MODID, "textures/gui/potion_icon_ward.png")).setBeneficial()); registerPotion(registry, "slow_time", new PotionSlowTime(false, 0x5be3bb).setBeneficial()); + + registerPotion(registry, "empowerment", new PotionMagicEffect(false, 0x8367bd, + new ResourceLocation(Wizardry.MODID, "textures/gui/potion_icon_empowerment.png")).setBeneficial()); + + registerPotion(registry, "curse_of_enfeeblement", new CurseEnfeeblement(true, 0x36000b)); + + registerPotion(registry, "curse_of_undeath", new CurseUndeath(true, 0x685c00)); + + registerPotion(registry, "containment", new PotionContainment(true, 0x7988cc)); + + registerPotion(registry, "frost_step", new PotionFrostStep(false, 0).setBeneficial()); + } } \ No newline at end of file diff --git a/src/main/java/electroblob/wizardry/registry/WizardryRecipes.java b/src/main/java/electroblob/wizardry/registry/WizardryRecipes.java new file mode 100644 index 00000000..f2691884 --- /dev/null +++ b/src/main/java/electroblob/wizardry/registry/WizardryRecipes.java @@ -0,0 +1,137 @@ +package electroblob.wizardry.registry; + +import electroblob.wizardry.Wizardry; +import electroblob.wizardry.item.IManaStoringItem; +import electroblob.wizardry.item.ItemManaFlask; +import net.minecraft.inventory.ContainerPlayer; +import net.minecraft.inventory.ContainerWorkbench; +import net.minecraft.inventory.IInventory; +import net.minecraft.item.Item; +import net.minecraft.item.ItemStack; +import net.minecraft.item.crafting.FurnaceRecipes; +import net.minecraft.item.crafting.IRecipe; +import net.minecraft.util.ResourceLocation; +import net.minecraftforge.event.RegistryEvent; +import net.minecraftforge.fml.common.Mod; +import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; +import net.minecraftforge.fml.common.gameevent.TickEvent; +import net.minecraftforge.oredict.OreDictionary; +import net.minecraftforge.oredict.ShapelessOreRecipe; +import net.minecraftforge.registries.IForgeRegistry; + +import java.util.LinkedList; +import java.util.Queue; + +/** + * Class responsible for defining and registering wizardry's non-JSON recipes (i.e. smelting recipes and dynamic + * crafting recipes). Also handles dynamic recipe display and usage. + * + * @author Electroblob + * @since Wizardry 4.2 + */ +@Mod.EventBusSubscriber +public final class WizardryRecipes { + + private WizardryRecipes(){} // No instances! + + private static final Queue chargingRecipeQueue = new LinkedList<>(); + + /** Adds the given item to the list of items that can be charged using mana flasks. Dynamic charging recipes + * will be added for these items during {@code RegistryEvent.Register}. The item must implement + * {@link IManaStoringItem} for the recipes to work correctly. This method should be called from the item's + * constructor. */ + public static void addToManaFlaskCharging(Item item){ + chargingRecipeQueue.offer(item); + } + + /** Now only deals with the dynamic crafting recipes and the smelting recipes. */ + @SubscribeEvent + public static void registerRecipes(RegistryEvent.Register event){ + + IForgeRegistry registry = event.getRegistry(); + + FurnaceRecipes.instance().addSmeltingRecipeForBlock(WizardryBlocks.crystal_ore, new ItemStack(WizardryItems.magic_crystal), 0.5f); + + // Mana flask recipes + + ItemStack smallFlaskStack = new ItemStack(WizardryItems.small_mana_flask); + ItemStack mediumFlaskStack = new ItemStack(WizardryItems.medium_mana_flask); + ItemStack largeFlaskStack = new ItemStack(WizardryItems.large_mana_flask); + + ItemStack chargeable; + + while(!chargingRecipeQueue.isEmpty()){ + // Use remove() and not poll() because the queue shouldn't be empty in here + chargeable = new ItemStack(chargingRecipeQueue.remove(), 1, OreDictionary.WILDCARD_VALUE); + + registry.register(new ShapelessOreRecipe(null, chargeable, chargeable, smallFlaskStack){ + @Override public boolean isDynamic(){ return true; } // Stops it appearing in the recipe book + }.setRegistryName(new ResourceLocation(Wizardry.MODID, "recipes/small_flask_" + chargeable.getItem().getRegistryName().getPath()))); + + registry.register(new ShapelessOreRecipe(null, chargeable, chargeable, mediumFlaskStack){ + @Override public boolean isDynamic(){ return true; } + }.setRegistryName(new ResourceLocation(Wizardry.MODID, "recipes/medium_flask_" + chargeable.getItem().getRegistryName().getPath()))); + + registry.register(new ShapelessOreRecipe(null, chargeable, chargeable, largeFlaskStack){ + @Override public boolean isDynamic(){ return true; } + }.setRegistryName(new ResourceLocation(Wizardry.MODID, "recipes/large_flask_" + chargeable.getItem().getRegistryName().getPath()))); + + } + } + + @SubscribeEvent + public static void onPlayerTickEvent(TickEvent.PlayerTickEvent event){ + + if(event.phase == TickEvent.Phase.START){ + + if(event.player.openContainer instanceof ContainerWorkbench){ + + IInventory craftMatrix = ((ContainerWorkbench)event.player.openContainer).craftMatrix; + ItemStack output = ((ContainerWorkbench)event.player.openContainer).craftResult.getStackInSlot(0); + processManaFlaskCrafting(craftMatrix, output); + + }else if(event.player.openContainer instanceof ContainerPlayer){ + + IInventory craftMatrix = ((ContainerPlayer)event.player.openContainer).craftMatrix; + ItemStack output = ((ContainerPlayer)event.player.openContainer).craftResult.getStackInSlot(0); + // Unfortunately I have no choice but to call this method every tick when the player isn't using another + // inventory, since the only thing tracking whether the player is looking at their inventory is the GUI + // itself, which is client-side only. + processManaFlaskCrafting(craftMatrix, output); + } + } + } + + private static void processManaFlaskCrafting(IInventory craftMatrix, ItemStack output){ + + // Charges wand using mana flask + + ItemManaFlask flask = null; + ItemStack input = ItemStack.EMPTY; + + for(int i = 0; i < craftMatrix.getSizeInventory(); i++){ + + ItemStack stack = craftMatrix.getStackInSlot(i); + + if(stack.getItem() instanceof ItemManaFlask){ + flask = (ItemManaFlask)stack.getItem(); + } + + if(stack.getItem() instanceof IManaStoringItem){ + input = stack; + } + } + + if(flask == null) return; + + if(output.getItem() instanceof IManaStoringItem && !input.isEmpty()){ + + output.setTagCompound((input.getTagCompound())); + + int currentMana = ((IManaStoringItem)input.getItem()).getMana(input); + + ((IManaStoringItem)output.getItem()).setMana(output, Math.min(currentMana + flask.size.capacity, + ((IManaStoringItem)input.getItem()).getManaCapacity(input))); + } + } +} diff --git a/src/main/java/electroblob/wizardry/registry/WizardryRegistry.java b/src/main/java/electroblob/wizardry/registry/WizardryRegistry.java deleted file mode 100644 index 6b150adc..00000000 --- a/src/main/java/electroblob/wizardry/registry/WizardryRegistry.java +++ /dev/null @@ -1,225 +0,0 @@ -package electroblob.wizardry.registry; - -import com.google.common.collect.Lists; -import electroblob.wizardry.Wizardry; -import electroblob.wizardry.constants.Element; -import electroblob.wizardry.constants.Tier; -import electroblob.wizardry.entity.EntityArc; -import electroblob.wizardry.entity.EntityMeteor; -import electroblob.wizardry.entity.EntityShield; -import electroblob.wizardry.entity.construct.*; -import electroblob.wizardry.entity.living.*; -import electroblob.wizardry.entity.projectile.*; -import electroblob.wizardry.loot.RandomSpell; -import electroblob.wizardry.loot.WizardSpell; -import electroblob.wizardry.tileentity.*; -import electroblob.wizardry.util.WizardryUtilities; -import net.minecraft.entity.Entity; -import net.minecraft.entity.EnumCreatureType; -import net.minecraft.init.Biomes; -import net.minecraft.inventory.EntityEquipmentSlot; -import net.minecraft.item.ItemStack; -import net.minecraft.item.crafting.FurnaceRecipes; -import net.minecraft.item.crafting.IRecipe; -import net.minecraft.util.ResourceLocation; -import net.minecraft.world.biome.Biome; -import net.minecraft.world.storage.loot.LootTableList; -import net.minecraft.world.storage.loot.functions.LootFunctionManager; -import net.minecraftforge.event.RegistryEvent; -import net.minecraftforge.fml.common.Mod; -import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; -import net.minecraftforge.fml.common.registry.EntityRegistry; -import net.minecraftforge.fml.common.registry.ForgeRegistries; -import net.minecraftforge.fml.common.registry.GameRegistry; -import net.minecraftforge.oredict.OreDictionary; -import net.minecraftforge.oredict.ShapelessOreRecipe; -import net.minecraftforge.registries.IForgeRegistry; - -import java.util.List; - -/** - * Class responsible for registering all the things that don't have (or need) instances: entities, loot tables, recipes, - * etc. - * - * @author Electroblob - * @since Wizardry 1.0 - */ -@Mod.EventBusSubscriber -public final class WizardryRegistry { - - /** Called from the preInit method in the main mod class to register the custom dungeon loot. */ - public static void registerLoot(){ - - /* Loot tables work as follows: Minecraft goes through each pool in turn. For each pool, it does a certain - * number of rolls, which can either be set to always be one number or a random number from a range. Each roll, - * it generates one stack of a single random entry in that pool, weighted according to the weights of the - * entries. Functions allow properties of that stack (stack size, damage, nbt) to be set, and even allow it to - * be replaced dynamically with a completely different item (though there's very little point in doing that as - * it could be achieved just as easily with more entries, which makes me think it would be bad practice). You - * can also use conditions to control whether an entry or pool is used at all, which is mostly for mob drops - * under specific conditions, but one of them is simply a random chance, meaning you could use it to make a pool - * that only gets rolled sometimes. All in all, this can get rather confusing, because stackable items can have - * 5 stages of randomness applied to them at once: a random chance for the pool, a random number of rolls for - * the pool, the weighted random chance of choosing that particular entry, a random chance for that entry, and a - * random stack size, and that's before you take functions into account. - * - * ...oh, and entries can be entire loot tables in themselves, allowing for potentially infinite levels of - * randomness. Yeah. */ - - // Always registers the loot tables, but only injects the additions into vanilla if the appropriate option is - // enabled in the config (see WizardryEventHandler). - LootFunctionManager.registerFunction(new RandomSpell.Serializer()); - LootFunctionManager.registerFunction(new WizardSpell.Serializer()); - LootTableList.register(new ResourceLocation(Wizardry.MODID, "chests/wizard_tower")); - LootTableList.register(new ResourceLocation(Wizardry.MODID, "chests/dungeon_additions")); - LootTableList.register(new ResourceLocation(Wizardry.MODID, "subsets/novice_wands")); - LootTableList.register(new ResourceLocation(Wizardry.MODID, "subsets/wizard_armour")); - LootTableList.register(new ResourceLocation(Wizardry.MODID, "subsets/arcane_tomes")); - LootTableList.register(new ResourceLocation(Wizardry.MODID, "subsets/wand_upgrades")); - LootTableList.register(new ResourceLocation(Wizardry.MODID, "entities/evil_wizard")); - // TODO: At the moment this is not used anywhere because I can't find a way to add it to all mobs. - // LootTableList.register(new ResourceLocation(Wizardry.MODID, "entities/mob_additions")); - - } - - /** Called from the preInit method in the main mod class to register all the tile entities. */ - public static void registerTileEntities(){ - - GameRegistry.registerTileEntity(TileEntityArcaneWorkbench.class, Wizardry.MODID + "ArcaneWorkbenchTileEntity"); - GameRegistry.registerTileEntity(TileEntityStatue.class, Wizardry.MODID + "PetrifiedStoneTileEntity"); - GameRegistry.registerTileEntity(TileEntityMagicLight.class, Wizardry.MODID + "MagicLightTileEntity"); - GameRegistry.registerTileEntity(TileEntityTimer.class, Wizardry.MODID + "TimerTileEntity"); - GameRegistry.registerTileEntity(TileEntityPlayerSave.class, Wizardry.MODID + "TileEntityPlayerSave"); - } - - /** Not actually the frequency at all; smaller numbers are more frequent. Vanilla uses 3 I think. */ - private static final int LIVING_UPDATE_INTERVAL = 3; - /** Not actually the frequency at all; smaller numbers are more frequent. */ - private static final int PROJECTILE_UPDATE_INTERVAL = 10; - - /** Called from the preInit method in the main mod class to register all the entities. */ - public static void registerEntities(){ - - int id = 0; // Incrementable index for the mod specific entity id. - - registerEntity(EntityZombieMinion.class, "zombie_minion", id++, 128, LIVING_UPDATE_INTERVAL, true); - registerEntity(EntityMagicMissile.class, "magic_missile", id++, 128, PROJECTILE_UPDATE_INTERVAL, true); - // TODO: This should be a particle - registerEntity(EntityArc.class, "arc", id++, 128, PROJECTILE_UPDATE_INTERVAL, false); - registerEntity(EntitySkeletonMinion.class, "skeleton_minion", id++, 128, LIVING_UPDATE_INTERVAL, true); - registerEntity(EntitySparkBomb.class, "spark_bomb", id++, 128, PROJECTILE_UPDATE_INTERVAL, true); - registerEntity(EntitySpiritWolf.class, "spirit_wolf", id++, 128, LIVING_UPDATE_INTERVAL, true); - registerEntity(EntityIceShard.class, "ice_shard", id++, 128, PROJECTILE_UPDATE_INTERVAL, true); - registerEntity(EntityBlazeMinion.class, "blaze_minion", id++, 128, LIVING_UPDATE_INTERVAL, true); - registerEntity(EntityIceWraith.class, "ice_wraith", id++, 128, LIVING_UPDATE_INTERVAL, true); - registerEntity(EntityLightningWraith.class, "lightning_wraith", id++, 128, LIVING_UPDATE_INTERVAL, true); - registerEntity(EntityBlackHole.class, "black_hole", id++, 128, PROJECTILE_UPDATE_INTERVAL, false); - registerEntity(EntityShield.class, "shield", id++, 128, 1, true); - registerEntity(EntityMeteor.class, "meteor", id++, 128, 5, true); - registerEntity(EntityBlizzard.class, "blizzard", id++, 128, PROJECTILE_UPDATE_INTERVAL, false); - registerEntityAndEgg(EntityWizard.class, "wizard", id++, 128, LIVING_UPDATE_INTERVAL, true, 0x19295e, 0xee9312); - registerEntity(EntityBubble.class, "bubble", id++, 128, 3, false); - registerEntity(EntityTornado.class, "tornado", id++, 128, 1, false); - registerEntity(EntityHammer.class, "lightning_hammer", id++, 128, 1, true); - registerEntity(EntityFirebomb.class, "firebomb", id++, 128, PROJECTILE_UPDATE_INTERVAL, true); - registerEntity(EntityForceOrb.class, "force_orb", id++, 128, PROJECTILE_UPDATE_INTERVAL, true); - registerEntity(EntityArrowRain.class, "arrow_rain", id++, 128, PROJECTILE_UPDATE_INTERVAL, false); - registerEntity(EntitySpark.class, "spark", id++, 128, PROJECTILE_UPDATE_INTERVAL, true); - registerEntity(EntityShadowWraith.class, "shadow_wraith", id++, 128, PROJECTILE_UPDATE_INTERVAL, true); - registerEntity(EntityDarknessOrb.class, "darkness_orb", id++, 128, PROJECTILE_UPDATE_INTERVAL, true); - registerEntity(EntitySpiderMinion.class, "spider_minion", id++, 128, LIVING_UPDATE_INTERVAL, true); - registerEntity(EntityHealAura.class, "healing_aura", id++, 128, PROJECTILE_UPDATE_INTERVAL, false); - registerEntity(EntityFireSigil.class, "fire_sigil", id++, 128, PROJECTILE_UPDATE_INTERVAL, false); - registerEntity(EntityFrostSigil.class, "frost_sigil", id++, 128, PROJECTILE_UPDATE_INTERVAL, false); - registerEntity(EntityLightningSigil.class, "lightning_sigil", id++, 128, PROJECTILE_UPDATE_INTERVAL, false); - registerEntity(EntityLightningArrow.class, "lightning_arrow", id++, 128, PROJECTILE_UPDATE_INTERVAL, true); - registerEntity(EntityFirebolt.class, "firebolt", id++, 128, PROJECTILE_UPDATE_INTERVAL, true); - registerEntity(EntityPoisonBomb.class, "poison_bomb", id++, 128, PROJECTILE_UPDATE_INTERVAL, true); - registerEntity(EntityIceCharge.class, "ice_charge", id++, 128, PROJECTILE_UPDATE_INTERVAL, true); - registerEntity(EntityForceArrow.class, "force_arrow", id++, 128, PROJECTILE_UPDATE_INTERVAL, true); - registerEntity(EntityDart.class, "dart", id++, 128, PROJECTILE_UPDATE_INTERVAL, true); - registerEntity(EntityMagicSlime.class, "magic_slime", id++, 128, LIVING_UPDATE_INTERVAL, true); - registerEntity(EntityForcefield.class, "forcefield", id++, 128, PROJECTILE_UPDATE_INTERVAL, false); - registerEntity(EntityFireRing.class, "ring_of_fire", id++, 128, PROJECTILE_UPDATE_INTERVAL, false); - registerEntity(EntityLightningDisc.class, "lightning_disc", id++, 128, PROJECTILE_UPDATE_INTERVAL, true); - registerEntity(EntityThunderbolt.class, "thunderbolt", id++, 128, PROJECTILE_UPDATE_INTERVAL, true); - registerEntity(EntityIceGiant.class, "ice_giant", id++, 128, LIVING_UPDATE_INTERVAL, true); - registerEntity(EntitySpiritHorse.class, "spirit_horse", id++, 128, LIVING_UPDATE_INTERVAL, true); - registerEntity(EntityPhoenix.class, "phoenix", id++, 128, LIVING_UPDATE_INTERVAL, true); - registerEntity(EntitySilverfishMinion.class, "silverfish_minion", id++, 128, LIVING_UPDATE_INTERVAL, true); - registerEntity(EntityDecay.class, "decay", id++, 128, PROJECTILE_UPDATE_INTERVAL, false); - registerEntity(EntityStormElemental.class, "storm_elemental", id++, 128, PROJECTILE_UPDATE_INTERVAL, true); - registerEntity(EntityEarthquake.class, "earthquake", id++, 128, PROJECTILE_UPDATE_INTERVAL, false); - registerEntity(EntityIceLance.class, "ice_lance", id++, 128, PROJECTILE_UPDATE_INTERVAL, true); - registerEntity(EntityHailstorm.class, "hailstorm", id++, 128, PROJECTILE_UPDATE_INTERVAL, false); - registerEntity(EntitySmokeBomb.class, "smoke_bomb", id++, 128, PROJECTILE_UPDATE_INTERVAL, true); - registerEntityAndEgg(EntityEvilWizard.class, "evil_wizard", id++, 128, LIVING_UPDATE_INTERVAL, true, 0x290404, 0xee9312); - registerEntity(EntityDecoy.class, "decoy", id++, 128, LIVING_UPDATE_INTERVAL, true); - registerEntity(EntityIceSpike.class, "ice_spike", id++, 128, 1, true); - // TODO: This should be a particle. - registerEntity(EntityLightningPulse.class, "lightning_pulse", id++, 128, PROJECTILE_UPDATE_INTERVAL, false); - registerEntity(EntityWitherSkeletonMinion.class, "wither_skeleton_minion", id++, 128, LIVING_UPDATE_INTERVAL, true); - - // TODO: May need fixing - List biomes = Lists.newArrayList(); - for (Biome biome : ForgeRegistries.BIOMES.getValuesCollection()) { - biomes.add(biome); - } - biomes.remove(Biomes.MUSHROOM_ISLAND); - biomes.remove(Biomes.MUSHROOM_ISLAND_SHORE); - // For reference: 5, 1, 1 are the parameters for the witch in vanilla. - EntityRegistry.addSpawn(EntityEvilWizard.class, 3, 1, 1, EnumCreatureType.MONSTER, biomes.toArray(new Biome[biomes.size()])); - - } - - /** Private helper method for registering entities; keeps things neater. For some reason, Forge 1.11.2 wants a - * ResourceLocation and a string name... probably because it's transitioning to the registry system. */ - private static void registerEntity(Class entityClass, String name, int id, int trackingRange, int updateFrequency, boolean sendsVelocityUpdates){ - ResourceLocation registryName = new ResourceLocation(Wizardry.MODID, name); - EntityRegistry.registerModEntity(registryName, entityClass, registryName.toString(), id, Wizardry.instance, trackingRange, updateFrequency, sendsVelocityUpdates); - } - - /** Private helper method for registering entities with eggs; keeps things neater. For some reason, Forge 1.11.2 - * wants a ResourceLocation and a string name... probably because it's transitioning to the registry system. */ - private static void registerEntityAndEgg(Class entityClass, String name, int id, int trackingRange, int updateFrequency, boolean sendsVelocityUpdates, int eggColour, int spotColour){ - ResourceLocation registryName = new ResourceLocation(Wizardry.MODID, name); - EntityRegistry.registerModEntity(registryName, entityClass, registryName.toString(), id, Wizardry.instance, trackingRange, updateFrequency, sendsVelocityUpdates); - EntityRegistry.registerEgg(registryName, eggColour, spotColour); - } - - /** Now only deals with the dynamic crafting recipes and the smelting recipes. */ - @SubscribeEvent - public static void registerRecipes(RegistryEvent.Register event){ - - IForgeRegistry registry = event.getRegistry(); - - FurnaceRecipes.instance().addSmeltingRecipeForBlock(WizardryBlocks.crystal_ore, new ItemStack(WizardryItems.magic_crystal), 0.5f); - - // Mana flask recipes - - ItemStack manaFlaskStack = new ItemStack(WizardryItems.mana_flask); - - ItemStack miscWandStack; - - for(Element element : Element.values()){ - for(Tier tier : Tier.values()){ - miscWandStack = new ItemStack(WizardryUtilities.getWand(tier, element), 1, OreDictionary.WILDCARD_VALUE); - registry.register(new ShapelessOreRecipe(null, miscWandStack, miscWandStack, manaFlaskStack){ - @Override public boolean isDynamic(){ return true; } // Stops it appearing in the recipe book - }.setRegistryName(new ResourceLocation(Wizardry.MODID, "recipes/flask_wand_" + element.getUnlocalisedName() + "_" + tier.getUnlocalisedName()))); - } - } - - ItemStack miscArmourStack; - - for(Element element : Element.values()){ - for(EntityEquipmentSlot slot : WizardryUtilities.ARMOUR_SLOTS){ - miscArmourStack = new ItemStack(WizardryUtilities.getArmour(element, slot), 1, OreDictionary.WILDCARD_VALUE); - registry.register(new ShapelessOreRecipe(null, miscArmourStack, miscArmourStack, manaFlaskStack){ - @Override public boolean isDynamic(){ return true; } // Stops it appearing in the recipe book - }.setRegistryName(new ResourceLocation(Wizardry.MODID, "recipes/flask_armour_" + element.getUnlocalisedName() + "_" + slot.getName()))); - } - } - } - -} diff --git a/src/main/java/electroblob/wizardry/registry/WizardrySounds.java b/src/main/java/electroblob/wizardry/registry/WizardrySounds.java index e472c4c5..97f9f25e 100644 --- a/src/main/java/electroblob/wizardry/registry/WizardrySounds.java +++ b/src/main/java/electroblob/wizardry/registry/WizardrySounds.java @@ -1,7 +1,10 @@ package electroblob.wizardry.registry; import electroblob.wizardry.Wizardry; +import electroblob.wizardry.misc.Forfeit; +import electroblob.wizardry.spell.Spell; import net.minecraft.util.ResourceLocation; +import net.minecraft.util.SoundCategory; import net.minecraft.util.SoundEvent; import net.minecraftforge.event.RegistryEvent; import net.minecraftforge.fml.common.Mod; @@ -16,27 +19,118 @@ import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; @Mod.EventBusSubscriber public final class WizardrySounds { - // Anything with LOOP in its name is intended to be played in a continuous loop. - public static final SoundEvent SPELL_SPARK = createSound("arc"); - public static final SoundEvent SPELL_CONJURATION = createSound("aura"); - public static final SoundEvent SPELL_SHOCKWAVE = createSound("boom"); - public static final SoundEvent SPELL_LOOP_CRACKLE = createSound("crackle"); - public static final SoundEvent SPELL_SUMMONING = createSound("darkaura"); - public static final SoundEvent SPELL_DEFLECTION = createSound("effect"); - public static final SoundEvent SPELL_LIGHTNING = createSound("electricitya"); - public static final SoundEvent SPELL_LOOP_LIGHTNING = createSound("electricityb"); - public static final SoundEvent SPELL_LOOP_FIRE = createSound("flameray"); - public static final SoundEvent SPELL_FREEZE = createSound("freeze"); - public static final SoundEvent SPELL_LOOP_ICE = createSound("frostray"); - public static final SoundEvent SPELL_HEAL = createSound("heal"); - public static final SoundEvent SPELL_ICE = createSound("ice"); - public static final SoundEvent SPELL_CONJURATION_LARGE = createSound("largeaura"); - public static final SoundEvent SPELL_MAGIC = createSound("magic"); - public static final SoundEvent SPELL_LOOP_SPARKLE = createSound("sparkle"); - public static final SoundEvent SPELL_LOOP_WIND = createSound("wind"); - public static final SoundEvent SPELL_EARTHQUAKE = createSound("rumble"); - public static final SoundEvent SPELL_FORCE = createSound("force"); - public static final SoundEvent SELECT_SPELL = createSound("select"); + private WizardrySounds(){} // No instances! + + /** Sound category for all spell-related sounds. This includes inanimate magical entities, but not minions. + * @see electroblob.wizardry.util.CustomSoundCategory */ + public static SoundCategory SPELLS; + + public static final SoundEvent BLOCK_ARCANE_WORKBENCH_SPELLBIND = createSound("block.arcane_workbench.bind_spell"); + public static final SoundEvent BLOCK_PEDESTAL_ACTIVATE = createSound("block.pedestal.activate"); + public static final SoundEvent BLOCK_PEDESTAL_CONQUER = createSound("block.pedestal.conquer"); + + public static final SoundEvent ITEM_WAND_SWITCH_SPELL = createSound("item.wand.switch_spell"); + public static final SoundEvent ITEM_WAND_LEVELUP = createSound("item.wand.levelup"); + public static final SoundEvent ITEM_WAND_MELEE = createSound("item.wand.melee"); + public static final SoundEvent ITEM_ARMOUR_EQUIP_SILK = createSound("item.armour.equip_silk"); + public static final SoundEvent ITEM_PURIFYING_ELIXIR_DRINK = createSound("item.purifying_elixir.drink"); + + public static final SoundEvent ENTITY_BLACK_HOLE_AMBIENT = createSound("entity.black_hole.ambient"); + public static final SoundEvent ENTITY_BLACK_HOLE_VANISH = createSound("entity.black_hole.vanish"); + public static final SoundEvent ENTITY_BUBBLE_POP = createSound("entity.bubble.pop"); + public static final SoundEvent ENTITY_BLIZZARD_AMBIENT = createSound("entity.blizzard.ambient"); + public static final SoundEvent ENTITY_DECAY_AMBIENT = createSound("entity.decay.ambient"); + public static final SoundEvent ENTITY_ENTRAPMENT_AMBIENT = createSound("entity.entrapment.ambient"); + public static final SoundEvent ENTITY_ENTRAPMENT_VANISH = createSound("entity.entrapment.vanish"); + public static final SoundEvent ENTITY_FIRE_RING_AMBIENT = createSound("entity.fire_ring.ambient"); + public static final SoundEvent ENTITY_FIRE_SIGIL_TRIGGER = createSound("entity.fire_sigil.trigger"); + public static final SoundEvent ENTITY_FORCEFIELD_DEFLECT = createSound("entity.forcefield.deflect"); + public static final SoundEvent ENTITY_FROST_SIGIL_TRIGGER = createSound("entity.frost_sigil.trigger"); + public static final SoundEvent ENTITY_HAMMER_ATTACK = createSound("entity.hammer.attack"); + public static final SoundEvent ENTITY_HAMMER_EXPLODE = createSound("entity.hammer.explode"); + public static final SoundEvent ENTITY_HAMMER_THROW = createSound("entity.hammer.throw"); + public static final SoundEvent ENTITY_HAMMER_LAND = createSound("entity.hammer.land"); + public static final SoundEvent ENTITY_HEAL_AURA_AMBIENT = createSound("entity.heal_aura.ambient"); + public static final SoundEvent ENTITY_ICE_SPIKE_EXTEND = createSound("entity.ice_spike.extend"); + public static final SoundEvent ENTITY_LIGHTNING_SIGIL_TRIGGER = createSound("entity.lightning_sigil.trigger"); + public static final SoundEvent ENTITY_METEOR_FALLING = createSound("entity.meteor.falling"); + public static final SoundEvent ENTITY_SHIELD_DEFLECT = createSound("entity.shield.deflect"); + public static final SoundEvent ENTITY_TORNADO_AMBIENT = createSound("entity.tornado.ambient"); + + public static final SoundEvent ENTITY_EVIL_WIZARD_AMBIENT = createSound("entity.evil_wizard.ambient"); + public static final SoundEvent ENTITY_EVIL_WIZARD_HURT = createSound("entity.evil_wizard.hurt"); + public static final SoundEvent ENTITY_EVIL_WIZARD_DEATH = createSound("entity.evil_wizard.death"); + public static final SoundEvent ENTITY_ICE_GIANT_ATTACK = createSound("entity.ice_giant.attack"); + public static final SoundEvent ENTITY_ICE_GIANT_DESPAWN = createSound("entity.ice_giant.despawn"); + public static final SoundEvent ENTITY_ICE_WRAITH_AMBIENT = createSound("entity.ice_wraith.ambient"); + public static final SoundEvent ENTITY_MAGIC_SLIME_ATTACK = createSound("entity.magic_slime.attack"); + public static final SoundEvent ENTITY_MAGIC_SLIME_EXPLODE = createSound("entity.magic_slime.explode"); + public static final SoundEvent ENTITY_MAGIC_SLIME_SPLAT = createSound("entity.magic_slime.splat"); + public static final SoundEvent ENTITY_PHOENIX_AMBIENT = createSound("entity.phoenix.ambient"); + public static final SoundEvent ENTITY_PHOENIX_BURN = createSound("entity.phoenix.burn"); + public static final SoundEvent ENTITY_PHOENIX_FLAP = createSound("entity.phoenix.flap"); + public static final SoundEvent ENTITY_PHOENIX_HURT = createSound("entity.phoenix.hurt"); + public static final SoundEvent ENTITY_PHOENIX_DEATH = createSound("entity.phoenix.death"); + public static final SoundEvent ENTITY_SHADOW_WRAITH_AMBIENT = createSound("entity.shadow_wraith.ambient"); + public static final SoundEvent ENTITY_SHADOW_WRAITH_NOISE = createSound("entity.shadow_wraith.noise"); + public static final SoundEvent ENTITY_SHADOW_WRAITH_HURT = createSound("entity.shadow_wraith.hurt"); + public static final SoundEvent ENTITY_SHADOW_WRAITH_DEATH = createSound("entity.shadow_wraith.death"); + public static final SoundEvent ENTITY_SPIRIT_HORSE_VANISH = createSound("entity.spirit_horse.vanish"); + public static final SoundEvent ENTITY_SPIRIT_WOLF_VANISH = createSound("entity.spirit_wolf.vanish"); + public static final SoundEvent ENTITY_STORM_ELEMENTAL_AMBIENT = createSound("entity.storm_elemental.ambient"); + public static final SoundEvent ENTITY_STORM_ELEMENTAL_BURN = createSound("entity.storm_elemental.burn"); + public static final SoundEvent ENTITY_STORM_ELEMENTAL_WIND = createSound("entity.storm_elemental.wind"); + public static final SoundEvent ENTITY_STORM_ELEMENTAL_HURT = createSound("entity.storm_elemental.hurt"); + public static final SoundEvent ENTITY_STORM_ELEMENTAL_DEATH = createSound("entity.storm_elemental.death"); + public static final SoundEvent ENTITY_WIZARD_YES = createSound("entity.wizard.yes"); + public static final SoundEvent ENTITY_WIZARD_NO = createSound("entity.wizard.no"); + public static final SoundEvent ENTITY_WIZARD_AMBIENT = createSound("entity.wizard.ambient"); + public static final SoundEvent ENTITY_WIZARD_TRADING = createSound("entity.wizard.trading"); + public static final SoundEvent ENTITY_WIZARD_HURT = createSound("entity.wizard.hurt"); + public static final SoundEvent ENTITY_WIZARD_DEATH = createSound("entity.wizard.death"); + + public static final SoundEvent ENTITY_DARKNESS_ORB_HIT = createSound("entity.darkness_orb.hit"); + public static final SoundEvent ENTITY_DART_HIT = createSound("entity.dart.hit"); + public static final SoundEvent ENTITY_DART_HIT_BLOCK = createSound("entity.dart.hit_block"); + public static final SoundEvent ENTITY_FIREBOLT_HIT = createSound("entity.firebolt.hit"); + public static final SoundEvent ENTITY_FIREBOMB_THROW = createSound("entity.firebomb.throw"); + public static final SoundEvent ENTITY_FIREBOMB_SMASH = createSound("entity.firebomb.smash"); + public static final SoundEvent ENTITY_FIREBOMB_FIRE = createSound("entity.firebomb.fire"); + public static final SoundEvent ENTITY_FORCE_ARROW_HIT = createSound("entity.force_arrow.hit"); + public static final SoundEvent ENTITY_FORCE_ORB_HIT = createSound("entity.force_orb.hit"); + public static final SoundEvent ENTITY_FORCE_ORB_HIT_BLOCK = createSound("entity.force_orb.hit_block"); + public static final SoundEvent ENTITY_ICEBALL_HIT = createSound("entity.iceball.hit"); + public static final SoundEvent ENTITY_ICE_CHARGE_SMASH = createSound("entity.ice_charge.smash"); + public static final SoundEvent ENTITY_ICE_CHARGE_ICE = createSound("entity.ice_charge.ice"); + public static final SoundEvent ENTITY_ICE_LANCE_SMASH = createSound("entity.ice_lance.smash"); + public static final SoundEvent ENTITY_ICE_LANCE_HIT = createSound("entity.ice_lance.hit"); + public static final SoundEvent ENTITY_ICE_SHARD_SMASH = createSound("entity.ice_shard.smash"); + public static final SoundEvent ENTITY_ICE_SHARD_HIT = createSound("entity.ice_shard.hit"); + public static final SoundEvent ENTITY_LIGHTNING_ARROW_HIT = createSound("entity.lightning_arrow.hit"); + public static final SoundEvent ENTITY_LIGHTNING_DISC_HIT = createSound("entity.lightning_disc.hit"); +// public static final SoundEvent ENTITY_MAGIC_FIREBALL_HIT = createSound("entity.magic_fireball.hit"); + public static final SoundEvent ENTITY_MAGIC_MISSILE_HIT = createSound("entity.magic_missile.hit"); + public static final SoundEvent ENTITY_POISON_BOMB_THROW = createSound("entity.poison_bomb.throw"); + public static final SoundEvent ENTITY_POISON_BOMB_SMASH = createSound("entity.poison_bomb.smash"); + public static final SoundEvent ENTITY_POISON_BOMB_POISON = createSound("entity.poison_bomb.poison"); + public static final SoundEvent ENTITY_SMOKE_BOMB_THROW = createSound("entity.smoke_bomb.throw"); + public static final SoundEvent ENTITY_SMOKE_BOMB_SMASH = createSound("entity.smoke_bomb.smash"); + public static final SoundEvent ENTITY_SMOKE_BOMB_SMOKE = createSound("entity.smoke_bomb.smoke"); + public static final SoundEvent ENTITY_HOMING_SPARK_HIT = createSound("entity.homing_spark.hit"); + public static final SoundEvent ENTITY_SPARK_BOMB_THROW = createSound("entity.spark_bomb.throw"); + public static final SoundEvent ENTITY_SPARK_BOMB_HIT = createSound("entity.spark_bomb.hit"); + public static final SoundEvent ENTITY_SPARK_BOMB_HIT_BLOCK = createSound("entity.spark_bomb.hit_block"); + public static final SoundEvent ENTITY_SPARK_BOMB_CHAIN = createSound("entity.spark_bomb.chain"); + public static final SoundEvent ENTITY_THUNDERBOLT_HIT = createSound("entity.thunderbolt.hit"); + + public static final SoundEvent SPELL_STATIC_AURA_RETALIATE = createSound("spell.static_aura.retaliate"); + public static final SoundEvent SPELL_CURSE_OF_SOULBINDING_RETALIATE = createSound("spell.curse_of_soulbinding.retaliate"); + public static final SoundEvent SPELL_TRANSPORTATION_TRAVEL = createSound("spell.transportation.travel"); + + public static final SoundEvent MISC_DISCOVER_SPELL = createSound("misc.discover_spell"); + public static final SoundEvent MISC_BOOK_OPEN = createSound("misc.book_open"); + public static final SoundEvent MISC_PAGE_TURN = createSound("misc.page_turn"); + public static final SoundEvent MISC_FREEZE = createSound("misc.freeze"); /** Trick borrowed from the Twilight Forest, makes things neater. */ public static SoundEvent createSound(String name){ @@ -44,27 +138,124 @@ public final class WizardrySounds { return new SoundEvent(new ResourceLocation(Wizardry.MODID, name)).setRegistryName(name); } + // For some reason, sound events seem to work even when they aren't registered, without even so much as a warning. + @SubscribeEvent public static void register(RegistryEvent.Register event){ - event.getRegistry().register(SPELL_SPARK); - event.getRegistry().register(SPELL_CONJURATION); - event.getRegistry().register(SPELL_SHOCKWAVE); - event.getRegistry().register(SPELL_LOOP_CRACKLE); - event.getRegistry().register(SPELL_SUMMONING); - event.getRegistry().register(SPELL_DEFLECTION); - event.getRegistry().register(SPELL_LIGHTNING); - event.getRegistry().register(SPELL_LOOP_LIGHTNING); - event.getRegistry().register(SPELL_LOOP_FIRE); - event.getRegistry().register(SPELL_FREEZE); - event.getRegistry().register(SPELL_LOOP_ICE); - event.getRegistry().register(SPELL_HEAL); - event.getRegistry().register(SPELL_ICE); - event.getRegistry().register(SPELL_CONJURATION_LARGE); - event.getRegistry().register(SPELL_MAGIC); - event.getRegistry().register(SPELL_LOOP_SPARKLE); - event.getRegistry().register(SPELL_LOOP_WIND); - event.getRegistry().register(SPELL_EARTHQUAKE); - event.getRegistry().register(SPELL_FORCE); - event.getRegistry().register(SELECT_SPELL); + + event.getRegistry().register(BLOCK_ARCANE_WORKBENCH_SPELLBIND); + event.getRegistry().register(BLOCK_PEDESTAL_ACTIVATE); + event.getRegistry().register(BLOCK_PEDESTAL_CONQUER); + + event.getRegistry().register(ITEM_WAND_SWITCH_SPELL); + event.getRegistry().register(ITEM_WAND_LEVELUP); + event.getRegistry().register(ITEM_WAND_MELEE); + event.getRegistry().register(ITEM_ARMOUR_EQUIP_SILK); + event.getRegistry().register(ITEM_PURIFYING_ELIXIR_DRINK); + + event.getRegistry().register(ENTITY_BLACK_HOLE_AMBIENT); + event.getRegistry().register(ENTITY_BLACK_HOLE_VANISH); + event.getRegistry().register(ENTITY_BUBBLE_POP); + event.getRegistry().register(ENTITY_BLIZZARD_AMBIENT); + event.getRegistry().register(ENTITY_DECAY_AMBIENT); + event.getRegistry().register(ENTITY_ENTRAPMENT_AMBIENT); + event.getRegistry().register(ENTITY_ENTRAPMENT_VANISH); + event.getRegistry().register(ENTITY_FIRE_RING_AMBIENT); + event.getRegistry().register(ENTITY_FIRE_SIGIL_TRIGGER); + event.getRegistry().register(ENTITY_FORCEFIELD_DEFLECT); + event.getRegistry().register(ENTITY_FROST_SIGIL_TRIGGER); + event.getRegistry().register(ENTITY_HAMMER_ATTACK); + event.getRegistry().register(ENTITY_HAMMER_EXPLODE); + event.getRegistry().register(ENTITY_HAMMER_THROW); + event.getRegistry().register(ENTITY_HAMMER_LAND); + event.getRegistry().register(ENTITY_HEAL_AURA_AMBIENT); + event.getRegistry().register(ENTITY_ICE_SPIKE_EXTEND); + event.getRegistry().register(ENTITY_LIGHTNING_SIGIL_TRIGGER); + event.getRegistry().register(ENTITY_METEOR_FALLING); + event.getRegistry().register(ENTITY_SHIELD_DEFLECT); + event.getRegistry().register(ENTITY_TORNADO_AMBIENT); + + event.getRegistry().register(ENTITY_EVIL_WIZARD_AMBIENT); + event.getRegistry().register(ENTITY_EVIL_WIZARD_HURT); + event.getRegistry().register(ENTITY_EVIL_WIZARD_DEATH); + event.getRegistry().register(ENTITY_ICE_GIANT_ATTACK); + event.getRegistry().register(ENTITY_ICE_GIANT_DESPAWN); + event.getRegistry().register(ENTITY_ICE_WRAITH_AMBIENT); + event.getRegistry().register(ENTITY_MAGIC_SLIME_ATTACK); + event.getRegistry().register(ENTITY_MAGIC_SLIME_EXPLODE); + event.getRegistry().register(ENTITY_MAGIC_SLIME_SPLAT); + event.getRegistry().register(ENTITY_PHOENIX_AMBIENT); + event.getRegistry().register(ENTITY_PHOENIX_BURN); + event.getRegistry().register(ENTITY_PHOENIX_FLAP); + event.getRegistry().register(ENTITY_PHOENIX_HURT); + event.getRegistry().register(ENTITY_PHOENIX_DEATH); + event.getRegistry().register(ENTITY_SHADOW_WRAITH_AMBIENT); + event.getRegistry().register(ENTITY_SHADOW_WRAITH_NOISE); + event.getRegistry().register(ENTITY_SHADOW_WRAITH_HURT); + event.getRegistry().register(ENTITY_SHADOW_WRAITH_DEATH); + event.getRegistry().register(ENTITY_SPIRIT_HORSE_VANISH); + event.getRegistry().register(ENTITY_SPIRIT_WOLF_VANISH); + event.getRegistry().register(ENTITY_STORM_ELEMENTAL_AMBIENT); + event.getRegistry().register(ENTITY_STORM_ELEMENTAL_BURN); + event.getRegistry().register(ENTITY_STORM_ELEMENTAL_WIND); + event.getRegistry().register(ENTITY_STORM_ELEMENTAL_HURT); + event.getRegistry().register(ENTITY_STORM_ELEMENTAL_DEATH); + event.getRegistry().register(ENTITY_WIZARD_YES); + event.getRegistry().register(ENTITY_WIZARD_NO); + event.getRegistry().register(ENTITY_WIZARD_AMBIENT); + event.getRegistry().register(ENTITY_WIZARD_TRADING); + event.getRegistry().register(ENTITY_WIZARD_HURT); + event.getRegistry().register(ENTITY_WIZARD_DEATH); + + event.getRegistry().register(ENTITY_DARKNESS_ORB_HIT); + event.getRegistry().register(ENTITY_DART_HIT); + event.getRegistry().register(ENTITY_DART_HIT_BLOCK); + event.getRegistry().register(ENTITY_FIREBOLT_HIT); + event.getRegistry().register(ENTITY_FIREBOMB_THROW); + event.getRegistry().register(ENTITY_FIREBOMB_SMASH); + event.getRegistry().register(ENTITY_FIREBOMB_FIRE); + event.getRegistry().register(ENTITY_FORCE_ARROW_HIT); + event.getRegistry().register(ENTITY_FORCE_ORB_HIT); + event.getRegistry().register(ENTITY_FORCE_ORB_HIT_BLOCK); + event.getRegistry().register(ENTITY_ICEBALL_HIT); + event.getRegistry().register(ENTITY_ICE_CHARGE_SMASH); + event.getRegistry().register(ENTITY_ICE_CHARGE_ICE); + event.getRegistry().register(ENTITY_ICE_LANCE_SMASH); + event.getRegistry().register(ENTITY_ICE_LANCE_HIT); + event.getRegistry().register(ENTITY_ICE_SHARD_SMASH); + event.getRegistry().register(ENTITY_ICE_SHARD_HIT); + event.getRegistry().register(ENTITY_LIGHTNING_ARROW_HIT); + event.getRegistry().register(ENTITY_LIGHTNING_DISC_HIT); +// event.getRegistry().register(ENTITY_MAGIC_FIREBALL_HIT); + event.getRegistry().register(ENTITY_MAGIC_MISSILE_HIT); + event.getRegistry().register(ENTITY_POISON_BOMB_THROW); + event.getRegistry().register(ENTITY_POISON_BOMB_SMASH); + event.getRegistry().register(ENTITY_POISON_BOMB_POISON); + event.getRegistry().register(ENTITY_SMOKE_BOMB_THROW); + event.getRegistry().register(ENTITY_SMOKE_BOMB_SMASH); + event.getRegistry().register(ENTITY_SMOKE_BOMB_SMOKE); + event.getRegistry().register(ENTITY_HOMING_SPARK_HIT); + event.getRegistry().register(ENTITY_SPARK_BOMB_THROW); + event.getRegistry().register(ENTITY_SPARK_BOMB_HIT); + event.getRegistry().register(ENTITY_SPARK_BOMB_HIT_BLOCK); + event.getRegistry().register(ENTITY_SPARK_BOMB_CHAIN); + event.getRegistry().register(ENTITY_THUNDERBOLT_HIT); + + event.getRegistry().register(SPELL_STATIC_AURA_RETALIATE); + event.getRegistry().register(SPELL_CURSE_OF_SOULBINDING_RETALIATE); + event.getRegistry().register(SPELL_TRANSPORTATION_TRAVEL); + + event.getRegistry().register(MISC_DISCOVER_SPELL); + event.getRegistry().register(MISC_BOOK_OPEN); + event.getRegistry().register(MISC_PAGE_TURN); + event.getRegistry().register(MISC_FREEZE); + + for(Spell spell : Spell.getSpells(Spell.allSpells)){ + event.getRegistry().registerAll(spell.getSounds()); + } + + for(Forfeit forfeit : Forfeit.getForfeits()){ + event.getRegistry().register(forfeit.getSound()); + } } } \ No newline at end of file diff --git a/src/main/java/electroblob/wizardry/registry/WizardryTabs.java b/src/main/java/electroblob/wizardry/registry/WizardryTabs.java index 6858715f..3e830707 100644 --- a/src/main/java/electroblob/wizardry/registry/WizardryTabs.java +++ b/src/main/java/electroblob/wizardry/registry/WizardryTabs.java @@ -1,10 +1,5 @@ package electroblob.wizardry.registry; -import java.util.Arrays; -import java.util.Collections; -import java.util.Comparator; -import java.util.List; - import electroblob.wizardry.item.ItemScroll; import electroblob.wizardry.item.ItemSpellBook; import electroblob.wizardry.spell.Spell; @@ -15,6 +10,10 @@ import net.minecraft.util.NonNullList; import net.minecraftforge.fml.relauncher.Side; import net.minecraftforge.fml.relauncher.SideOnly; +import java.util.ArrayList; +import java.util.Comparator; +import java.util.List; + /** * Class responsible for defining and storing all of wizardry's creative tabs. Also handles sorting of the items. * @@ -23,111 +22,100 @@ import net.minecraftforge.fml.relauncher.SideOnly; */ public final class WizardryTabs { - private static Comparator itemSorter; - private static Comparator spellItemSorter; + private WizardryTabs(){} // No instances! - // Creative Tabs - public static final CreativeTabs WIZARDRY = new CreativeTabs("ebwizardry"){ + public static final CreativeTabs WIZARDRY = new CreativeTabListed("ebwizardry"); + public static final CreativeTabs GEAR = new CreativeTabListed("ebwizardrygear"); + public static final CreativeTabs SPELLS = new CreativeTabSorted("ebwizardryspells", + + (stack1, stack2) -> { - @Override - @SideOnly(Side.CLIENT) - public ItemStack createIcon(){ - return new ItemStack(WizardryItems.wizard_handbook); - } + if((stack1.getItem() instanceof ItemSpellBook && stack2.getItem() instanceof ItemSpellBook) + || (stack1.getItem() instanceof ItemScroll && stack2.getItem() instanceof ItemScroll)){ - @Override - @SideOnly(Side.CLIENT) - public void displayAllRelevantItems(NonNullList items){ - super.displayAllRelevantItems(items); - Collections.sort(items, itemSorter); - } - }; + Spell spell1 = Spell.byMetadata(stack1.getItemDamage()); + Spell spell2 = Spell.byMetadata(stack2.getItemDamage()); + + return spell1.compareTo(spell2); + + }else if(stack1.getItem() instanceof ItemScroll){ + return 1; + }else if(stack2.getItem() instanceof ItemScroll){ + return -1; + } + return 0; + }, + + true); - public static final CreativeTabs SPELLS = new CreativeTabs("ebwizardryspells"){ + public static class CreativeTabSorted extends CreativeTabs { + + private ItemStack iconItem; + private final Comparator sorter; + private final boolean searchable; + + public CreativeTabSorted(String label, Comparator sorter){ + this(label, sorter, false); + } + + public CreativeTabSorted(String label, Comparator sorter, boolean searchable){ + super(label); + this.sorter = sorter; + this.searchable = searchable; + } @Override @SideOnly(Side.CLIENT) public ItemStack createIcon(){ - return new ItemStack(WizardryItems.spell_book); + return iconItem; + } + + public void setIconItem(ItemStack iconItem){ + this.iconItem = iconItem; } @Override @SideOnly(Side.CLIENT) public void displayAllRelevantItems(NonNullList items){ super.displayAllRelevantItems(items); - Collections.sort(items, spellItemSorter); + items.sort(sorter); } @Override public boolean hasSearchBar(){ - return true; + return searchable; } @Override @SideOnly(Side.CLIENT) public String getBackgroundImageName(){ - return "item_search.png"; + return searchable ? "item_search.png" : super.getBackgroundImageName(); } - }; + } + + public static class CreativeTabListed extends CreativeTabSorted { - /** Initialises the item sorters for the creative tabs. */ - public static void sort(){ + public final List order; - List orderedItemList = Arrays.asList( - - Item.getItemFromBlock(WizardryBlocks.arcane_workbench), - Item.getItemFromBlock(WizardryBlocks.crystal_ore), Item.getItemFromBlock(WizardryBlocks.crystal_block), - Item.getItemFromBlock(WizardryBlocks.crystal_flower), - Item.getItemFromBlock(WizardryBlocks.transportation_stone), WizardryItems.magic_crystal, - WizardryItems.magic_wand, WizardryItems.apprentice_wand, WizardryItems.advanced_wand, - WizardryItems.master_wand, WizardryItems.arcane_tome, WizardryItems.wizard_handbook, - WizardryItems.basic_fire_wand, WizardryItems.basic_ice_wand, WizardryItems.basic_lightning_wand, - WizardryItems.basic_necromancy_wand, WizardryItems.basic_earth_wand, WizardryItems.basic_sorcery_wand, - WizardryItems.basic_healing_wand, WizardryItems.smoke_bomb, WizardryItems.firebomb, - WizardryItems.poison_bomb, WizardryItems.blank_scroll, WizardryItems.identification_scroll, - WizardryItems.mana_flask, WizardryItems.storage_upgrade, WizardryItems.siphon_upgrade, - WizardryItems.condenser_upgrade, WizardryItems.range_upgrade, WizardryItems.duration_upgrade, - WizardryItems.cooldown_upgrade, WizardryItems.blast_upgrade, WizardryItems.attunement_upgrade, - WizardryItems.magic_silk, WizardryItems.armour_upgrade, WizardryItems.wizard_hat, - WizardryItems.wizard_robe, WizardryItems.wizard_leggings, WizardryItems.wizard_boots, - WizardryItems.wizard_hat_fire, WizardryItems.wizard_robe_fire, WizardryItems.wizard_leggings_fire, - WizardryItems.wizard_boots_fire, WizardryItems.wizard_hat_ice, WizardryItems.wizard_robe_ice, - WizardryItems.wizard_leggings_ice, WizardryItems.wizard_boots_ice, WizardryItems.wizard_hat_lightning, - WizardryItems.wizard_robe_lightning, WizardryItems.wizard_leggings_lightning, - WizardryItems.wizard_boots_lightning, WizardryItems.wizard_hat_necromancy, - WizardryItems.wizard_robe_necromancy, WizardryItems.wizard_leggings_necromancy, - WizardryItems.wizard_boots_necromancy, WizardryItems.wizard_hat_earth, WizardryItems.wizard_robe_earth, - WizardryItems.wizard_leggings_earth, WizardryItems.wizard_boots_earth, WizardryItems.wizard_hat_sorcery, - WizardryItems.wizard_robe_sorcery, WizardryItems.wizard_leggings_sorcery, - WizardryItems.wizard_boots_sorcery, WizardryItems.wizard_hat_healing, WizardryItems.wizard_robe_healing, - WizardryItems.wizard_leggings_healing, WizardryItems.wizard_boots_healing); - - itemSorter = (stack1, stack2) -> { - // Neither stack is in the creative tab - if(!orderedItemList.contains(stack1.getItem()) && !orderedItemList.contains(stack2.getItem())) return 0; - if(!orderedItemList.contains(stack1.getItem())) return 1; // Only stack 2 is in the creative tab - if(!orderedItemList.contains(stack2.getItem())) return -1; // Only stack 1 is in the creative tab - // Both stacks are in the creative tab - return orderedItemList.indexOf(stack1.getItem()) - orderedItemList.indexOf(stack2.getItem()); - }; - - spellItemSorter = (stack1, stack2) -> { - - if((stack1.getItem() instanceof ItemSpellBook && stack2.getItem() instanceof ItemSpellBook) - || (stack1.getItem() instanceof ItemScroll && stack2.getItem() instanceof ItemScroll)){ - - Spell spell1 = Spell.get(stack1.getItemDamage()); - Spell spell2 = Spell.get(stack2.getItemDamage()); - - return spell1.compareTo(spell2); - - }else if(stack1.getItem() instanceof ItemScroll){ - return 1; - }else if(stack2.getItem() instanceof ItemScroll){ - return -1; - } - return 0; - }; + public CreativeTabListed(String label){ + // Can't accomplish this in a single constructor... just a quirk of the java compiler! + this(label, new ArrayList<>()); + } + + // Hey, maybe someone might want to keep a reference to the list, or pass in a different one. + public CreativeTabListed(String label, List order){ + + super(label, (stack1, stack2) -> { + // Neither stack is in the creative tab + if(!order.contains(stack1.getItem()) && !order.contains(stack2.getItem())) return 0; + if(!order.contains(stack1.getItem())) return 1; // Only stack 2 is in the creative tab + if(!order.contains(stack2.getItem())) return -1; // Only stack 1 is in the creative tab + // Both stacks are in the creative tab + return order.indexOf(stack1.getItem()) - order.indexOf(stack2.getItem()); + }); + + this.order = order; + } } } diff --git a/src/main/java/electroblob/wizardry/spell/Arc.java b/src/main/java/electroblob/wizardry/spell/Arc.java index 4da75483..adfe2670 100644 --- a/src/main/java/electroblob/wizardry/spell/Arc.java +++ b/src/main/java/electroblob/wizardry/spell/Arc.java @@ -1,32 +1,32 @@ package electroblob.wizardry.spell; -import electroblob.wizardry.constants.Element; -import electroblob.wizardry.constants.SpellType; -import electroblob.wizardry.constants.Tier; -import electroblob.wizardry.entity.EntityArc; -import electroblob.wizardry.registry.WizardrySounds; import electroblob.wizardry.util.MagicDamage; import electroblob.wizardry.util.MagicDamage.DamageType; import electroblob.wizardry.util.ParticleBuilder; +import electroblob.wizardry.util.ParticleBuilder.Type; import electroblob.wizardry.util.SpellModifiers; import electroblob.wizardry.util.WizardryUtilities; import net.minecraft.entity.Entity; import net.minecraft.entity.EntityLivingBase; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.item.EnumAction; import net.minecraft.util.EnumFacing; import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.Vec3d; import net.minecraft.util.text.TextComponentTranslation; import net.minecraft.world.World; public class Arc extends SpellRay { - - private static final float BASE_DAMAGE = 3; public Arc(){ - super("arc", Tier.BASIC, Element.LIGHTNING, SpellType.ATTACK, 5, 15, false, 8, null); + super("arc", false, EnumAction.NONE); + this.aimAssist(0.6f); + this.soundValues(1, 1.7f, 0.2f); + this.addProperties(DAMAGE); } @Override - protected boolean onEntityHit(World world, Entity target, EntityLivingBase caster, int ticksInUse, SpellModifiers modifiers){ + protected boolean onEntityHit(World world, Entity target, Vec3d hit, EntityLivingBase caster, Vec3d origin, int ticksInUse, SpellModifiers modifiers){ if(WizardryUtilities.isLiving(target)){ @@ -44,11 +44,9 @@ public class Arc extends SpellRay { target.getName(), this.getNameForTranslationFormatted()), true); }else{ target.attackEntityFrom(MagicDamage.causeDirectMagicDamage(caster, DamageType.SHOCK), - BASE_DAMAGE * modifiers.get(SpellModifiers.POTENCY)); + getProperty(DAMAGE).floatValue() * modifiers.get(SpellModifiers.POTENCY)); } - - // TODO: Does this mean that players hit by the spell hear no sound? - target.playSound(WizardrySounds.SPELL_SPARK, 1.0F, world.rand.nextFloat() * 0.4F + 1.5F); + return true; } @@ -56,12 +54,12 @@ public class Arc extends SpellRay { } @Override - protected boolean onBlockHit(World world, BlockPos pos, EnumFacing side, EntityLivingBase caster, int ticksInUse, SpellModifiers modifiers){ + protected boolean onBlockHit(World world, BlockPos pos, EnumFacing side, Vec3d hit, EntityLivingBase caster, Vec3d origin, int ticksInUse, SpellModifiers modifiers){ return false; } @Override - protected boolean onMiss(World world, EntityLivingBase caster, int ticksInUse, SpellModifiers modifiers){ + protected boolean onMiss(World world, EntityLivingBase caster, Vec3d origin, Vec3d direction, int ticksInUse, SpellModifiers modifiers){ return false; } diff --git a/src/main/java/electroblob/wizardry/spell/ArcaneJammer.java b/src/main/java/electroblob/wizardry/spell/ArcaneJammer.java index 099943c5..7f4be44a 100644 --- a/src/main/java/electroblob/wizardry/spell/ArcaneJammer.java +++ b/src/main/java/electroblob/wizardry/spell/ArcaneJammer.java @@ -1,47 +1,43 @@ package electroblob.wizardry.spell; -import electroblob.wizardry.constants.Element; -import electroblob.wizardry.constants.SpellType; -import electroblob.wizardry.constants.Tier; -import electroblob.wizardry.entity.living.EntityWizard; import electroblob.wizardry.event.SpellCastEvent; -import electroblob.wizardry.registry.WizardryAdvancementTriggers; import electroblob.wizardry.registry.WizardryItems; import electroblob.wizardry.registry.WizardryPotions; -import electroblob.wizardry.registry.WizardrySounds; import electroblob.wizardry.util.ParticleBuilder; import electroblob.wizardry.util.ParticleBuilder.Type; import electroblob.wizardry.util.SpellModifiers; import electroblob.wizardry.util.WizardryUtilities; import net.minecraft.entity.Entity; import net.minecraft.entity.EntityLivingBase; -import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.entity.monster.EntitySpellcasterIllager; +import net.minecraft.item.EnumAction; import net.minecraft.potion.PotionEffect; import net.minecraft.util.EnumFacing; import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.Vec3d; import net.minecraft.world.World; +import net.minecraftforge.event.entity.living.LivingEvent; import net.minecraftforge.fml.common.Mod; +import net.minecraftforge.fml.common.eventhandler.EventPriority; import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; @Mod.EventBusSubscriber public class ArcaneJammer extends SpellRay { public ArcaneJammer(){ - super("arcane_jammer", Tier.ADVANCED, Element.HEALING, SpellType.ATTACK, 30, 50, false, 10, WizardrySounds.SPELL_DEFLECTION); + super("arcane_jammer", false, EnumAction.NONE); this.soundValues(0.7f, 1, 0.4f); + this.addProperties(EFFECT_DURATION); } @Override - protected boolean onEntityHit(World world, Entity target, EntityLivingBase caster, int ticksInUse, SpellModifiers modifiers){ + protected boolean onEntityHit(World world, Entity target, Vec3d hit, EntityLivingBase caster, Vec3d origin, int ticksInUse, SpellModifiers modifiers){ if(WizardryUtilities.isLiving(target)){ - if(target instanceof EntityWizard && caster instanceof EntityPlayer) - WizardryAdvancementTriggers.jam_wizard.triggerFor((EntityPlayer)caster); - if(!world.isRemote){ ((EntityLivingBase)target).addPotionEffect(new PotionEffect(WizardryPotions.arcane_jammer, - (int)(300 * modifiers.get(WizardryItems.duration_upgrade)), 0)); + (int)(getProperty(EFFECT_DURATION).floatValue() * modifiers.get(WizardryItems.duration_upgrade)), 0)); } } @@ -49,12 +45,12 @@ public class ArcaneJammer extends SpellRay { } @Override - protected boolean onBlockHit(World world, BlockPos pos, EnumFacing side, EntityLivingBase caster, int ticksInUse, SpellModifiers modifiers){ + protected boolean onBlockHit(World world, BlockPos pos, EnumFacing side, Vec3d hit, EntityLivingBase caster, Vec3d origin, int ticksInUse, SpellModifiers modifiers){ return false; } @Override - protected boolean onMiss(World world, EntityLivingBase caster, int ticksInUse, SpellModifiers modifiers){ + protected boolean onMiss(World world, EntityLivingBase caster, Vec3d origin, Vec3d direction, int ticksInUse, SpellModifiers modifiers){ return true; } @@ -64,10 +60,18 @@ public class ArcaneJammer extends SpellRay { .spawn(world); } - @SubscribeEvent + @SubscribeEvent(priority = EventPriority.HIGHEST) // Prevents all spells so it comes before everything else public static void onSpellCastPreEvent(SpellCastEvent.Pre event){ // Arcane jammer prevents spell casting. if(event.getCaster() != null && event.getCaster().isPotionActive(WizardryPotions.arcane_jammer)) event.setCanceled(true); } + @SubscribeEvent + public static void onLivingUpdateEvent(LivingEvent.LivingUpdateEvent event){ + if(event.getEntity() instanceof EntitySpellcasterIllager + && event.getEntityLiving().isPotionActive(WizardryPotions.arcane_jammer)){ + ((EntitySpellcasterIllager)event.getEntity()).setSpellType(EntitySpellcasterIllager.SpellType.NONE); + } + } + } diff --git a/src/main/java/electroblob/wizardry/spell/ArcaneLock.java b/src/main/java/electroblob/wizardry/spell/ArcaneLock.java new file mode 100644 index 00000000..38930604 --- /dev/null +++ b/src/main/java/electroblob/wizardry/spell/ArcaneLock.java @@ -0,0 +1,133 @@ +package electroblob.wizardry.spell; + +import electroblob.wizardry.Wizardry; +import electroblob.wizardry.util.AllyDesignationSystem; +import electroblob.wizardry.util.NBTExtras; +import electroblob.wizardry.util.SpellModifiers; +import electroblob.wizardry.util.WizardryUtilities; +import net.minecraft.entity.Entity; +import net.minecraft.entity.EntityLivingBase; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.item.EnumAction; +import net.minecraft.server.MinecraftServer; +import net.minecraft.tileentity.TileEntity; +import net.minecraft.util.EnumFacing; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.Vec3d; +import net.minecraft.world.World; +import net.minecraftforge.event.entity.player.PlayerInteractEvent; +import net.minecraftforge.event.world.ExplosionEvent; +import net.minecraftforge.fml.common.Mod; +import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; + +@Mod.EventBusSubscriber +public class ArcaneLock extends SpellRay { + + /** The NBT tag name for storing the owner's UUID in the tile entity data. */ + public static final String NBT_KEY = "arcaneLockOwner"; + + public ArcaneLock(){ + super("arcane_lock", false, EnumAction.NONE); + } + + @Override public boolean requiresPacket(){ return true; } + + @Override public boolean canBeCastByDispensers(){ return false; } + + @Override public boolean canBeCastByNPCs(){ return false; } + + @Override + protected boolean onEntityHit(World world, Entity target, Vec3d hit, EntityLivingBase caster, Vec3d origin, int ticksInUse, SpellModifiers modifiers){ + return false; + } + + @Override + protected boolean onBlockHit(World world, BlockPos pos, EnumFacing side, Vec3d hit, EntityLivingBase caster, Vec3d origin, int ticksInUse, SpellModifiers modifiers){ + + if(caster instanceof EntityPlayer){ + + TileEntity tileentity = world.getTileEntity(pos); + + if(tileentity != null){ + + if(tileentity.getTileData().hasUniqueId(NBT_KEY)){ + // Unlocking + if(world.getPlayerEntityByUUID(tileentity.getTileData().getUniqueId(NBT_KEY)) == caster){ + NBTExtras.removeUniqueId(tileentity.getTileData(), NBT_KEY); + return true; + } + }else{ + // Locking + tileentity.getTileData().setUniqueId(NBT_KEY, caster.getUniqueID()); + return true; + } + } + } + + return false; + } + + @Override + protected boolean onMiss(World world, EntityLivingBase caster, Vec3d origin, Vec3d direction, int ticksInUse, SpellModifiers modifiers){ + return false; + } + + @SubscribeEvent + public static void onLeftClickBlockEvent(PlayerInteractEvent.LeftClickBlock event){ + + if(!canBypassLocks(event.getEntityPlayer())){ + + TileEntity tileentity = event.getWorld().getTileEntity(event.getPos()); + + // Prevents arcane-locked containers from being broken + // Need to check if it has the unique id first because if it is absent getUniqueId will return the nil UUID + if(tileentity != null && tileentity.getTileData().hasUniqueId(ArcaneLock.NBT_KEY)){ + // Only the player that owns the lock may break the container + // If nobody owns it (i.e. it's part of a shrine), player will be null + // Why is getUniqueId marked @Nullable? It literally creates a UUID and returns it! + if(event.getEntityPlayer().getUniqueID() != tileentity.getTileData().getUniqueId(ArcaneLock.NBT_KEY)){ + event.setCanceled(true); + } + } + } + } + + @SubscribeEvent + public static void onRightClickBlockEvent(PlayerInteractEvent.RightClickBlock event){ + + if(!canBypassLocks(event.getEntityPlayer())){ + + TileEntity tileentity = event.getWorld().getTileEntity(event.getPos()); + + // Prevents arcane-locked containers from being opened + // Need to check if it has the unique id first because if it is absent getUniqueId will return the nil UUID + if(tileentity != null && tileentity.getTileData().hasUniqueId(ArcaneLock.NBT_KEY)){ + // Why is getUniqueId marked @Nullable? It literally creates a UUID and returns it! + EntityPlayer owner = event.getWorld().getPlayerEntityByUUID(tileentity.getTileData().getUniqueId(ArcaneLock.NBT_KEY)); + // Only the player that owns the lock or an ally of that player may open the container + // If nobody owns it (i.e. it's part of a shrine, or the owner logged out), player will be null + // Unfortunately we can't get the owner's allies if the owner is offline + // Perhaps if this crops up again we can store inverted 'ally of' maps as well? + if(owner == null || (owner != event.getEntityPlayer() && !AllyDesignationSystem.isPlayerAlly(owner, event.getEntityPlayer()))){ + event.setCanceled(true); + } + } + } + } + + private static boolean canBypassLocks(EntityPlayer player){ + + if(!player.isCreative()) return false; + if(Wizardry.settings.creativeBypassesArcaneLock) return true; + MinecraftServer server = player.world.getMinecraftServer(); + return server != null && WizardryUtilities.isPlayerOp(player, server); + } + + @SubscribeEvent + public static void onExplosionEvent(ExplosionEvent.Detonate event){ + // Prevents arcane-locked containers from being exploded + event.getAffectedBlocks().removeIf(pos -> event.getWorld().getTileEntity(pos) != null + && event.getWorld().getTileEntity(pos).getTileData().hasUniqueId(NBT_KEY)); + } + +} diff --git a/src/main/java/electroblob/wizardry/spell/ArrowRain.java b/src/main/java/electroblob/wizardry/spell/ArrowRain.java index 796641fd..11f598ae 100644 --- a/src/main/java/electroblob/wizardry/spell/ArrowRain.java +++ b/src/main/java/electroblob/wizardry/spell/ArrowRain.java @@ -1,23 +1,20 @@ package electroblob.wizardry.spell; -import electroblob.wizardry.constants.Element; -import electroblob.wizardry.constants.SpellType; -import electroblob.wizardry.constants.Tier; import electroblob.wizardry.entity.construct.EntityArrowRain; -import electroblob.wizardry.registry.WizardrySounds; import electroblob.wizardry.util.SpellModifiers; import net.minecraft.entity.EntityLivingBase; +import net.minecraft.util.EnumFacing; import net.minecraft.world.World; public class ArrowRain extends SpellConstructRanged { public ArrowRain(){ - super("arrow_rain", Tier.MASTER, Element.SORCERY, SpellType.ATTACK, 75, 300, EntityArrowRain::new, 120, 20, WizardrySounds.SPELL_SUMMONING); + super("arrow_rain", EntityArrowRain::new, false); this.floor(true); } @Override - protected boolean spawnConstruct(World world, double x, double y, double z, EntityLivingBase caster, SpellModifiers modifiers){ + protected boolean spawnConstruct(World world, double x, double y, double z, EnumFacing side, EntityLivingBase caster, SpellModifiers modifiers){ // Moves the entity back towards the caster a bit, so the area of effect is better centred on the position. // 3 is the distance to move the entity back towards the caster. @@ -29,11 +26,11 @@ public class ArrowRain extends SpellConstructRanged { // Moves the entity up 5 blocks so that it is above mobs' heads. y += 5; - return super.spawnConstruct(world, x, y, z, caster, modifiers); + return super.spawnConstruct(world, x, y, z, side, caster, modifiers); } @Override - protected void addConstructExtras(EntityArrowRain construct, EntityLivingBase caster, SpellModifiers modifiers){ + protected void addConstructExtras(EntityArrowRain construct, EnumFacing side, EntityLivingBase caster, SpellModifiers modifiers){ // Makes the arrows shoot in the direction the caster was looking when they cast the spell. construct.rotationYaw = caster.rotationYawHead; } diff --git a/src/main/java/electroblob/wizardry/spell/Banish.java b/src/main/java/electroblob/wizardry/spell/Banish.java index f1523866..9777892f 100644 --- a/src/main/java/electroblob/wizardry/spell/Banish.java +++ b/src/main/java/electroblob/wizardry/spell/Banish.java @@ -1,8 +1,5 @@ package electroblob.wizardry.spell; -import electroblob.wizardry.constants.Element; -import electroblob.wizardry.constants.SpellType; -import electroblob.wizardry.constants.Tier; import electroblob.wizardry.registry.WizardryItems; import electroblob.wizardry.util.ParticleBuilder; import electroblob.wizardry.util.ParticleBuilder.Type; @@ -10,79 +7,48 @@ import electroblob.wizardry.util.SpellModifiers; import electroblob.wizardry.util.WizardryUtilities; import net.minecraft.entity.Entity; import net.minecraft.entity.EntityLivingBase; -import net.minecraft.init.SoundEvents; +import net.minecraft.item.EnumAction; import net.minecraft.util.EnumFacing; import net.minecraft.util.EnumParticleTypes; import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.MathHelper; +import net.minecraft.util.math.Vec3d; import net.minecraft.world.World; public class Banish extends SpellRay { + public static final String MINIMUM_TELEPORT_DISTANCE = "minimum_teleport_distance"; + public static final String MAXIMUM_TELEPORT_DISTANCE = "maximum_teleport_distance"; + public Banish(){ - super("banish", Tier.APPRENTICE, Element.NECROMANCY, SpellType.ATTACK, 15, 40, false, 10, SoundEvents.ENTITY_ENDERMEN_TELEPORT); + super("banish", false, EnumAction.NONE); + this.addProperties(MINIMUM_TELEPORT_DISTANCE, MAXIMUM_TELEPORT_DISTANCE); } @Override - protected boolean onEntityHit(World world, Entity target, EntityLivingBase caster, int ticksInUse, SpellModifiers modifiers){ + protected boolean onEntityHit(World world, Entity target, Vec3d hit, EntityLivingBase caster, Vec3d origin, int ticksInUse, SpellModifiers modifiers){ if(target instanceof EntityLivingBase){ EntityLivingBase entity = (EntityLivingBase)target; - double radius = (8 + world.rand.nextDouble() * 8) * modifiers.get(WizardryItems.range_upgrade); - double angle = world.rand.nextDouble() * Math.PI * 2; + double minRadius = getProperty(MINIMUM_TELEPORT_DISTANCE).doubleValue(); + double maxRadius = getProperty(MAXIMUM_TELEPORT_DISTANCE).doubleValue(); + double radius = (minRadius + world.rand.nextDouble() * maxRadius-minRadius) * modifiers.get(WizardryItems.blast_upgrade); - int x = MathHelper.floor(entity.posX + Math.sin(angle) * radius); - int z = MathHelper.floor(entity.posZ - Math.cos(angle) * radius); - int y = WizardryUtilities.getNearestFloorLevel(world, - new BlockPos(x, (int)caster.getEntityBoundingBox().minY, z), (int)radius); - - if(world.isRemote){ - for(int i=0; i<10; i++){ - double dx1 = entity.posX; - double dy1 = entity.getEntityBoundingBox().minY + entity.height * world.rand.nextFloat(); - double dz1 = entity.posZ; - world.spawnParticle(EnumParticleTypes.PORTAL, dx1, dy1, dz1, world.rand.nextDouble() - 0.5, - world.rand.nextDouble() - 0.5, world.rand.nextDouble() - 0.5); - } - - // Can't be bothered to route this through the proxies! - if(entity == net.minecraft.client.Minecraft.getMinecraft().player) - electroblob.wizardry.client.WizardryClientEventHandler.playBlinkEffect(); - } - - if(y > -1){ - - // This means stuff like snow layers is ignored, meaning when on snow-covered ground the target does - // not teleport 1 block above the ground. - if(!world.getBlockState(new BlockPos(x, y, z)).getMaterial().blocksMovement()){ - y--; - } - - if(world.getBlockState(new BlockPos(x, y + 1, z)).getMaterial().blocksMovement() - || world.getBlockState(new BlockPos(x, y + 2, z)).getMaterial().blocksMovement()){ - return false; - } - - if(!world.isRemote){ - entity.setPositionAndUpdate(x + 0.5, y + 1, z + 0.5); - } - - entity.playSound(SoundEvents.ENTITY_ENDERMEN_TELEPORT, 1.0F, 1.0f); - } + teleport(entity, world, radius); } return true; } @Override - protected boolean onBlockHit(World world, BlockPos pos, EnumFacing side, EntityLivingBase caster, int ticksInUse, SpellModifiers modifiers){ + protected boolean onBlockHit(World world, BlockPos pos, EnumFacing side, Vec3d hit, EntityLivingBase caster, Vec3d origin, int ticksInUse, SpellModifiers modifiers){ return false; } @Override - protected boolean onMiss(World world, EntityLivingBase caster, int ticksInUse, SpellModifiers modifiers){ + protected boolean onMiss(World world, EntityLivingBase caster, Vec3d origin, Vec3d direction, int ticksInUse, SpellModifiers modifiers){ return true; } @@ -92,4 +58,52 @@ public class Banish extends SpellRay { ParticleBuilder.create(Type.DARK_MAGIC).pos(x, y, z).clr(0.2f, 0, 0.2f).spawn(world); } + // Extracted as a separate method for external use + public boolean teleport(EntityLivingBase entity, World world, double radius){ + + float angle = world.rand.nextFloat() * (float)Math.PI * 2; + + int x = MathHelper.floor(entity.posX + MathHelper.sin(angle) * radius); + int z = MathHelper.floor(entity.posZ - MathHelper.cos(angle) * radius); + Integer y = WizardryUtilities.getNearestFloor(world, + new BlockPos(x, (int)entity.getEntityBoundingBox().minY, z), (int)radius); + + if(world.isRemote){ + + for(int i=0; i<10; i++){ + double dx1 = entity.posX; + double dy1 = entity.getEntityBoundingBox().minY + entity.height * world.rand.nextFloat(); + double dz1 = entity.posZ; + world.spawnParticle(EnumParticleTypes.PORTAL, dx1, dy1, dz1, world.rand.nextDouble() - 0.5, + world.rand.nextDouble() - 0.5, world.rand.nextDouble() - 0.5); + } + + // Can't be bothered to route this through the proxies! + if(entity == net.minecraft.client.Minecraft.getMinecraft().player) + electroblob.wizardry.client.WizardryClientEventHandler.playBlinkEffect(); + } + + if(y != null){ + + // This means stuff like snow layers is ignored, meaning when on snow-covered ground the target does + // not teleport 1 block above the ground. + if(!world.getBlockState(new BlockPos(x, y, z)).getMaterial().blocksMovement()){ + y--; + } + + if(world.getBlockState(new BlockPos(x, y + 1, z)).getMaterial().blocksMovement() + || world.getBlockState(new BlockPos(x, y + 2, z)).getMaterial().blocksMovement()){ + return false; + } + + if(!world.isRemote){ + entity.setPositionAndUpdate(x + 0.5, y + 1, z + 0.5); + } + + this.playSound(world, entity, 0, -1, new SpellModifiers()); + } + + return true; + } + } diff --git a/src/main/java/electroblob/wizardry/spell/Blink.java b/src/main/java/electroblob/wizardry/spell/Blink.java index 8aacc347..f6adf784 100644 --- a/src/main/java/electroblob/wizardry/spell/Blink.java +++ b/src/main/java/electroblob/wizardry/spell/Blink.java @@ -1,15 +1,12 @@ package electroblob.wizardry.spell; -import electroblob.wizardry.constants.Element; -import electroblob.wizardry.constants.SpellType; -import electroblob.wizardry.constants.Tier; import electroblob.wizardry.registry.WizardryItems; +import electroblob.wizardry.util.RayTracer; import electroblob.wizardry.util.SpellModifiers; import electroblob.wizardry.util.WizardryUtilities; import net.minecraft.entity.EntityLiving; import net.minecraft.entity.EntityLivingBase; import net.minecraft.entity.player.EntityPlayer; -import net.minecraft.init.SoundEvents; import net.minecraft.item.EnumAction; import net.minecraft.util.EnumFacing; import net.minecraft.util.EnumHand; @@ -22,14 +19,15 @@ import net.minecraft.world.World; public class Blink extends Spell { public Blink(){ - super("blink", Tier.APPRENTICE, Element.SORCERY, SpellType.UTILITY, 15, 25, EnumAction.NONE, false); + super("blink", EnumAction.NONE, false); + addProperties(RANGE); } @Override public boolean cast(World world, EntityPlayer caster, EnumHand hand, int ticksInUse, SpellModifiers modifiers){ - RayTraceResult rayTrace = WizardryUtilities.standardBlockRayTrace(world, caster, - 25 * modifiers.get(WizardryItems.range_upgrade), false); + RayTraceResult rayTrace = RayTracer.standardBlockRayTrace(world, caster, + getProperty(RANGE).doubleValue() * modifiers.get(WizardryItems.range_upgrade), false); // It's worth noting that on the client side, the cast() method only gets called if the server side // cast method succeeded, so you need not check any conditions for spawning particles. @@ -52,8 +50,8 @@ public class Blink extends Spell { BlockPos pos = rayTrace.getBlockPos(); - // Can't teleport onto the ceiling. - if(rayTrace.sideHit == EnumFacing.DOWN) return false; + // Leave space for the player's head + if(rayTrace.sideHit == EnumFacing.DOWN) pos = pos.down(); // This means stuff like snow layers is ignored, meaning when on snow-covered ground the player does // not teleport 1 block above the ground. @@ -61,7 +59,7 @@ public class Blink extends Spell { pos = pos.down(); } - pos = rayTrace.getBlockPos().offset(rayTrace.sideHit); + pos = pos.offset(rayTrace.sideHit); // Prevents the player from teleporting into blocks and suffocating. if(world.getBlockState(pos).getMaterial().blocksMovement() @@ -70,11 +68,11 @@ public class Blink extends Spell { } // Plays before and after so it is heard from both positions - WizardryUtilities.playSoundAtPlayer(caster, SoundEvents.ENTITY_ENDERMEN_TELEPORT, 1.0F, 1.0f); + this.playSound(world, caster, ticksInUse, -1, modifiers); if(!world.isRemote) caster.setPositionAndUpdate(pos.getX() + 0.5, pos.getY(), pos.getZ() + 0.5); - WizardryUtilities.playSoundAtPlayer(caster, SoundEvents.ENTITY_ENDERMEN_TELEPORT, 1.0F, 1.0f); + this.playSound(world, caster, ticksInUse, -1, modifiers); caster.swingArm(hand); return true; } @@ -86,14 +84,14 @@ public class Blink extends Spell { public boolean cast(World world, EntityLiving caster, EnumHand hand, int ticksInUse, EntityLivingBase target, SpellModifiers modifiers){ - double angle = Math.atan2(target.posZ - caster.posZ, target.posX - caster.posX) - + world.rand.nextDouble() * Math.PI; + float angle = (float)(Math.atan2(target.posZ - caster.posZ, target.posX - caster.posX) + + world.rand.nextDouble() * Math.PI); double radius = caster.getDistance(target.posX, target.getEntityBoundingBox().minY, target.posZ) + world.rand.nextDouble() * 3.0d; - int x = MathHelper.floor(target.posX + Math.sin(angle) * radius); - int z = MathHelper.floor(target.posZ - Math.cos(angle) * radius); - int y = WizardryUtilities.getNearestFloorLevel(world, new BlockPos(caster), (int)radius); + int x = MathHelper.floor(target.posX + MathHelper.sin(angle) * radius); + int z = MathHelper.floor(target.posZ - MathHelper.cos(angle) * radius); + Integer y = WizardryUtilities.getNearestFloor(world, new BlockPos(caster), (int)radius); // It's worth noting that on the client side, the cast() method only gets called if the server side // cast method succeeded, so you need not check any conditions for spawning particles. @@ -109,7 +107,7 @@ public class Blink extends Spell { } } - if(y > -1){ + if(y != null){ // This means stuff like snow layers is ignored, meaning when on snow-covered ground the caster does // not teleport 1 block above the ground. @@ -123,13 +121,13 @@ public class Blink extends Spell { } // Plays before and after so it is heard from both positions - caster.playSound(SoundEvents.ENTITY_ENDERMEN_TELEPORT, 1.0F, 1.0f); + this.playSound(world, caster, ticksInUse, -1, modifiers); if(!world.isRemote){ caster.setPositionAndUpdate(x + 0.5, y + 1, z + 0.5); } - caster.playSound(SoundEvents.ENTITY_ENDERMEN_TELEPORT, 1.0F, 1.0f); + this.playSound(world, caster, ticksInUse, -1, modifiers); caster.swingArm(hand); return true; } diff --git a/src/main/java/electroblob/wizardry/spell/Bubble.java b/src/main/java/electroblob/wizardry/spell/Bubble.java index 34b1698f..2ac47406 100644 --- a/src/main/java/electroblob/wizardry/spell/Bubble.java +++ b/src/main/java/electroblob/wizardry/spell/Bubble.java @@ -1,11 +1,7 @@ package electroblob.wizardry.spell; -import electroblob.wizardry.constants.Element; -import electroblob.wizardry.constants.SpellType; -import electroblob.wizardry.constants.Tier; import electroblob.wizardry.entity.construct.EntityBubble; import electroblob.wizardry.registry.WizardryItems; -import electroblob.wizardry.registry.WizardrySounds; import electroblob.wizardry.util.MagicDamage; import electroblob.wizardry.util.MagicDamage.DamageType; import electroblob.wizardry.util.ParticleBuilder; @@ -13,40 +9,30 @@ import electroblob.wizardry.util.ParticleBuilder.Type; import electroblob.wizardry.util.SpellModifiers; import electroblob.wizardry.util.WizardryUtilities; import net.minecraft.entity.Entity; -import net.minecraft.entity.EntityLiving; import net.minecraft.entity.EntityLivingBase; -import net.minecraft.entity.player.EntityPlayer; -import net.minecraft.init.SoundEvents; +import net.minecraft.item.EnumAction; import net.minecraft.util.EnumFacing; -import net.minecraft.util.EnumHand; import net.minecraft.util.EnumParticleTypes; +import net.minecraft.util.SoundEvent; import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.Vec3d; import net.minecraft.world.World; public class Bubble extends SpellRay { public Bubble(){ - super("bubble", Tier.APPRENTICE, Element.EARTH, SpellType.ATTACK, 15, 20, false, 10, WizardrySounds.SPELL_ICE); + super("bubble", false, EnumAction.NONE); this.soundValues(0.5f, 1.1f, 0.2f); + addProperties(DURATION); } - + @Override - public boolean cast(World world, EntityPlayer caster, EnumHand hand, int ticksInUse, SpellModifiers modifiers){ - // This spell uses more than one sound, so this is required... - boolean flag = super.cast(world, caster, hand, ticksInUse, modifiers); - if(flag) WizardryUtilities.playSoundAtPlayer(caster, SoundEvents.ENTITY_GENERIC_SWIM, 1, 1 + 0.2f * world.rand.nextFloat()); - return flag; + protected SoundEvent[] createSounds(){ + return this.createSoundsWithSuffixes("shoot", "splash"); } - + @Override - public boolean cast(World world, EntityLiving caster, EnumHand hand, int ticksInUse, EntityLivingBase target, SpellModifiers modifiers){ - boolean flag = super.cast(world, caster, hand, ticksInUse, target, modifiers); - if(flag) caster.playSound(SoundEvents.ENTITY_GENERIC_SWIM, 1.0F, world.rand.nextFloat() * 0.2F + 1.0F); - return flag; - } - - @Override - protected boolean onEntityHit(World world, Entity target, EntityLivingBase caster, int ticksInUse, SpellModifiers modifiers){ + protected boolean onEntityHit(World world, Entity target, Vec3d hit, EntityLivingBase caster, Vec3d origin, int ticksInUse, SpellModifiers modifiers){ if(WizardryUtilities.isLiving(target)){ @@ -57,7 +43,7 @@ public class Bubble extends SpellRay { EntityBubble bubble = new EntityBubble(world); bubble.setPosition(target.posX, target.posY, target.posZ); bubble.setCaster(caster); - bubble.lifetime = ((int)(200 * modifiers.get(WizardryItems.duration_upgrade))); + bubble.lifetime = ((int)(getProperty(DURATION).floatValue() * modifiers.get(WizardryItems.duration_upgrade))); bubble.isDarkOrb = false; bubble.damageMultiplier = modifiers.get(SpellModifiers.POTENCY); @@ -70,12 +56,12 @@ public class Bubble extends SpellRay { } @Override - protected boolean onBlockHit(World world, BlockPos pos, EnumFacing side, EntityLivingBase caster, int ticksInUse, SpellModifiers modifiers){ + protected boolean onBlockHit(World world, BlockPos pos, EnumFacing side, Vec3d hit, EntityLivingBase caster, Vec3d origin, int ticksInUse, SpellModifiers modifiers){ return false; } @Override - protected boolean onMiss(World world, EntityLivingBase caster, int ticksInUse, SpellModifiers modifiers){ + protected boolean onMiss(World world, EntityLivingBase caster, Vec3d origin, Vec3d direction, int ticksInUse, SpellModifiers modifiers){ return true; } diff --git a/src/main/java/electroblob/wizardry/spell/ChainLightning.java b/src/main/java/electroblob/wizardry/spell/ChainLightning.java index 36bfa78d..83b3df2f 100644 --- a/src/main/java/electroblob/wizardry/spell/ChainLightning.java +++ b/src/main/java/electroblob/wizardry/spell/ChainLightning.java @@ -1,79 +1,81 @@ package electroblob.wizardry.spell; -import java.util.List; - -import electroblob.wizardry.constants.Element; -import electroblob.wizardry.constants.SpellType; -import electroblob.wizardry.constants.Tier; -import electroblob.wizardry.entity.EntityArc; -import electroblob.wizardry.registry.WizardrySounds; -import electroblob.wizardry.util.MagicDamage; +import electroblob.wizardry.util.*; import electroblob.wizardry.util.MagicDamage.DamageType; -import electroblob.wizardry.util.ParticleBuilder; -import electroblob.wizardry.util.SpellModifiers; -import electroblob.wizardry.util.WizardryUtilities; +import electroblob.wizardry.util.ParticleBuilder.Type; import net.minecraft.entity.Entity; import net.minecraft.entity.EntityLivingBase; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.item.EnumAction; import net.minecraft.util.EnumFacing; import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.Vec3d; import net.minecraft.util.text.TextComponentTranslation; import net.minecraft.world.World; +import java.util.List; + public class ChainLightning extends SpellRay { - private static final float PRIMARY_DAMAGE = 10; - private static final float SECONDARY_DAMAGE = 8; - private static final float TERTIARY_DAMAGE = 6; + public static final String PRIMARY_DAMAGE = "primary_damage"; + public static final String SECONDARY_DAMAGE = "secondary_damage"; + public static final String TERTIARY_DAMAGE = "tertiary_damage"; - private static final double PRIMARY_RANGE = 10; - private static final double SECONDARY_RANGE = 5; - private static final double TERTIARY_RANGE = 5; + public static final String SECONDARY_RANGE = "secondary_range"; + public static final String TERTIARY_RANGE = "tertiary_range"; - private static final int SECONDARY_MAX_TARGETS = 5; - private static final int TERTIARY_MAX_TARGETS = 2; // This is per secondary target, giving 10 in total + public static final String SECONDARY_MAX_TARGETS = "secondary_max_targets"; + public static final String TERTIARY_MAX_TARGETS = "tertiary_max_targets"; // This is per secondary target public ChainLightning(){ - super("chain_lightning", Tier.ADVANCED, Element.LIGHTNING, SpellType.ATTACK, 25, 50, false, PRIMARY_RANGE, null); + super("chain_lightning", false, EnumAction.NONE); + this.aimAssist(0.6f); + this.soundValues(1, 1.7f, 0.2f); + addProperties(PRIMARY_DAMAGE, SECONDARY_DAMAGE, TERTIARY_DAMAGE, SECONDARY_RANGE, TERTIARY_RANGE, + SECONDARY_MAX_TARGETS, TERTIARY_MAX_TARGETS); } @Override - protected boolean onEntityHit(World world, Entity target, EntityLivingBase caster, int ticksInUse, SpellModifiers modifiers){ + protected boolean onEntityHit(World world, Entity target, Vec3d hit, EntityLivingBase caster, Vec3d origin, int ticksInUse, SpellModifiers modifiers){ // Anything can be attacked with the initial arc, because the player has control over where it goes. If they // hit a minion or an ally, it's their problem! if(WizardryUtilities.isLiving(target)){ - electrocute(world, caster, caster, target, PRIMARY_DAMAGE * modifiers.get(SpellModifiers.POTENCY)); + electrocute(world, caster, origin, target, getProperty(PRIMARY_DAMAGE).floatValue() + * modifiers.get(SpellModifiers.POTENCY)); // Secondary chaining effect - List secondaryTargets = WizardryUtilities.getEntitiesWithinRadius(SECONDARY_RANGE, - target.posX, target.posY + target.height / 2, target.posZ, world); + List secondaryTargets = WizardryUtilities.getEntitiesWithinRadius( + getProperty(SECONDARY_RANGE).doubleValue(), target.posX, target.posY + target.height / 2, target.posZ, world); secondaryTargets.remove(target); secondaryTargets.removeIf(e -> !WizardryUtilities.isLiving(e)); - secondaryTargets.removeIf(e -> !WizardryUtilities.isValidTarget(caster, e)); - if(secondaryTargets.size() > SECONDARY_MAX_TARGETS) secondaryTargets = secondaryTargets.subList(0, SECONDARY_MAX_TARGETS); + secondaryTargets.removeIf(e -> !AllyDesignationSystem.isValidTarget(caster, e)); + if(secondaryTargets.size() > getProperty(SECONDARY_MAX_TARGETS).intValue()) + secondaryTargets = secondaryTargets.subList(0, getProperty(SECONDARY_MAX_TARGETS).intValue()); for(EntityLivingBase secondaryTarget : secondaryTargets){ - electrocute(world, caster, target, secondaryTarget, - SECONDARY_DAMAGE * modifiers.get(SpellModifiers.POTENCY)); + electrocute(world, caster, target.getPositionVector().add(0, target.height/2, 0), secondaryTarget, + getProperty(SECONDARY_DAMAGE).floatValue() * modifiers.get(SpellModifiers.POTENCY)); // Tertiary chaining effect - List tertiaryTargets = WizardryUtilities.getEntitiesWithinRadius(TERTIARY_RANGE, - secondaryTarget.posX, secondaryTarget.posY + secondaryTarget.height / 2, - secondaryTarget.posZ, world); + List tertiaryTargets = WizardryUtilities.getEntitiesWithinRadius( + getProperty(TERTIARY_RANGE).doubleValue(), secondaryTarget.posX, + secondaryTarget.posY + secondaryTarget.height / 2, secondaryTarget.posZ, world); tertiaryTargets.remove(target); tertiaryTargets.removeAll(secondaryTargets); tertiaryTargets.removeIf(e -> !WizardryUtilities.isLiving(e)); - tertiaryTargets.removeIf(e -> !WizardryUtilities.isValidTarget(caster, e)); - if(tertiaryTargets.size() > TERTIARY_MAX_TARGETS) tertiaryTargets = tertiaryTargets.subList(0, TERTIARY_MAX_TARGETS); + tertiaryTargets.removeIf(e -> !AllyDesignationSystem.isValidTarget(caster, e)); + if(tertiaryTargets.size() > getProperty(TERTIARY_MAX_TARGETS).intValue()) + tertiaryTargets = tertiaryTargets.subList(0, getProperty(TERTIARY_MAX_TARGETS).intValue()); for(EntityLivingBase tertiaryTarget : tertiaryTargets){ - electrocute(world, caster, secondaryTarget, tertiaryTarget, - TERTIARY_DAMAGE * modifiers.get(SpellModifiers.POTENCY)); + electrocute(world, caster, secondaryTarget.getPositionVector().add(0, secondaryTarget.height/2, 0), + tertiaryTarget, getProperty(TERTIARY_DAMAGE).floatValue() * modifiers.get(SpellModifiers.POTENCY)); } } @@ -84,16 +86,16 @@ public class ChainLightning extends SpellRay { } @Override - protected boolean onBlockHit(World world, BlockPos pos, EnumFacing side, EntityLivingBase caster, int ticksInUse, SpellModifiers modifiers){ + protected boolean onBlockHit(World world, BlockPos pos, EnumFacing side, Vec3d hit, EntityLivingBase caster, Vec3d origin, int ticksInUse, SpellModifiers modifiers){ return false; } @Override - protected boolean onMiss(World world, EntityLivingBase caster, int ticksInUse, SpellModifiers modifiers){ + protected boolean onMiss(World world, EntityLivingBase caster, Vec3d origin, Vec3d direction, int ticksInUse, SpellModifiers modifiers){ return false; } - private void electrocute(World world, Entity caster, Entity origin, Entity target, float damage){ + private void electrocute(World world, Entity caster, Vec3d origin, Entity target, float damage){ if(MagicDamage.isEntityImmune(DamageType.SHOCK, target)){ if(!world.isRemote && caster instanceof EntityPlayer) ((EntityPlayer)caster).sendStatusMessage( @@ -111,7 +113,7 @@ public class ChainLightning extends SpellRay { ParticleBuilder.spawnShockParticles(world, target.posX, target.getEntityBoundingBox().minY + target.height/2, target.posZ); } - target.playSound(WizardrySounds.SPELL_SPARK, 1, 1.5f + 0.4f * world.rand.nextFloat()); + //target.playSound(WizardrySounds.SPELL_SPARK, 1, 1.5f + 0.4f * world.rand.nextFloat()); } } diff --git a/src/main/java/electroblob/wizardry/spell/Charge.java b/src/main/java/electroblob/wizardry/spell/Charge.java new file mode 100644 index 00000000..d6e9a4df --- /dev/null +++ b/src/main/java/electroblob/wizardry/spell/Charge.java @@ -0,0 +1,125 @@ +package electroblob.wizardry.spell; + +import electroblob.wizardry.data.IVariable; +import electroblob.wizardry.data.Persistence; +import electroblob.wizardry.data.WizardData; +import electroblob.wizardry.registry.Spells; +import electroblob.wizardry.registry.WizardryItems; +import electroblob.wizardry.util.MagicDamage; +import electroblob.wizardry.util.ParticleBuilder; +import electroblob.wizardry.util.ParticleBuilder.Type; +import electroblob.wizardry.util.SpellModifiers; +import electroblob.wizardry.util.WizardryUtilities; +import net.minecraft.entity.EntityLivingBase; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.init.SoundEvents; +import net.minecraft.item.EnumAction; +import net.minecraft.util.EnumHand; +import net.minecraft.util.EnumParticleTypes; +import net.minecraft.util.math.Vec3d; +import net.minecraft.world.World; +import net.minecraftforge.event.entity.living.LivingAttackEvent; +import net.minecraftforge.fml.common.Mod; +import net.minecraftforge.fml.common.eventhandler.EventPriority; +import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; + +import java.util.List; + +@Mod.EventBusSubscriber +public class Charge extends Spell { + + public static final IVariable CHARGE_TIME = new IVariable.Variable(Persistence.NEVER).withTicker(Charge::update); + public static final IVariable CHARGE_MODIFIERS = new IVariable.Variable<>(Persistence.NEVER); + + public static final String CHARGE_SPEED = "charge_speed"; + public static final String KNOCKBACK_STRENGTH = "knockback_strength"; + + private static final double EXTRA_HIT_MARGIN = 1; + + public Charge(){ + super("charge", EnumAction.NONE, false); + addProperties(CHARGE_SPEED, DURATION, DAMAGE, KNOCKBACK_STRENGTH); + this.soundValues(0.6f, 1, 0); + } + + @Override + public boolean cast(World world, EntityPlayer caster, EnumHand hand, int ticksInUse, SpellModifiers modifiers){ + + WizardData.get(caster).setVariable(CHARGE_TIME, (int)(getProperty(DURATION).floatValue() + * modifiers.get(WizardryItems.duration_upgrade))); + + WizardData.get(caster).setVariable(CHARGE_MODIFIERS, modifiers); + + if(world.isRemote) world.spawnParticle(EnumParticleTypes.EXPLOSION_LARGE, caster.posX, caster.posY + caster.height/2, caster.posZ, 0, 0, 0); + + this.playSound(world, caster, ticksInUse, -1, modifiers); + + return true; + } + + private static int update(EntityPlayer player, Integer chargeTime){ + + if(chargeTime == null) chargeTime = 0; + + if(chargeTime > 0){ + + SpellModifiers modifiers = WizardData.get(player).getVariable(CHARGE_MODIFIERS); + if(modifiers == null) modifiers = new SpellModifiers(); + + Vec3d look = player.getLookVec(); + + float speed = Spells.charge.getProperty(Charge.CHARGE_SPEED).floatValue() * modifiers.get(WizardryItems.range_upgrade); + + player.motionX = look.x * speed; + player.motionZ = look.z * speed; + + if(player.world.isRemote){ + for(int i = 0; i < 5; i++){ + ParticleBuilder.create(Type.SPARK, player).spawn(player.world); + } + } + + List collided = player.world.getEntitiesWithinAABB(EntityLivingBase.class, player.getEntityBoundingBox().grow(EXTRA_HIT_MARGIN)); + + collided.remove(player); + + float damage = Spells.charge.getProperty(DAMAGE).floatValue() * modifiers.get(SpellModifiers.POTENCY); + float knockback = Spells.charge.getProperty(KNOCKBACK_STRENGTH).floatValue(); + + collided.forEach(e -> e.attackEntityFrom(MagicDamage.causeDirectMagicDamage(player, MagicDamage.DamageType.SHOCK), damage)); + collided.forEach(e -> e.addVelocity(player.motionX * knockback, player.motionY * knockback + 0.3f, player.motionZ * knockback)); + + if(player.world.isRemote) player.world.spawnParticle(EnumParticleTypes.EXPLOSION_LARGE, + player.posX + player.motionX, player.posY + player.height/2, player.posZ + player.motionZ, 0, 0, 0); + + if(collided.isEmpty()) chargeTime--; + else{ + WizardryUtilities.playSoundAtPlayer(player, SoundEvents.ENTITY_GENERIC_HURT, 1, 1); + chargeTime = 0; + } + } + + return chargeTime; + } + + @SubscribeEvent(priority = EventPriority.HIGH) + public static void onLivingAttackEvent(LivingAttackEvent event){ + // Players are immune to melee damage while charging + if(event.getEntity() instanceof EntityPlayer && event.getSource().getTrueSource() instanceof EntityLivingBase){ + + EntityPlayer player = (EntityPlayer)event.getEntity(); + EntityLivingBase attacker = (EntityLivingBase)event.getSource().getTrueSource(); + + if(WizardData.get(player) != null){ + + Integer chargeTime = WizardData.get(player).getVariable(CHARGE_TIME); + + if(chargeTime != null && chargeTime > 0 + && player.getEntityBoundingBox().grow(EXTRA_HIT_MARGIN).intersects(attacker.getEntityBoundingBox())){ + event.setCanceled(true); + } + } + } + } + +} diff --git a/src/main/java/electroblob/wizardry/spell/Clairvoyance.java b/src/main/java/electroblob/wizardry/spell/Clairvoyance.java index 870f994a..0e638ceb 100644 --- a/src/main/java/electroblob/wizardry/spell/Clairvoyance.java +++ b/src/main/java/electroblob/wizardry/spell/Clairvoyance.java @@ -1,21 +1,17 @@ package electroblob.wizardry.spell; -import electroblob.wizardry.WizardData; -import electroblob.wizardry.constants.Element; -import electroblob.wizardry.constants.SpellType; -import electroblob.wizardry.constants.Tier; -import electroblob.wizardry.item.ItemWand; +import electroblob.wizardry.data.IStoredVariable; +import electroblob.wizardry.data.Persistence; +import electroblob.wizardry.data.WizardData; +import electroblob.wizardry.item.ISpellCastingItem; +import electroblob.wizardry.misc.WizardryPathFinder; import electroblob.wizardry.packet.PacketClairvoyance; import electroblob.wizardry.packet.WizardryPacketHandler; import electroblob.wizardry.registry.Spells; import electroblob.wizardry.registry.WizardryItems; -import electroblob.wizardry.registry.WizardrySounds; import electroblob.wizardry.util.ParticleBuilder; import electroblob.wizardry.util.ParticleBuilder.Type; import electroblob.wizardry.util.SpellModifiers; -import electroblob.wizardry.util.WandHelper; -import electroblob.wizardry.util.WizardryPathFinder; -import electroblob.wizardry.util.WizardryUtilities; import net.minecraft.entity.SharedMonsterAttributes; import net.minecraft.entity.monster.EntityZombie; import net.minecraft.entity.player.EntityPlayer; @@ -39,23 +35,30 @@ public class Clairvoyance extends Spell { /** The number of ticks it takes each path particle to move from one path point to the next. */ public static final int PARTICLE_MOVEMENT_INTERVAL = 45; + public static final IStoredVariable LOCATION_KEY = IStoredVariable.StoredVariable.ofBlockPos("clairvoyancePos", Persistence.ALWAYS); + public static final IStoredVariable DIMENSION_KEY = IStoredVariable.StoredVariable.ofInt("clairvoyanceDimension", Persistence.ALWAYS); + public Clairvoyance(){ - super("clairvoyance", Tier.APPRENTICE, Element.SORCERY, SpellType.UTILITY, 20, 100, EnumAction.BOW, false); + super("clairvoyance", EnumAction.BOW, false); + addProperties(RANGE, DURATION); + WizardData.registerStoredVariables(LOCATION_KEY, DIMENSION_KEY); } - @Override - public boolean doesSpellRequirePacket(){ - return false; - } + @Override public boolean canBeCastByNPCs() { return false; } + @Override public boolean canBeCastByDispensers() { return false; } @Override public boolean cast(World world, EntityPlayer caster, EnumHand hand, int ticksInUse, SpellModifiers modifiers){ - WizardData properties = WizardData.get(caster); + WizardData data = WizardData.get(caster); - if(properties != null && !caster.isSneaking()){ - if(caster.dimension == properties.getClairvoyanceDimension()){ - if(properties.getClairvoyanceLocation() != null){ + if(data != null && !caster.isSneaking()){ + + Integer dimension = data.getVariable(DIMENSION_KEY); + BlockPos location = data.getVariable(LOCATION_KEY); + + if(dimension != null && caster.dimension == dimension){ + if(location != null){ if(!world.isRemote) caster.sendStatusMessage(new TextComponentTranslation("spell." + this.getUnlocalisedName() + ".searching"), true); @@ -66,16 +69,15 @@ public class Clairvoyance extends Spell { } }; arbitraryZombie.getEntityAttribute(SharedMonsterAttributes.FOLLOW_RANGE) - .setBaseValue(256 * modifiers.get(WizardryItems.range_upgrade)); + .setBaseValue(getProperty(RANGE).doubleValue() * modifiers.get(WizardryItems.range_upgrade)); arbitraryZombie.setPosition(caster.posX, caster.posY, caster.posZ); arbitraryZombie.setPathPriority(PathNodeType.WATER, 0.0F); arbitraryZombie.onGround = true; - BlockPos destination = properties.getClairvoyanceLocation(); - WizardryPathFinder pathfinder = new WizardryPathFinder(arbitraryZombie.getNavigator().getNodeProcessor()); - Path path = pathfinder.findPath(world, arbitraryZombie, destination, 256 * modifiers.get(WizardryItems.range_upgrade)); + Path path = pathfinder.findPath(world, arbitraryZombie, location, + getProperty(RANGE).floatValue() * modifiers.get(WizardryItems.range_upgrade)); if(path != null && path.getFinalPathPoint() != null){ @@ -83,9 +85,9 @@ public class Clairvoyance extends Spell { int y = path.getFinalPathPoint().y; int z = path.getFinalPathPoint().z; - if(x == destination.getX() && y == destination.getY() && z == destination.getZ()){ + if(x == location.getX() && y == location.getY() && z == location.getZ()){ - WizardryUtilities.playSoundAtPlayer(caster, WizardrySounds.SPELL_CONJURATION, 1.0f, 1.0f); + this.playSound(world, caster, ticksInUse, -1, modifiers); if(!world.isRemote && caster instanceof EntityPlayerMP){ WizardryPacketHandler.net.sendTo(new PacketClairvoyance.Message(path, modifiers.get(WizardryItems.duration_upgrade)), @@ -107,13 +109,16 @@ public class Clairvoyance extends Spell { } // Fixes the problem with the sound not playing for the client of the caster. - if(world.isRemote) WizardryUtilities.playSoundAtPlayer(caster, WizardrySounds.SPELL_CONJURATION, 1.0f, 1.0f); + if(world.isRemote) this.playSound(world, caster, ticksInUse, -1, modifiers); return false; } public static void spawnPathPaticles(World world, Path path, float durationMultiplier){ + // A bit annoying that we have to use the reference here but there's no easy way around it + float duration = Spells.clairvoyance.getProperty(DURATION).floatValue(); + PathPoint point, nextPoint; while(!path.isFinished()){ @@ -127,7 +132,7 @@ public class Clairvoyance extends Spell { (nextPoint.x - point.x) / (float)PARTICLE_MOVEMENT_INTERVAL, (nextPoint.y - point.y) / (float)PARTICLE_MOVEMENT_INTERVAL, (nextPoint.z - point.z) / (float)PARTICLE_MOVEMENT_INTERVAL) - .time((int)(1800 * durationMultiplier)).clr(0, 1, 0.3f).spawn(world); + .time((int)(duration * durationMultiplier)).clr(0, 1, 0.3f).spawn(world); path.incrementPathIndex(); path.incrementPathIndex(); @@ -136,7 +141,7 @@ public class Clairvoyance extends Spell { point = path.getFinalPathPoint(); ParticleBuilder.create(Type.PATH).pos(point.x + 0.5, point.y + 0.5, point.z + 0.5) - .time((int)(1800 * durationMultiplier)).clr(1, 1, 1).spawn(world); + .time((int)(duration * durationMultiplier)).clr(1f, 1f, 1f).spawn(world); } @SubscribeEvent @@ -145,17 +150,19 @@ public class Clairvoyance extends Spell { if(event.getEntityPlayer().isSneaking()){ // The event now has an ItemStack, which greatly simplifies hand-related stuff. - ItemStack wand = event.getItemStack(); + ItemStack stack = event.getItemStack(); - if(wand.getItem() instanceof ItemWand && WandHelper.getCurrentSpell(wand) instanceof Clairvoyance){ + if(stack.getItem() instanceof ISpellCastingItem + && ((ISpellCastingItem)stack.getItem()).getCurrentSpell(stack) instanceof Clairvoyance){ - WizardData properties = WizardData.get(event.getEntityPlayer()); + WizardData data = WizardData.get(event.getEntityPlayer()); + + if(data != null){ - if(properties != null){ - // THIS is why BlockPos is a thing - in 1.7.10 this requires a clumsy switch statement. BlockPos pos = event.getPos().offset(event.getFace()); - properties.setClairvoyancePoint(pos, event.getWorld().provider.getDimension()); + data.setVariable(LOCATION_KEY, pos); + data.setVariable(DIMENSION_KEY, event.getWorld().provider.getDimension()); if(!event.getWorld().isRemote){ event.getEntityPlayer().sendStatusMessage( diff --git a/src/main/java/electroblob/wizardry/spell/Cobwebs.java b/src/main/java/electroblob/wizardry/spell/Cobwebs.java index 1e78ac2d..9d2367a1 100644 --- a/src/main/java/electroblob/wizardry/spell/Cobwebs.java +++ b/src/main/java/electroblob/wizardry/spell/Cobwebs.java @@ -1,63 +1,58 @@ package electroblob.wizardry.spell; -import electroblob.wizardry.constants.Element; -import electroblob.wizardry.constants.SpellType; -import electroblob.wizardry.constants.Tier; +import electroblob.wizardry.constants.Constants; import electroblob.wizardry.registry.WizardryBlocks; import electroblob.wizardry.registry.WizardryItems; import electroblob.wizardry.tileentity.TileEntityTimer; import electroblob.wizardry.util.SpellModifiers; +import electroblob.wizardry.util.WizardryUtilities; import net.minecraft.entity.Entity; import net.minecraft.entity.EntityLivingBase; -import net.minecraft.init.SoundEvents; +import net.minecraft.item.EnumAction; import net.minecraft.util.EnumFacing; import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.Vec3d; import net.minecraft.world.World; +import java.util.List; + public class Cobwebs extends SpellRay { - private static final int BASE_DURATION = 400; - public Cobwebs(){ - super("cobwebs", Tier.ADVANCED, Element.EARTH, SpellType.ATTACK, 30, 70, false, 12, SoundEvents.BLOCK_LAVA_EXTINGUISH); - this.ignoreEntities(true); + super("cobwebs", false, EnumAction.NONE); + this.ignoreLivingEntities(true); + addProperties(EFFECT_RADIUS, DURATION); } - @Override public boolean doesSpellRequirePacket(){ return false; } + @Override public boolean requiresPacket(){ return false; } @Override - protected boolean onEntityHit(World world, Entity target, EntityLivingBase caster, int ticksInUse, SpellModifiers modifiers){ + protected boolean onEntityHit(World world, Entity target, Vec3d hit, EntityLivingBase caster, Vec3d origin, int ticksInUse, SpellModifiers modifiers){ return false; } @Override - protected boolean onBlockHit(World world, BlockPos pos, EnumFacing side, EntityLivingBase caster, int ticksInUse, SpellModifiers modifiers){ + protected boolean onBlockHit(World world, BlockPos pos, EnumFacing side, Vec3d hit, EntityLivingBase caster, Vec3d origin, int ticksInUse, SpellModifiers modifiers){ boolean flag = false; pos = pos.offset(side); - if(world.isAirBlock(pos)){ - if(!world.isRemote){ - world.setBlockState(pos, WizardryBlocks.vanishing_cobweb.getDefaultState()); - if(world.getTileEntity(pos) instanceof TileEntityTimer){ - ((TileEntityTimer)world.getTileEntity(pos)) - .setLifetime((int)(BASE_DURATION * modifiers.get(WizardryItems.duration_upgrade))); - } - } - flag = true; - } + int blastUpgradeCount = (int)((modifiers.get(WizardryItems.blast_upgrade) - 1) / Constants.RANGE_INCREASE_PER_LEVEL + 0.5f); - for(EnumFacing facing : EnumFacing.values()){ + float radius = getProperty(EFFECT_RADIUS).floatValue() + 0.73f * blastUpgradeCount; - BlockPos pos1 = pos.offset(facing); + List sphere = WizardryUtilities.getBlockSphere(pos, radius * modifiers.get(WizardryItems.blast_upgrade)); + + for(BlockPos pos1 : sphere){ if(world.isAirBlock(pos1)){ if(!world.isRemote){ world.setBlockState(pos1, WizardryBlocks.vanishing_cobweb.getDefaultState()); if(world.getTileEntity(pos1) instanceof TileEntityTimer){ ((TileEntityTimer)world.getTileEntity(pos1)) - .setLifetime((int)(BASE_DURATION * modifiers.get(WizardryItems.duration_upgrade))); + .setLifetime((int)(getProperty(DURATION).doubleValue() + * modifiers.get(WizardryItems.duration_upgrade))); } } flag = true; @@ -68,7 +63,7 @@ public class Cobwebs extends SpellRay { } @Override - protected boolean onMiss(World world, EntityLivingBase caster, int ticksInUse, SpellModifiers modifiers){ + protected boolean onMiss(World world, EntityLivingBase caster, Vec3d origin, Vec3d direction, int ticksInUse, SpellModifiers modifiers){ return false; } diff --git a/src/main/java/electroblob/wizardry/spell/ConjureArmour.java b/src/main/java/electroblob/wizardry/spell/ConjureArmour.java index 9ae9ce91..ff2294a2 100644 --- a/src/main/java/electroblob/wizardry/spell/ConjureArmour.java +++ b/src/main/java/electroblob/wizardry/spell/ConjureArmour.java @@ -1,22 +1,28 @@ package electroblob.wizardry.spell; -import electroblob.wizardry.constants.Element; -import electroblob.wizardry.constants.SpellType; -import electroblob.wizardry.constants.Tier; +import com.google.common.collect.ImmutableMap; import electroblob.wizardry.item.IConjuredItem; import electroblob.wizardry.registry.WizardryItems; -import electroblob.wizardry.registry.WizardrySounds; import electroblob.wizardry.util.SpellModifiers; import electroblob.wizardry.util.WizardryUtilities; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.inventory.EntityEquipmentSlot; +import net.minecraft.item.Item; import net.minecraft.item.ItemStack; import net.minecraft.nbt.NBTTagList; +import java.util.Map; + public class ConjureArmour extends SpellConjuration { + + private static final Map SPECTRAL_ARMOUR_MAP = ImmutableMap.of( + EntityEquipmentSlot.HEAD, WizardryItems.spectral_helmet, + EntityEquipmentSlot.CHEST, WizardryItems.spectral_chestplate, + EntityEquipmentSlot.LEGS, WizardryItems.spectral_leggings, + EntityEquipmentSlot.FEET, WizardryItems.spectral_boots); public ConjureArmour(){ - super("conjure_armour", Tier.ADVANCED, Element.HEALING, SpellType.DEFENCE, 45, 50, null, WizardrySounds.SPELL_CONJURATION); + super("conjure_armour", null); } @Override @@ -29,9 +35,9 @@ public class ConjureArmour extends SpellConjuration { for(EntityEquipmentSlot slot : WizardryUtilities.ARMOUR_SLOTS){ if(caster.getItemStackFromSlot(slot).isEmpty() && - !WizardryUtilities.doesPlayerHaveItem(caster, WizardryItems.SPECTRAL_ARMOUR_MAP.get(slot))){ + !WizardryUtilities.doesPlayerHaveItem(caster, SPECTRAL_ARMOUR_MAP.get(slot))){ - armour = new ItemStack(WizardryItems.SPECTRAL_ARMOUR_MAP.get(slot)); + armour = new ItemStack(SPECTRAL_ARMOUR_MAP.get(slot)); IConjuredItem.setDurationMultiplier(armour, modifiers.get(WizardryItems.duration_upgrade)); // Sets a blank "ench" tag to trick the renderer into showing the enchantment effect on the armour model armour.getTagCompound().setTag("ench", new NBTTagList()); diff --git a/src/main/java/electroblob/wizardry/spell/ConjureBlock.java b/src/main/java/electroblob/wizardry/spell/ConjureBlock.java new file mode 100644 index 00000000..23250b49 --- /dev/null +++ b/src/main/java/electroblob/wizardry/spell/ConjureBlock.java @@ -0,0 +1,79 @@ +package electroblob.wizardry.spell; + +import electroblob.wizardry.registry.WizardryBlocks; +import electroblob.wizardry.registry.WizardryItems; +import electroblob.wizardry.tileentity.TileEntityTimer; +import electroblob.wizardry.util.ParticleBuilder; +import electroblob.wizardry.util.ParticleBuilder.Type; +import electroblob.wizardry.util.SpellModifiers; +import electroblob.wizardry.util.WizardryUtilities; +import net.minecraft.entity.Entity; +import net.minecraft.entity.EntityLivingBase; +import net.minecraft.item.EnumAction; +import net.minecraft.util.EnumFacing; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.Vec3d; +import net.minecraft.world.World; + +public class ConjureBlock extends SpellRay { + + private static final String BLOCK_LIFETIME = "block_lifetime"; + + public ConjureBlock(){ + super("conjure_block", false, EnumAction.NONE); + this.ignoreLivingEntities(true); + addProperties(BLOCK_LIFETIME); + } + + @Override + protected boolean onEntityHit(World world, Entity target, Vec3d hit, EntityLivingBase caster, Vec3d origin, int ticksInUse, SpellModifiers modifiers){ + return false; + } + + @Override + protected boolean onBlockHit(World world, BlockPos pos, EnumFacing side, Vec3d hit, EntityLivingBase caster, Vec3d origin, int ticksInUse, SpellModifiers modifiers){ + + if(world.getBlockState(pos).getBlock() == WizardryBlocks.spectral_block){ + + if(!world.isRemote){ + // Dispelling of blocks + world.setBlockToAir(pos); + }else{ + ParticleBuilder.create(Type.FLASH).pos(pos.getX() + 0.5, pos.getY() + 0.5, pos.getZ() + 0.5).scale(3) + .clr(0.75f, 1, 0.85f).spawn(world); + } + + return true; + } + + pos = pos.offset(side); + + if(world.isRemote){ + ParticleBuilder.create(Type.FLASH).pos(pos.getX() + 0.5, pos.getY() + 0.5, pos.getZ() + 0.5).scale(3) + .clr(0.75f, 1, 0.85f).spawn(world); + } + + if(WizardryUtilities.canBlockBeReplaced(world, pos)){ + + if(!world.isRemote){ + + world.setBlockState(pos, WizardryBlocks.spectral_block.getDefaultState()); + + if(world.getTileEntity(pos) instanceof TileEntityTimer){ + ((TileEntityTimer)world.getTileEntity(pos)).setLifetime((int)(getProperty(BLOCK_LIFETIME).floatValue() + * modifiers.get(WizardryItems.duration_upgrade))); + } + } + + return true; + } + + return false; + } + + @Override + protected boolean onMiss(World world, EntityLivingBase caster, Vec3d origin, Vec3d direction, int ticksInUse, SpellModifiers modifiers){ + return false; + } + +} diff --git a/src/main/java/electroblob/wizardry/spell/Containment.java b/src/main/java/electroblob/wizardry/spell/Containment.java new file mode 100644 index 00000000..cc9c0b71 --- /dev/null +++ b/src/main/java/electroblob/wizardry/spell/Containment.java @@ -0,0 +1,54 @@ +package electroblob.wizardry.spell; + +import electroblob.wizardry.registry.WizardryItems; +import electroblob.wizardry.registry.WizardryPotions; +import electroblob.wizardry.util.ParticleBuilder; +import electroblob.wizardry.util.ParticleBuilder.Type; +import electroblob.wizardry.util.SpellModifiers; +import electroblob.wizardry.util.WizardryUtilities; +import net.minecraft.entity.Entity; +import net.minecraft.entity.EntityLivingBase; +import net.minecraft.item.EnumAction; +import net.minecraft.potion.PotionEffect; +import net.minecraft.util.EnumFacing; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.Vec3d; +import net.minecraft.world.World; + +public class Containment extends SpellRay { + + public Containment(){ + super("containment", false, EnumAction.NONE); + this.soundValues(1, 1, 0.2f); + addProperties(EFFECT_DURATION, EFFECT_STRENGTH); + } + + @Override + protected boolean onEntityHit(World world, Entity target, Vec3d hit, EntityLivingBase caster, Vec3d origin, int ticksInUse, SpellModifiers modifiers){ + + if(WizardryUtilities.isLiving(target)){ + ((EntityLivingBase)target).addPotionEffect(new PotionEffect(WizardryPotions.containment, + (int)(getProperty(EFFECT_DURATION).floatValue() * modifiers.get(WizardryItems.duration_upgrade)), + getProperty(EFFECT_STRENGTH).intValue() + SpellBuff.getStandardBonusAmplifier(modifiers.get(SpellModifiers.POTENCY)))); + } + + return true; + } + + @Override + protected boolean onBlockHit(World world, BlockPos pos, EnumFacing side, Vec3d hit, EntityLivingBase caster, Vec3d origin, int ticksInUse, SpellModifiers modifiers){ + return false; + } + + @Override + protected boolean onMiss(World world, EntityLivingBase caster, Vec3d origin, Vec3d direction, int ticksInUse, SpellModifiers modifiers){ + return true; + } + + @Override + protected void spawnParticle(World world, double x, double y, double z, double vx, double vy, double vz){ + ParticleBuilder.create(Type.PATH).pos(x, y, z).clr(0x7988cc).time(20 + world.rand.nextInt(8)).spawn(world); + ParticleBuilder.create(Type.SPARKLE).pos(x, y, z).time(12 + world.rand.nextInt(8)).clr(1f, 1f, 1f).spawn(world); + } + +} diff --git a/src/main/java/electroblob/wizardry/spell/CureEffects.java b/src/main/java/electroblob/wizardry/spell/CureEffects.java index d0f4a372..6be6e69a 100644 --- a/src/main/java/electroblob/wizardry/spell/CureEffects.java +++ b/src/main/java/electroblob/wizardry/spell/CureEffects.java @@ -1,25 +1,36 @@ package electroblob.wizardry.spell; -import electroblob.wizardry.constants.Element; -import electroblob.wizardry.constants.SpellType; -import electroblob.wizardry.constants.Tier; -import electroblob.wizardry.registry.WizardrySounds; import electroblob.wizardry.util.SpellModifiers; import net.minecraft.entity.EntityLivingBase; +import net.minecraft.init.Items; +import net.minecraft.item.ItemStack; +import net.minecraft.potion.PotionEffect; public class CureEffects extends SpellBuff { public CureEffects(){ - super("cure_effects", Tier.APPRENTICE, Element.HEALING, SpellType.DEFENCE, 25, 40, WizardrySounds.SPELL_HEAL, 0.8f, 0.8f, 1); + super("cure_effects", 0.8f, 0.8f, 1); this.soundValues(0.7f, 1.2f, 0.4f); } @Override protected boolean applyEffects(EntityLivingBase caster, SpellModifiers modifiers){ - + if(!caster.getActivePotionEffects().isEmpty()){ - caster.clearActivePotions(); - return true; + + ItemStack milk = new ItemStack(Items.MILK_BUCKET); + + boolean flag = false; + + for(PotionEffect effect : caster.getActivePotionEffects()){ + // The PotionEffect version (as opposed to Potion) does not call cleanup callbacks + if(effect.isCurativeItem(milk)){ + caster.removePotionEffect(effect.getPotion()); + flag = true; + } + } + + return flag; } return false; diff --git a/src/main/java/electroblob/wizardry/spell/CurseOfEnfeeblement.java b/src/main/java/electroblob/wizardry/spell/CurseOfEnfeeblement.java new file mode 100644 index 00000000..a6a5f2e1 --- /dev/null +++ b/src/main/java/electroblob/wizardry/spell/CurseOfEnfeeblement.java @@ -0,0 +1,60 @@ +package electroblob.wizardry.spell; + +import electroblob.wizardry.registry.WizardryPotions; +import electroblob.wizardry.util.MagicDamage; +import electroblob.wizardry.util.ParticleBuilder; +import electroblob.wizardry.util.ParticleBuilder.Type; +import electroblob.wizardry.util.SpellModifiers; +import electroblob.wizardry.util.WizardryUtilities; +import net.minecraft.entity.Entity; +import net.minecraft.entity.EntityLivingBase; +import net.minecraft.item.EnumAction; +import net.minecraft.potion.PotionEffect; +import net.minecraft.util.EnumFacing; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.Vec3d; +import net.minecraft.world.World; + +public class CurseOfEnfeeblement extends SpellRay { + + public CurseOfEnfeeblement(){ + super("curse_of_enfeeblement", false, EnumAction.NONE); + this.soundValues(1, 1.1f, 0.2f); + addProperties(EFFECT_STRENGTH); + } + + @Override + protected boolean onEntityHit(World world, Entity target, Vec3d hit, EntityLivingBase caster, Vec3d origin, int ticksInUse, SpellModifiers modifiers){ + + if(WizardryUtilities.isLiving(target)){ + // This will actually run out in the end, but only if you leave Minecraft running for 3.4 years + ((EntityLivingBase)target).addPotionEffect(new PotionEffect(WizardryPotions.curse_of_enfeeblement, + Integer.MAX_VALUE, getProperty(EFFECT_STRENGTH).intValue() + SpellBuff.getStandardBonusAmplifier(modifiers.get(SpellModifiers.POTENCY)))); + // Reduce the target's health to its new max health if necessary + if(((EntityLivingBase)target).getHealth() > ((EntityLivingBase)target).getMaxHealth()){ + target.attackEntityFrom(MagicDamage.causeDirectMagicDamage(caster, MagicDamage.DamageType.WITHER), + ((EntityLivingBase)target).getHealth() - ((EntityLivingBase)target).getMaxHealth()); + } + } + + return true; + } + + @Override + protected boolean onBlockHit(World world, BlockPos pos, EnumFacing side, Vec3d hit, EntityLivingBase caster, Vec3d origin, int ticksInUse, SpellModifiers modifiers){ + return false; + } + + @Override + protected boolean onMiss(World world, EntityLivingBase caster, Vec3d origin, Vec3d direction, int ticksInUse, SpellModifiers modifiers){ + return true; + } + + @Override + protected void spawnParticle(World world, double x, double y, double z, double vx, double vy, double vz){ + ParticleBuilder.create(Type.DARK_MAGIC).pos(x, y, z).clr(0.2f, 0, 0.3f).spawn(world); + ParticleBuilder.create(Type.DARK_MAGIC).pos(x, y, z).clr(0.1f, 0, 0).spawn(world); + ParticleBuilder.create(Type.SPARKLE).pos(x, y, z).time(12 + world.rand.nextInt(8)).clr(0.4f, 0, 0).spawn(world); + } + +} diff --git a/src/main/java/electroblob/wizardry/spell/CurseOfSoulbinding.java b/src/main/java/electroblob/wizardry/spell/CurseOfSoulbinding.java index 76797c44..c7721ba5 100644 --- a/src/main/java/electroblob/wizardry/spell/CurseOfSoulbinding.java +++ b/src/main/java/electroblob/wizardry/spell/CurseOfSoulbinding.java @@ -1,54 +1,80 @@ package electroblob.wizardry.spell; -import electroblob.wizardry.WizardData; -import electroblob.wizardry.constants.Element; -import electroblob.wizardry.constants.SpellType; -import electroblob.wizardry.constants.Tier; -import electroblob.wizardry.util.IElementalDamage; -import electroblob.wizardry.util.ParticleBuilder; +import electroblob.wizardry.data.IStoredVariable; +import electroblob.wizardry.data.Persistence; +import electroblob.wizardry.data.WizardData; +import electroblob.wizardry.integration.DamageSafetyChecker; +import electroblob.wizardry.registry.WizardryPotions; +import electroblob.wizardry.registry.WizardrySounds; +import electroblob.wizardry.util.*; import electroblob.wizardry.util.ParticleBuilder.Type; -import electroblob.wizardry.util.SpellModifiers; -import electroblob.wizardry.util.WizardryUtilities; import net.minecraft.entity.Entity; import net.minecraft.entity.EntityLivingBase; import net.minecraft.entity.player.EntityPlayer; -import net.minecraft.init.SoundEvents; +import net.minecraft.item.EnumAction; +import net.minecraft.nbt.NBTTagList; +import net.minecraft.nbt.NBTUtil; +import net.minecraft.potion.PotionEffect; +import net.minecraft.util.DamageSource; import net.minecraft.util.EnumFacing; import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.Vec3d; import net.minecraft.world.World; import net.minecraftforge.event.entity.living.LivingHurtEvent; import net.minecraftforge.fml.common.Mod; import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; +import java.util.HashSet; +import java.util.Iterator; +import java.util.Set; +import java.util.UUID; + @Mod.EventBusSubscriber public class CurseOfSoulbinding extends SpellRay { + public static final IStoredVariable> TARGETS_KEY = new IStoredVariable.StoredVariable<>("soulboundCreatures", + s -> NBTExtras.listToNBT(s, NBTUtil::createUUIDTag), + // For some reason gradle screams at me unless I explicitly declare the type of t here, despite IntelliJ being fine without it + (NBTTagList t) -> new HashSet<>(NBTExtras.NBTToList(t, NBTUtil::getUUIDFromTag)), + // Curse of soulbinding is lifted when the caster dies, but not when they switch dimensions. + Persistence.DIMENSION_CHANGE); + public CurseOfSoulbinding(){ - super("curse_of_soulbinding", Tier.ADVANCED, Element.NECROMANCY, SpellType.ATTACK, 35, 100, false, 10, SoundEvents.ENTITY_WITHER_SPAWN); + super("curse_of_soulbinding", false, EnumAction.NONE); this.soundValues(1, 1.1f, 0.2f); + WizardData.registerStoredVariables(TARGETS_KEY); } - + @Override public boolean canBeCastByNPCs() { return false; } + // You can't damage a dispenser so this would be nonsense! + @Override public boolean canBeCastByDispensers() { return false; } @Override - protected boolean onEntityHit(World world, Entity target, EntityLivingBase caster, int ticksInUse, SpellModifiers modifiers){ + protected boolean onEntityHit(World world, Entity target, Vec3d hit, EntityLivingBase caster, Vec3d origin, int ticksInUse, SpellModifiers modifiers){ - if(WizardryUtilities.isLiving(target) && caster instanceof EntityPlayer - && WizardData.get((EntityPlayer)caster) != null){ - // Return false if soulbinding failed (e.g. if the target is already soulbound) - if(!WizardData.get((EntityPlayer)caster).soulbind((EntityLivingBase)target)) return false; + if(WizardryUtilities.isLiving(target) && caster instanceof EntityPlayer){ + WizardData data = WizardData.get((EntityPlayer)caster); + if(data != null){ + // Return false if soulbinding failed (e.g. if the target is already soulbound) + if(getSoulboundCreatures(data).add(target.getUniqueID())){ + // This will actually run out in the end, but only if you leave Minecraft running for 3.4 years + ((EntityLivingBase)target).addPotionEffect(new PotionEffect(WizardryPotions.curse_of_soulbinding, Integer.MAX_VALUE)); + }else{ + return false; + } + } } return true; } @Override - protected boolean onBlockHit(World world, BlockPos pos, EnumFacing side, EntityLivingBase caster, int ticksInUse, SpellModifiers modifiers){ + protected boolean onBlockHit(World world, BlockPos pos, EnumFacing side, Vec3d hit, EntityLivingBase caster, Vec3d origin, int ticksInUse, SpellModifiers modifiers){ return false; } @Override - protected boolean onMiss(World world, EntityLivingBase caster, int ticksInUse, SpellModifiers modifiers){ + protected boolean onMiss(World world, EntityLivingBase caster, Vec3d origin, Vec3d direction, int ticksInUse, SpellModifiers modifiers){ return true; } @@ -65,11 +91,41 @@ public class CurseOfSoulbinding extends SpellRay { if(!event.getEntity().world.isRemote && event.getEntityLiving() instanceof EntityPlayer && !event.getSource().isUnblockable() && !(event.getSource() instanceof IElementalDamage && ((IElementalDamage)event.getSource()).isRetaliatory())){ - WizardData data = WizardData.get((EntityPlayer)event.getEntityLiving()); + + EntityPlayer player = (EntityPlayer)event.getEntityLiving(); + WizardData data = WizardData.get(player); + if(data != null){ - data.damageAllSoulboundCreatures(event.getAmount(), event.getSource().getDamageType()); + + for(Iterator iterator = getSoulboundCreatures(data).iterator(); iterator.hasNext();){ + + Entity entity = WizardryUtilities.getEntityByUUID(player.world, iterator.next()); + + if(entity == null) iterator.remove(); + + if(entity instanceof EntityLivingBase){ + // Retaliatory effect + if(DamageSafetyChecker.attackEntitySafely(entity, MagicDamage.causeDirectMagicDamage(player, + MagicDamage.DamageType.MAGIC, true), event.getAmount(), event.getSource().getDamageType(), + DamageSource.MAGIC, false)){ + // Sound only plays if the damage succeeds + entity.playSound(WizardrySounds.SPELL_CURSE_OF_SOULBINDING_RETALIATE, 1.0F, player.world.rand.nextFloat() * 0.2F + 1.0F); + } + } + } + } } } + public static Set getSoulboundCreatures(WizardData data){ + + if(data.getVariable(TARGETS_KEY) == null){ + Set result = new HashSet<>(); + data.setVariable(TARGETS_KEY, result); + return result; + + }else return data.getVariable(TARGETS_KEY); + } + } diff --git a/src/main/java/electroblob/wizardry/spell/CurseOfUndeath.java b/src/main/java/electroblob/wizardry/spell/CurseOfUndeath.java new file mode 100644 index 00000000..f97e1148 --- /dev/null +++ b/src/main/java/electroblob/wizardry/spell/CurseOfUndeath.java @@ -0,0 +1,55 @@ +package electroblob.wizardry.spell; + +import electroblob.wizardry.registry.WizardryPotions; +import electroblob.wizardry.util.ParticleBuilder; +import electroblob.wizardry.util.ParticleBuilder.Type; +import electroblob.wizardry.util.SpellModifiers; +import electroblob.wizardry.util.WizardryUtilities; +import net.minecraft.entity.Entity; +import net.minecraft.entity.EntityLivingBase; +import net.minecraft.item.EnumAction; +import net.minecraft.potion.PotionEffect; +import net.minecraft.util.EnumFacing; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.Vec3d; +import net.minecraft.world.World; + +public class CurseOfUndeath extends SpellRay { + + public CurseOfUndeath(){ + super("curse_of_undeath", false, EnumAction.NONE); + this.soundValues(1, 1.1f, 0.2f); + addProperties(EFFECT_STRENGTH); + } + + @Override + protected boolean onEntityHit(World world, Entity target, Vec3d hit, EntityLivingBase caster, Vec3d origin, int ticksInUse, SpellModifiers modifiers){ + + if(WizardryUtilities.isLiving(target)){ + + // This will actually run out in the end, but only if you leave Minecraft running for 3.4 years + ((EntityLivingBase)target).addPotionEffect(new PotionEffect(WizardryPotions.curse_of_undeath, Integer.MAX_VALUE, + getProperty(EFFECT_STRENGTH).intValue() + SpellBuff.getStandardBonusAmplifier(modifiers.get(SpellModifiers.POTENCY)))); + } + + return true; + } + + @Override + protected boolean onBlockHit(World world, BlockPos pos, EnumFacing side, Vec3d hit, EntityLivingBase caster, Vec3d origin, int ticksInUse, SpellModifiers modifiers){ + return false; + } + + @Override + protected boolean onMiss(World world, EntityLivingBase caster, Vec3d origin, Vec3d direction, int ticksInUse, SpellModifiers modifiers){ + return true; + } + + @Override + protected void spawnParticle(World world, double x, double y, double z, double vx, double vy, double vz){ + ParticleBuilder.create(Type.DARK_MAGIC).pos(x, y, z).clr(0x686c00).spawn(world); + ParticleBuilder.create(Type.DARK_MAGIC).pos(x, y, z).clr(0x251609).spawn(world); + ParticleBuilder.create(Type.SPARKLE).pos(x, y, z).time(12 + world.rand.nextInt(8)).clr(0xe6e592).spawn(world); + } + +} diff --git a/src/main/java/electroblob/wizardry/spell/Decay.java b/src/main/java/electroblob/wizardry/spell/Decay.java index 598a09c6..dc6e9f41 100644 --- a/src/main/java/electroblob/wizardry/spell/Decay.java +++ b/src/main/java/electroblob/wizardry/spell/Decay.java @@ -1,43 +1,43 @@ package electroblob.wizardry.spell; -import electroblob.wizardry.constants.Element; -import electroblob.wizardry.constants.SpellType; -import electroblob.wizardry.constants.Tier; import electroblob.wizardry.entity.construct.EntityDecay; import electroblob.wizardry.registry.WizardryItems; import electroblob.wizardry.util.SpellModifiers; import electroblob.wizardry.util.WizardryUtilities; import net.minecraft.entity.EntityLivingBase; -import net.minecraft.init.SoundEvents; +import net.minecraft.util.EnumFacing; import net.minecraft.util.math.BlockPos; import net.minecraft.world.World; public class Decay extends SpellConstructRanged { - - private static final int BASE_SPAWN_COUNT = 5; + + public static final String DECAY_PATCHES_SPAWNED = "decay_patches_spawned"; public Decay(){ - super("decay", Tier.ADVANCED, Element.NECROMANCY, SpellType.ATTACK, 50, 200, EntityDecay::new, 400, 12, SoundEvents.ENTITY_WITHER_SHOOT); + super("decay", EntityDecay::new, false); this.soundValues(1, 1.1f, 0.1f); this.floor(true); this.overlap(true); + addProperties(DECAY_PATCHES_SPAWNED, EFFECT_DURATION); } @Override - protected boolean spawnConstruct(World world, double x, double y, double z, EntityLivingBase caster, SpellModifiers modifiers){ + protected boolean spawnConstruct(World world, double x, double y, double z, EnumFacing side, EntityLivingBase caster, SpellModifiers modifiers){ if(world.getBlockState(new BlockPos(x, y, z)).isNormalCube()) return false; - super.spawnConstruct(world, x, y, z, caster, modifiers); - - int quantity = (int)(BASE_SPAWN_COUNT * modifiers.get(WizardryItems.blast_upgrade)); - int horizontalRange = (int)(2 * modifiers.get(WizardryItems.blast_upgrade)); + super.spawnConstruct(world, x, y, z, side, caster, modifiers); + + float decayCount = getProperty(DECAY_PATCHES_SPAWNED).floatValue(); + int quantity = (int)(decayCount * modifiers.get(WizardryItems.blast_upgrade)); + // If there are more decay patches, they need more space to spawn in + int horizontalRange = (int)(0.4 * decayCount * modifiers.get(WizardryItems.blast_upgrade)); int verticalRange = (int)(6 * modifiers.get(WizardryItems.blast_upgrade)); for(int i=0; i targets = WizardryUtilities.getEntitiesWithinRadius( - BASE_RADIUS * modifiers.get(WizardryItems.blast_upgrade), pos.getX(), pos.getY(), pos.getZ(), world); + List targets = WizardryUtilities.getEntitiesWithinRadius(getProperty(BLAST_RADIUS).doubleValue() + * modifiers.get(WizardryItems.blast_upgrade), pos.getX(), pos.getY(), pos.getZ(), world); for(EntityLivingBase target : targets){ target.attackEntityFrom(MagicDamage.causeDirectMagicDamage(caster, DamageType.BLAST), // Damage decreases with distance but cannot be less than 0, naturally. - Math.max(12.0f - (float)target.getDistance(pos.getX() + 0.5, pos.getY() + 0.5, pos.getZ() + 0.5) - * 4, 0) * modifiers.get(SpellModifiers.POTENCY)); + Math.max(getProperty(MAX_DAMAGE).floatValue() - (float)target.getDistance(pos.getX() + 0.5, + pos.getY() + 0.5, pos.getZ() + 0.5) * 4, 0) * modifiers.get(SpellModifiers.POTENCY)); } }else{ @@ -56,7 +56,7 @@ public class Detonate extends SpellRay { } @Override - protected boolean onMiss(World world, EntityLivingBase caster, int ticksInUse, SpellModifiers modifiers){ + protected boolean onMiss(World world, EntityLivingBase caster, Vec3d origin, Vec3d direction, int ticksInUse, SpellModifiers modifiers){ return false; } diff --git a/src/main/java/electroblob/wizardry/spell/Disintegration.java b/src/main/java/electroblob/wizardry/spell/Disintegration.java new file mode 100644 index 00000000..0dda0a58 --- /dev/null +++ b/src/main/java/electroblob/wizardry/spell/Disintegration.java @@ -0,0 +1,97 @@ +package electroblob.wizardry.spell; + +import electroblob.wizardry.entity.projectile.EntityEmber; +import electroblob.wizardry.registry.WizardryItems; +import electroblob.wizardry.util.MagicDamage; +import electroblob.wizardry.util.MagicDamage.DamageType; +import electroblob.wizardry.util.ParticleBuilder; +import electroblob.wizardry.util.ParticleBuilder.Type; +import electroblob.wizardry.util.SpellModifiers; +import electroblob.wizardry.util.WizardryUtilities; +import net.minecraft.entity.Entity; +import net.minecraft.entity.EntityLivingBase; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.item.EnumAction; +import net.minecraft.util.DamageSource; +import net.minecraft.util.EnumFacing; +import net.minecraft.util.EnumParticleTypes; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.Vec3d; +import net.minecraft.util.text.TextComponentTranslation; +import net.minecraft.world.World; + +public class Disintegration extends SpellRay { + + public static final String EMBER_COUNT = "ember_count"; + public static final String EMBER_LIFETIME = "ember_lifetime"; + + public Disintegration(){ + super("disintegration", false, EnumAction.NONE); + addProperties(DAMAGE, BURN_DURATION, EMBER_LIFETIME, EMBER_COUNT); + } + + @Override + protected boolean onEntityHit(World world, Entity target, Vec3d hit, EntityLivingBase caster, Vec3d origin, int ticksInUse, SpellModifiers modifiers){ + + if(MagicDamage.isEntityImmune(DamageType.FIRE, target)){ + if(!world.isRemote && caster instanceof EntityPlayer) ((EntityPlayer)caster).sendStatusMessage( + new TextComponentTranslation("spell.resist", target.getName(), this.getNameForTranslationFormatted()), true); + }else{ + + target.setFire((int)(getProperty(BURN_DURATION).floatValue() * modifiers.get(WizardryItems.duration_upgrade))); + WizardryUtilities.attackEntityWithoutKnockback(target, caster == null ? DamageSource.MAGIC : + MagicDamage.causeDirectMagicDamage(caster, DamageType.FIRE), + getProperty(DAMAGE).floatValue() * modifiers.get(SpellModifiers.POTENCY)); + + if(!world.isRemote && target instanceof EntityLivingBase && ((EntityLivingBase)target).getHealth() <= 0){ + spawnEmbers(world, caster, target, getProperty(EMBER_COUNT).intValue()); + } + } + + return true; + } + + public static void spawnEmbers(World world, EntityLivingBase caster, Entity target, int count){ + + for(int i = 0; i < count; i++){ + EntityEmber ember = new EntityEmber(world, caster); + double x = (world.rand.nextDouble() - 0.5) * target.width; + double y = world.rand.nextDouble() * target.height; + double z = (world.rand.nextDouble() - 0.5) * target.width; + ember.setPosition(target.posX + x, target.posY + y, target.posZ + z); + float speed = 0.2f; + ember.setVelocity(x * speed, y * 0.5f * speed, z * speed); + world.spawnEntity(ember); + } + } + + @Override + protected boolean onBlockHit(World world, BlockPos pos, EnumFacing side, Vec3d hit, EntityLivingBase caster, Vec3d origin, int ticksInUse, SpellModifiers modifiers){ + + if(world.isRemote){ + + for(int i = 0; i < 8; i++){ + world.spawnParticle(EnumParticleTypes.LAVA, hit.x, hit.y, hit.z, 0, 0, 0); + } + + if(world.getBlockState(pos).getMaterial().isSolid()){ + Vec3d vec = hit.add(new Vec3d(side.getDirectionVec()).scale(WizardryUtilities.ANTI_Z_FIGHTING_OFFSET)); + ParticleBuilder.create(Type.SCORCH).pos(vec).face(side).clr(1, 0.2f, 0).spawn(world); + } + } + + return false; + } + + @Override + protected boolean onMiss(World world, EntityLivingBase caster, Vec3d origin, Vec3d direction, int ticksInUse, SpellModifiers modifiers){ + return true; + } + + @Override + protected void spawnParticleRay(World world, Vec3d origin, Vec3d direction, EntityLivingBase caster, double distance){ + Vec3d endpoint = origin.add(direction.scale(distance)); + ParticleBuilder.create(Type.BEAM).clr(1, 0.4f, 0).fade(1, 0.1f, 0).time(4).pos(origin).target(endpoint).spawn(world); + } + +} diff --git a/src/main/java/electroblob/wizardry/spell/Divination.java b/src/main/java/electroblob/wizardry/spell/Divination.java new file mode 100644 index 00000000..f4ed42b6 --- /dev/null +++ b/src/main/java/electroblob/wizardry/spell/Divination.java @@ -0,0 +1,149 @@ +package electroblob.wizardry.spell; + +import electroblob.wizardry.Wizardry; +import electroblob.wizardry.block.BlockCrystalOre; +import electroblob.wizardry.registry.WizardryItems; +import electroblob.wizardry.util.ParticleBuilder; +import electroblob.wizardry.util.RelativeFacing; +import electroblob.wizardry.util.SpellModifiers; +import electroblob.wizardry.util.WizardryUtilities; +import net.minecraft.block.Block; +import net.minecraft.block.BlockOre; +import net.minecraft.block.BlockRedstoneOre; +import net.minecraft.entity.Entity; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.item.EnumAction; +import net.minecraft.item.ItemStack; +import net.minecraft.item.crafting.FurnaceRecipes; +import net.minecraft.util.EnumFacing; +import net.minecraft.util.EnumHand; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.Vec3d; +import net.minecraft.util.text.TextComponentTranslation; +import net.minecraft.world.World; + +import java.util.Arrays; +import java.util.Comparator; +import java.util.List; + +public class Divination extends Spell { + + private static final float NUDGE_SPEED = 0.2f; + + public Divination(){ + super("divination", EnumAction.NONE, false); + addProperties(RANGE); + } + + /** A set of constants representing the different 'signal strengths' for the divination spell. In practical + * terms, this means different chat readouts and effects. */ + protected enum Strength { + + NOTHING("nothing", -1), + WEAK("weak", 0), + MODERATE("moderate", 0.25f), + STRONG("strong", 0.5f), + VERY_STRONG("very_strong", 0.75f); + + String key; + float minWeight; + + Strength(String key, float minWeight){ + this.key = key; + this.minWeight = minWeight; + } + + protected static Strength forWeight(float weight){ + return Arrays.stream(values()).filter(s -> s.minWeight < weight).max(Comparator.naturalOrder()).orElse(NOTHING); + } + } + + @Override + public boolean cast(World world, EntityPlayer caster, EnumHand hand, int ticksInUse, SpellModifiers modifiers){ + + double range = getProperty(RANGE).floatValue() * modifiers.get(WizardryItems.range_upgrade); + + List sphere = WizardryUtilities.getBlockSphere(caster.getPosition(), range); + + sphere.removeIf(b -> !(world.getBlockState(b).getBlock() instanceof BlockOre + || world.getBlockState(b).getBlock() instanceof BlockRedstoneOre + || world.getBlockState(b).getBlock() instanceof BlockCrystalOre + || Arrays.asList(Wizardry.settings.divinationOreWhitelist) + .contains(world.getBlockState(b).getBlock().getRegistryName()))); + + Strength strength = Strength.NOTHING; + + EnumFacing direction = EnumFacing.DOWN; // Doesn't matter what this is + + if(!sphere.isEmpty()){ + + // Sorts the positions based on weight (see below), in ascending order + sphere.sort(Comparator.comparingDouble(b -> calculateWeight(world, caster, b, range, modifiers))); + + // The weights are sorted in ascending order, so this must be the largest + BlockPos target = sphere.get(sphere.size() - 1); + + direction = EnumFacing.getFacingFromVector((float)(target.getX() + 0.5 - caster.posX), + (float)(target.getY() + 0.5 - (caster.getEntityBoundingBox().minY + caster.getEyeHeight())), + (float)(target.getZ() + 0.5 - caster.posZ)); + + if(world.isRemote) ParticleBuilder.create(ParticleBuilder.Type.SPARKLE).pos(target.getX() + 0.5, + target.getY() + 1.5, target.getZ() + 0.5).spawn(world); + + strength = Strength.forWeight(calculateWeight(world, caster, target, range, modifiers)); + } + + if(!world.isRemote){ + caster.sendStatusMessage(new TextComponentTranslation("spell." + this.getUnlocalisedName() + "." + + strength.key, new TextComponentTranslation("spell." + this.getUnlocalisedName() + "." + + RelativeFacing.relativise(direction, caster).name)), false); + }else{ + switch(strength){ + case NOTHING: break; + case WEAK: break; + case MODERATE: + spawnHintParticles(world, caster, 3, direction); + break; + case STRONG: + spawnHintParticles(world, caster, 8, direction); + break; + case VERY_STRONG: + spawnHintParticles(world, caster, 12, direction); + caster.addVelocity(direction.getXOffset() * NUDGE_SPEED, direction.getYOffset() * NUDGE_SPEED, + direction.getZOffset() * NUDGE_SPEED); + break; + } + } + + return true; + } + + private static void spawnHintParticles(World world, Entity caster, int count, EnumFacing direction){ + + Vec3d vec = new Vec3d(caster.getPosition().offset(EnumFacing.UP).offset(direction, 2)).add(0.5, 0.5, 0.5); + + for(int i=0; i { + public class Earthquake extends SpellConstruct { + + public static final String SPREAD_SPEED = "spread_speed"; public Earthquake(){ - super("earthquake", Tier.MASTER, Element.EARTH, SpellType.ATTACK, 75, 250, EnumAction.NONE, EntityEarthquake::new, -1, WizardrySounds.SPELL_EARTHQUAKE); + super("earthquake", EnumAction.NONE, EntityEarthquake::new, true); this.soundValues(2, 1, 0); this.overlap(true); this.floor(true); + addProperties(EFFECT_RADIUS, SPREAD_SPEED); } // This one spawns particles - @Override public boolean doesSpellRequirePacket(){ return true; } + @Override public boolean requiresPacket(){ return true; } @Override - protected void addConstructExtras(EntityEarthquake construct, EntityLivingBase caster, SpellModifiers modifiers){ - construct.lifetime = (int)(20 * modifiers.get(WizardryItems.blast_upgrade)); + protected void addConstructExtras(EntityEarthquake construct, EnumFacing side, EntityLivingBase caster, SpellModifiers modifiers){ + // Calculates the lifetime based on the base radius and spread speed + // Also overwrites the -1 lifetime set due to permanent being true + construct.lifetime = (int)(getProperty(EFFECT_RADIUS).floatValue()/getProperty(SPREAD_SPEED).floatValue() + * modifiers.get(WizardryItems.blast_upgrade)); } @Override - protected boolean spawnConstruct(World world, double x, double y, double z, EntityLivingBase caster, SpellModifiers modifiers){ + protected boolean spawnConstruct(World world, double x, double y, double z, EnumFacing side, EntityLivingBase caster, SpellModifiers modifiers){ - // TODO: Couldn't this be moved to EntityEarthquake? if(world.isRemote){ world.spawnParticle(EnumParticleTypes.EXPLOSION_LARGE, caster.posX, @@ -49,15 +51,13 @@ public class Earthquake extends SpellConstruct { particleZ = caster.posZ - 1.0d + 2 * world.rand.nextDouble(); IBlockState block = WizardryUtilities.getBlockEntityIsStandingOn(caster); - if(block != null){ - world.spawnParticle(EnumParticleTypes.BLOCK_DUST, particleX, caster.getEntityBoundingBox().minY, - particleZ, particleX - caster.posX, 0, particleZ - caster.posZ, - Block.getStateId(block)); - } + world.spawnParticle(EnumParticleTypes.BLOCK_DUST, particleX, caster.getEntityBoundingBox().minY, + particleZ, particleX - caster.posX, 0, particleZ - caster.posZ, + Block.getStateId(block)); } } - return super.spawnConstruct(world, x, y, z, caster, modifiers); + return super.spawnConstruct(world, x, y, z, side, caster, modifiers); } } diff --git a/src/main/java/electroblob/wizardry/spell/EmpoweringPresence.java b/src/main/java/electroblob/wizardry/spell/EmpoweringPresence.java new file mode 100644 index 00000000..ad42d9c3 --- /dev/null +++ b/src/main/java/electroblob/wizardry/spell/EmpoweringPresence.java @@ -0,0 +1,81 @@ +package electroblob.wizardry.spell; + +import electroblob.wizardry.constants.Constants; +import electroblob.wizardry.event.SpellCastEvent; +import electroblob.wizardry.registry.WizardryItems; +import electroblob.wizardry.registry.WizardryPotions; +import electroblob.wizardry.util.AllyDesignationSystem; +import electroblob.wizardry.util.ParticleBuilder; +import electroblob.wizardry.util.ParticleBuilder.Type; +import electroblob.wizardry.util.SpellModifiers; +import electroblob.wizardry.util.WizardryUtilities; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.item.EnumAction; +import net.minecraft.potion.PotionEffect; +import net.minecraft.util.EnumHand; +import net.minecraft.util.math.MathHelper; +import net.minecraft.world.World; +import net.minecraftforge.fml.common.Mod; +import net.minecraftforge.fml.common.eventhandler.EventPriority; +import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; + +import java.util.List; + +@Mod.EventBusSubscriber +public class EmpoweringPresence extends Spell { + + public EmpoweringPresence(){ + super("empowering_presence", EnumAction.BOW, false); + addProperties(EFFECT_RADIUS, EFFECT_DURATION, EFFECT_STRENGTH); + } + + @Override + public boolean cast(World world, EntityPlayer caster, EnumHand hand, int ticksInUse, SpellModifiers modifiers){ + + List targets = WizardryUtilities.getEntitiesWithinRadius(getProperty(EFFECT_RADIUS).doubleValue() + * modifiers.get(WizardryItems.blast_upgrade), caster.posX, caster.posY, caster.posZ, world, EntityPlayer.class); + + for(EntityPlayer target : targets){ + if(AllyDesignationSystem.isPlayerAlly(caster, target) || target == caster){ + + int bonusAmplifier = SpellBuff.getStandardBonusAmplifier(modifiers.get(SpellModifiers.POTENCY)); + + target.addPotionEffect(new PotionEffect(WizardryPotions.empowerment, + (int)(getProperty(EFFECT_DURATION).floatValue() * modifiers.get(WizardryItems.duration_upgrade)), + getProperty(EFFECT_STRENGTH).intValue() + bonusAmplifier)); + } + } + + if(world.isRemote){ + + for(int i = 0; i < 50 * modifiers.get(WizardryItems.blast_upgrade); i++){ + + double radius = (1 + world.rand.nextDouble() * 4) * modifiers.get(WizardryItems.blast_upgrade); + float angle = world.rand.nextFloat() * (float)Math.PI * 2; + + double x = caster.posX + radius * MathHelper.cos(angle); + double y = caster.getEntityBoundingBox().minY; + double z = caster.posZ + radius * MathHelper.sin(angle); + + ParticleBuilder.create(Type.SPARKLE).pos(x, y, z).vel(0, 0.03, 0).time(50).clr(0.5f, 0.4f, 0.75f).spawn(world); + + } + } + + //WizardryUtilities.playSoundAtPlayer(caster, WizardrySounds.SPELL_CONJURATION, 1, 1 + 0.2f * world.rand.nextFloat()); + return true; + } + + @SubscribeEvent(priority = EventPriority.LOW) // Doesn't really matter but there's no point processing it if casting is blocked + public static void onSpellCastPreEvent(SpellCastEvent.Pre event){ + // Empowerment stacks extra potency on top of the existing potency. + if(event.getCaster() != null && event.getCaster().isPotionActive(WizardryPotions.empowerment)){ + + float potency = 1 + Constants.EMPOWERMENT_POTENCY_PER_LEVEL + * (event.getCaster().getActivePotionEffect(WizardryPotions.empowerment).getAmplifier() + 1); + + event.getModifiers().set(SpellModifiers.POTENCY, + event.getModifiers().get(SpellModifiers.POTENCY) * potency, true); + } + } +} \ No newline at end of file diff --git a/src/main/java/electroblob/wizardry/spell/Entrapment.java b/src/main/java/electroblob/wizardry/spell/Entrapment.java index 931a230e..7f20fbd8 100644 --- a/src/main/java/electroblob/wizardry/spell/Entrapment.java +++ b/src/main/java/electroblob/wizardry/spell/Entrapment.java @@ -1,8 +1,5 @@ package electroblob.wizardry.spell; -import electroblob.wizardry.constants.Element; -import electroblob.wizardry.constants.SpellType; -import electroblob.wizardry.constants.Tier; import electroblob.wizardry.entity.construct.EntityBubble; import electroblob.wizardry.registry.WizardryItems; import electroblob.wizardry.util.MagicDamage; @@ -13,21 +10,25 @@ import electroblob.wizardry.util.SpellModifiers; import electroblob.wizardry.util.WizardryUtilities; import net.minecraft.entity.Entity; import net.minecraft.entity.EntityLivingBase; -import net.minecraft.init.SoundEvents; +import net.minecraft.item.EnumAction; import net.minecraft.util.EnumFacing; import net.minecraft.util.EnumParticleTypes; import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.Vec3d; import net.minecraft.world.World; public class Entrapment extends SpellRay { + public static final String DAMAGE_INTERVAL = "damage_interval"; + public Entrapment(){ - super("entrapment", Tier.ADVANCED, Element.NECROMANCY, SpellType.ATTACK, 35, 75, false, 10, SoundEvents.ENTITY_WITHER_SHOOT); + super("entrapment", false, EnumAction.NONE); this.soundValues(1, 0.85f, 0.3f); + addProperties(EFFECT_DURATION, DAMAGE_INTERVAL); } @Override - protected boolean onEntityHit(World world, Entity target, EntityLivingBase caster, int ticksInUse, SpellModifiers modifiers){ + protected boolean onEntityHit(World world, Entity target, Vec3d hit, EntityLivingBase caster, Vec3d origin, int ticksInUse, SpellModifiers modifiers){ if(WizardryUtilities.isLiving(target)){ @@ -38,7 +39,7 @@ public class Entrapment extends SpellRay { EntityBubble bubble = new EntityBubble(world); bubble.setPosition(target.posX, target.posY, target.posZ); bubble.setCaster(caster); - bubble.lifetime = ((int)(200 * modifiers.get(WizardryItems.duration_upgrade))); + bubble.lifetime = ((int)(getProperty(EFFECT_DURATION).floatValue() * modifiers.get(WizardryItems.duration_upgrade))); bubble.isDarkOrb = true; bubble.damageMultiplier = modifiers.get(SpellModifiers.POTENCY); @@ -51,12 +52,12 @@ public class Entrapment extends SpellRay { } @Override - protected boolean onBlockHit(World world, BlockPos pos, EnumFacing side, EntityLivingBase caster, int ticksInUse, SpellModifiers modifiers){ + protected boolean onBlockHit(World world, BlockPos pos, EnumFacing side, Vec3d hit, EntityLivingBase caster, Vec3d origin, int ticksInUse, SpellModifiers modifiers){ return false; } @Override - protected boolean onMiss(World world, EntityLivingBase caster, int ticksInUse, SpellModifiers modifiers){ + protected boolean onMiss(World world, EntityLivingBase caster, Vec3d origin, Vec3d direction, int ticksInUse, SpellModifiers modifiers){ return true; } diff --git a/src/main/java/electroblob/wizardry/spell/Evade.java b/src/main/java/electroblob/wizardry/spell/Evade.java new file mode 100644 index 00000000..9df46093 --- /dev/null +++ b/src/main/java/electroblob/wizardry/spell/Evade.java @@ -0,0 +1,48 @@ +package electroblob.wizardry.spell; + +import electroblob.wizardry.util.SpellModifiers; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.item.EnumAction; +import net.minecraft.util.EnumHand; +import net.minecraft.util.math.Vec3d; +import net.minecraft.world.World; + +public class Evade extends Spell { + + private static final String EVADE_VELOCITY = "evade_velocity"; + + private static final float UPWARD_VELOCITY = 0.25f; + + public Evade(){ + super("evade", EnumAction.NONE, false); + addProperties(EVADE_VELOCITY); + } + + @Override + public boolean requiresPacket(){ + return false; + } + + @Override + public boolean cast(World world, EntityPlayer caster, EnumHand hand, int ticksInUse, SpellModifiers modifiers){ + + Vec3d look = caster.getLookVec(); + // We want a horizontal only vector + look = look.subtract(0, look.y, 0).normalize(); + + Vec3d evadeDirection; + if(caster.moveStrafing == 0){ + // If the caster isn't strafing, pick a random direction + evadeDirection = look.rotateYaw(world.rand.nextBoolean() ? (float)Math.PI/2f : (float)-Math.PI/2f); + }else{ + // Otherwise, evade always moves whichever direction the caster was already strafing + evadeDirection = look.rotateYaw(Math.signum(caster.moveStrafing) * (float)Math.PI/2f); + } + + evadeDirection = evadeDirection.scale(getProperty(EVADE_VELOCITY).floatValue() * modifiers.get(SpellModifiers.POTENCY)); + caster.addVelocity(evadeDirection.x, UPWARD_VELOCITY, evadeDirection.z); + + return true; + } + +} diff --git a/src/main/java/electroblob/wizardry/spell/FireBreath.java b/src/main/java/electroblob/wizardry/spell/FireBreath.java new file mode 100644 index 00000000..338f375d --- /dev/null +++ b/src/main/java/electroblob/wizardry/spell/FireBreath.java @@ -0,0 +1,95 @@ +package electroblob.wizardry.spell; + +import electroblob.wizardry.registry.WizardryItems; +import electroblob.wizardry.util.MagicDamage; +import electroblob.wizardry.util.MagicDamage.DamageType; +import electroblob.wizardry.util.ParticleBuilder; +import electroblob.wizardry.util.ParticleBuilder.Type; +import electroblob.wizardry.util.SpellModifiers; +import electroblob.wizardry.util.WizardryUtilities; +import net.minecraft.entity.Entity; +import net.minecraft.entity.EntityLivingBase; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.init.Blocks; +import net.minecraft.item.EnumAction; +import net.minecraft.util.EnumFacing; +import net.minecraft.util.SoundEvent; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.Vec3d; +import net.minecraft.util.text.TextComponentTranslation; +import net.minecraft.world.World; + +public class FireBreath extends SpellRay { + + public FireBreath(){ + super("fire_breath", true, EnumAction.NONE); + this.particleVelocity(1); + this.particleJitter(0.3); + this.particleSpacing(0.25); + addProperties(DAMAGE, BURN_DURATION); + } + + @Override + protected SoundEvent[] createSounds(){ + return this.createContinuousSpellSounds(); + } + + @Override + protected void playSound(World world, EntityLivingBase entity, int ticksInUse, int duration, SpellModifiers modifiers, String... sounds){ + this.playSoundLoop(world, entity, ticksInUse); + } + + @Override + protected void playSound(World world, double x, double y, double z, int ticksInUse, int duration, SpellModifiers modifiers, String... sounds){ + this.playSoundLoop(world, x, y, z, ticksInUse, duration); + } + + @Override + protected boolean onEntityHit(World world, Entity target, Vec3d hit, EntityLivingBase caster, Vec3d origin, int ticksInUse, SpellModifiers modifiers){ + // Fire can damage armour stands + if(target instanceof EntityLivingBase){ + + if(MagicDamage.isEntityImmune(DamageType.FIRE, target)){ + if(!world.isRemote && ticksInUse == 1 && caster instanceof EntityPlayer) ((EntityPlayer)caster) + .sendStatusMessage(new TextComponentTranslation("spell.resist", target.getName(), + this.getNameForTranslationFormatted()), true); + // This now only damages in line with the maxHurtResistantTime. Some mods don't play nicely and fiddle + // with this mechanic for their own purposes, so this line makes sure that doesn't affect wizardry. + }else if(ticksInUse % ((EntityLivingBase)target).maxHurtResistantTime == 1){ + target.setFire((int)(getProperty(BURN_DURATION).floatValue() * modifiers.get(WizardryItems.duration_upgrade))); + WizardryUtilities.attackEntityWithoutKnockback(target, + MagicDamage.causeDirectMagicDamage(caster, DamageType.FIRE), + getProperty(DAMAGE).floatValue() * modifiers.get(SpellModifiers.POTENCY)); + } + } + + return true; + } + + @Override + protected boolean onBlockHit(World world, BlockPos pos, EnumFacing side, Vec3d hit, EntityLivingBase caster, Vec3d origin, int ticksInUse, SpellModifiers modifiers){ + + if(!WizardryUtilities.canDamageBlocks(caster, world)) return false; + + pos = pos.offset(side); + + if(world.isAirBlock(pos)){ + if(!world.isRemote) world.setBlockState(pos, Blocks.FIRE.getDefaultState()); + return true; + } + + return false; + } + + @Override + protected boolean onMiss(World world, EntityLivingBase caster, Vec3d origin, Vec3d direction, int ticksInUse, SpellModifiers modifiers){ + return true; + } + + @Override + protected void spawnParticle(World world, double x, double y, double z, double vx, double vy, double vz){ + ParticleBuilder.create(Type.MAGIC_FIRE).pos(x, y, z).vel(vx, vy, vz).scale(2 + world.rand.nextFloat()).collide(true).spawn(world); + ParticleBuilder.create(Type.MAGIC_FIRE).pos(x, y, z).vel(vx, vy, vz).scale(2 + world.rand.nextFloat()).collide(true).spawn(world); + } + +} diff --git a/src/main/java/electroblob/wizardry/spell/Firestorm.java b/src/main/java/electroblob/wizardry/spell/Firestorm.java deleted file mode 100644 index fc15aa2e..00000000 --- a/src/main/java/electroblob/wizardry/spell/Firestorm.java +++ /dev/null @@ -1,110 +0,0 @@ -package electroblob.wizardry.spell; - -import electroblob.wizardry.constants.Element; -import electroblob.wizardry.constants.SpellType; -import electroblob.wizardry.constants.Tier; -import electroblob.wizardry.registry.WizardryItems; -import electroblob.wizardry.registry.WizardrySounds; -import electroblob.wizardry.util.MagicDamage; -import electroblob.wizardry.util.MagicDamage.DamageType; -import electroblob.wizardry.util.ParticleBuilder; -import electroblob.wizardry.util.ParticleBuilder.Type; -import electroblob.wizardry.util.SpellModifiers; -import electroblob.wizardry.util.WizardryUtilities; -import net.minecraft.entity.Entity; -import net.minecraft.entity.EntityLiving; -import net.minecraft.entity.EntityLivingBase; -import net.minecraft.entity.player.EntityPlayer; -import net.minecraft.init.Blocks; -import net.minecraft.init.SoundEvents; -import net.minecraft.util.EnumFacing; -import net.minecraft.util.EnumHand; -import net.minecraft.util.math.BlockPos; -import net.minecraft.util.text.TextComponentTranslation; -import net.minecraft.world.World; - -public class Firestorm extends SpellRay { - - private static final float BASE_DAMAGE = 6; - /** The base duration for which entities are set on fire by this spell. */ - private static final int BASE_DURATION = 10; - - public Firestorm(){ - super("firestorm", Tier.MASTER, Element.FIRE, SpellType.ATTACK, 15, 0, true, 10, null); - this.particleVelocity(1); - this.particleDither(0.3); - this.particleSpacing(0.25); - } - - @Override - public boolean cast(World world, EntityPlayer caster, EnumHand hand, int ticksInUse, SpellModifiers modifiers){ - // Temporary solution until I implement a better continuous sound system - boolean flag = super.cast(world, caster, hand, ticksInUse, modifiers); - if(flag){ - if(ticksInUse % 16 == 0){ - if(ticksInUse == 0) WizardryUtilities.playSoundAtPlayer(caster, SoundEvents.ENTITY_BLAZE_SHOOT, 1, 1); - WizardryUtilities.playSoundAtPlayer(caster, WizardrySounds.SPELL_LOOP_FIRE, 0.5f, 1.0f); - } - } - return flag; - } - - @Override - public boolean cast(World world, EntityLiving caster, EnumHand hand, int ticksInUse, EntityLivingBase target, SpellModifiers modifiers){ - boolean flag = super.cast(world, caster, hand, ticksInUse, target, modifiers); - if(flag){ - if(ticksInUse % 16 == 0){ - if(ticksInUse == 0) caster.playSound(SoundEvents.ENTITY_BLAZE_SHOOT, 1, 1); - caster.playSound(WizardrySounds.SPELL_LOOP_FIRE, 0.5f, 1.0f); - } - } - return flag; - } - - @Override - protected boolean onEntityHit(World world, Entity target, EntityLivingBase caster, int ticksInUse, SpellModifiers modifiers){ - // Fire can damage armour stands - if(target instanceof EntityLivingBase){ - - if(MagicDamage.isEntityImmune(DamageType.FIRE, target)){ - if(!world.isRemote && ticksInUse == 1 && caster instanceof EntityPlayer) ((EntityPlayer)caster) - .sendStatusMessage(new TextComponentTranslation("spell.resist", target.getName(), - this.getNameForTranslationFormatted()), true); - }else{ - target.setFire((int)(BASE_DURATION * modifiers.get(WizardryItems.duration_upgrade))); - WizardryUtilities.attackEntityWithoutKnockback(target, - MagicDamage.causeDirectMagicDamage(caster, DamageType.FIRE), - BASE_DAMAGE * modifiers.get(SpellModifiers.POTENCY)); - } - - return true; - } - - return false; - } - - @Override - protected boolean onBlockHit(World world, BlockPos pos, EnumFacing side, EntityLivingBase caster, int ticksInUse, SpellModifiers modifiers){ - - pos = pos.offset(side); - - if(world.isAirBlock(pos)){ - if(!world.isRemote) world.setBlockState(pos, Blocks.FIRE.getDefaultState()); - return true; - } - - return false; - } - - @Override - protected boolean onMiss(World world, EntityLivingBase caster, int ticksInUse, SpellModifiers modifiers){ - return true; - } - - @Override - protected void spawnParticle(World world, double x, double y, double z, double vx, double vy, double vz){ - ParticleBuilder.create(Type.MAGIC_FIRE).pos(x, y, z).vel(vx, vy, vz).scale(3 + world.rand.nextFloat()).spawn(world); - ParticleBuilder.create(Type.MAGIC_FIRE).pos(x, y, z).vel(vx, vy, vz).scale(3 + world.rand.nextFloat()).spawn(world); - } - -} diff --git a/src/main/java/electroblob/wizardry/spell/FlameRay.java b/src/main/java/electroblob/wizardry/spell/FlameRay.java index 893d9284..b13e2e45 100644 --- a/src/main/java/electroblob/wizardry/spell/FlameRay.java +++ b/src/main/java/electroblob/wizardry/spell/FlameRay.java @@ -1,10 +1,6 @@ package electroblob.wizardry.spell; -import electroblob.wizardry.constants.Element; -import electroblob.wizardry.constants.SpellType; -import electroblob.wizardry.constants.Tier; import electroblob.wizardry.registry.WizardryItems; -import electroblob.wizardry.registry.WizardrySounds; import electroblob.wizardry.util.MagicDamage; import electroblob.wizardry.util.MagicDamage.DamageType; import electroblob.wizardry.util.ParticleBuilder; @@ -12,55 +8,45 @@ import electroblob.wizardry.util.ParticleBuilder.Type; import electroblob.wizardry.util.SpellModifiers; import electroblob.wizardry.util.WizardryUtilities; import net.minecraft.entity.Entity; -import net.minecraft.entity.EntityLiving; import net.minecraft.entity.EntityLivingBase; import net.minecraft.entity.player.EntityPlayer; -import net.minecraft.init.SoundEvents; +import net.minecraft.item.EnumAction; import net.minecraft.util.EnumFacing; -import net.minecraft.util.EnumHand; +import net.minecraft.util.SoundEvent; import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.Vec3d; import net.minecraft.util.text.TextComponentTranslation; import net.minecraft.world.World; public class FlameRay extends SpellRay { - - private static final float BASE_DAMAGE = 3; - /** The base duration for which entities are set on fire by this spell. */ - private static final int BASE_DURATION = 10; public FlameRay(){ - super("flame_ray", Tier.APPRENTICE, Element.FIRE, SpellType.ATTACK, 5, 0, true, 10, null); + super("flame_ray", true, EnumAction.NONE); this.particleVelocity(1); this.particleSpacing(0.5); + addProperties(DAMAGE, BURN_DURATION); + this.soundValues(1.5f, 1, 0); + } + + // The following three methods serve as a good example of how to implement continuous spell sounds (hint: it's easy) + + @Override + protected SoundEvent[] createSounds(){ + return this.createContinuousSpellSounds(); } @Override - public boolean cast(World world, EntityPlayer caster, EnumHand hand, int ticksInUse, SpellModifiers modifiers){ - // TODO: Temporary solution until I implement a better continuous sound system - boolean flag = super.cast(world, caster, hand, ticksInUse, modifiers); - if(flag){ - if(ticksInUse % 16 == 0){ - if(ticksInUse == 0) WizardryUtilities.playSoundAtPlayer(caster, SoundEvents.ENTITY_BLAZE_SHOOT, 1, 1); - WizardryUtilities.playSoundAtPlayer(caster, WizardrySounds.SPELL_LOOP_FIRE, 0.5f, 1.0f); - } - } - return flag; + protected void playSound(World world, EntityLivingBase entity, int ticksInUse, int duration, SpellModifiers modifiers, String... sounds){ + this.playSoundLoop(world, entity, ticksInUse); } @Override - public boolean cast(World world, EntityLiving caster, EnumHand hand, int ticksInUse, EntityLivingBase target, SpellModifiers modifiers){ - boolean flag = super.cast(world, caster, hand, ticksInUse, target, modifiers); - if(flag){ - if(ticksInUse % 16 == 0){ - if(ticksInUse == 0) caster.playSound(SoundEvents.ENTITY_BLAZE_SHOOT, 1, 1); - caster.playSound(WizardrySounds.SPELL_LOOP_FIRE, 0.5f, 1.0f); - } - } - return flag; + protected void playSound(World world, double x, double y, double z, int ticksInUse, int duration, SpellModifiers modifiers, String... sounds){ + this.playSoundLoop(world, x, y, z, ticksInUse, duration); } @Override - protected boolean onEntityHit(World world, Entity target, EntityLivingBase caster, int ticksInUse, SpellModifiers modifiers){ + protected boolean onEntityHit(World world, Entity target, Vec3d hit, EntityLivingBase caster, Vec3d origin, int ticksInUse, SpellModifiers modifiers){ // Fire can damage armour stands if(target instanceof EntityLivingBase){ @@ -68,33 +54,33 @@ public class FlameRay extends SpellRay { if(!world.isRemote && ticksInUse == 1 && caster instanceof EntityPlayer) ((EntityPlayer)caster) .sendStatusMessage(new TextComponentTranslation("spell.resist", target.getName(), this.getNameForTranslationFormatted()), true); - }else{ - target.setFire((int)(BASE_DURATION * modifiers.get(WizardryItems.duration_upgrade))); + // This now only damages in line with the maxHurtResistantTime. Some mods don't play nicely and fiddle + // with this mechanic for their own purposes, so this line makes sure that doesn't affect wizardry. + }else if(ticksInUse % ((EntityLivingBase)target).maxHurtResistantTime == 1){ + target.setFire((int)(getProperty(BURN_DURATION).floatValue() * modifiers.get(WizardryItems.duration_upgrade))); WizardryUtilities.attackEntityWithoutKnockback(target, MagicDamage.causeDirectMagicDamage(caster, DamageType.FIRE), - BASE_DAMAGE * modifiers.get(SpellModifiers.POTENCY)); + getProperty(DAMAGE).floatValue() * modifiers.get(SpellModifiers.POTENCY)); } - - return true; } + return true; + } + + @Override + protected boolean onBlockHit(World world, BlockPos pos, EnumFacing side, Vec3d hit, EntityLivingBase caster, Vec3d origin, int ticksInUse, SpellModifiers modifiers){ return false; } @Override - protected boolean onBlockHit(World world, BlockPos pos, EnumFacing side, EntityLivingBase caster, int ticksInUse, SpellModifiers modifiers){ - return false; - } - - @Override - protected boolean onMiss(World world, EntityLivingBase caster, int ticksInUse, SpellModifiers modifiers){ + protected boolean onMiss(World world, EntityLivingBase caster, Vec3d origin, Vec3d direction, int ticksInUse, SpellModifiers modifiers){ return true; } @Override protected void spawnParticle(World world, double x, double y, double z, double vx, double vy, double vz){ - ParticleBuilder.create(Type.MAGIC_FIRE).pos(x, y, z).vel(vx, vy, vz).spawn(world); - ParticleBuilder.create(Type.MAGIC_FIRE).pos(x, y, z).vel(vx, vy, vz).spawn(world); + ParticleBuilder.create(Type.MAGIC_FIRE).pos(x, y, z).vel(vx, vy, vz).collide(true).spawn(world); + ParticleBuilder.create(Type.MAGIC_FIRE).pos(x, y, z).vel(vx, vy, vz).collide(true).spawn(world); } } diff --git a/src/main/java/electroblob/wizardry/spell/FlamingAxe.java b/src/main/java/electroblob/wizardry/spell/FlamingAxe.java index 33498792..1f87a883 100644 --- a/src/main/java/electroblob/wizardry/spell/FlamingAxe.java +++ b/src/main/java/electroblob/wizardry/spell/FlamingAxe.java @@ -1,19 +1,16 @@ package electroblob.wizardry.spell; -import electroblob.wizardry.constants.Element; -import electroblob.wizardry.constants.SpellType; -import electroblob.wizardry.constants.Tier; import electroblob.wizardry.registry.WizardryItems; import electroblob.wizardry.util.SpellModifiers; import net.minecraft.entity.EntityLivingBase; -import net.minecraft.init.SoundEvents; import net.minecraft.util.EnumParticleTypes; import net.minecraft.world.World; public class FlamingAxe extends SpellConjuration { public FlamingAxe(){ - super("flaming_axe", Tier.ADVANCED, Element.FIRE, SpellType.UTILITY, 45, 50, WizardryItems.flaming_axe, SoundEvents.ENTITY_BLAZE_SHOOT); + super("flaming_axe", WizardryItems.flaming_axe); + addProperties(DAMAGE, BURN_DURATION); } @Override diff --git a/src/main/java/electroblob/wizardry/spell/FlamingWeapon.java b/src/main/java/electroblob/wizardry/spell/FlamingWeapon.java index 1c940d4e..bb1c3611 100644 --- a/src/main/java/electroblob/wizardry/spell/FlamingWeapon.java +++ b/src/main/java/electroblob/wizardry/spell/FlamingWeapon.java @@ -1,13 +1,9 @@ package electroblob.wizardry.spell; -import electroblob.wizardry.WizardData; import electroblob.wizardry.constants.Constants; -import electroblob.wizardry.constants.Element; -import electroblob.wizardry.constants.SpellType; -import electroblob.wizardry.constants.Tier; +import electroblob.wizardry.data.WizardData; import electroblob.wizardry.registry.WizardryEnchantments; import electroblob.wizardry.registry.WizardryItems; -import electroblob.wizardry.registry.WizardrySounds; import electroblob.wizardry.util.ParticleBuilder; import electroblob.wizardry.util.ParticleBuilder.Type; import electroblob.wizardry.util.SpellModifiers; @@ -15,16 +11,15 @@ import electroblob.wizardry.util.WizardryUtilities; import net.minecraft.enchantment.EnchantmentHelper; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.item.EnumAction; -import net.minecraft.item.ItemBow; import net.minecraft.item.ItemStack; -import net.minecraft.item.ItemSword; import net.minecraft.util.EnumHand; import net.minecraft.world.World; public class FlamingWeapon extends Spell { public FlamingWeapon(){ - super("flaming_weapon", Tier.ADVANCED, Element.FIRE, SpellType.UTILITY, 35, 70, EnumAction.BOW, false); + super("flaming_weapon", EnumAction.BOW, false); + addProperties(EFFECT_DURATION); } @Override @@ -36,17 +31,17 @@ public class FlamingWeapon extends Spell { for(ItemStack stack : WizardryUtilities.getPrioritisedHotbarAndOffhand(caster)){ - if((stack.getItem() instanceof ItemSword || stack.getItem() instanceof ItemBow) + if((ImbueWeapon.isSword(stack.getItem()) || ImbueWeapon.isBow(stack.getItem())) && !EnchantmentHelper.getEnchantments(stack).containsKey(WizardryEnchantments.flaming_weapon)){ // The enchantment level as determined by the damage multiplier. The + 0.5f is so that // weird float processing doesn't incorrectly round it down. stack.addEnchantment(WizardryEnchantments.flaming_weapon, modifiers.get(SpellModifiers.POTENCY) == 1.0f ? 1 : (int)((modifiers.get(SpellModifiers.POTENCY) - 1.0f) - / Constants.DAMAGE_INCREASE_PER_TIER + 0.5f)); + / Constants.POTENCY_INCREASE_PER_TIER + 0.5f)); WizardData.get(caster).setImbuementDuration(WizardryEnchantments.flaming_weapon, - (int)(900 * modifiers.get(WizardryItems.duration_upgrade))); + (int)(getProperty(EFFECT_DURATION).floatValue() * modifiers.get(WizardryItems.duration_upgrade))); if(world.isRemote){ for(int i=0; i<10; i++){ @@ -57,7 +52,7 @@ public class FlamingWeapon extends Spell { } } - WizardryUtilities.playSoundAtPlayer(caster, WizardrySounds.SPELL_CONJURATION, 1.0f, 1.0f); + this.playSound(world, caster, ticksInUse, -1, modifiers); return true; } diff --git a/src/main/java/electroblob/wizardry/spell/Flight.java b/src/main/java/electroblob/wizardry/spell/Flight.java index eb36ceff..9e2d0d8a 100644 --- a/src/main/java/electroblob/wizardry/spell/Flight.java +++ b/src/main/java/electroblob/wizardry/spell/Flight.java @@ -1,40 +1,47 @@ package electroblob.wizardry.spell; -import electroblob.wizardry.constants.Element; -import electroblob.wizardry.constants.SpellType; -import electroblob.wizardry.constants.Tier; +import electroblob.wizardry.Wizardry; import electroblob.wizardry.util.ParticleBuilder; import electroblob.wizardry.util.ParticleBuilder.Type; import electroblob.wizardry.util.SpellModifiers; -import electroblob.wizardry.util.WizardryUtilities; import net.minecraft.entity.player.EntityPlayer; -import net.minecraft.init.SoundEvents; import net.minecraft.item.EnumAction; import net.minecraft.util.EnumHand; import net.minecraft.world.World; public class Flight extends Spell { + public static final String SPEED = "speed"; + public static final String ACCELERATION = "acceleration"; + + private static final double Y_NUDGE_ACCELERATION = 0.075; + public Flight(){ - super("flight", Tier.MASTER, Element.EARTH, SpellType.UTILITY, 10, 0, EnumAction.NONE, true); + super("flight", EnumAction.NONE, true); + addProperties(SPEED, ACCELERATION); } @Override public boolean cast(World world, EntityPlayer caster, EnumHand hand, int ticksInUse, SpellModifiers modifiers){ - if(!caster.isInWater() && !caster.isElytraFlying()){ + if(!caster.isInWater() && !caster.isInLava() && !caster.isElytraFlying()){ + + float speed = getProperty(SPEED).floatValue() * modifiers.get(SpellModifiers.POTENCY); + float acceleration = getProperty(ACCELERATION).floatValue() * modifiers.get(SpellModifiers.POTENCY); + // The division thingy checks if the look direction is the opposite way to the velocity. If this is the // case then the velocity should be added regardless of the player's current speed. - if((Math.abs(caster.motionX) < 0.6 || caster.motionX / caster.getLookVec().x < 0) - && (Math.abs(caster.motionZ) < 0.6 || caster.motionZ / caster.getLookVec().z < 0)){ - caster.addVelocity(caster.getLookVec().x / 20, 0, caster.getLookVec().z / 20); + if((Math.abs(caster.motionX) < speed || caster.motionX / caster.getLookVec().x < 0) + && (Math.abs(caster.motionZ) < speed || caster.motionZ / caster.getLookVec().z < 0)){ + caster.addVelocity(caster.getLookVec().x * acceleration, 0, caster.getLookVec().z * acceleration); } // y velocity is handled separately to stop the player from falling from the sky when they reach maximum // horizontal speed. - if(Math.abs(caster.motionY) < 0.6 || caster.motionY / caster.getLookVec().y < 0){ - caster.motionY += caster.getLookVec().y / 20 + 0.075; + if(Math.abs(caster.motionY) < speed || caster.motionY / caster.getLookVec().y < 0){ + caster.motionY += caster.getLookVec().y * acceleration + Y_NUDGE_ACCELERATION; } - caster.fallDistance = 0.0f; + + if(!Wizardry.settings.replaceVanillaFallDamage) caster.fallDistance = 0.0f; } if(world.isRemote){ @@ -45,12 +52,10 @@ public class Flight extends Spell { x = caster.posX - 1 + world.rand.nextDouble() * 2; y = caster.getEntityBoundingBox().minY + caster.getEyeHeight() - 0.5 + world.rand.nextDouble(); z = caster.posZ - 1 + world.rand.nextDouble() * 2; - ParticleBuilder.create(Type.SPARKLE).pos(x, y, z).vel(0, -0.1, 0).time(15).clr(1, 1, 1).spawn(world); + ParticleBuilder.create(Type.SPARKLE).pos(x, y, z).vel(0, -0.1, 0).time(15).clr(1f, 1f, 1f).spawn(world); } - if(ticksInUse % 24 == 0){ - WizardryUtilities.playSoundAtPlayer(caster, SoundEvents.ENTITY_ENDERDRAGON_FLAP, 0.5F, 1.0f); - } + if(ticksInUse % 24 == 0) playSound(world, caster, ticksInUse, -1, modifiers); return true; } diff --git a/src/main/java/electroblob/wizardry/spell/FontOfMana.java b/src/main/java/electroblob/wizardry/spell/FontOfMana.java index 6963c42f..4dc20f74 100644 --- a/src/main/java/electroblob/wizardry/spell/FontOfMana.java +++ b/src/main/java/electroblob/wizardry/spell/FontOfMana.java @@ -1,13 +1,9 @@ package electroblob.wizardry.spell; -import java.util.List; - -import electroblob.wizardry.constants.Element; -import electroblob.wizardry.constants.SpellType; -import electroblob.wizardry.constants.Tier; +import electroblob.wizardry.event.SpellCastEvent; import electroblob.wizardry.registry.WizardryItems; import electroblob.wizardry.registry.WizardryPotions; -import electroblob.wizardry.registry.WizardrySounds; +import electroblob.wizardry.util.AllyDesignationSystem; import electroblob.wizardry.util.ParticleBuilder; import electroblob.wizardry.util.ParticleBuilder.Type; import electroblob.wizardry.util.SpellModifiers; @@ -16,50 +12,67 @@ import net.minecraft.entity.player.EntityPlayer; import net.minecraft.item.EnumAction; import net.minecraft.potion.PotionEffect; import net.minecraft.util.EnumHand; +import net.minecraft.util.math.MathHelper; import net.minecraft.world.World; +import net.minecraftforge.fml.common.eventhandler.EventPriority; +import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; + +import java.util.List; public class FontOfMana extends Spell { public FontOfMana(){ - super("font_of_mana", Tier.MASTER, Element.HEALING, SpellType.UTILITY, 100, 250, EnumAction.BOW, false); + super("font_of_mana", EnumAction.BOW, false); + this.soundValues(0.7f, 1.2f, 0.4f); + addProperties(EFFECT_RADIUS, EFFECT_DURATION, EFFECT_STRENGTH); } @Override public boolean cast(World world, EntityPlayer caster, EnumHand hand, int ticksInUse, SpellModifiers modifiers){ + double maxRadius = getProperty(EFFECT_RADIUS).doubleValue(); + List targets = WizardryUtilities.getEntitiesWithinRadius( - 5 * modifiers.get(WizardryItems.blast_upgrade), caster.posX, caster.posY, caster.posZ, world, - EntityPlayer.class); + maxRadius * modifiers.get(WizardryItems.blast_upgrade), + caster.posX, caster.posY, caster.posZ, world, EntityPlayer.class); for(EntityPlayer target : targets){ - if(WizardryUtilities.isPlayerAlly(caster, target) || target == caster){ - // Damage multiplier can only ever be 1 or 1.6 for master spells, so there's little point in actually - // calculating this. + if(AllyDesignationSystem.isPlayerAlly(caster, target) || target == caster){ target.addPotionEffect(new PotionEffect(WizardryPotions.font_of_mana, - (int)(600 * modifiers.get(WizardryItems.duration_upgrade)), - modifiers.get(SpellModifiers.POTENCY) > 1 ? 1 : 0)); + (int)(getProperty(EFFECT_DURATION).floatValue() * modifiers.get(WizardryItems.duration_upgrade)), + (int)(getProperty(EFFECT_STRENGTH).intValue() + (modifiers.get(SpellModifiers.POTENCY) - 1) * 2))); } } if(world.isRemote){ for(int i = 0; i < 100 * modifiers.get(WizardryItems.blast_upgrade); i++){ - - double radius = (1 + world.rand.nextDouble() * 4) * modifiers.get(WizardryItems.blast_upgrade); - double angle = world.rand.nextDouble() * Math.PI * 2; + + double radius = (1 + world.rand.nextDouble() * (maxRadius - 1)) * modifiers.get(WizardryItems.blast_upgrade); + float angle = world.rand.nextFloat() * (float)Math.PI * 2; + ; float hue = world.rand.nextFloat() * 0.4f; - - double x = caster.posX + radius * Math.cos(angle); + + double x = caster.posX + radius * MathHelper.cos(angle); double y = caster.getEntityBoundingBox().minY; - double z = caster.posZ + radius * Math.sin(angle); - + double z = caster.posZ + radius * MathHelper.sin(angle); + ParticleBuilder.create(Type.SPARKLE).pos(x, y, z).vel(0, 0.03, 0).time(50) - .clr(1, 1 - hue, 0.6f + hue).spawn(world); + .clr(1, 1 - hue, 0.6f + hue).spawn(world); } } - WizardryUtilities.playSoundAtPlayer(caster, WizardrySounds.SPELL_HEAL, 0.7F, - world.rand.nextFloat() * 0.4F + 1.0F); + playSound(world, caster, ticksInUse, -1, modifiers); + return true; } -} + @SubscribeEvent(priority = EventPriority.LOW) // Doesn't really matter but there's no point processing it if casting is blocked + public static void onSpellCastPreEvent(SpellCastEvent.Pre event){ + // Moved from ItemWand (quite why this wasn't done with modifiers before I don't know!) + if(event.getCaster() != null && event.getCaster().isPotionActive(WizardryPotions.font_of_mana)){ + // Dividing by this rather than setting it takes upgrades and font of mana into account simultaneously + event.getModifiers().set(WizardryItems.cooldown_upgrade, event.getModifiers().get(WizardryItems.cooldown_upgrade) + / (2 + event.getCaster().getActivePotionEffect(WizardryPotions.font_of_mana).getAmplifier()), false); + } + } +} \ No newline at end of file diff --git a/src/main/java/electroblob/wizardry/spell/ForceArrow.java b/src/main/java/electroblob/wizardry/spell/ForceArrow.java new file mode 100644 index 00000000..4996b3d0 --- /dev/null +++ b/src/main/java/electroblob/wizardry/spell/ForceArrow.java @@ -0,0 +1,21 @@ +package electroblob.wizardry.spell; + +import electroblob.wizardry.entity.projectile.EntityForceArrow; +import electroblob.wizardry.util.SpellModifiers; +import net.minecraft.entity.EntityLivingBase; + +import javax.annotation.Nullable; + +public class ForceArrow extends SpellArrow { + + public ForceArrow(){ + super("force_arrow", EntityForceArrow::new); + this.addProperties(Spell.DAMAGE); + this.soundValues(1, 1.3f, 0.2f); + } + + @Override + protected void addArrowExtras(EntityForceArrow arrow, @Nullable EntityLivingBase caster, SpellModifiers modifiers){ + arrow.setMana((int)(this.getCost() * modifiers.get(SpellModifiers.COST))); + } +} diff --git a/src/main/java/electroblob/wizardry/spell/Forcefield.java b/src/main/java/electroblob/wizardry/spell/Forcefield.java new file mode 100644 index 00000000..bfc298b2 --- /dev/null +++ b/src/main/java/electroblob/wizardry/spell/Forcefield.java @@ -0,0 +1,21 @@ +package electroblob.wizardry.spell; + +import electroblob.wizardry.entity.construct.EntityForcefield; +import electroblob.wizardry.registry.WizardryItems; +import electroblob.wizardry.util.SpellModifiers; +import net.minecraft.entity.EntityLivingBase; +import net.minecraft.item.EnumAction; +import net.minecraft.util.EnumFacing; + +public class Forcefield extends SpellConstruct { + + public Forcefield(){ + super("forcefield", EnumAction.BOW, EntityForcefield::new, false); + addProperties(Spell.EFFECT_RADIUS); + } + + @Override + protected void addConstructExtras(EntityForcefield construct, EnumFacing side, EntityLivingBase caster, SpellModifiers modifiers){ + construct.setRadius(getProperty(EFFECT_RADIUS).floatValue() * modifiers.get(WizardryItems.blast_upgrade)); + } +} diff --git a/src/main/java/electroblob/wizardry/spell/ForestOfThorns.java b/src/main/java/electroblob/wizardry/spell/ForestOfThorns.java new file mode 100644 index 00000000..93860407 --- /dev/null +++ b/src/main/java/electroblob/wizardry/spell/ForestOfThorns.java @@ -0,0 +1,99 @@ +package electroblob.wizardry.spell; + +import electroblob.wizardry.block.BlockThorns; +import electroblob.wizardry.registry.WizardryBlocks; +import electroblob.wizardry.registry.WizardryItems; +import electroblob.wizardry.tileentity.TileEntityPlayerSaveTimed; +import electroblob.wizardry.util.SpellModifiers; +import electroblob.wizardry.util.WizardryUtilities; +import net.minecraft.entity.EntityLiving; +import net.minecraft.entity.EntityLivingBase; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.item.EnumAction; +import net.minecraft.tileentity.TileEntity; +import net.minecraft.util.EnumFacing; +import net.minecraft.util.EnumHand; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.MathHelper; +import net.minecraft.world.World; + +import javax.annotation.Nullable; +import java.util.ArrayList; +import java.util.List; + +public class ForestOfThorns extends Spell { + + public ForestOfThorns(){ + super("forest_of_thorns", EnumAction.BOW, false); + addProperties(EFFECT_RADIUS, DURATION, DAMAGE); + } + + @Override public boolean requiresPacket(){ return false; } + @Override public boolean canBeCastByNPCs(){ return true; } + @Override public boolean canBeCastByDispensers(){ return true; } + + @Override + public boolean cast(World world, EntityPlayer caster, EnumHand hand, int ticksInUse, SpellModifiers modifiers){ + if(!summonThorns(world, caster, caster.getPosition(), modifiers)) return false; + this.playSound(world, caster, ticksInUse, -1, modifiers); + return true; + } + + @Override + public boolean cast(World world, EntityLiving caster, EnumHand hand, int ticksInUse, EntityLivingBase target, SpellModifiers modifiers){ + if(!summonThorns(world, caster, caster.getPosition(), modifiers)) return false; + this.playSound(world, caster, ticksInUse, -1, modifiers); + return true; + } + + @Override + public boolean cast(World world, double x, double y, double z, EnumFacing direction, int ticksInUse, int duration, SpellModifiers modifiers){ + if(!summonThorns(world, null, new BlockPos(x, y, z).offset(direction), modifiers)) return false; + this.playSound(world, x, y, z, ticksInUse, duration, modifiers); + return true; + } + + private boolean summonThorns(World world, @Nullable EntityLivingBase caster, BlockPos origin, SpellModifiers modifiers){ + + if(!world.isRemote){ + + double radius = getProperty(EFFECT_RADIUS).doubleValue() * modifiers.get(WizardryItems.blast_upgrade); + + List ring = new ArrayList<>((int)(7 * radius)); // 7 is a bit more than 2 pi + + for(int x = -(int)radius; x <= radius; x++){ + + for(int z = -(int)radius; z <= radius; z++){ + + double distance = MathHelper.sqrt(x*x + z*z); + + if(distance > radius || distance < radius - 1.5) continue; + + Integer y = WizardryUtilities.getNearestSurface(world, origin.add(x, 0, z), EnumFacing.UP, (int)radius, true, WizardryUtilities.SurfaceCriteria.BUILDABLE); + if(y != null) ring.add(new BlockPos(origin.getX() + x, y, origin.getZ() + z)); + } + } + + if(ring.isEmpty()) return false; + + // Because we're always using EnumFacing.UP in the code above, we can be sure that pos is the block above the floor + for(BlockPos pos : ring){ + + ((BlockThorns)WizardryBlocks.thorns).placeAt(world, pos, 3); + + for(int i=0; i<2; i++){ + + TileEntity tileentity = world.getTileEntity(pos.up(i)); + + if(tileentity instanceof TileEntityPlayerSaveTimed){ + ((TileEntityPlayerSaveTimed)tileentity).setLifetime((int)(getProperty(DURATION).floatValue() + * modifiers.get(WizardryItems.duration_upgrade))); + if(caster != null) ((TileEntityPlayerSaveTimed)tileentity).setCaster(caster); + } + } + } + } + + return true; + } +} diff --git a/src/main/java/electroblob/wizardry/spell/ForestsCurse.java b/src/main/java/electroblob/wizardry/spell/ForestsCurse.java index 0cd51ef4..edb3f8d4 100644 --- a/src/main/java/electroblob/wizardry/spell/ForestsCurse.java +++ b/src/main/java/electroblob/wizardry/spell/ForestsCurse.java @@ -1,8 +1,5 @@ package electroblob.wizardry.spell; -import electroblob.wizardry.constants.Element; -import electroblob.wizardry.constants.SpellType; -import electroblob.wizardry.constants.Tier; import electroblob.wizardry.registry.WizardryItems; import electroblob.wizardry.util.MagicDamage; import electroblob.wizardry.util.MagicDamage.DamageType; @@ -12,19 +9,16 @@ import electroblob.wizardry.util.SpellModifiers; import electroblob.wizardry.util.WizardryUtilities; import net.minecraft.entity.EntityLivingBase; import net.minecraft.init.MobEffects; -import net.minecraft.init.SoundEvents; import net.minecraft.item.EnumAction; import net.minecraft.potion.PotionEffect; import net.minecraft.world.World; public class ForestsCurse extends SpellAreaEffect { - - private static final int BASE_DAMAGE = 4; - private static final int BASE_DURATION = 140; public ForestsCurse(){ - super("forests_curse", Tier.MASTER, Element.EARTH, SpellType.ATTACK, 75, 200, EnumAction.BOW, 5, SoundEvents.ENTITY_WITHER_SPAWN); + super("forests_curse", EnumAction.BOW); this.soundValues(1, 1.1f, 0.2f); + addProperties(DAMAGE, EFFECT_DURATION, EFFECT_STRENGTH); } @Override @@ -33,13 +27,15 @@ public class ForestsCurse extends SpellAreaEffect { if(!MagicDamage.isEntityImmune(DamageType.POISON, target) && WizardryUtilities.isLiving(target)){ target.attackEntityFrom(MagicDamage.causeDirectMagicDamage(caster, DamageType.POISON), - BASE_DAMAGE * modifiers.get(SpellModifiers.POTENCY)); - - int duration = (int)(BASE_DURATION * modifiers.get(WizardryItems.duration_upgrade)); - - target.addPotionEffect(new PotionEffect(MobEffects.POISON, duration, 2)); - target.addPotionEffect(new PotionEffect(MobEffects.SLOWNESS, duration, 2)); - target.addPotionEffect(new PotionEffect(MobEffects.WEAKNESS, duration, 2)); + getProperty(DAMAGE).floatValue() * modifiers.get(SpellModifiers.POTENCY)); + + int bonusAmplifier = SpellBuff.getStandardBonusAmplifier(modifiers.get(SpellModifiers.POTENCY)); + int duration = (int)(getProperty(EFFECT_DURATION).floatValue() * modifiers.get(WizardryItems.duration_upgrade)); + int amplifier = (int)(getProperty(EFFECT_STRENGTH).floatValue() + bonusAmplifier); + + target.addPotionEffect(new PotionEffect(MobEffects.POISON, duration, amplifier)); + target.addPotionEffect(new PotionEffect(MobEffects.SLOWNESS, duration, amplifier)); + target.addPotionEffect(new PotionEffect(MobEffects.WEAKNESS, duration, amplifier)); } } diff --git a/src/main/java/electroblob/wizardry/spell/Freeze.java b/src/main/java/electroblob/wizardry/spell/Freeze.java index ab335bc6..d0d59939 100644 --- a/src/main/java/electroblob/wizardry/spell/Freeze.java +++ b/src/main/java/electroblob/wizardry/spell/Freeze.java @@ -1,12 +1,7 @@ package electroblob.wizardry.spell; -import electroblob.wizardry.constants.Element; -import electroblob.wizardry.constants.SpellType; -import electroblob.wizardry.constants.Tier; -import electroblob.wizardry.entity.living.EntityBlazeMinion; import electroblob.wizardry.registry.WizardryItems; import electroblob.wizardry.registry.WizardryPotions; -import electroblob.wizardry.registry.WizardrySounds; import electroblob.wizardry.util.MagicDamage; import electroblob.wizardry.util.MagicDamage.DamageType; import electroblob.wizardry.util.ParticleBuilder; @@ -17,33 +12,33 @@ import net.minecraft.entity.Entity; import net.minecraft.entity.EntityLivingBase; import net.minecraft.entity.monster.EntityBlaze; import net.minecraft.entity.monster.EntityMagmaCube; +import net.minecraft.entity.player.EntityPlayer; import net.minecraft.init.Blocks; +import net.minecraft.item.EnumAction; import net.minecraft.potion.PotionEffect; import net.minecraft.util.EnumFacing; import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.Vec3d; import net.minecraft.util.text.TextComponentTranslation; import net.minecraft.world.World; public class Freeze extends SpellRay { - - /** The base duration of the frostbite effect appled by this spell. */ - private static final int BASE_DURATION = 200; - /** The base damage dealt to entities vulnerable to frost. */ - private static final float BASE_DAMAGE = 3; public Freeze(){ - super("freeze", Tier.BASIC, Element.ICE, SpellType.ATTACK, 5, 10, false, 10, WizardrySounds.SPELL_ICE); + super("freeze", false, EnumAction.NONE); this.soundValues(1, 1.4f, 0.4f); + addProperties(DAMAGE, EFFECT_DURATION, EFFECT_STRENGTH); + this.hitLiquids(true); } @Override - protected boolean onEntityHit(World world, Entity target, EntityLivingBase caster, int ticksInUse, SpellModifiers modifiers){ + protected boolean onEntityHit(World world, Entity target, Vec3d hit, EntityLivingBase caster, Vec3d origin, int ticksInUse, SpellModifiers modifiers){ if(WizardryUtilities.isLiving(target)){ - if(target instanceof EntityBlaze || target instanceof EntityMagmaCube || target instanceof EntityBlazeMinion){ + if(target instanceof EntityBlaze || target instanceof EntityMagmaCube){ target.attackEntityFrom(MagicDamage.causeDirectMagicDamage(caster, DamageType.FROST), - BASE_DAMAGE * modifiers.get(SpellModifiers.POTENCY)); + getProperty(DAMAGE).floatValue() * modifiers.get(SpellModifiers.POTENCY)); } if(MagicDamage.isEntityImmune(DamageType.FROST, target)){ @@ -51,11 +46,12 @@ public class Freeze extends SpellRay { new TextComponentTranslation("spell.resist", target.getName(), this.getNameForTranslationFormatted()), true); }else{ ((EntityLivingBase)target).addPotionEffect(new PotionEffect(WizardryPotions.frost, - (int)(BASE_DURATION * modifiers.get(WizardryItems.duration_upgrade)), 1)); + (int)(getProperty(EFFECT_DURATION).floatValue() * modifiers.get(WizardryItems.duration_upgrade)), + getProperty(EFFECT_STRENGTH).intValue())); } if(target.isBurning()) target.extinguish(); - + return true; } @@ -63,24 +59,27 @@ public class Freeze extends SpellRay { } @Override - protected boolean onBlockHit(World world, BlockPos pos, EnumFacing side, EntityLivingBase caster, int ticksInUse, SpellModifiers modifiers){ - - if(world.getBlockState(pos).getBlock() == Blocks.WATER && !world.isRemote){ - world.setBlockState(pos, Blocks.ICE.getDefaultState()); - }else if(world.getBlockState(pos).getBlock() == Blocks.LAVA && !world.isRemote){ - world.setBlockState(pos, Blocks.OBSIDIAN.getDefaultState()); - }else if(world.getBlockState(pos).getBlock() == Blocks.FLOWING_LAVA && !world.isRemote){ - world.setBlockState(pos, Blocks.COBBLESTONE.getDefaultState()); - }else if(side == EnumFacing.UP && !world.isRemote && world.isSideSolid(pos, EnumFacing.UP) - && WizardryUtilities.canBlockBeReplaced(world, pos.up())){ - world.setBlockState(pos.up(), Blocks.SNOW_LAYER.getDefaultState()); + protected boolean onBlockHit(World world, BlockPos pos, EnumFacing side, Vec3d hit, EntityLivingBase caster, Vec3d origin, int ticksInUse, SpellModifiers modifiers){ + + if(WizardryUtilities.canDamageBlocks(caster, world)){ + + if(world.getBlockState(pos).getBlock() == Blocks.WATER && !world.isRemote){ + world.setBlockState(pos, Blocks.ICE.getDefaultState()); + }else if(world.getBlockState(pos).getBlock() == Blocks.LAVA && !world.isRemote){ + world.setBlockState(pos, Blocks.OBSIDIAN.getDefaultState()); + }else if(world.getBlockState(pos).getBlock() == Blocks.FLOWING_LAVA && !world.isRemote){ + world.setBlockState(pos, Blocks.COBBLESTONE.getDefaultState()); + }else if(side == EnumFacing.UP && !world.isRemote && world.isSideSolid(pos, EnumFacing.UP) + && WizardryUtilities.canBlockBeReplaced(world, pos.up())){ + world.setBlockState(pos.up(), Blocks.SNOW_LAYER.getDefaultState()); + } } return true; // Always succeeds if it hits a block } @Override - protected boolean onMiss(World world, EntityLivingBase caster, int ticksInUse, SpellModifiers modifiers){ + protected boolean onMiss(World world, EntityLivingBase caster, Vec3d origin, Vec3d direction, int ticksInUse, SpellModifiers modifiers){ return false; } diff --git a/src/main/java/electroblob/wizardry/spell/FreezingWeapon.java b/src/main/java/electroblob/wizardry/spell/FreezingWeapon.java index 19b8a8bc..1c798319 100644 --- a/src/main/java/electroblob/wizardry/spell/FreezingWeapon.java +++ b/src/main/java/electroblob/wizardry/spell/FreezingWeapon.java @@ -1,13 +1,9 @@ package electroblob.wizardry.spell; -import electroblob.wizardry.WizardData; import electroblob.wizardry.constants.Constants; -import electroblob.wizardry.constants.Element; -import electroblob.wizardry.constants.SpellType; -import electroblob.wizardry.constants.Tier; +import electroblob.wizardry.data.WizardData; import electroblob.wizardry.registry.WizardryEnchantments; import electroblob.wizardry.registry.WizardryItems; -import electroblob.wizardry.registry.WizardrySounds; import electroblob.wizardry.util.ParticleBuilder; import electroblob.wizardry.util.ParticleBuilder.Type; import electroblob.wizardry.util.SpellModifiers; @@ -15,9 +11,7 @@ import electroblob.wizardry.util.WizardryUtilities; import net.minecraft.enchantment.EnchantmentHelper; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.item.EnumAction; -import net.minecraft.item.ItemBow; import net.minecraft.item.ItemStack; -import net.minecraft.item.ItemSword; import net.minecraft.util.EnumHand; import net.minecraft.world.World; @@ -30,7 +24,8 @@ public class FreezingWeapon extends Spell { public static final String FREEZING_ARROW_NBT_KEY = "frostLevel"; public FreezingWeapon(){ - super("freezing_weapon", Tier.ADVANCED, Element.ICE, SpellType.UTILITY, 35, 70, EnumAction.BOW, false); + super("freezing_weapon", EnumAction.BOW, false); + addProperties(EFFECT_DURATION); } @Override @@ -42,17 +37,17 @@ public class FreezingWeapon extends Spell { for(ItemStack stack : WizardryUtilities.getPrioritisedHotbarAndOffhand(caster)){ - if((stack.getItem() instanceof ItemSword || stack.getItem() instanceof ItemBow) + if((ImbueWeapon.isSword(stack.getItem()) || ImbueWeapon.isBow(stack.getItem())) && !EnchantmentHelper.getEnchantments(stack).containsKey(WizardryEnchantments.freezing_weapon)){ // The enchantment level as determined by the damage multiplier. The + 0.5f is so that // weird float processing doesn't incorrectly round it down. stack.addEnchantment(WizardryEnchantments.freezing_weapon, modifiers.get(SpellModifiers.POTENCY) == 1.0f ? 1 : (int)((modifiers.get(SpellModifiers.POTENCY) - 1.0f) - / Constants.DAMAGE_INCREASE_PER_TIER + 0.5f)); + / Constants.POTENCY_INCREASE_PER_TIER + 0.5f)); WizardData.get(caster).setImbuementDuration(WizardryEnchantments.freezing_weapon, - (int)(900 * modifiers.get(WizardryItems.duration_upgrade))); + (int)(getProperty(EFFECT_DURATION).floatValue() * modifiers.get(WizardryItems.duration_upgrade))); if(world.isRemote){ for(int i=0; i<10; i++){ @@ -63,7 +58,7 @@ public class FreezingWeapon extends Spell { } } - WizardryUtilities.playSoundAtPlayer(caster, WizardrySounds.SPELL_CONJURATION, 1, 1); + this.playSound(world, caster, ticksInUse, -1, modifiers); return true; } diff --git a/src/main/java/electroblob/wizardry/spell/FrostAxe.java b/src/main/java/electroblob/wizardry/spell/FrostAxe.java index e9b15a57..31c104db 100644 --- a/src/main/java/electroblob/wizardry/spell/FrostAxe.java +++ b/src/main/java/electroblob/wizardry/spell/FrostAxe.java @@ -1,10 +1,6 @@ package electroblob.wizardry.spell; -import electroblob.wizardry.constants.Element; -import electroblob.wizardry.constants.SpellType; -import electroblob.wizardry.constants.Tier; import electroblob.wizardry.registry.WizardryItems; -import electroblob.wizardry.registry.WizardrySounds; import electroblob.wizardry.util.ParticleBuilder; import electroblob.wizardry.util.ParticleBuilder.Type; import electroblob.wizardry.util.SpellModifiers; @@ -14,7 +10,7 @@ import net.minecraft.world.World; public class FrostAxe extends SpellConjuration { public FrostAxe(){ - super("frost_axe", Tier.ADVANCED, Element.ICE, SpellType.UTILITY, 45, 50, WizardryItems.frost_axe, WizardrySounds.SPELL_ICE); + super("frost_axe", WizardryItems.frost_axe); } @Override diff --git a/src/main/java/electroblob/wizardry/spell/FrostRay.java b/src/main/java/electroblob/wizardry/spell/FrostRay.java index 6aa97807..7f4dbcaa 100644 --- a/src/main/java/electroblob/wizardry/spell/FrostRay.java +++ b/src/main/java/electroblob/wizardry/spell/FrostRay.java @@ -1,11 +1,7 @@ package electroblob.wizardry.spell; -import electroblob.wizardry.constants.Element; -import electroblob.wizardry.constants.SpellType; -import electroblob.wizardry.constants.Tier; import electroblob.wizardry.registry.WizardryItems; import electroblob.wizardry.registry.WizardryPotions; -import electroblob.wizardry.registry.WizardrySounds; import electroblob.wizardry.util.MagicDamage; import electroblob.wizardry.util.MagicDamage.DamageType; import electroblob.wizardry.util.ParticleBuilder; @@ -13,57 +9,45 @@ import electroblob.wizardry.util.ParticleBuilder.Type; import electroblob.wizardry.util.SpellModifiers; import electroblob.wizardry.util.WizardryUtilities; import net.minecraft.entity.Entity; -import net.minecraft.entity.EntityLiving; import net.minecraft.entity.EntityLivingBase; import net.minecraft.entity.monster.EntityBlaze; import net.minecraft.entity.monster.EntityMagmaCube; import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.item.EnumAction; import net.minecraft.potion.PotionEffect; import net.minecraft.util.EnumFacing; -import net.minecraft.util.EnumHand; +import net.minecraft.util.SoundEvent; import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.Vec3d; import net.minecraft.util.text.TextComponentTranslation; import net.minecraft.world.World; public class FrostRay extends SpellRay { - private static final float BASE_DAMAGE = 3; - /** The base duration of the forstbite effect applied by this spell. */ - private static final int BASE_DURATION = 200; - public FrostRay(){ - super("frost_ray", Tier.APPRENTICE, Element.ICE, SpellType.ATTACK, 5, 0, true, 10, null); + super("frost_ray", true, EnumAction.NONE); this.particleVelocity(1); this.particleSpacing(0.5); - } - - @Override - public boolean cast(World world, EntityPlayer caster, EnumHand hand, int ticksInUse, SpellModifiers modifiers){ - // TODO: Temporary solution until I implement a better continuous sound system - boolean flag = super.cast(world, caster, hand, ticksInUse, modifiers); - if(flag){ - if(ticksInUse % 12 == 0){ - if(ticksInUse == 0) WizardryUtilities.playSoundAtPlayer(caster, WizardrySounds.SPELL_ICE, 0.5f, 1); - WizardryUtilities.playSoundAtPlayer(caster, WizardrySounds.SPELL_LOOP_ICE, 0.5f, 1); - } - } - return flag; + addProperties(DAMAGE, EFFECT_DURATION, EFFECT_STRENGTH); } @Override - public boolean cast(World world, EntityLiving caster, EnumHand hand, int ticksInUse, EntityLivingBase target, SpellModifiers modifiers){ - boolean flag = super.cast(world, caster, hand, ticksInUse, target, modifiers); - if(flag){ - if(ticksInUse % 12 == 0){ - if(ticksInUse == 0) caster.playSound(WizardrySounds.SPELL_ICE, 0.5f, 1); - caster.playSound(WizardrySounds.SPELL_LOOP_ICE, 0.5f, 1); - } - } - return flag; + protected SoundEvent[] createSounds(){ + return this.createContinuousSpellSounds(); + } + + @Override + protected void playSound(World world, EntityLivingBase entity, int ticksInUse, int duration, SpellModifiers modifiers, String... sounds){ + this.playSoundLoop(world, entity, ticksInUse); + } + + @Override + protected void playSound(World world, double x, double y, double z, int ticksInUse, int duration, SpellModifiers modifiers, String... sounds){ + this.playSoundLoop(world, x, y, z, ticksInUse, duration); } @Override - protected boolean onEntityHit(World world, Entity target, EntityLivingBase caster, int ticksInUse, SpellModifiers modifiers){ + protected boolean onEntityHit(World world, Entity target, Vec3d hit, EntityLivingBase caster, Vec3d origin, int ticksInUse, SpellModifiers modifiers){ if(WizardryUtilities.isLiving(target)){ @@ -73,32 +57,33 @@ public class FrostRay extends SpellRay { if(!world.isRemote && ticksInUse == 1 && caster instanceof EntityPlayer) ((EntityPlayer)caster) .sendStatusMessage(new TextComponentTranslation("spell.resist", target.getName(), this.getNameForTranslationFormatted()), true); - }else{ + // This now only damages in line with the maxHurtResistantTime. Some mods don't play nicely and fiddle + // with this mechanic for their own purposes, so this line makes sure that doesn't affect wizardry. + }else if(ticksInUse % ((EntityLivingBase)target).maxHurtResistantTime == 1){ // For frost ray the entity can move slightly, unlike freeze ((EntityLivingBase)target).addPotionEffect(new PotionEffect(WizardryPotions.frost, - (int)(BASE_DURATION * modifiers.get(WizardryItems.duration_upgrade)), 0)); + (int)(getProperty(EFFECT_DURATION).floatValue() * modifiers.get(WizardryItems.duration_upgrade)), + getProperty(EFFECT_STRENGTH).intValue())); - float damage = BASE_DAMAGE * modifiers.get(SpellModifiers.POTENCY); + float damage = getProperty(DAMAGE).floatValue() * modifiers.get(SpellModifiers.POTENCY); if(target instanceof EntityBlaze || target instanceof EntityMagmaCube) damage *= 2; WizardryUtilities.attackEntityWithoutKnockback(target, MagicDamage.causeDirectMagicDamage(caster, DamageType.FROST), damage); } - - return true; } + return true; + } + + @Override + protected boolean onBlockHit(World world, BlockPos pos, EnumFacing side, Vec3d hit, EntityLivingBase caster, Vec3d origin, int ticksInUse, SpellModifiers modifiers){ return false; } @Override - protected boolean onBlockHit(World world, BlockPos pos, EnumFacing side, EntityLivingBase caster, int ticksInUse, SpellModifiers modifiers){ - return false; - } - - @Override - protected boolean onMiss(World world, EntityLivingBase caster, int ticksInUse, SpellModifiers modifiers){ + protected boolean onMiss(World world, EntityLivingBase caster, Vec3d origin, Vec3d direction, int ticksInUse, SpellModifiers modifiers){ return true; } @@ -106,8 +91,8 @@ public class FrostRay extends SpellRay { protected void spawnParticle(World world, double x, double y, double z, double vx, double vy, double vz){ float brightness = world.rand.nextFloat(); ParticleBuilder.create(Type.SPARKLE).pos(x, y, z).vel(vx, vy, vz).time(8 + world.rand.nextInt(12)) - .clr(0.4f + 0.6f * brightness, 0.6f + 0.4f*brightness, 1).spawn(world); - ParticleBuilder.create(Type.SNOW).pos(x, y, z).vel(vx, vy, vz).time(8 + world.rand.nextInt(12)).spawn(world); + .clr(0.4f + 0.6f * brightness, 0.6f + 0.4f*brightness, 1).collide(true).spawn(world); + ParticleBuilder.create(Type.SNOW).pos(x, y, z).vel(vx, vy, vz).time(8 + world.rand.nextInt(12)).collide(true).spawn(world); } } diff --git a/src/main/java/electroblob/wizardry/spell/Glide.java b/src/main/java/electroblob/wizardry/spell/Glide.java index 7821c800..c1c465ad 100644 --- a/src/main/java/electroblob/wizardry/spell/Glide.java +++ b/src/main/java/electroblob/wizardry/spell/Glide.java @@ -1,41 +1,66 @@ package electroblob.wizardry.spell; -import electroblob.wizardry.constants.Element; -import electroblob.wizardry.constants.SpellType; -import electroblob.wizardry.constants.Tier; +import electroblob.wizardry.Wizardry; +import electroblob.wizardry.registry.WizardrySounds; import electroblob.wizardry.util.ParticleBuilder; import electroblob.wizardry.util.ParticleBuilder.Type; import electroblob.wizardry.util.SpellModifiers; -import electroblob.wizardry.util.WizardryUtilities; +import net.minecraft.entity.EntityLivingBase; import net.minecraft.entity.player.EntityPlayer; -import net.minecraft.init.SoundEvents; import net.minecraft.item.EnumAction; import net.minecraft.util.EnumHand; +import net.minecraft.util.SoundEvent; import net.minecraft.world.World; public class Glide extends Spell { + public static final String SPEED = "speed"; + public static final String FALL_SPEED = "fall_speed"; + public static final String ACCELERATION = "acceleration"; + public Glide(){ - super("glide", Tier.ADVANCED, Element.EARTH, SpellType.UTILITY, 5, 0, EnumAction.NONE, true); + super("glide", EnumAction.NONE, true); + addProperties(SPEED, FALL_SPEED, ACCELERATION); + } + + @Override + protected void playSound(World world, EntityLivingBase entity, int ticksInUse, int duration, SpellModifiers modifiers, String... sounds){ + if(ticksInUse == 0 && world.isRemote) Wizardry.proxy.playSpellSoundLoop(entity, this, this.sounds[0], this.sounds[0], this.sounds[0], + WizardrySounds.SPELLS, volume, pitch + pitchVariation * (world.rand.nextFloat() - 0.5f)); + } + + @Override + protected void playSound(World world, double x, double y, double z, int ticksInUse, int duration, SpellModifiers modifiers, String... sounds){ + if(ticksInUse == 0 && world.isRemote){ + Wizardry.proxy.playSpellSoundLoop(world, x, y, z, this, this.sounds[0], this.sounds[0], this.sounds[0], + WizardrySounds.SPELLS, volume, pitch + pitchVariation * (world.rand.nextFloat() - 0.5f), duration); + } } @Override public boolean cast(World world, EntityPlayer caster, EnumHand hand, int ticksInUse, SpellModifiers modifiers){ if(caster.motionY < -0.1 && !caster.isInWater()){ - caster.motionY = -0.1; - if(Math.abs(caster.motionX) < 0.4 && Math.abs(caster.motionZ) < 0.4){ - caster.addVelocity(caster.getLookVec().x / 8, 0, caster.getLookVec().z / 8); - // entityplayer.moveEntity(entityplayer.motionX*10, 0, entityplayer.motionZ*10); + + float speed = getProperty(SPEED).floatValue() * modifiers.get(SpellModifiers.POTENCY); + // There seems to be some sort of 'terminal velocity', presumably due to the slight slowing-down effect in + // vanilla - this means we have to apply potency modifiers to the acceleration as well as the speed or they + // appear to have no effect (a bug which had me confused for quite a while!) This also applies to flight. + float acceleration = getProperty(ACCELERATION).floatValue() * modifiers.get(SpellModifiers.POTENCY); + + caster.motionY = -getProperty(FALL_SPEED).floatValue(); + if(Math.abs(caster.motionX) < speed && Math.abs(caster.motionZ) < speed){ + caster.addVelocity(caster.getLookVec().x * acceleration, 0, caster.getLookVec().z * acceleration); } - caster.fallDistance = 0.0f; + + if(!Wizardry.settings.replaceVanillaFallDamage) caster.fallDistance = 0.0f; } if(world.isRemote){ double x = caster.posX - 0.25 + world.rand.nextDouble() / 2; double y = caster.getEntityBoundingBox().minY + world.rand.nextDouble(); double z = caster.posZ - 0.25 + world.rand.nextDouble() / 2; - ParticleBuilder.create(Type.SPARKLE).pos(x, y, z).vel(0, -0.1, 0).time(15).clr(1, 1, 1).spawn(world); + ParticleBuilder.create(Type.SPARKLE).pos(x, y, z).vel(0, -0.1, 0).time(15).clr(1f, 1f, 1f).spawn(world); x = caster.posX - 0.25 + world.rand.nextDouble() / 2; y = caster.getEntityBoundingBox().minY + world.rand.nextDouble(); z = caster.posZ - 0.25 + world.rand.nextDouble() / 2; @@ -43,7 +68,7 @@ public class Glide extends Spell { } if(ticksInUse % 24 == 0){ - WizardryUtilities.playSoundAtPlayer(caster, SoundEvents.ITEM_ELYTRA_FLYING, 0.5F, 1.0f); + this.playSound(world, caster, ticksInUse, -1, modifiers); } return true; diff --git a/src/main/java/electroblob/wizardry/spell/Grapple.java b/src/main/java/electroblob/wizardry/spell/Grapple.java new file mode 100644 index 00000000..6ee73cab --- /dev/null +++ b/src/main/java/electroblob/wizardry/spell/Grapple.java @@ -0,0 +1,419 @@ +package electroblob.wizardry.spell; + +import electroblob.wizardry.Wizardry; +import electroblob.wizardry.data.IVariable; +import electroblob.wizardry.data.Persistence; +import electroblob.wizardry.data.WizardData; +import electroblob.wizardry.item.ItemArtefact; +import electroblob.wizardry.registry.Spells; +import electroblob.wizardry.registry.WizardryItems; +import electroblob.wizardry.util.ParticleBuilder; +import electroblob.wizardry.util.ParticleBuilder.Type; +import electroblob.wizardry.util.RayTracer; +import electroblob.wizardry.util.SpellModifiers; +import electroblob.wizardry.util.WizardryUtilities; +import net.minecraft.entity.Entity; +import net.minecraft.entity.EntityLiving; +import net.minecraft.entity.EntityLivingBase; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.entity.player.EntityPlayerMP; +import net.minecraft.item.EnumAction; +import net.minecraft.network.play.server.SPacketEntityVelocity; +import net.minecraft.util.EnumFacing; +import net.minecraft.util.EnumHand; +import net.minecraft.util.SoundEvent; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.RayTraceResult; +import net.minecraft.util.math.Vec3d; +import net.minecraft.world.World; + +import javax.annotation.Nullable; + +public class Grapple extends Spell { + + /** The speed at which the vine extends/retracts from the caster, in blocks per tick. */ + public static final String EXTENSION_SPEED = "extension_speed"; + /** The speed at which the vine reels in the caster or target, in blocks per tick. */ + public static final String REEL_SPEED = "reel_speed"; + + public static final IVariable TARGET_KEY = new IVariable.Variable(Persistence.NEVER) + .withTicker(Grapple::update); + + /** The distance from the target position at which the spell will stop reeling in entities. */ + private static final double MINIMUM_REEL_DISTANCE = 3; + /** The acceleration with which the vine reels in the caster or target. */ + private static final double REEL_ACCELERATION = 0.3; + /** The speed at which the caster or target is lowered when the caster is sneaking. */ + private static final double PAYOUT_SPEED = 0.25; + /** Once attached, the vine can stretch beyond the maximum range by this factor before breaking. */ + private static final double STRETCH_LIMIT = 1.5; + /** The distance between spawned particles. */ + protected static final double PARTICLE_SPACING = 1.5; + /** The maximum jitter (random position offset) for spawned particles. */ + protected static final double PARTICLE_JITTER = 0.04; + + public Grapple(){ + super("grapple", EnumAction.NONE, true); + addProperties(RANGE, EXTENSION_SPEED, REEL_SPEED); + } + + @Override + public boolean canBeCastByNPCs(){ + return super.canBeCastByNPCs(); + } + + @Override + public boolean canBeCastByDispensers(){ + return true; + } + + @Override + protected SoundEvent[] createSounds(){ + return this.createSoundsWithSuffixes("shoot", "attach", "pull", "release"); + } + + @Override + public boolean cast(World world, EntityPlayer caster, EnumHand hand, int ticksInUse, SpellModifiers modifiers){ + + WizardData data = WizardData.get(caster); + + Vec3d origin = new Vec3d(caster.posX, caster.getEntityBoundingBox().minY + caster.getEyeHeight(), caster.posZ); + + float extensionSpeed = getProperty(EXTENSION_SPEED).floatValue() * modifiers.get(SpellModifiers.POTENCY); + + RayTraceResult hit = data.getVariable(TARGET_KEY); + + // Initial targeting + if(hit == null){ + hit = findTarget(world, caster, origin, caster.getLookVec(), modifiers); + data.setVariable(TARGET_KEY, hit); + caster.swingArm(hand); + // This condition prevents the sound playing every tick after a missed shot has finished extending + if(hit.typeOfHit != RayTraceResult.Type.MISS + || ticksInUse * extensionSpeed < getProperty(RANGE).floatValue() * modifiers.get(WizardryItems.range_upgrade)){ + this.playSound(world, caster, ticksInUse, -1, modifiers, "shoot"); + } + } + + Vec3d target = hit.hitVec; + + if(hit.entityHit instanceof EntityLivingBase){ + // If the target is an entity, we need to use the entity's centre rather than the original hit position + // because the entity will have moved! + target = new Vec3d(hit.entityHit.posX, hit.entityHit.getEntityBoundingBox().minY + hit.entityHit.height/2, hit.entityHit.posZ); + } + + double distance = origin.distanceTo(target); + Vec3d direction = target.subtract(origin).normalize(); + + double maxLength = getProperty(RANGE).floatValue() * modifiers.get(WizardryItems.range_upgrade) * STRETCH_LIMIT; + + // If the vine stretched too far + if(distance > maxLength){ + if(world.isRemote && (ticksInUse-1) * extensionSpeed < distance){ + spawnLeafParticles(world, origin.subtract(0, SpellRay.Y_OFFSET, 0), direction, distance); + } + data.setVariable(TARGET_KEY, null); + return false; // The spell is finished + } + + boolean extending = ticksInUse * extensionSpeed < distance; + + if(extending){ + // Extension + if(world.isRemote){ + // world.getTotalWorldTime() - ticksInUse generates a constant but unique seed each time the spell is cast + ParticleBuilder.create(Type.VINE).entity(caster).pos(0, caster.getEyeHeight() - SpellRay.Y_OFFSET, 0) + .target(origin.add(direction.scale(ticksInUse * extensionSpeed))).tvel(direction.scale(extensionSpeed)) + .seed(world.getTotalWorldTime() - ticksInUse).spawn(world); + } + + }else{ + // Retraction + Vec3d velocity = direction.scale(getProperty(REEL_SPEED).floatValue() * modifiers.get(SpellModifiers.POTENCY)); + + int retractTime = ticksInUse - (int)(distance/extensionSpeed); + + switch(hit.typeOfHit){ + + case BLOCK: + // Payout + if(caster.isSneaking() && ItemArtefact.isArtefactActive(caster, WizardryItems.charm_abseiling)) + velocity = new Vec3d(velocity.x, distance < maxLength-1 ? -PAYOUT_SPEED : distance-maxLength+1, velocity.z); + + // Reel the caster towards the block hit + double ax = (velocity.x - caster.motionX) * REEL_ACCELERATION; + double ay = (velocity.y - caster.motionY) * REEL_ACCELERATION; + double az = (velocity.z - caster.motionZ) * REEL_ACCELERATION; + caster.addVelocity(ax, ay, az); + + if(caster.motionY > 0 && !Wizardry.settings.replaceVanillaFallDamage) caster.fallDistance = 0; // Reset fall distance if the caster moves upwards + + if(world.isRemote){ + ParticleBuilder.create(Type.VINE).entity(caster).pos(0, caster.getEyeHeight() - SpellRay.Y_OFFSET, 0) + .target(target).seed(world.getTotalWorldTime() - ticksInUse).spawn(world); + } + + if(retractTime == 1){ // Just hit + this.playSound(world, caster, ticksInUse, -1, modifiers, "pull"); + this.playSound(world, hit.hitVec, ticksInUse, -1, modifiers, "attach"); + } + + break; + + case ENTITY: + // Payout + if(caster.isSneaking() && ItemArtefact.isArtefactActive(caster, WizardryItems.charm_abseiling)) + velocity = new Vec3d(velocity.x, distance < maxLength-1 ? PAYOUT_SPEED : maxLength-1-distance, velocity.z); + + // Reel the entity hit towards the caster + Entity entity = hit.entityHit; + + if(distance > MINIMUM_REEL_DISTANCE){ + double ax1 = (-velocity.x - entity.motionX) * REEL_ACCELERATION; + double ay1 = (-velocity.y - entity.motionY) * REEL_ACCELERATION; + double az1 = (-velocity.z - entity.motionZ) * REEL_ACCELERATION; + entity.addVelocity(ax1, ay1, az1); + // Player motion is handled on that player's client so needs packets + if(entity instanceof EntityPlayerMP){ + ((EntityPlayerMP)entity).connection.sendPacket(new SPacketEntityVelocity(entity)); + } + } + + if(world.isRemote){ + ParticleBuilder.create(Type.VINE).entity(caster).pos(0, caster.getEyeHeight() - SpellRay.Y_OFFSET, 0) + .target(entity).seed(world.getTotalWorldTime() - ticksInUse).spawn(world); + } + + if(retractTime == 1){ // Just hit + this.playSound(world, caster, ticksInUse, -1, modifiers, "pull"); + this.playSound(world, entity.posX, entity.posY, entity.posZ, ticksInUse, -1, modifiers, "attach"); + } + + break; + + default: + // Missed + if(world.isRemote && (ticksInUse-1) * extensionSpeed < distance){ + spawnLeafParticles(world, origin.subtract(0, SpellRay.Y_OFFSET, 0), direction, distance); + } + //caster.resetActiveHand(); + data.setVariable(TARGET_KEY, null); + return false; // The spell is finished + } + } + + return true; + } + + @Override + public boolean cast(World world, EntityLiving caster, EnumHand hand, int ticksInUse, EntityLivingBase target, SpellModifiers modifiers){ + + Vec3d origin = new Vec3d(caster.posX, caster.getEntityBoundingBox().minY + caster.getEyeHeight(), caster.posZ); + + // If the target is an entity, we need to use the entity's centre rather than the original hit position + // because the entity will have moved! + Vec3d targetVec = new Vec3d(target.posX, target.getEntityBoundingBox().minY + target.height/2, target.posZ); + + double distance = origin.distanceTo(targetVec); + + // Can't cast the spell at all if the target is too far away + if(ticksInUse <= 1 && distance > getProperty(RANGE).floatValue() * modifiers.get(WizardryItems.range_upgrade)) + return false; + + Vec3d vec = targetVec.subtract(origin).normalize(); + + float extensionSpeed = getProperty(EXTENSION_SPEED).floatValue() * modifiers.get(SpellModifiers.POTENCY); + + // If the vine stretched too far + if(distance > getProperty(RANGE).floatValue() * modifiers.get(WizardryItems.range_upgrade) * STRETCH_LIMIT){ + if(world.isRemote && (ticksInUse-1) * extensionSpeed < distance){ + spawnLeafParticles(world, origin.subtract(0, SpellRay.Y_OFFSET, 0), vec, distance); + } + return false; + } + + Vec3d hookPosition; + + if(ticksInUse * extensionSpeed < distance){ + // Extension + hookPosition = origin.add(vec.scale(ticksInUse * extensionSpeed)); + + }else{ + // Retraction + Vec3d velocity = vec.scale(getProperty(REEL_SPEED).floatValue() * modifiers.get(SpellModifiers.POTENCY)); + + // Reel the entity hit towards the caster + if(distance > MINIMUM_REEL_DISTANCE){ + double ax1 = (-velocity.x - target.motionX) * REEL_ACCELERATION; + double ay1 = (-velocity.y - target.motionY) * REEL_ACCELERATION; + double az1 = (-velocity.z - target.motionZ) * REEL_ACCELERATION; + target.addVelocity(ax1, ay1, az1); + // Player motion is handled on that player's client so needs packets + if(target instanceof EntityPlayerMP){ + ((EntityPlayerMP)target).connection.sendPacket(new SPacketEntityVelocity(target)); + } + } + + hookPosition = targetVec; + } + + if(world.isRemote){ + // world.getTotalWorldTime() - ticksInUse generates a constant but unique seed each time the spell is cast + ParticleBuilder.create(Type.VINE).pos(origin).target(hookPosition).tvel(vec.scale(extensionSpeed)) + .seed(world.getTotalWorldTime() - ticksInUse).spawn(world); + } + + return true; + } + + @Override + public boolean cast(World world, double x, double y, double z, EnumFacing direction, int ticksInUse, int duration, SpellModifiers modifiers){ + + Vec3d origin = new Vec3d(x, y, z); + + RayTraceResult result = findTarget(world, null, origin, new Vec3d(direction.getDirectionVec()), modifiers); + + if(result.entityHit instanceof EntityLivingBase){ + + Entity entity = result.entityHit; + + // If the target is an entity, we need to use the entity's centre rather than the original hit position + // because the entity will have moved! + Vec3d target = new Vec3d(entity.posX, entity.getEntityBoundingBox().minY + entity.height/2, entity.posZ); + + double distance = origin.distanceTo(target); + Vec3d vec = target.subtract(origin).normalize(); + + float extensionSpeed = getProperty(EXTENSION_SPEED).floatValue() * modifiers.get(SpellModifiers.POTENCY); + + // If the vine stretched too far + if(distance > getProperty(RANGE).floatValue() * modifiers.get(WizardryItems.range_upgrade) * STRETCH_LIMIT){ + if(world.isRemote && (ticksInUse-1) * extensionSpeed < distance){ + spawnLeafParticles(world, origin.subtract(0, SpellRay.Y_OFFSET, 0), vec, distance); + } + return false; + } + + Vec3d hookPosition; + + if(ticksInUse * extensionSpeed < distance){ + // Extension + hookPosition = origin.add(vec.scale(ticksInUse * extensionSpeed)); + + }else{ + // Retraction + Vec3d velocity = vec.scale(getProperty(REEL_SPEED).floatValue() * modifiers.get(SpellModifiers.POTENCY)); + + // Reel the entity hit towards the caster + if(distance > MINIMUM_REEL_DISTANCE){ + double ax1 = (-velocity.x - entity.motionX) * REEL_ACCELERATION; + double ay1 = (-velocity.y - entity.motionY) * REEL_ACCELERATION; + double az1 = (-velocity.z - entity.motionZ) * REEL_ACCELERATION; + entity.addVelocity(ax1, ay1, az1); + // Player motion is handled on that player's client so needs packets + if(entity instanceof EntityPlayerMP){ + ((EntityPlayerMP)entity).connection.sendPacket(new SPacketEntityVelocity(entity)); + } + } + + hookPosition = target; + } + + if(world.isRemote){ + // world.getTotalWorldTime() - ticksInUse generates a constant but unique seed each time the spell is cast + ParticleBuilder.create(Type.VINE).pos(origin).target(hookPosition).seed(world.getTotalWorldTime() - ticksInUse).spawn(world); + } + + return true; + } + + return false; + } + + @Override + public void finishCasting(World world, @Nullable EntityLivingBase caster, double x, double y, double z, EnumFacing facing, int duration, SpellModifiers modifiers){ + + Vec3d origin = null; + Vec3d direction = null; + Vec3d target = null; + + if(caster != null){ + + origin = new Vec3d(caster.posX, caster.getEntityBoundingBox().minY + caster.getEyeHeight(), caster.posZ); + + if(caster instanceof EntityPlayer){ + WizardData data = WizardData.get((EntityPlayer)caster); + if(data != null){ + RayTraceResult hit = data.getVariable(TARGET_KEY); + if(hit != null) target = hit.hitVec; + } + }else if(caster instanceof EntityLiving){ + Entity entity = ((EntityLiving)caster).getAttackTarget(); + if(entity != null) target = new Vec3d(entity.posX, entity.getEntityBoundingBox().minY + entity.height/2, entity.posZ); + } + + if(target != null) direction = target.subtract(origin).normalize(); + + this.playSound(world, caster, duration, duration, modifiers, "release"); + + }else if(!Double.isNaN(x) && !Double.isNaN(y) && !Double.isNaN(z)){ + + origin = new Vec3d(x, y, z); + direction = new Vec3d(facing.getDirectionVec()); + RayTraceResult result = findTarget(world, null, origin, direction, modifiers); + target = result.hitVec; + + this.playSound(world, origin, duration, duration, modifiers, "release"); + } + + if(world.isRemote && origin != null && direction != null){ + + float extensionSpeed = getProperty(EXTENSION_SPEED).floatValue() * modifiers.get(SpellModifiers.POTENCY); + double distance = Math.min(target.subtract(origin).length(), duration * extensionSpeed); + + spawnLeafParticles(world, origin, direction, distance); + } + } + + private void spawnLeafParticles(World world, Vec3d origin, Vec3d direction, double distance){ + // Copied from SpellRay + for(double d = PARTICLE_SPACING; d <= distance; d += PARTICLE_SPACING){ + double x = origin.x + d*direction.x;// + PARTICLE_JITTER * (world.rand.nextDouble()*2 - 1); + double y = origin.y + d*direction.y;// + PARTICLE_JITTER * (world.rand.nextDouble()*2 - 1); + double z = origin.z + d*direction.z;// + PARTICLE_JITTER * (world.rand.nextDouble()*2 - 1); + ParticleBuilder.create(Type.LEAF, world.rand, x, y, z, PARTICLE_JITTER, true).time(25 + world.rand.nextInt(5)).spawn(world); + } + } + + private RayTraceResult findTarget(World world, @Nullable EntityLivingBase caster, Vec3d origin, Vec3d direction, SpellModifiers modifiers){ + + double range = getProperty(RANGE).floatValue() * modifiers.get(WizardryItems.range_upgrade); + + Vec3d endpoint = origin.add(direction.scale(range)); + + RayTraceResult result = RayTracer.rayTrace(world, origin, endpoint, 0, false, + true, false, Entity.class, RayTracer.ignoreEntityFilter(caster)); + + // Non-solid blocks (or if the result is null) count as misses + if(result == null || result.typeOfHit == RayTraceResult.Type.BLOCK + && !world.getBlockState(result.getBlockPos()).getMaterial().isSolid()){ + return new RayTraceResult(RayTraceResult.Type.MISS, endpoint, EnumFacing.DOWN, new BlockPos(endpoint)); + // Immovable entities count as misses too, but the endpoint is the hit vector instead + }else if(result.entityHit != null && !result.entityHit.canBePushed()){ + return new RayTraceResult(RayTraceResult.Type.MISS, result.hitVec, EnumFacing.DOWN, new BlockPos(endpoint)); + } + // If the ray trace missed, result.hitVec will be the endpoint anyway - neat! + return result; + } + + private static RayTraceResult update(EntityPlayer player, RayTraceResult grapplingTarget){ + + if(grapplingTarget != null && (!WizardryUtilities.isCasting(player, Spells.grapple) + || (grapplingTarget.entityHit != null && !grapplingTarget.entityHit.isEntityAlive()))){ + return null; + } + + return grapplingTarget; + } +} diff --git a/src/main/java/electroblob/wizardry/spell/GreaterFireball.java b/src/main/java/electroblob/wizardry/spell/GreaterFireball.java deleted file mode 100644 index 84db6989..00000000 --- a/src/main/java/electroblob/wizardry/spell/GreaterFireball.java +++ /dev/null @@ -1,85 +0,0 @@ -package electroblob.wizardry.spell; - -import electroblob.wizardry.constants.Element; -import electroblob.wizardry.constants.SpellType; -import electroblob.wizardry.constants.Tier; -import electroblob.wizardry.util.SpellModifiers; -import electroblob.wizardry.util.WizardryUtilities; -import net.minecraft.entity.EntityLiving; -import net.minecraft.entity.EntityLivingBase; -import net.minecraft.entity.player.EntityPlayer; -import net.minecraft.entity.projectile.EntityLargeFireball; -import net.minecraft.init.SoundEvents; -import net.minecraft.item.EnumAction; -import net.minecraft.util.EnumHand; -import net.minecraft.util.math.Vec3d; -import net.minecraft.world.World; - -public class GreaterFireball extends Spell { - - public GreaterFireball(){ - super("greater_fireball", Tier.ADVANCED, Element.FIRE, SpellType.ATTACK, 20, 30, EnumAction.NONE, false); - } - - @Override - public boolean doesSpellRequirePacket(){ - return false; - } - - @Override - public boolean cast(World world, EntityPlayer caster, EnumHand hand, int ticksInUse, SpellModifiers modifiers){ - - Vec3d look = caster.getLookVec(); - - if(!world.isRemote){ - EntityLargeFireball fireball = new EntityLargeFireball(world, caster, 1, 1, 1); - fireball.setPosition(caster.posX + look.x, caster.posY + look.y + 1.3, caster.posZ + look.z); - fireball.accelerationX = look.x * 0.1; - fireball.accelerationY = look.y * 0.1; - fireball.accelerationZ = look.z * 0.1; - world.spawnEntity(fireball); - } - - WizardryUtilities.playSoundAtPlayer(caster, SoundEvents.ENTITY_BLAZE_SHOOT, 1, 1); - caster.swingArm(hand); - return true; - } - - @Override - public boolean cast(World world, EntityLiving caster, EnumHand hand, int ticksInUse, EntityLivingBase target, - SpellModifiers modifiers){ - - if(target != null){ - - if(!world.isRemote){ - - EntityLargeFireball fireball = new EntityLargeFireball(world, caster, 1, 1, 1); - - double dx = target.posX - caster.posX; - double dy = target.getEntityBoundingBox().minY + (double)(target.height / 2.0F) - - (caster.posY + (double)(caster.height / 2.0F)); - double dz = target.posZ - caster.posZ; - - fireball.accelerationX = dx / caster.getDistance(target) * 0.1; - fireball.accelerationY = dy / caster.getDistance(target) * 0.1; - fireball.accelerationZ = dz / caster.getDistance(target) * 0.1; - - fireball.setPosition(caster.posX, caster.posY + caster.getEyeHeight(), caster.posZ); - - world.spawnEntity(fireball); - } - - caster.playSound(SoundEvents.ENTITY_BLAZE_SHOOT, 1, 1); - caster.swingArm(hand); - return true; - } - - return false; - } - - @Override - public boolean canBeCastByNPCs(){ - return true; - } - -} diff --git a/src/main/java/electroblob/wizardry/spell/GreaterHeal.java b/src/main/java/electroblob/wizardry/spell/GreaterHeal.java index 52452809..9d7055fc 100644 --- a/src/main/java/electroblob/wizardry/spell/GreaterHeal.java +++ b/src/main/java/electroblob/wizardry/spell/GreaterHeal.java @@ -1,24 +1,21 @@ package electroblob.wizardry.spell; -import electroblob.wizardry.constants.Element; -import electroblob.wizardry.constants.SpellType; -import electroblob.wizardry.constants.Tier; -import electroblob.wizardry.registry.WizardrySounds; import electroblob.wizardry.util.SpellModifiers; import net.minecraft.entity.EntityLivingBase; public class GreaterHeal extends SpellBuff { public GreaterHeal(){ - super("greater_heal", Tier.ADVANCED, Element.HEALING, SpellType.DEFENCE, 15, 40, WizardrySounds.SPELL_HEAL, 1, 1, 0.3f); + super("greater_heal", 1, 1, 0.3f); this.soundValues(0.7f, 1.2f, 0.4f); + addProperties(HEALTH); } @Override protected boolean applyEffects(EntityLivingBase caster, SpellModifiers modifiers){ if(caster.getHealth() < caster.getMaxHealth() && caster.getHealth() > 0){ - caster.heal(8 * modifiers.get(SpellModifiers.POTENCY)); + caster.heal(getProperty(HEALTH).floatValue() * modifiers.get(SpellModifiers.POTENCY)); return true; } diff --git a/src/main/java/electroblob/wizardry/spell/GreaterTelekinesis.java b/src/main/java/electroblob/wizardry/spell/GreaterTelekinesis.java new file mode 100644 index 00000000..3929d8d2 --- /dev/null +++ b/src/main/java/electroblob/wizardry/spell/GreaterTelekinesis.java @@ -0,0 +1,159 @@ +package electroblob.wizardry.spell; + +import electroblob.wizardry.Wizardry; +import electroblob.wizardry.entity.EntityLevitatingBlock; +import electroblob.wizardry.item.ItemArtefact; +import electroblob.wizardry.registry.WizardryItems; +import electroblob.wizardry.util.ParticleBuilder; +import electroblob.wizardry.util.ParticleBuilder.Type; +import electroblob.wizardry.util.SpellModifiers; +import electroblob.wizardry.util.WizardryUtilities; +import net.minecraft.entity.Entity; +import net.minecraft.entity.EntityLivingBase; +import net.minecraft.entity.item.EntityTNTPrimed; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.entity.player.EntityPlayerMP; +import net.minecraft.item.EnumAction; +import net.minecraft.network.play.server.SPacketEntityVelocity; +import net.minecraft.util.EnumFacing; +import net.minecraft.util.SoundEvent; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.MathHelper; +import net.minecraft.util.math.Vec3d; +import net.minecraft.util.text.TextComponentTranslation; +import net.minecraft.world.World; + +public class GreaterTelekinesis extends SpellRay { + + public static final String HOLD_RANGE = "hold_range"; + public static final String THROW_VELOCITY = "throw_velocity"; + + /** Makes things a bit smoother-looking / 'realistic'. */ + private static final float UNDERSHOOT = 0.2f; + + public GreaterTelekinesis(){ + super("greater_telekinesis", true, EnumAction.NONE); + this.aimAssist(0.4f); + this.particleSpacing(1); + this.particleJitter(0.05); + this.particleVelocity(0.3); + addProperties(HOLD_RANGE, THROW_VELOCITY, DAMAGE); + this.soundValues(0.8f, 1, 0.2f); + } + + @Override public boolean canBeCastByNPCs() { return false; } + @Override public boolean canBeCastByDispensers() { return false; } + + @Override + protected SoundEvent[] createSounds(){ + return this.createContinuousSpellSounds(); + } + + @Override + protected void playSound(World world, EntityLivingBase entity, int ticksInUse, int duration, SpellModifiers modifiers, String... sounds){ + this.playSoundLoop(world, entity, ticksInUse); + } + + @Override + protected void playSound(World world, double x, double y, double z, int ticksInUse, int duration, SpellModifiers modifiers, String... sounds){ + this.playSoundLoop(world, x, y, z, ticksInUse, duration); + } + + @Override + protected boolean onEntityHit(World world, Entity target, Vec3d hit, EntityLivingBase caster, Vec3d origin, int ticksInUse, SpellModifiers modifiers){ + + // Can't be cast by dispensers so we know caster isn't null, but just in case... + if(caster != null && (target instanceof EntityLivingBase || target instanceof EntityLevitatingBlock || target instanceof EntityTNTPrimed)){ + + if(target instanceof EntityPlayer && ((caster instanceof EntityPlayer && !Wizardry.settings.playersMoveEachOther) + || ItemArtefact.isArtefactActive((EntityPlayer)target, WizardryItems.amulet_anchoring))){ + + if(!world.isRemote && caster instanceof EntityPlayer) ((EntityPlayer)caster).sendStatusMessage( + new TextComponentTranslation("spell.resist", target.getName(), this.getNameForTranslationFormatted()), true); + return false; + } + + if(target instanceof EntityLevitatingBlock){ + ((EntityLevitatingBlock)target).suspend(); + ((EntityLevitatingBlock)target).setCaster(caster); // Yep, you can steal other players' blocks in mid-air! + } + + Vec3d targetPos = target.getPositionVector().add(0, target.height/2, 0); + + if(caster.isSneaking()){ + + Vec3d look = caster.getLookVec().scale(getProperty(THROW_VELOCITY).floatValue() * modifiers.get(WizardryItems.range_upgrade)); + target.addVelocity(look.x, look.y, look.z); + if(caster instanceof EntityPlayer) caster.swingArm(caster.getActiveHand()); + + }else{ + + WizardryUtilities.undoGravity(target); + + // The following code extrapolates the entity's current velocity to determine whether it will pass the + // target position in the next tick, and adds or subtracts velocity accordingly. + + Vec3d vec = origin.add(caster.getLookVec().scale(getProperty(HOLD_RANGE).floatValue())); + + Vec3d velocity = vec.subtract(targetPos).subtract(target.motionX, target.motionY, target.motionZ) + .scale(1 - UNDERSHOOT); + + target.addVelocity(velocity.x, velocity.y, velocity.z); + } + + // Player motion is handled on that player's client so needs packets + if(target instanceof EntityPlayerMP){ + ((EntityPlayerMP)target).connection.sendPacket(new SPacketEntityVelocity(target)); + } + + if(world.isRemote){ + + ParticleBuilder.create(Type.BEAM).entity(caster).clr(0.2f, 0.6f + 0.3f * world.rand.nextFloat(), 1) + .pos(origin.subtract(caster.getPositionVector())).target(target).time(0) + .scale(MathHelper.sin(ticksInUse * 0.3f) * 0.1f + 0.9f).spawn(world); + + if(ticksInUse % 18 == 1) ParticleBuilder.create(Type.FLASH).entity(target).pos(0, target.height/2, 0) + .scale(2.5f).time(30).clr(0.2f, 0.8f, 1).fade(1f, 1f, 1f).spawn(world); + + ParticleBuilder.create(Type.SPARKLE, target).vel(0, 0.05, 0).time(15).scale(0.6f).clr(0.2f, 0.6f, 1) + .fade(1f, 1f, 1f).spawn(world); + } + + return true; + } + + return false; + } + + @Override + protected boolean onBlockHit(World world, BlockPos pos, EnumFacing side, Vec3d hit, EntityLivingBase caster, Vec3d origin, int ticksInUse, SpellModifiers modifiers){ + + if(WizardryUtilities.canDamageBlocks(caster, world) && !WizardryUtilities.isBlockUnbreakable(world, pos) + && world.getBlockState(pos).getMaterial().isSolid() + && (world.getTileEntity(pos) == null || !world.getTileEntity(pos).getTileData().hasUniqueId(ArcaneLock.NBT_KEY))){ + + if(!world.isRemote){ + + EntityLevitatingBlock block = new EntityLevitatingBlock(world, pos.getX() + 0.5, pos.getY() + 0.5, pos.getZ() + 0.5, + world.getBlockState(pos)); + + block.fallTime = 1; + block.damageMultiplier = modifiers.get(SpellModifiers.POTENCY); + block.setCaster(caster); + + world.spawnEntity(block); + world.setBlockToAir(pos); + } + + return true; + } + + return false; + } + + @Override + protected boolean onMiss(World world, EntityLivingBase caster, Vec3d origin, Vec3d direction, int ticksInUse, SpellModifiers modifiers){ + return false; + } + +} diff --git a/src/main/java/electroblob/wizardry/spell/GroupHeal.java b/src/main/java/electroblob/wizardry/spell/GroupHeal.java index 71593ec1..cc2677e0 100644 --- a/src/main/java/electroblob/wizardry/spell/GroupHeal.java +++ b/src/main/java/electroblob/wizardry/spell/GroupHeal.java @@ -1,16 +1,8 @@ package electroblob.wizardry.spell; -import java.util.List; - -import electroblob.wizardry.Wizardry; -import electroblob.wizardry.constants.Element; -import electroblob.wizardry.constants.SpellType; -import electroblob.wizardry.constants.Tier; -import electroblob.wizardry.entity.living.ISummonedCreature; import electroblob.wizardry.registry.WizardryItems; -import electroblob.wizardry.registry.WizardrySounds; +import electroblob.wizardry.util.AllyDesignationSystem; import electroblob.wizardry.util.ParticleBuilder; -import electroblob.wizardry.util.ParticleBuilder.Type; import electroblob.wizardry.util.SpellModifiers; import electroblob.wizardry.util.WizardryUtilities; import net.minecraft.entity.EntityLivingBase; @@ -19,10 +11,14 @@ import net.minecraft.item.EnumAction; import net.minecraft.util.EnumHand; import net.minecraft.world.World; +import java.util.List; + public class GroupHeal extends Spell { public GroupHeal(){ - super("group_heal", Tier.ADVANCED, Element.HEALING, SpellType.DEFENCE, 35, 150, EnumAction.BOW, false); + super("group_heal", EnumAction.BOW, false); + this.soundValues(0.7f, 1.2f, 0.4f); + addProperties(EFFECT_RADIUS, HEALTH); } @Override @@ -30,64 +26,20 @@ public class GroupHeal extends Spell { boolean flag = false; - List targets = WizardryUtilities.getEntitiesWithinRadius( - 5 * modifiers.get(WizardryItems.blast_upgrade), caster.posX, caster.posY, caster.posZ, world); + List targets = WizardryUtilities.getEntitiesWithinRadius(getProperty(EFFECT_RADIUS).floatValue() + * modifiers.get(WizardryItems.blast_upgrade), caster.posX, caster.posY, caster.posZ, world); for(EntityLivingBase target : targets){ - if(target instanceof EntityPlayer){ + if(target == caster || AllyDesignationSystem.isAllied(caster, target)){ - if(WizardryUtilities.isPlayerAlly(caster, (EntityPlayer)target) || target == caster){ + if(target.getHealth() < target.getMaxHealth() && target.getHealth() > 0){ - if(((EntityPlayer)target).shouldHeal()){ + target.heal(getProperty(HEALTH).floatValue() * modifiers.get(SpellModifiers.POTENCY)); - target.heal(6 * modifiers.get(SpellModifiers.POTENCY)); - - if(world.isRemote){ - - for(int i = 0; i < 10; i++){ - double x = caster.posX + world.rand.nextDouble() * 2 - 1; - double y = caster.getEntityBoundingBox().minY + caster.getEyeHeight() - 0.5 + world.rand.nextDouble(); - double z = caster.posZ + world.rand.nextDouble() * 2 - 1; - ParticleBuilder.create(Type.SPARKLE).pos(x, y, z).vel(0, 0.1, 0).clr(1, 1, 0.3f).spawn(world); - } - - ParticleBuilder.create(Type.BUFF).entity(caster).clr(1, 1, 0.3f).spawn(world); - } - - WizardryUtilities.playSoundAtPlayer(caster, WizardrySounds.SPELL_HEAL, 0.7F, - world.rand.nextFloat() * 0.4F + 1.0F); - flag = true; - } - } - - // Now also works on summoned creatures - }else if(target instanceof ISummonedCreature){ - - EntityLivingBase summoner = ((ISummonedCreature)target).getCaster(); - - if(summoner == caster || (summoner instanceof EntityPlayer - && WizardryUtilities.isPlayerAlly(caster, (EntityPlayer)summoner))){ - - if(target.getHealth() < target.getMaxHealth() && target.getHealth() > 0){ - - target.heal(6 * modifiers.get(SpellModifiers.POTENCY)); - - if(world.isRemote){ - for(int i = 0; i < 10; i++){ - double x = caster.posX + world.rand.nextDouble() * 2 - 1; - double y = caster.getEntityBoundingBox().minY + caster.getEyeHeight() - 0.5 + world.rand.nextDouble(); - double z = caster.posZ + world.rand.nextDouble() * 2 - 1; - ParticleBuilder.create(Type.SPARKLE).pos(x, y, z).vel(0, 0.1, 0).clr(1, 1, 0.3f).spawn(world); - } - - ParticleBuilder.create(Type.BUFF).entity(caster).clr(1, 1, 0.3f).spawn(world); - } - - WizardryUtilities.playSoundAtPlayer(caster, WizardrySounds.SPELL_HEAL, 0.7F, - world.rand.nextFloat() * 0.4F + 1.0F); - flag = true; - } + if(world.isRemote) ParticleBuilder.spawnHealParticles(world, target); + playSound(world, target, ticksInUse, -1, modifiers); + flag = true; } } } diff --git a/src/main/java/electroblob/wizardry/spell/GrowthAura.java b/src/main/java/electroblob/wizardry/spell/GrowthAura.java index c873ba80..929c803f 100644 --- a/src/main/java/electroblob/wizardry/spell/GrowthAura.java +++ b/src/main/java/electroblob/wizardry/spell/GrowthAura.java @@ -1,9 +1,7 @@ package electroblob.wizardry.spell; -import electroblob.wizardry.constants.Element; -import electroblob.wizardry.constants.SpellType; -import electroblob.wizardry.constants.Tier; -import electroblob.wizardry.registry.WizardrySounds; +import electroblob.wizardry.item.ItemArtefact; +import electroblob.wizardry.registry.WizardryItems; import electroblob.wizardry.util.SpellModifiers; import electroblob.wizardry.util.WizardryUtilities; import net.minecraft.block.IGrowable; @@ -15,14 +13,18 @@ import net.minecraft.util.EnumHand; import net.minecraft.util.math.BlockPos; import net.minecraft.world.World; +import java.util.List; + public class GrowthAura extends Spell { public GrowthAura(){ - super("growth_aura", Tier.APPRENTICE, Element.EARTH, SpellType.UTILITY, 20, 50, EnumAction.NONE, false); + super("growth_aura", EnumAction.NONE, false); + addProperties(EFFECT_RADIUS); + soundValues(0.7f, 1.2f, 0.2f); } @Override - public boolean doesSpellRequirePacket(){ + public boolean requiresPacket(){ return false; } @@ -31,45 +33,43 @@ public class GrowthAura extends Spell { boolean flag = false; - for(int i = -2; i < 1; i++){ + List sphere = WizardryUtilities.getBlockSphere(caster.getPosition(), + getProperty(EFFECT_RADIUS).floatValue() * modifiers.get(WizardryItems.blast_upgrade)); - for(int j = -1; j < 2; j++){ + for(BlockPos pos : sphere){ - int x = (int)caster.posX + i; - int y = WizardryUtilities.getNearestFloorLevelC(world, - new BlockPos(caster.posX + i, caster.posY, caster.posZ + j), 2) - 1; - int z = (int)caster.posZ + j; + IBlockState state = world.getBlockState(pos); - BlockPos pos = new BlockPos(x, y, z); + if(state.getBlock() instanceof IGrowable){ - if(y > -1 && caster.getDistance(x, y, z) <= 2){ + IGrowable plant = (IGrowable)state.getBlock(); - IBlockState state = world.getBlockState(pos); + if(plant.canGrow(world, pos, state, world.isRemote)){ - if(state.getBlock() instanceof IGrowable){ - - IGrowable igrowable = (IGrowable)state.getBlock(); - - if(igrowable.canGrow(world, pos, state, world.isRemote)){ - - if(!world.isRemote){ - if(igrowable.canUseBonemeal(world, world.rand, pos, state)){ - igrowable.grow(world, world.rand, pos, state); + if(!world.isRemote){ + if(plant.canUseBonemeal(world, world.rand, pos, state)){ + if(world.rand.nextFloat() < 0.35f && ItemArtefact.isArtefactActive(caster, WizardryItems.charm_growth)){ + while(plant.canGrow(world, pos, state, false)){ + plant.grow(world, world.rand, pos, state); + state = world.getBlockState(pos); // Update the state with the new one + plant = (IGrowable)state.getBlock(); // Update the block with the new one } }else{ - // Yes, it's meant to be 0, and it automatically changes it to 15. - ItemDye.spawnBonemealParticles(world, pos, 0); + plant.grow(world, world.rand, pos, state); } - - flag = true; } + }else{ + // Yes, it's meant to be 0, and it automatically changes it to 15. + ItemDye.spawnBonemealParticles(world, pos, 0); } + + flag = true; } } } - if(flag) WizardryUtilities.playSoundAtPlayer(caster, WizardrySounds.SPELL_HEAL, 0.7F, - world.rand.nextFloat() * 0.4F + 1.0F); + if(flag) this.playSound(world, caster, ticksInUse, -1, modifiers); + return flag; } diff --git a/src/main/java/electroblob/wizardry/spell/Hailstorm.java b/src/main/java/electroblob/wizardry/spell/Hailstorm.java index b054517e..b68d2ecd 100644 --- a/src/main/java/electroblob/wizardry/spell/Hailstorm.java +++ b/src/main/java/electroblob/wizardry/spell/Hailstorm.java @@ -1,23 +1,20 @@ package electroblob.wizardry.spell; -import electroblob.wizardry.constants.Element; -import electroblob.wizardry.constants.SpellType; -import electroblob.wizardry.constants.Tier; import electroblob.wizardry.entity.construct.EntityHailstorm; -import electroblob.wizardry.registry.WizardrySounds; import electroblob.wizardry.util.SpellModifiers; import net.minecraft.entity.EntityLivingBase; +import net.minecraft.util.EnumFacing; import net.minecraft.world.World; public class Hailstorm extends SpellConstructRanged { public Hailstorm(){ - super("hailstorm", Tier.MASTER, Element.ICE, SpellType.ATTACK, 75, 300, EntityHailstorm::new, 120, 20, WizardrySounds.SPELL_ICE); + super("hailstorm", EntityHailstorm::new, false); this.floor(true); } @Override - protected boolean spawnConstruct(World world, double x, double y, double z, EntityLivingBase caster, SpellModifiers modifiers){ + protected boolean spawnConstruct(World world, double x, double y, double z, EnumFacing side, EntityLivingBase caster, SpellModifiers modifiers){ // Moves the entity back towards the caster a bit, so the area of effect is better centred on the position. // 3 is the distance to move the entity back towards the caster. @@ -29,13 +26,13 @@ public class Hailstorm extends SpellConstructRanged { // Moves the entity up 5 blocks so that it is above mobs' heads. y += 5; - return super.spawnConstruct(world, x, y, z, caster, modifiers); + return super.spawnConstruct(world, x, y, z, side, caster, modifiers); } @Override - protected void addConstructExtras(EntityHailstorm construct, EntityLivingBase caster, SpellModifiers modifiers){ + protected void addConstructExtras(EntityHailstorm construct, EnumFacing side, EntityLivingBase caster, SpellModifiers modifiers){ // Makes the arrows shoot in the direction the caster was looking when they cast the spell. - construct.rotationYaw = caster.rotationYawHead; + if(caster != null) construct.rotationYaw = caster.rotationYawHead; } } diff --git a/src/main/java/electroblob/wizardry/spell/Heal.java b/src/main/java/electroblob/wizardry/spell/Heal.java index 46055d50..8bc201da 100644 --- a/src/main/java/electroblob/wizardry/spell/Heal.java +++ b/src/main/java/electroblob/wizardry/spell/Heal.java @@ -1,24 +1,21 @@ package electroblob.wizardry.spell; -import electroblob.wizardry.constants.Element; -import electroblob.wizardry.constants.SpellType; -import electroblob.wizardry.constants.Tier; -import electroblob.wizardry.registry.WizardrySounds; import electroblob.wizardry.util.SpellModifiers; import net.minecraft.entity.EntityLivingBase; public class Heal extends SpellBuff { public Heal(){ - super("heal", Tier.BASIC, Element.HEALING, SpellType.DEFENCE, 5, 20, WizardrySounds.SPELL_HEAL, 1, 1, 0.3f); + super("heal", 1, 1, 0.3f); this.soundValues(0.7f, 1.2f, 0.4f); + addProperties(HEALTH); } @Override protected boolean applyEffects(EntityLivingBase caster, SpellModifiers modifiers){ if(caster.getHealth() < caster.getMaxHealth() && caster.getHealth() > 0){ - caster.heal(4 * modifiers.get(SpellModifiers.POTENCY)); + caster.heal(getProperty(HEALTH).floatValue() * modifiers.get(SpellModifiers.POTENCY)); return true; } diff --git a/src/main/java/electroblob/wizardry/spell/HealAlly.java b/src/main/java/electroblob/wizardry/spell/HealAlly.java index e36ab8eb..ffcbf274 100644 --- a/src/main/java/electroblob/wizardry/spell/HealAlly.java +++ b/src/main/java/electroblob/wizardry/spell/HealAlly.java @@ -1,29 +1,26 @@ package electroblob.wizardry.spell; -import electroblob.wizardry.Wizardry; -import electroblob.wizardry.constants.Element; -import electroblob.wizardry.constants.SpellType; -import electroblob.wizardry.constants.Tier; -import electroblob.wizardry.registry.WizardrySounds; import electroblob.wizardry.util.ParticleBuilder; -import electroblob.wizardry.util.ParticleBuilder.Type; import electroblob.wizardry.util.SpellModifiers; import electroblob.wizardry.util.WizardryUtilities; import net.minecraft.entity.Entity; import net.minecraft.entity.EntityLivingBase; +import net.minecraft.item.EnumAction; import net.minecraft.util.EnumFacing; import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.Vec3d; import net.minecraft.world.World; public class HealAlly extends SpellRay { public HealAlly(){ - super("heal_ally", Tier.APPRENTICE, Element.HEALING, SpellType.DEFENCE, 10, 20, false, 10, WizardrySounds.SPELL_HEAL); + super("heal_ally", false, EnumAction.NONE); this.soundValues(0.7f, 1.2f, 0.4f); + addProperties(HEALTH); } @Override - protected boolean onEntityHit(World world, Entity target, EntityLivingBase caster, int ticksInUse, SpellModifiers modifiers){ + protected boolean onEntityHit(World world, Entity target, Vec3d hit, EntityLivingBase caster, Vec3d origin, int ticksInUse, SpellModifiers modifiers){ if(WizardryUtilities.isLiving(target)){ @@ -31,21 +28,10 @@ public class HealAlly extends SpellRay { if(entity.getHealth() < entity.getMaxHealth() && entity.getHealth() > 0){ - entity.heal((int)(5 * modifiers.get(SpellModifiers.POTENCY))); + entity.heal(getProperty(HEALTH).floatValue() * modifiers.get(SpellModifiers.POTENCY)); - if(world.isRemote){ - - float r = 1; float g = 1; float b = 0.3f; - - for(int i = 0; i < 10; i++){ - double x1 = (double)((float)entity.posX + world.rand.nextFloat() * 2 - 1.0f); - double y1 = (double)((float)entity.getEntityBoundingBox().minY + entity.getEyeHeight() - 0.5f + world.rand.nextFloat()); - double z1 = (double)((float)entity.posZ + world.rand.nextFloat() * 2 - 1.0f); - ParticleBuilder.create(Type.SPARKLE).pos(x1, y1, z1).vel(0, 0.1F, 0).clr(r, g, b).spawn(world); - } - - ParticleBuilder.create(Type.BUFF).entity(caster).clr(r, g, b).spawn(world); - } + if(world.isRemote) ParticleBuilder.spawnHealParticles(world, entity); + playSound(world, entity, ticksInUse, -1, modifiers); } return true; @@ -55,12 +41,12 @@ public class HealAlly extends SpellRay { } @Override - protected boolean onBlockHit(World world, BlockPos pos, EnumFacing side, EntityLivingBase caster, int ticksInUse, SpellModifiers modifiers){ + protected boolean onBlockHit(World world, BlockPos pos, EnumFacing side, Vec3d hit, EntityLivingBase caster, Vec3d origin, int ticksInUse, SpellModifiers modifiers){ return false; } @Override - protected boolean onMiss(World world, EntityLivingBase caster, int ticksInUse, SpellModifiers modifiers){ + protected boolean onMiss(World world, EntityLivingBase caster, Vec3d origin, Vec3d direction, int ticksInUse, SpellModifiers modifiers){ return false; } diff --git a/src/main/java/electroblob/wizardry/spell/IceAge.java b/src/main/java/electroblob/wizardry/spell/IceAge.java index 040e5c32..8c94d203 100644 --- a/src/main/java/electroblob/wizardry/spell/IceAge.java +++ b/src/main/java/electroblob/wizardry/spell/IceAge.java @@ -1,163 +1,89 @@ package electroblob.wizardry.spell; -import java.util.List; - -import electroblob.wizardry.constants.Element; -import electroblob.wizardry.constants.SpellType; -import electroblob.wizardry.constants.Tier; -import electroblob.wizardry.registry.WizardryAdvancementTriggers; +import electroblob.wizardry.block.BlockStatue; import electroblob.wizardry.registry.WizardryBlocks; import electroblob.wizardry.registry.WizardryItems; import electroblob.wizardry.registry.WizardrySounds; -import electroblob.wizardry.tileentity.TileEntityStatue; +import electroblob.wizardry.util.AllyDesignationSystem; import electroblob.wizardry.util.SpellModifiers; import electroblob.wizardry.util.WizardryUtilities; import net.minecraft.entity.EntityLiving; import net.minecraft.entity.EntityLivingBase; -import net.minecraft.entity.monster.EntityBlaze; -import net.minecraft.entity.monster.EntityMagmaCube; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.init.Blocks; import net.minecraft.item.EnumAction; +import net.minecraft.util.EnumFacing; import net.minecraft.util.EnumHand; import net.minecraft.util.math.BlockPos; import net.minecraft.world.World; +import java.util.List; + public class IceAge extends Spell { - private static final int baseDuration = 1200; - public IceAge(){ - super("ice_age", Tier.MASTER, Element.ICE, SpellType.ATTACK, 70, 250, EnumAction.BOW, false); + super("ice_age", EnumAction.BOW, false); + this.soundValues(0.7f, 1.0f, 0); + addProperties(EFFECT_RADIUS, EFFECT_DURATION); } @Override - public boolean doesSpellRequirePacket(){ + public boolean requiresPacket(){ return false; } @Override public boolean cast(World world, EntityPlayer caster, EnumHand hand, int ticksInUse, SpellModifiers modifiers){ - List targets = WizardryUtilities.getEntitiesWithinRadius( - 7 * modifiers.get(WizardryItems.blast_upgrade), caster.posX, caster.posY, caster.posZ, world); + float radius = getProperty(EFFECT_RADIUS).floatValue() * modifiers.get(WizardryItems.blast_upgrade); + + List targets = WizardryUtilities.getEntitiesWithinRadius(radius, caster.posX, caster.posY, caster.posZ, world); for(EntityLivingBase target : targets){ - if(WizardryUtilities.isValidTarget(caster, target)){ + if(AllyDesignationSystem.isValidTarget(caster, target)){ if(!world.isRemote){ - if(target instanceof EntityBlaze || target instanceof EntityMagmaCube){ - // These have been removed for the time being because they cause the entity to sink into the - // floor when it breaks out. - // target.attackEntityFrom(WizardryUtilities.causePlayerMagicDamage(entityplayer), 8.0f * - // modifiers.get(SpellModifiers.DAMAGE)); - }else{ - // target.attackEntityFrom(WizardryUtilities.causePlayerMagicDamage(entityplayer), 4.0f * - // modifiers.get(SpellModifiers.DAMAGE)); - } - if(target.isBurning()){ - target.extinguish(); - } - - if(target instanceof EntityBlaze) WizardryAdvancementTriggers.freeze_blaze.triggerFor(caster); if(target instanceof EntityLiving){ - - // Stops the entity looking red while frozen and the resulting z-fighting - target.hurtTime = 0; - - BlockPos pos = new BlockPos(target); - - // Short mobs such as spiders and pigs - if((target.height < 1.2 || target.isChild()) - && WizardryUtilities.canBlockBeReplaced(world, pos)){ - world.setBlockState(pos, WizardryBlocks.ice_statue.getDefaultState()); - if(world.getTileEntity(pos) instanceof TileEntityStatue){ - ((TileEntityStatue)world.getTileEntity(pos)).setCreatureAndPart((EntityLiving)target, 1, - 1); - ((TileEntityStatue)world.getTileEntity(pos)).setLifetime( - (int)(baseDuration * modifiers.get(WizardryItems.duration_upgrade))); - } - target.setDead(); - target.playSound(WizardrySounds.SPELL_FREEZE, 1.0F, world.rand.nextFloat() * 0.4F + 0.8F); - } - // Normal sized mobs like zombies and skeletons - else if(target.height < 2.5 && WizardryUtilities.canBlockBeReplaced(world, pos) - && WizardryUtilities.canBlockBeReplaced(world, pos.up())){ - world.setBlockState(pos, WizardryBlocks.ice_statue.getDefaultState()); - if(world.getTileEntity(pos) instanceof TileEntityStatue){ - ((TileEntityStatue)world.getTileEntity(pos)).setCreatureAndPart((EntityLiving)target, 1, - 2); - ((TileEntityStatue)world.getTileEntity(pos)).setLifetime( - (int)(baseDuration * modifiers.get(WizardryItems.duration_upgrade))); - } - - world.setBlockState(pos.up(), WizardryBlocks.ice_statue.getDefaultState()); - if(world.getTileEntity(pos.up()) instanceof TileEntityStatue){ - ((TileEntityStatue)world.getTileEntity(pos.up())) - .setCreatureAndPart((EntityLiving)target, 2, 2); - } - target.setDead(); - target.playSound(WizardrySounds.SPELL_FREEZE, 1.0F, world.rand.nextFloat() * 0.4F + 0.8F); - } - // Tall mobs like endermen - else if(WizardryUtilities.canBlockBeReplaced(world, pos) - && WizardryUtilities.canBlockBeReplaced(world, pos.up()) - && WizardryUtilities.canBlockBeReplaced(world, pos.up(2))){ - world.setBlockState(pos, WizardryBlocks.ice_statue.getDefaultState()); - if(world.getTileEntity(pos) instanceof TileEntityStatue){ - ((TileEntityStatue)world.getTileEntity(pos)).setCreatureAndPart((EntityLiving)target, 1, - 3); - ((TileEntityStatue)world.getTileEntity(pos)).setLifetime( - (int)(baseDuration * modifiers.get(WizardryItems.duration_upgrade))); - } - - world.setBlockState(pos.up(), WizardryBlocks.ice_statue.getDefaultState()); - if(world.getTileEntity(pos.up()) instanceof TileEntityStatue){ - ((TileEntityStatue)world.getTileEntity(pos.up())) - .setCreatureAndPart((EntityLiving)target, 2, 3); - } - - world.setBlockState(pos.up(2), WizardryBlocks.ice_statue.getDefaultState()); - if(world.getTileEntity(pos.up(2)) instanceof TileEntityStatue){ - ((TileEntityStatue)world.getTileEntity(pos.up(2))) - .setCreatureAndPart((EntityLiving)target, 3, 3); - } - target.setDead(); - target.playSound(WizardrySounds.SPELL_FREEZE, 1.0F, world.rand.nextFloat() * 0.4F + 0.8F); + if(((BlockStatue)WizardryBlocks.ice_statue).convertToStatue((EntityLiving)target, + (int)(getProperty(EFFECT_DURATION).floatValue() * modifiers.get(WizardryItems.duration_upgrade)))){ + target.playSound(WizardrySounds.MISC_FREEZE, 1.0F, world.rand.nextFloat() * 0.4F + 0.8F); } } } } } - if(!world.isRemote){ - for(int i = -7; i < 8; i++){ - for(int j = -7; j < 8; j++){ + if(!world.isRemote && WizardryUtilities.canDamageBlocks(caster, world)){ + for(int i = -(int)radius; i < (int)radius + 1; i++){ + for(int j = -(int)radius; j < (int)radius + 1; j++){ BlockPos pos = new BlockPos(caster).add(i, 0, j); - int y = WizardryUtilities.getNearestFloorLevelB(world, new BlockPos(pos), 7); + Integer y = WizardryUtilities.getNearestSurface(world, new BlockPos(pos), EnumFacing.UP, (int)radius, true, WizardryUtilities.SurfaceCriteria.BUILDABLE); - pos = new BlockPos(pos.getX(), y, pos.getZ()); + if(y != null){ - double dist = caster.getDistance((int)caster.posX + i, y, (int)caster.posZ + j); + pos = new BlockPos(pos.getX(), y, pos.getZ()); - // Randomised with weighting so that the nearer the block the more likely it is to be snowed. - if(y != -1 && world.rand.nextInt((int)dist * 2 + 1) < 7 && dist < 8){ - if(world.getBlockState(pos.down()) == Blocks.WATER.getDefaultState()){ - world.setBlockState(pos.down(), Blocks.ICE.getDefaultState()); - }else if(world.getBlockState(pos.down()) == Blocks.LAVA.getDefaultState()){ - world.setBlockState(pos.down(), Blocks.OBSIDIAN.getDefaultState()); - }else if(world.getBlockState(pos.down()) == Blocks.FLOWING_LAVA.getDefaultState()){ - world.setBlockState(pos.down(), Blocks.COBBLESTONE.getDefaultState()); - }else if(Blocks.SNOW_LAYER.canPlaceBlockAt(world, pos)){ - world.setBlockState(pos, Blocks.SNOW_LAYER.getDefaultState()); + double dist = caster.getDistance((int)caster.posX + i, y, (int)caster.posZ + j); + + // Randomised with weighting so that the nearer the block the more likely it is to be snowed. + if(y != -1 && world.rand.nextInt((int)dist * 2 + 1) < radius && dist < radius){ + if(world.getBlockState(pos.down()) == Blocks.WATER.getDefaultState()){ + world.setBlockState(pos.down(), Blocks.ICE.getDefaultState()); + }else if(world.getBlockState(pos.down()) == Blocks.LAVA.getDefaultState()){ + world.setBlockState(pos.down(), Blocks.OBSIDIAN.getDefaultState()); + }else if(world.getBlockState(pos.down()) == Blocks.FLOWING_LAVA.getDefaultState()){ + world.setBlockState(pos.down(), Blocks.COBBLESTONE.getDefaultState()); + }else if(Blocks.SNOW_LAYER.canPlaceBlockAt(world, pos)){ + world.setBlockState(pos, Blocks.SNOW_LAYER.getDefaultState()); + } } } } } } - WizardryUtilities.playSoundAtPlayer(caster, WizardrySounds.SPELL_ICE, 0.7F, 1.0f); - WizardryUtilities.playSoundAtPlayer(caster, WizardrySounds.SPELL_LOOP_WIND, 1.0F, 1.0f); + + this.playSound(world, caster, ticksInUse, -1, modifiers); return true; } diff --git a/src/main/java/electroblob/wizardry/spell/IceSpikes.java b/src/main/java/electroblob/wizardry/spell/IceSpikes.java index 7a07adc7..5f7f7d26 100644 --- a/src/main/java/electroblob/wizardry/spell/IceSpikes.java +++ b/src/main/java/electroblob/wizardry/spell/IceSpikes.java @@ -1,49 +1,62 @@ package electroblob.wizardry.spell; -import electroblob.wizardry.constants.Element; -import electroblob.wizardry.constants.SpellType; -import electroblob.wizardry.constants.Tier; import electroblob.wizardry.entity.construct.EntityIceSpike; import electroblob.wizardry.registry.WizardryItems; -import electroblob.wizardry.registry.WizardrySounds; import electroblob.wizardry.util.SpellModifiers; import electroblob.wizardry.util.WizardryUtilities; import net.minecraft.entity.EntityLivingBase; +import net.minecraft.util.EnumFacing; import net.minecraft.util.math.BlockPos; -import net.minecraft.util.math.MathHelper; +import net.minecraft.util.math.Vec3d; import net.minecraft.world.World; public class IceSpikes extends SpellConstructRanged { - private static final int BASE_SPAWN_COUNT = 17; // Was 18, reduced to 17 to account for the extra one in the middle. + public static final String ICE_SPIKE_COUNT = "ice_spike_count"; public IceSpikes(){ - // Base duration is set to -1 so that the superclass doesn't waste time retrieving the duration multiplier - super("ice_spikes", Tier.ADVANCED, Element.ICE, SpellType.ATTACK, 30, 75, EntityIceSpike::new, -1, 20, WizardrySounds.SPELL_ICE); + super("ice_spikes", EntityIceSpike::new, true); + addProperties(EFFECT_RADIUS, ICE_SPIKE_COUNT, DAMAGE, EFFECT_DURATION, EFFECT_STRENGTH); + this.ignoreUncollidables(true); } @Override - protected boolean spawnConstruct(World world, double x, double y, double z, EntityLivingBase caster, SpellModifiers modifiers){ - - if(world.getBlockState(new BlockPos(x, y, z)).isNormalCube()) return false; + protected boolean spawnConstruct(World world, double x, double y, double z, EnumFacing side, EntityLivingBase caster, SpellModifiers modifiers){ + + BlockPos blockHit = new BlockPos(x, y, z); + if(side != null && side.getAxisDirection() == EnumFacing.AxisDirection.NEGATIVE) blockHit = blockHit.offset(side); + + if(world.getBlockState(blockHit).isNormalCube()) return false; + + Vec3d origin = new Vec3d(x, y, z); + + Vec3d pos = origin.add(new Vec3d(side.getOpposite().getDirectionVec())); // Now always spawns a spike exactly at the position aimed at - super.spawnConstruct(world, x, y-1, z, caster, modifiers); - - int quantity = (int)(BASE_SPAWN_COUNT * modifiers.get(WizardryItems.blast_upgrade)); + super.spawnConstruct(world, pos.x, pos.y, pos.z, side, caster, modifiers); + // -1 because of the one spawned above + int quantity = (int)(getProperty(ICE_SPIKE_COUNT).floatValue() * modifiers.get(WizardryItems.blast_upgrade)) - 1; + + float maxRadius = getProperty(EFFECT_RADIUS).floatValue() * modifiers.get(WizardryItems.blast_upgrade); for(int i=0; i -1){ - super.spawnConstruct(world, x1, y1, z1, caster, modifiers); + // First, generate a random vector of length radius with a z component of zero + // Then rotate it so that what was south is now the side that was hit + Vec3d offset = Vec3d.fromPitchYaw(world.rand.nextFloat() * 180 - 90, world.rand.nextBoolean() ? 0 : 180) + .scale(radius).rotateYaw(side.getHorizontalAngle() * (float)Math.PI/180).rotatePitch(WizardryUtilities.getPitch(side) * (float)Math.PI/180); + + if(side.getAxis().isHorizontal()) offset = offset.rotateYaw((float)Math.PI/2); + + Integer surface = WizardryUtilities.getNearestSurface(world, new BlockPos(origin.add(offset)), side, + (int)maxRadius, true, WizardryUtilities.SurfaceCriteria.basedOn(World::isBlockFullCube)); + + if(surface != null){ + Vec3d vec = WizardryUtilities.replaceComponent(origin.add(offset), side.getAxis(), surface) + .subtract(new Vec3d(side.getDirectionVec())); + super.spawnConstruct(world, vec.x, vec.y, vec.z, side, caster, modifiers); } } @@ -51,9 +64,10 @@ public class IceSpikes extends SpellConstructRanged { } @Override - protected void addConstructExtras(EntityIceSpike construct, EntityLivingBase caster, SpellModifiers modifiers){ + protected void addConstructExtras(EntityIceSpike construct, EnumFacing side, EntityLivingBase caster, SpellModifiers modifiers){ // In this particular case, lifetime is implemented as a delay instead so is treated differently. construct.lifetime = 30 + construct.world.rand.nextInt(15); + construct.setFacing(side); } } diff --git a/src/main/java/electroblob/wizardry/spell/IceStatue.java b/src/main/java/electroblob/wizardry/spell/IceStatue.java index 9c5b1cfd..35665491 100644 --- a/src/main/java/electroblob/wizardry/spell/IceStatue.java +++ b/src/main/java/electroblob/wizardry/spell/IceStatue.java @@ -1,54 +1,56 @@ package electroblob.wizardry.spell; import electroblob.wizardry.block.BlockStatue; -import electroblob.wizardry.constants.Element; -import electroblob.wizardry.constants.SpellType; -import electroblob.wizardry.constants.Tier; import electroblob.wizardry.registry.WizardryBlocks; import electroblob.wizardry.registry.WizardryItems; -import electroblob.wizardry.registry.WizardrySounds; import electroblob.wizardry.util.ParticleBuilder; import electroblob.wizardry.util.ParticleBuilder.Type; import electroblob.wizardry.util.SpellModifiers; import net.minecraft.entity.Entity; import net.minecraft.entity.EntityLiving; import net.minecraft.entity.EntityLivingBase; +import net.minecraft.item.EnumAction; import net.minecraft.util.EnumFacing; +import net.minecraft.util.SoundEvent; import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.Vec3d; import net.minecraft.world.World; public class IceStatue extends SpellRay { - private static final int BASE_DURATION = 400; - public IceStatue(){ - super("ice_statue", Tier.APPRENTICE, Element.ICE, SpellType.ATTACK, 15, 40, false, 10, WizardrySounds.SPELL_ICE); + super("ice_statue", false, EnumAction.NONE); this.soundValues(1, 1.4f, 0.4f); + addProperties(EFFECT_DURATION); } @Override - protected boolean onEntityHit(World world, Entity target, EntityLivingBase caster, int ticksInUse, SpellModifiers modifiers){ + protected SoundEvent[] createSounds(){ + return createSoundsWithSuffixes("shoot", "freeze"); + } + + @Override + protected boolean onEntityHit(World world, Entity target, Vec3d hit, EntityLivingBase caster, Vec3d origin, int ticksInUse, SpellModifiers modifiers){ if(target instanceof EntityLiving && !world.isRemote){ // Unchecked cast is fine because the block is a static final field if(((BlockStatue)WizardryBlocks.ice_statue).convertToStatue((EntityLiving)target, - (int)(BASE_DURATION * modifiers.get(WizardryItems.duration_upgrade)))){ - - target.playSound(WizardrySounds.SPELL_FREEZE, 1.0F, world.rand.nextFloat() * 0.4F + 0.8F); - return true; + (int)(getProperty(EFFECT_DURATION).floatValue() * modifiers.get(WizardryItems.duration_upgrade)))){ + + //target.playSound(WizardrySounds.SPELL_FREEZE, 1.0F, world.rand.nextFloat() * 0.4F + 0.8F); } } + return true; + } + + @Override + protected boolean onBlockHit(World world, BlockPos pos, EnumFacing side, Vec3d hit, EntityLivingBase caster, Vec3d origin, int ticksInUse, SpellModifiers modifiers){ return false; } @Override - protected boolean onBlockHit(World world, BlockPos pos, EnumFacing side, EntityLivingBase caster, int ticksInUse, SpellModifiers modifiers){ - return false; - } - - @Override - protected boolean onMiss(World world, EntityLivingBase caster, int ticksInUse, SpellModifiers modifiers){ + protected boolean onMiss(World world, EntityLivingBase caster, Vec3d origin, Vec3d direction, int ticksInUse, SpellModifiers modifiers){ return true; } diff --git a/src/main/java/electroblob/wizardry/spell/Ignite.java b/src/main/java/electroblob/wizardry/spell/Ignite.java index 0acbe1c5..b686d89d 100644 --- a/src/main/java/electroblob/wizardry/spell/Ignite.java +++ b/src/main/java/electroblob/wizardry/spell/Ignite.java @@ -1,34 +1,32 @@ package electroblob.wizardry.spell; -import electroblob.wizardry.constants.Element; -import electroblob.wizardry.constants.SpellType; -import electroblob.wizardry.constants.Tier; import electroblob.wizardry.registry.WizardryItems; import electroblob.wizardry.util.MagicDamage; import electroblob.wizardry.util.MagicDamage.DamageType; import electroblob.wizardry.util.SpellModifiers; +import electroblob.wizardry.util.WizardryUtilities; import net.minecraft.entity.Entity; import net.minecraft.entity.EntityLivingBase; +import net.minecraft.entity.player.EntityPlayer; import net.minecraft.init.Blocks; -import net.minecraft.init.SoundEvents; +import net.minecraft.item.EnumAction; import net.minecraft.util.EnumFacing; import net.minecraft.util.EnumParticleTypes; import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.Vec3d; import net.minecraft.util.text.TextComponentTranslation; import net.minecraft.world.World; public class Ignite extends SpellRay { - - /** The base duration for which entities are set on fire by this spell. */ - private static final int BASE_DURATION = 10; public Ignite(){ - super("ignite", Tier.BASIC, Element.FIRE, SpellType.ATTACK, 5, 10, false, 10, SoundEvents.ITEM_FLINTANDSTEEL_USE); + super("ignite", false, EnumAction.NONE); this.soundValues(1, 1, 0.4f); + addProperties(BURN_DURATION); } @Override - protected boolean onEntityHit(World world, Entity target, EntityLivingBase caster, int ticksInUse, SpellModifiers modifiers){ + protected boolean onEntityHit(World world, Entity target, Vec3d hit, EntityLivingBase caster, Vec3d origin, int ticksInUse, SpellModifiers modifiers){ // Fire can damage armour stands, so this includes them if(target instanceof EntityLivingBase) { @@ -36,7 +34,7 @@ public class Ignite extends SpellRay { if(!world.isRemote && caster instanceof EntityPlayer) ((EntityPlayer)caster).sendStatusMessage( new TextComponentTranslation("spell.resist", target.getName(), this.getNameForTranslationFormatted()), true); }else{ - target.setFire((int)(BASE_DURATION * modifiers.get(WizardryItems.duration_upgrade))); + target.setFire((int)(getProperty(BURN_DURATION).floatValue() * modifiers.get(WizardryItems.duration_upgrade))); } return true; @@ -46,8 +44,10 @@ public class Ignite extends SpellRay { } @Override - protected boolean onBlockHit(World world, BlockPos pos, EnumFacing side, EntityLivingBase caster, int ticksInUse, SpellModifiers modifiers){ - + protected boolean onBlockHit(World world, BlockPos pos, EnumFacing side, Vec3d hit, EntityLivingBase caster, Vec3d origin, int ticksInUse, SpellModifiers modifiers){ + + if(!WizardryUtilities.canDamageBlocks(caster, world)) return false; + pos = pos.offset(side); if(world.isAirBlock(pos)){ @@ -63,7 +63,7 @@ public class Ignite extends SpellRay { } @Override - protected boolean onMiss(World world, EntityLivingBase caster, int ticksInUse, SpellModifiers modifiers){ + protected boolean onMiss(World world, EntityLivingBase caster, Vec3d origin, Vec3d direction, int ticksInUse, SpellModifiers modifiers){ return false; } diff --git a/src/main/java/electroblob/wizardry/spell/ImbueWeapon.java b/src/main/java/electroblob/wizardry/spell/ImbueWeapon.java index ec1178fd..a41cd34b 100644 --- a/src/main/java/electroblob/wizardry/spell/ImbueWeapon.java +++ b/src/main/java/electroblob/wizardry/spell/ImbueWeapon.java @@ -1,30 +1,27 @@ package electroblob.wizardry.spell; -import electroblob.wizardry.WizardData; +import electroblob.wizardry.Wizardry; import electroblob.wizardry.constants.Constants; -import electroblob.wizardry.constants.Element; -import electroblob.wizardry.constants.SpellType; -import electroblob.wizardry.constants.Tier; +import electroblob.wizardry.data.WizardData; import electroblob.wizardry.registry.WizardryEnchantments; import electroblob.wizardry.registry.WizardryItems; -import electroblob.wizardry.registry.WizardrySounds; import electroblob.wizardry.util.ParticleBuilder; import electroblob.wizardry.util.ParticleBuilder.Type; import electroblob.wizardry.util.SpellModifiers; import electroblob.wizardry.util.WizardryUtilities; import net.minecraft.enchantment.EnchantmentHelper; import net.minecraft.entity.player.EntityPlayer; -import net.minecraft.item.EnumAction; -import net.minecraft.item.ItemBow; -import net.minecraft.item.ItemStack; -import net.minecraft.item.ItemSword; +import net.minecraft.item.*; import net.minecraft.util.EnumHand; import net.minecraft.world.World; +import java.util.Arrays; + public class ImbueWeapon extends Spell { public ImbueWeapon(){ - super("imbue_weapon", Tier.APPRENTICE, Element.SORCERY, SpellType.UTILITY, 20, 50, EnumAction.BOW, false); + super("imbue_weapon", EnumAction.BOW, false); + addProperties(EFFECT_DURATION); } @Override @@ -35,29 +32,29 @@ public class ImbueWeapon extends Spell { for(ItemStack stack : WizardryUtilities.getPrioritisedHotbarAndOffhand(caster)){ - if(stack.getItem() instanceof ItemSword + if(isSword(stack.getItem()) && !EnchantmentHelper.getEnchantments(stack).containsKey(WizardryEnchantments.magic_sword) && WizardData.get(caster).getImbuementDuration(WizardryEnchantments.magic_sword) <= 0){ // The enchantment level as determined by the damage multiplier. The + 0.5f is so that // weird float processing doesn't incorrectly round it down. stack.addEnchantment(WizardryEnchantments.magic_sword, modifiers.get(SpellModifiers.POTENCY) == 1.0f ? 1 - : (int)((modifiers.get(SpellModifiers.POTENCY) - 1.0f) / Constants.DAMAGE_INCREASE_PER_TIER + : (int)((modifiers.get(SpellModifiers.POTENCY) - 1.0f) / Constants.POTENCY_INCREASE_PER_TIER + 0.5f)); WizardData.get(caster).setImbuementDuration(WizardryEnchantments.magic_sword, - (int)(900 * modifiers.get(WizardryItems.duration_upgrade))); + (int)(getProperty(EFFECT_DURATION).floatValue() * modifiers.get(WizardryItems.duration_upgrade))); - }else if(stack.getItem() instanceof ItemBow + }else if(isBow(stack.getItem()) && !EnchantmentHelper.getEnchantments(stack).containsKey(WizardryEnchantments.magic_bow) && WizardData.get(caster).getImbuementDuration(WizardryEnchantments.magic_bow) <= 0){ // The enchantment level as determined by the damage multiplier. The + 0.5f is so that // weird float processing doesn't incorrectly round it down. stack.addEnchantment(WizardryEnchantments.magic_bow, modifiers.get(SpellModifiers.POTENCY) == 1.0f ? 1 - : (int)((modifiers.get(SpellModifiers.POTENCY) - 1.0f) / Constants.DAMAGE_INCREASE_PER_TIER + : (int)((modifiers.get(SpellModifiers.POTENCY) - 1.0f) / Constants.POTENCY_INCREASE_PER_TIER + 0.5f)); WizardData.get(caster).setImbuementDuration(WizardryEnchantments.magic_bow, - (int)(900 * modifiers.get(WizardryItems.duration_upgrade))); + (int)(getProperty(EFFECT_DURATION).floatValue() * modifiers.get(WizardryItems.duration_upgrade))); }else{ continue; @@ -72,11 +69,21 @@ public class ImbueWeapon extends Spell { } } - WizardryUtilities.playSoundAtPlayer(caster, WizardrySounds.SPELL_CONJURATION, 1, 1); + this.playSound(world, caster, ticksInUse, -1, modifiers); return true; } } return false; } + /** Returns true if the given item counts as a sword, i.e. it extends {@link ItemSword} or is in the whitelist. */ + public static boolean isSword(Item item){ + return item instanceof ItemSword || Arrays.asList(Wizardry.settings.swordItemWhitelist).contains(item.getRegistryName()); + } + + /** Returns true if the given item counts as a bow, i.e. it extends {@link ItemBow} or is in the whitelist. */ + public static boolean isBow(Item item){ + return item instanceof ItemBow || Arrays.asList(Wizardry.settings.bowItemWhitelist).contains(item.getRegistryName()); + } + } diff --git a/src/main/java/electroblob/wizardry/spell/Intimidate.java b/src/main/java/electroblob/wizardry/spell/Intimidate.java index 626c7210..6c9889ea 100644 --- a/src/main/java/electroblob/wizardry/spell/Intimidate.java +++ b/src/main/java/electroblob/wizardry/spell/Intimidate.java @@ -1,10 +1,5 @@ package electroblob.wizardry.spell; -import java.util.List; - -import electroblob.wizardry.constants.Element; -import electroblob.wizardry.constants.SpellType; -import electroblob.wizardry.constants.Tier; import electroblob.wizardry.registry.WizardryItems; import electroblob.wizardry.registry.WizardryPotions; import electroblob.wizardry.util.ParticleBuilder; @@ -13,11 +8,9 @@ import electroblob.wizardry.util.SpellModifiers; import electroblob.wizardry.util.WizardryUtilities; import net.minecraft.entity.Entity; import net.minecraft.entity.EntityCreature; -import net.minecraft.entity.EntityLiving; import net.minecraft.entity.EntityLivingBase; import net.minecraft.entity.ai.RandomPositionGenerator; import net.minecraft.entity.player.EntityPlayer; -import net.minecraft.init.SoundEvents; import net.minecraft.item.EnumAction; import net.minecraft.nbt.NBTTagCompound; import net.minecraft.pathfinding.PathPoint; @@ -29,17 +22,22 @@ import net.minecraftforge.event.entity.living.LivingEvent.LivingUpdateEvent; import net.minecraftforge.fml.common.Mod; import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; +import java.util.List; + @Mod.EventBusSubscriber public class Intimidate extends Spell { /** The NBT tag name for storing the feared entity's UUID in the target's tag compound. */ public static final String NBT_KEY = "fearedEntity"; - - private static final double BASE_RANGE = 8; - private static final int BASE_DURATION = 600; + + // These aren't spell properties because they're part fo the actual potion effect, not the spell itself. + // However, the avoid distance can be modified using the potion amplifier. + private static final double BASE_AVOID_DISTANCE = 16; + private static final double AVOID_DISTANCE_PER_LEVEL = 4; public Intimidate(){ - super("intimidate", Tier.APPRENTICE, Element.NECROMANCY, SpellType.ATTACK, 20, 100, EnumAction.BOW, false); + super("intimidate", EnumAction.BOW, false); + addProperties(EFFECT_RADIUS, EFFECT_DURATION, EFFECT_STRENGTH); } @Override @@ -48,19 +46,21 @@ public class Intimidate extends Spell { if(!world.isRemote){ List entities = WizardryUtilities.getEntitiesWithinRadius( - BASE_RANGE * modifiers.get(WizardryItems.range_upgrade), caster.posX, caster.posY, caster.posZ, - world, EntityCreature.class); + getProperty(EFFECT_RADIUS).floatValue() * modifiers.get(WizardryItems.range_upgrade), + caster.posX, caster.posY, caster.posZ, world, EntityCreature.class); for(EntityCreature target : entities){ + // Why do we need this here? + //runAway(target, caster); - runAway(target, caster); + int bonusAmplifier = SpellBuff.getStandardBonusAmplifier(modifiers.get(SpellModifiers.POTENCY)); NBTTagCompound entityNBT = target.getEntityData(); if(entityNBT != null) entityNBT.setUniqueId(NBT_KEY, caster.getUniqueID()); - ((EntityLiving)target).addPotionEffect(new PotionEffect(WizardryPotions.fear, - (int)(BASE_DURATION * modifiers.get(WizardryItems.duration_upgrade)), 0)); - + target.addPotionEffect(new PotionEffect(WizardryPotions.fear, + (int)(getProperty(EFFECT_DURATION).floatValue() * modifiers.get(WizardryItems.duration_upgrade)), + getProperty(EFFECT_STRENGTH).intValue() + bonusAmplifier)); } }else{ @@ -71,7 +71,7 @@ public class Intimidate extends Spell { ParticleBuilder.create(Type.DARK_MAGIC).pos(x, y, z).clr(0.9f, 0.1f, 0).spawn(world); } } - WizardryUtilities.playSoundAtPlayer(caster, SoundEvents.ENTITY_ENDERDRAGON_GROWL, 1.0f, 1.0f); + this.playSound(world, caster, ticksInUse, -1, modifiers); return true; } @@ -81,13 +81,14 @@ public class Intimidate extends Spell { * * @param target The entity running away * @param caster The entity that is being run away from + * @param distance How far the entity will run from the caster * @return True if a new path was found and set, false if not. */ - public static boolean runAway(EntityCreature target, EntityLivingBase caster){ + public static boolean runAway(EntityCreature target, EntityLivingBase caster, double distance){ - if(target.getDistance(caster) < 16){ + if(target.getDistance(caster) < distance){ - Vec3d Vec3d = RandomPositionGenerator.findRandomTargetBlockAwayFrom(target, 16, 7, + Vec3d Vec3d = RandomPositionGenerator.findRandomTargetBlockAwayFrom(target, (int)distance, (int)(distance/2), new Vec3d(caster.posX, caster.posY, caster.posZ)); if(Vec3d == null){ @@ -95,15 +96,14 @@ public class Intimidate extends Spell { }else{ // In both cases it is necessary to check if the entity already has a path so it doesn't change - // direction - // every tick, unless that path is towards the caster. + // direction every tick, unless that path is towards the caster. // Path path = target.getNavigator().getPathToXYZ(Vec3d.xCoord, Vec3d.yCoord, Vec3d.zCoord); boolean flag = true; if(!target.getNavigator().noPath()){ PathPoint point = target.getNavigator().getPath().getFinalPathPoint(); - if(point != null) flag = caster.getDistance(point.x, point.y, point.z) < 16; + if(point != null) flag = caster.getDistance(point.x, point.y, point.z) < distance; } // Has a built in mind trick effect because for whatever reason this makes it work with skeletons. target.setAttackTarget(null); @@ -129,7 +129,9 @@ public class Intimidate extends Spell { Entity caster = WizardryUtilities.getEntityByUUID(creature.world, entityNBT.getUniqueId(NBT_KEY)); if(caster instanceof EntityLivingBase){ - runAway(creature, (EntityLivingBase)caster); + double distance = BASE_AVOID_DISTANCE + AVOID_DISTANCE_PER_LEVEL + * event.getEntityLiving().getActivePotionEffect(WizardryPotions.fear).getAmplifier(); + runAway(creature, (EntityLivingBase)caster, distance); } } } diff --git a/src/main/java/electroblob/wizardry/spell/InvigoratingPresence.java b/src/main/java/electroblob/wizardry/spell/InvigoratingPresence.java index 425e7c3b..c6c473b8 100644 --- a/src/main/java/electroblob/wizardry/spell/InvigoratingPresence.java +++ b/src/main/java/electroblob/wizardry/spell/InvigoratingPresence.java @@ -1,12 +1,7 @@ package electroblob.wizardry.spell; -import java.util.List; - -import electroblob.wizardry.constants.Element; -import electroblob.wizardry.constants.SpellType; -import electroblob.wizardry.constants.Tier; import electroblob.wizardry.registry.WizardryItems; -import electroblob.wizardry.registry.WizardrySounds; +import electroblob.wizardry.util.AllyDesignationSystem; import electroblob.wizardry.util.ParticleBuilder; import electroblob.wizardry.util.ParticleBuilder.Type; import electroblob.wizardry.util.SpellModifiers; @@ -16,29 +11,34 @@ import net.minecraft.init.MobEffects; import net.minecraft.item.EnumAction; import net.minecraft.potion.PotionEffect; import net.minecraft.util.EnumHand; +import net.minecraft.util.math.MathHelper; import net.minecraft.world.World; +import java.util.List; + public class InvigoratingPresence extends Spell { - - private static final double BASE_RANGE = 5; - private static final int BASE_DURATION = 900; public InvigoratingPresence(){ - super("invigorating_presence", Tier.APPRENTICE, Element.HEALING, SpellType.UTILITY, 30, 60, EnumAction.BOW, false); + super("invigorating_presence", EnumAction.BOW, false); + this.soundValues(0.7f, 1.2f, 0.4f); + addProperties(EFFECT_RADIUS, EFFECT_DURATION, EFFECT_STRENGTH); } @Override public boolean cast(World world, EntityPlayer caster, EnumHand hand, int ticksInUse, SpellModifiers modifiers){ List targets = WizardryUtilities.getEntitiesWithinRadius( - BASE_RANGE * modifiers.get(WizardryItems.blast_upgrade), caster.posX, caster.posY, caster.posZ, world, - EntityPlayer.class); + getProperty(EFFECT_RADIUS).floatValue() * modifiers.get(WizardryItems.blast_upgrade), + caster.posX, caster.posY, caster.posZ, world, EntityPlayer.class); for(EntityPlayer target : targets){ - if(WizardryUtilities.isPlayerAlly(caster, target) || target == caster){ - // Strength 2 for 45 seconds. + if(AllyDesignationSystem.isPlayerAlly(caster, target) || target == caster){ + + int bonusAmplifier = SpellBuff.getStandardBonusAmplifier(modifiers.get(SpellModifiers.POTENCY)); + target.addPotionEffect(new PotionEffect(MobEffects.STRENGTH, - (int)(BASE_DURATION * modifiers.get(WizardryItems.duration_upgrade)), 1, false, false)); + (int)(getProperty(EFFECT_DURATION).floatValue() * modifiers.get(WizardryItems.duration_upgrade)), + getProperty(EFFECT_STRENGTH).intValue() + bonusAmplifier)); } } @@ -47,18 +47,18 @@ public class InvigoratingPresence extends Spell { for(int i = 0; i < 50 * modifiers.get(WizardryItems.blast_upgrade); i++){ double radius = (1 + world.rand.nextDouble() * 4) * modifiers.get(WizardryItems.blast_upgrade); - double angle = world.rand.nextDouble() * Math.PI * 2; + float angle = world.rand.nextFloat() * (float)Math.PI * 2;; - double x = caster.posX + radius * Math.cos(angle); + double x = caster.posX + radius * MathHelper.cos(angle); double y = caster.getEntityBoundingBox().minY; - double z = caster.posZ + radius * Math.sin(angle); + double z = caster.posZ + radius * MathHelper.sin(angle); ParticleBuilder.create(Type.SPARKLE).pos(x, y, z).vel(0, 0.03, 0).time(50).clr(1, 0.2f, 0.2f).spawn(world); } } - WizardryUtilities.playSoundAtPlayer(caster, WizardrySounds.SPELL_CONJURATION, 1, 1 + 0.2f * world.rand.nextFloat()); + playSound(world, caster, ticksInUse, -1, modifiers); return true; } diff --git a/src/main/java/electroblob/wizardry/spell/InvokeWeather.java b/src/main/java/electroblob/wizardry/spell/InvokeWeather.java index 71ce3368..e62718ac 100644 --- a/src/main/java/electroblob/wizardry/spell/InvokeWeather.java +++ b/src/main/java/electroblob/wizardry/spell/InvokeWeather.java @@ -1,25 +1,26 @@ package electroblob.wizardry.spell; -import java.util.Random; - -import electroblob.wizardry.constants.Element; -import electroblob.wizardry.constants.SpellType; -import electroblob.wizardry.constants.Tier; +import electroblob.wizardry.item.ItemArtefact; +import electroblob.wizardry.registry.WizardryItems; import electroblob.wizardry.util.ParticleBuilder; import electroblob.wizardry.util.ParticleBuilder.Type; import electroblob.wizardry.util.SpellModifiers; -import electroblob.wizardry.util.WizardryUtilities; import net.minecraft.entity.player.EntityPlayer; -import net.minecraft.init.SoundEvents; import net.minecraft.item.EnumAction; import net.minecraft.util.EnumHand; import net.minecraft.util.text.TextComponentTranslation; import net.minecraft.world.World; +import java.util.Random; + public class InvokeWeather extends Spell { + public static final String THUNDERSTORM_CHANCE = "thunderstorm_chance"; + public InvokeWeather(){ - super("invoke_weather", Tier.ADVANCED, Element.LIGHTNING, SpellType.UTILITY, 30, 100, EnumAction.BOW, false); + super("invoke_weather", EnumAction.BOW, false); + addProperties(THUNDERSTORM_CHANCE); + soundValues(0.5f, 1, 0); } @Override @@ -32,20 +33,21 @@ public class InvokeWeather extends Spell { int standardWeatherTime = (300 + (new Random()).nextInt(600)) * 20; if(world.isRaining()){ - caster.sendMessage(new TextComponentTranslation("spell." + this.getUnlocalisedName() + ".sun")); + caster.sendStatusMessage(new TextComponentTranslation("spell." + this.getUnlocalisedName() + ".sun"), true); world.getWorldInfo().setCleanWeatherTime(standardWeatherTime); world.getWorldInfo().setRainTime(0); world.getWorldInfo().setThunderTime(0); world.getWorldInfo().setRaining(false); world.getWorldInfo().setThundering(false); }else{ - caster.sendMessage(new TextComponentTranslation("spell." + this.getUnlocalisedName() + ".rain")); + caster.sendStatusMessage(new TextComponentTranslation("spell." + this.getUnlocalisedName() + ".rain"), true); world.getWorldInfo().setCleanWeatherTime(0); world.getWorldInfo().setRainTime(standardWeatherTime); world.getWorldInfo().setThunderTime(standardWeatherTime); world.getWorldInfo().setRaining(true); - // 1/3 chance for a thunderstorm - world.getWorldInfo().setThundering(world.rand.nextInt(3) == 0); + // Thunderstorm is guaranteed if the caster has a bottled thundercloud charm equipped + world.getWorldInfo().setThundering(ItemArtefact.isArtefactActive(caster, WizardryItems.charm_storm) + || world.rand.nextFloat() < getProperty(THUNDERSTORM_CHANCE).floatValue()); } } @@ -58,7 +60,7 @@ public class InvokeWeather extends Spell { } } - WizardryUtilities.playSoundAtPlayer(caster, SoundEvents.ENTITY_LIGHTNING_THUNDER, 0.5f, 1.0f); + this.playSound(world, caster, ticksInUse, -1, modifiers); return true; } diff --git a/src/main/java/electroblob/wizardry/spell/Leap.java b/src/main/java/electroblob/wizardry/spell/Leap.java index 2bb1263b..16b69acc 100644 --- a/src/main/java/electroblob/wizardry/spell/Leap.java +++ b/src/main/java/electroblob/wizardry/spell/Leap.java @@ -1,12 +1,7 @@ package electroblob.wizardry.spell; -import electroblob.wizardry.constants.Element; -import electroblob.wizardry.constants.SpellType; -import electroblob.wizardry.constants.Tier; import electroblob.wizardry.util.SpellModifiers; -import electroblob.wizardry.util.WizardryUtilities; import net.minecraft.entity.player.EntityPlayer; -import net.minecraft.init.SoundEvents; import net.minecraft.item.EnumAction; import net.minecraft.util.EnumHand; import net.minecraft.util.EnumParticleTypes; @@ -14,8 +9,13 @@ import net.minecraft.world.World; public class Leap extends Spell { + public static final String HORIZONTAL_SPEED = "horizontal_speed"; + public static final String VERTICAL_SPEED = "vertical_speed"; + public Leap(){ - super("leap", Tier.BASIC, Element.EARTH, SpellType.UTILITY, 10, 20, EnumAction.NONE, false); + super("leap", EnumAction.NONE, false); + addProperties(HORIZONTAL_SPEED, VERTICAL_SPEED); + soundValues(0.5f, 1, 0); } @Override @@ -23,19 +23,20 @@ public class Leap extends Spell { if(caster.onGround){ - caster.motionY = 0.65 * modifiers.get(SpellModifiers.POTENCY); - caster.addVelocity(caster.getLookVec().x * 0.3, 0, caster.getLookVec().z * 0.3); + caster.motionY = getProperty(VERTICAL_SPEED).floatValue() * modifiers.get(SpellModifiers.POTENCY); + double horizontalSpeed = getProperty(HORIZONTAL_SPEED).floatValue(); + caster.addVelocity(caster.getLookVec().x * horizontalSpeed, 0, caster.getLookVec().z * horizontalSpeed); if(world.isRemote){ for(int i = 0; i < 10; i++){ - double x = (double)(caster.posX + world.rand.nextFloat() - 0.5F); - double y = (double)(caster.getEntityBoundingBox().minY); - double z = (double)(caster.posZ + world.rand.nextFloat() - 0.5F); + double x = caster.posX + world.rand.nextFloat() - 0.5F; + double y = caster.getEntityBoundingBox().minY; + double z = caster.posZ + world.rand.nextFloat() - 0.5F; world.spawnParticle(EnumParticleTypes.CLOUD, x, y, z, 0, 0, 0); } } - WizardryUtilities.playSoundAtPlayer(caster, SoundEvents.ENTITY_ENDERDRAGON_FLAP, 0.5F, 1.0f); + this.playSound(world, caster, ticksInUse, -1, modifiers); caster.swingArm(hand); return true; } diff --git a/src/main/java/electroblob/wizardry/spell/Levitation.java b/src/main/java/electroblob/wizardry/spell/Levitation.java index 60e16ab8..f70e8f29 100644 --- a/src/main/java/electroblob/wizardry/spell/Levitation.java +++ b/src/main/java/electroblob/wizardry/spell/Levitation.java @@ -1,30 +1,49 @@ package electroblob.wizardry.spell; import electroblob.wizardry.Wizardry; -import electroblob.wizardry.constants.Element; -import electroblob.wizardry.constants.SpellType; -import electroblob.wizardry.constants.Tier; -import electroblob.wizardry.registry.WizardrySounds; import electroblob.wizardry.util.ParticleBuilder; import electroblob.wizardry.util.ParticleBuilder.Type; import electroblob.wizardry.util.SpellModifiers; +import net.minecraft.entity.EntityLivingBase; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.item.EnumAction; import net.minecraft.util.EnumHand; +import net.minecraft.util.SoundEvent; import net.minecraft.world.World; public class Levitation extends Spell { + public static final String SPEED = "speed"; + public static final String ACCELERATION = "acceleration"; + public Levitation(){ - super("levitation", Tier.ADVANCED, Element.SORCERY, SpellType.UTILITY, 10, 0, EnumAction.BOW, true); + super("levitation", EnumAction.BOW, true); + addProperties(SPEED, ACCELERATION); + soundValues(0.5f, 1, 0); + } + + @Override + protected SoundEvent[] createSounds(){ + return this.createContinuousSpellSounds(); + } + + @Override + protected void playSound(World world, EntityLivingBase entity, int ticksInUse, int duration, SpellModifiers modifiers, String... sounds){ + this.playSoundLoop(world, entity, ticksInUse); + } + + @Override + protected void playSound(World world, double x, double y, double z, int ticksInUse, int duration, SpellModifiers modifiers, String... sounds){ + this.playSoundLoop(world, x, y, z, ticksInUse, duration); } @Override public boolean cast(World world, EntityPlayer caster, EnumHand hand, int ticksInUse, SpellModifiers modifiers){ - caster.fallDistance = 0; + if(!Wizardry.settings.replaceVanillaFallDamage) caster.fallDistance = 0; - caster.motionY = caster.motionY < 0.5 ? caster.motionY + 0.1 : caster.motionY; + caster.motionY = caster.motionY < getProperty(SPEED).floatValue() ? caster.motionY + + getProperty(ACCELERATION).floatValue() : caster.motionY; if(world.isRemote){ double x = caster.posX - 0.25 + world.rand.nextDouble() * 0.5; @@ -32,9 +51,9 @@ public class Levitation extends Spell { double z = caster.posZ - 0.25 + world.rand.nextDouble() * 0.5; ParticleBuilder.create(Type.SPARKLE).pos(x, y, z).vel(0, -0.1, 0).time(15).clr(0.5f, 1, 0.7f).spawn(world); } - if(ticksInUse % 24 == 0 && world.isRemote){ - Wizardry.proxy.playMovingSound(caster, WizardrySounds.SPELL_LOOP_SPARKLE, 0.5f, 1, false); - } + + this.playSound(world, caster, ticksInUse, -1, modifiers); + return true; } diff --git a/src/main/java/electroblob/wizardry/spell/LifeDrain.java b/src/main/java/electroblob/wizardry/spell/LifeDrain.java index b60109f9..a4cf6add 100644 --- a/src/main/java/electroblob/wizardry/spell/LifeDrain.java +++ b/src/main/java/electroblob/wizardry/spell/LifeDrain.java @@ -1,9 +1,5 @@ package electroblob.wizardry.spell; -import electroblob.wizardry.constants.Element; -import electroblob.wizardry.constants.SpellType; -import electroblob.wizardry.constants.Tier; -import electroblob.wizardry.registry.WizardrySounds; import electroblob.wizardry.util.MagicDamage; import electroblob.wizardry.util.MagicDamage.DamageType; import electroblob.wizardry.util.ParticleBuilder; @@ -11,79 +7,67 @@ import electroblob.wizardry.util.ParticleBuilder.Type; import electroblob.wizardry.util.SpellModifiers; import electroblob.wizardry.util.WizardryUtilities; import net.minecraft.entity.Entity; -import net.minecraft.entity.EntityLiving; import net.minecraft.entity.EntityLivingBase; -import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.item.EnumAction; import net.minecraft.util.EnumFacing; -import net.minecraft.util.EnumHand; +import net.minecraft.util.SoundEvent; import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.Vec3d; import net.minecraft.world.World; public class LifeDrain extends SpellRay { - - private static final float BASE_DAMAGE = 2; - /** The fraction of the damage dealt that is transferred to the caster as healing. */ - private static final float HEAL_FACTOR = 0.35f; + + public static final String HEAL_FACTOR = "heal_factor"; public LifeDrain(){ - super("life_drain", Tier.APPRENTICE, Element.NECROMANCY, SpellType.ATTACK, 10, 0, true, 10, null); + super("life_drain", true, EnumAction.NONE); this.particleVelocity(-0.5); this.particleSpacing(0.4); - } - - @Override - public boolean cast(World world, EntityPlayer caster, EnumHand hand, int ticksInUse, SpellModifiers modifiers){ - // TODO: Temporary solution until I implement a better continuous sound system - boolean flag = super.cast(world, caster, hand, ticksInUse, modifiers); - if(flag){ - if(ticksInUse % 18 == 0){ - if(ticksInUse == 0) WizardryUtilities.playSoundAtPlayer(caster, WizardrySounds.SPELL_SUMMONING, 1, 0.6f); - WizardryUtilities.playSoundAtPlayer(caster, WizardrySounds.SPELL_LOOP_CRACKLE, 2, 1); - } - } - return flag; + addProperties(DAMAGE, HEAL_FACTOR); + this.soundValues(0.6f, 1, 0); } @Override - public boolean cast(World world, EntityLiving caster, EnumHand hand, int ticksInUse, EntityLivingBase target, SpellModifiers modifiers){ - boolean flag = super.cast(world, caster, hand, ticksInUse, target, modifiers); - if(flag){ - if(ticksInUse % 18 == 0){ - if(ticksInUse == 0) caster.playSound(WizardrySounds.SPELL_SUMMONING, 1, 0.6f); - caster.playSound(WizardrySounds.SPELL_LOOP_CRACKLE, 2, 1); - } - } - return flag; + protected SoundEvent[] createSounds(){ + return this.createContinuousSpellSounds(); } @Override - protected boolean onEntityHit(World world, Entity target, EntityLivingBase caster, int ticksInUse, SpellModifiers modifiers){ + protected void playSound(World world, EntityLivingBase entity, int ticksInUse, int duration, SpellModifiers modifiers, String... sounds){ + this.playSoundLoop(world, entity, ticksInUse); + } + + @Override + protected void playSound(World world, double x, double y, double z, int ticksInUse, int duration, SpellModifiers modifiers, String... sounds){ + this.playSoundLoop(world, x, y, z, ticksInUse, duration); + } + + @Override + protected boolean onEntityHit(World world, Entity target, Vec3d hit, EntityLivingBase caster, Vec3d origin, int ticksInUse, SpellModifiers modifiers){ if(WizardryUtilities.isLiving(target)){ if(ticksInUse % 12 == 0){ - float damage = BASE_DAMAGE * modifiers.get(SpellModifiers.POTENCY); + float damage = getProperty(DAMAGE).floatValue() * modifiers.get(SpellModifiers.POTENCY); WizardryUtilities.attackEntityWithoutKnockback(target, MagicDamage.causeDirectMagicDamage(caster, DamageType.MAGIC), damage); - caster.heal(damage * HEAL_FACTOR); + if(caster != null) caster.heal(damage * getProperty(HEAL_FACTOR).floatValue()); } - - return true; } + return true; + } + + @Override + protected boolean onBlockHit(World world, BlockPos pos, EnumFacing side, Vec3d hit, EntityLivingBase caster, Vec3d origin, int ticksInUse, SpellModifiers modifiers){ return false; } @Override - protected boolean onBlockHit(World world, BlockPos pos, EnumFacing side, EntityLivingBase caster, int ticksInUse, SpellModifiers modifiers){ - return false; - } - - @Override - protected boolean onMiss(World world, EntityLivingBase caster, int ticksInUse, SpellModifiers modifiers){ + protected boolean onMiss(World world, EntityLivingBase caster, Vec3d origin, Vec3d direction, int ticksInUse, SpellModifiers modifiers){ return true; } diff --git a/src/main/java/electroblob/wizardry/spell/Light.java b/src/main/java/electroblob/wizardry/spell/Light.java index 76b5fb9b..95571fb5 100644 --- a/src/main/java/electroblob/wizardry/spell/Light.java +++ b/src/main/java/electroblob/wizardry/spell/Light.java @@ -1,14 +1,11 @@ package electroblob.wizardry.spell; -import electroblob.wizardry.constants.Element; -import electroblob.wizardry.constants.SpellType; -import electroblob.wizardry.constants.Tier; +import electroblob.wizardry.item.ItemArtefact; import electroblob.wizardry.registry.WizardryBlocks; import electroblob.wizardry.registry.WizardryItems; -import electroblob.wizardry.registry.WizardrySounds; import electroblob.wizardry.tileentity.TileEntityTimer; +import electroblob.wizardry.util.RayTracer; import electroblob.wizardry.util.SpellModifiers; -import electroblob.wizardry.util.WizardryUtilities; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.item.EnumAction; import net.minecraft.util.EnumHand; @@ -19,18 +16,21 @@ import net.minecraft.world.World; public class Light extends Spell { public Light(){ - super("light", Tier.BASIC, Element.SORCERY, SpellType.UTILITY, 5, 15, EnumAction.NONE, false); + super("light", EnumAction.NONE, false); + addProperties(RANGE, DURATION); } @Override - public boolean doesSpellRequirePacket(){ + public boolean requiresPacket(){ return false; } @Override public boolean cast(World world, EntityPlayer caster, EnumHand hand, int ticksInUse, SpellModifiers modifiers){ - RayTraceResult rayTrace = WizardryUtilities.standardBlockRayTrace(world, caster, 4, false); + double range = getProperty(RANGE).floatValue() * modifiers.get(WizardryItems.range_upgrade); + + RayTraceResult rayTrace = RayTracer.standardBlockRayTrace(world, caster, range, false); if(rayTrace != null && rayTrace.typeOfHit == RayTraceResult.Type.BLOCK){ @@ -41,20 +41,21 @@ public class Light extends Spell { if(!world.isRemote){ world.setBlockState(pos, WizardryBlocks.magic_light.getDefaultState()); if(world.getTileEntity(pos) instanceof TileEntityTimer){ - ((TileEntityTimer)world.getTileEntity(pos)) - .setLifetime((int)(600 * modifiers.get(WizardryItems.duration_upgrade))); + int lifetime = ItemArtefact.isArtefactActive(caster, WizardryItems.charm_light) ? -1 + : (int)(getProperty(DURATION).floatValue() * modifiers.get(WizardryItems.duration_upgrade)); + ((TileEntityTimer)world.getTileEntity(pos)).setLifetime(lifetime); } } caster.swingArm(hand); - WizardryUtilities.playSoundAtPlayer(caster, WizardrySounds.SPELL_CONJURATION, 1.0f, 1.0f); + this.playSound(world, caster, ticksInUse, -1, modifiers); return true; } }else{ - int x = (int)(Math.floor(caster.posX) + caster.getLookVec().x * 4); - int y = (int)(Math.floor(caster.posY) + caster.eyeHeight + caster.getLookVec().y * 4); - int z = (int)(Math.floor(caster.posZ) + caster.getLookVec().z * 4); + int x = (int)(Math.floor(caster.posX) + caster.getLookVec().x * range); + int y = (int)(Math.floor(caster.posY) + caster.eyeHeight + caster.getLookVec().y * range); + int z = (int)(Math.floor(caster.posZ) + caster.getLookVec().z * range); BlockPos pos = new BlockPos(x, y, z); @@ -62,12 +63,13 @@ public class Light extends Spell { if(!world.isRemote){ world.setBlockState(pos, WizardryBlocks.magic_light.getDefaultState()); if(world.getTileEntity(pos) instanceof TileEntityTimer){ - ((TileEntityTimer)world.getTileEntity(pos)) - .setLifetime((int)(600 * modifiers.get(WizardryItems.duration_upgrade))); + int lifetime = ItemArtefact.isArtefactActive(caster, WizardryItems.charm_light) ? -1 + : (int)(getProperty(DURATION).floatValue() * modifiers.get(WizardryItems.duration_upgrade)); + ((TileEntityTimer)world.getTileEntity(pos)).setLifetime(lifetime); } } caster.swingArm(hand); - WizardryUtilities.playSoundAtPlayer(caster, WizardrySounds.SPELL_CONJURATION, 1.0f, 1.0f); + this.playSound(world, caster, ticksInUse, -1, modifiers); return true; } } diff --git a/src/main/java/electroblob/wizardry/spell/LightningBolt.java b/src/main/java/electroblob/wizardry/spell/LightningBolt.java index 49c854d3..461cb126 100644 --- a/src/main/java/electroblob/wizardry/spell/LightningBolt.java +++ b/src/main/java/electroblob/wizardry/spell/LightningBolt.java @@ -1,52 +1,51 @@ package electroblob.wizardry.spell; -import electroblob.wizardry.constants.Element; -import electroblob.wizardry.constants.SpellType; -import electroblob.wizardry.constants.Tier; -import electroblob.wizardry.registry.WizardryAdvancementTriggers; +import electroblob.wizardry.Wizardry; import electroblob.wizardry.util.SpellModifiers; -import electroblob.wizardry.util.WizardryUtilities; import net.minecraft.entity.Entity; import net.minecraft.entity.EntityLivingBase; import net.minecraft.entity.effect.EntityLightningBolt; -import net.minecraft.entity.monster.EntityCreeper; -import net.minecraft.entity.passive.EntityPig; import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.item.EnumAction; import net.minecraft.nbt.NBTTagCompound; import net.minecraft.util.EnumFacing; import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.Vec3d; import net.minecraft.world.World; -import net.minecraftforge.event.entity.EntityStruckByLightningEvent; -import net.minecraftforge.fml.common.Mod; -import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; -@Mod.EventBusSubscriber +//@Mod.EventBusSubscriber public class LightningBolt extends SpellRay { /** The NBT key used to store the UUID of the player that summoned the lightning bolt. Used for achievements. */ public static final String NBT_KEY = "summoningPlayer"; public LightningBolt(){ - super("lightning_bolt", Tier.ADVANCED, Element.LIGHTNING, SpellType.ATTACK, 40, 80, false, 200, null); - this.ignoreEntities(true); + super("lightning_bolt", false, EnumAction.NONE); + this.ignoreLivingEntities(true); } - @Override public boolean doesSpellRequirePacket(){ return false; } + @Override public boolean requiresPacket(){ return false; } @Override - protected boolean onEntityHit(World world, Entity target, EntityLivingBase caster, int ticksInUse, SpellModifiers modifiers){ + protected boolean onEntityHit(World world, Entity target, Vec3d hit, EntityLivingBase caster, Vec3d origin, int ticksInUse, SpellModifiers modifiers){ return false; } @Override - protected boolean onBlockHit(World world, BlockPos pos, EnumFacing side, EntityLivingBase caster, int ticksInUse, SpellModifiers modifiers){ + protected boolean onBlockHit(World world, BlockPos pos, EnumFacing side, Vec3d hit, EntityLivingBase caster, Vec3d origin, int ticksInUse, SpellModifiers modifiers){ if(world.canBlockSeeSky(pos.up())){ if(!world.isRemote){ + // Temporarily disable the fire tick gamerule if player block damage is disabled + // Bit of a hack but it works fine! + boolean doFireTick = world.getGameRules().getBoolean("doFireTick"); + if(doFireTick && !Wizardry.settings.playerBlockDamage) world.getGameRules().setOrCreateGameRule("doFireTick", "false"); EntityLightningBolt entitylightning = new EntityLightningBolt(world, pos.getX(), pos.getY(), pos.getZ(), false); world.addWeatherEffect(entitylightning); + // Reset doFireTick to true if it was true before + if(doFireTick && !Wizardry.settings.playerBlockDamage) world.getGameRules().setOrCreateGameRule("doFireTick", "true"); // Code for eventhandler recognition for achievements if(caster instanceof EntityPlayer){ @@ -62,26 +61,26 @@ public class LightningBolt extends SpellRay { } @Override - protected boolean onMiss(World world, EntityLivingBase caster, int ticksInUse, SpellModifiers modifiers){ + protected boolean onMiss(World world, EntityLivingBase caster, Vec3d origin, Vec3d direction, int ticksInUse, SpellModifiers modifiers){ return false; } - @SubscribeEvent - public static void onEntityStruckByLightningEvent(EntityStruckByLightningEvent event){ - - if(event.getLightning().getEntityData() != null && event.getLightning().getEntityData().hasUniqueId(NBT_KEY)){ - - EntityPlayer player = (EntityPlayer)WizardryUtilities.getEntityByUUID(event.getLightning().world, - event.getLightning().getEntityData().getUniqueId("summoningPlayer")); - - if(event.getEntity() instanceof EntityCreeper){ - WizardryAdvancementTriggers.charge_creeper.triggerFor(player); - } - - if(event.getEntity() instanceof EntityPig){ - WizardryAdvancementTriggers.frankenstein.triggerFor(player); - } - } - } +// @SubscribeEvent +// public static void onEntityStruckByLightningEvent(EntityStruckByLightningEvent event){ +// +// if(event.getLightning().getEntityData() != null && event.getLightning().getEntityData().hasUniqueId(NBT_KEY)){ +// +// EntityPlayer player = (EntityPlayer)WizardryUtilities.getEntityByUUID(event.getLightning().world, +// event.getLightning().getEntityData().getUniqueId("summoningPlayer")); +// +// if(event.getEntity() instanceof EntityCreeper){ +// WizardryAdvancementTriggers.charge_creeper.triggerFor(player); +// } +// +// if(event.getEntity() instanceof EntityPig){ +// WizardryAdvancementTriggers.frankenstein.triggerFor(player); +// } +// } +// } } diff --git a/src/main/java/electroblob/wizardry/spell/LightningHammer.java b/src/main/java/electroblob/wizardry/spell/LightningHammer.java index e31c283e..faa1354b 100644 --- a/src/main/java/electroblob/wizardry/spell/LightningHammer.java +++ b/src/main/java/electroblob/wizardry/spell/LightningHammer.java @@ -1,33 +1,33 @@ package electroblob.wizardry.spell; -import electroblob.wizardry.constants.Element; -import electroblob.wizardry.constants.SpellType; -import electroblob.wizardry.constants.Tier; import electroblob.wizardry.entity.construct.EntityHammer; -import electroblob.wizardry.registry.WizardrySounds; import electroblob.wizardry.util.SpellModifiers; import net.minecraft.entity.EntityLivingBase; +import net.minecraft.util.EnumFacing; import net.minecraft.util.math.BlockPos; import net.minecraft.world.World; public class LightningHammer extends SpellConstructRanged { + public static final String ATTACK_INTERVAL = "attack_interval"; + public static final String SECONDARY_MAX_TARGETS = "secondary_max_targets"; + public LightningHammer(){ - super("lightning_hammer", Tier.MASTER, Element.LIGHTNING, SpellType.ATTACK, 100, 300, EntityHammer::new, 600, 40, WizardrySounds.SPELL_SUMMONING); + super("lightning_hammer", EntityHammer::new, false); this.soundValues(3, 1, 0); this.floor(true); this.overlap(true); + addProperties(EFFECT_RADIUS, SECONDARY_MAX_TARGETS, ATTACK_INTERVAL, DIRECT_DAMAGE, SPLASH_DAMAGE); } @Override - protected boolean spawnConstruct(World world, double x, double y, double z, EntityLivingBase caster, SpellModifiers modifiers){ - // TESTME: Does this need to be one block higher? + protected boolean spawnConstruct(World world, double x, double y, double z, EnumFacing side, EntityLivingBase caster, SpellModifiers modifiers){ if(!world.canBlockSeeSky(new BlockPos(x, y, z))) return false; - return super.spawnConstruct(world, x, y + 50, z, caster, modifiers); + return super.spawnConstruct(world, x, y + 50, z, side, caster, modifiers); } @Override - protected void addConstructExtras(EntityHammer construct, EntityLivingBase caster, SpellModifiers modifiers){ + protected void addConstructExtras(EntityHammer construct, EnumFacing side, EntityLivingBase caster, SpellModifiers modifiers){ construct.motionY = -2; } diff --git a/src/main/java/electroblob/wizardry/spell/LightningPulse.java b/src/main/java/electroblob/wizardry/spell/LightningPulse.java index 69c1543b..42b8037b 100644 --- a/src/main/java/electroblob/wizardry/spell/LightningPulse.java +++ b/src/main/java/electroblob/wizardry/spell/LightningPulse.java @@ -1,56 +1,52 @@ package electroblob.wizardry.spell; -import java.util.List; - -import electroblob.wizardry.constants.Element; -import electroblob.wizardry.constants.SpellType; -import electroblob.wizardry.constants.Tier; import electroblob.wizardry.registry.WizardryItems; -import electroblob.wizardry.registry.WizardrySounds; -import electroblob.wizardry.util.MagicDamage; +import electroblob.wizardry.util.*; import electroblob.wizardry.util.MagicDamage.DamageType; -import electroblob.wizardry.util.ParticleBuilder; import electroblob.wizardry.util.ParticleBuilder.Type; -import electroblob.wizardry.util.SpellModifiers; -import electroblob.wizardry.util.WizardryUtilities; import net.minecraft.entity.EntityLivingBase; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.entity.player.EntityPlayerMP; import net.minecraft.item.EnumAction; import net.minecraft.network.play.server.SPacketEntityVelocity; import net.minecraft.util.EnumHand; +import net.minecraft.util.SoundEvent; import net.minecraft.util.math.MathHelper; import net.minecraft.world.World; +import java.util.List; + public class LightningPulse extends Spell { - - private static final double BASE_RADIUS = 3; - private static final float BASE_DAMAGE = 8; + + public static final String REPULSION_VELOCITY = "repulsion_velocity"; public LightningPulse(){ - super("lightning_pulse", Tier.ADVANCED, Element.LIGHTNING, SpellType.ATTACK, 25, 75, EnumAction.NONE, false); - } - - @Override - public boolean doesSpellRequirePacket(){ - return false; + super("lightning_pulse", EnumAction.NONE, false); + addProperties(EFFECT_RADIUS, DAMAGE, REPULSION_VELOCITY); + this.soundValues(2, 1, 0); } // TODO: NPC casting support + @Override + protected SoundEvent[] createSounds(){ + return createSoundsWithSuffixes("spark", "explosion"); + } + @Override public boolean cast(World world, EntityPlayer caster, EnumHand hand, int ticksInUse, SpellModifiers modifiers){ if(caster.onGround){ List targets = WizardryUtilities.getEntitiesWithinRadius( - BASE_RADIUS * modifiers.get(WizardryItems.blast_upgrade), caster.posX, caster.posY, caster.posZ, world); + getProperty(EFFECT_RADIUS).floatValue() * modifiers.get(WizardryItems.blast_upgrade), + caster.posX, caster.posY, caster.posZ, world); for(EntityLivingBase target : targets){ - if(WizardryUtilities.isValidTarget(caster, target)){ + if(AllyDesignationSystem.isValidTarget(caster, target)){ // Base damage is 4 hearts no matter where the target is. target.attackEntityFrom(MagicDamage.causeDirectMagicDamage(caster, DamageType.SHOCK), - BASE_DAMAGE * modifiers.get(SpellModifiers.POTENCY)); + getProperty(DAMAGE).floatValue() * modifiers.get(SpellModifiers.POTENCY)); if(!world.isRemote){ @@ -61,9 +57,9 @@ public class LightningPulse extends Spell { dx /= vectorLength; dz /= vectorLength; - target.motionX = 0.8 * dx; + target.motionX = getProperty(REPULSION_VELOCITY).floatValue() * dx; target.motionY = 0; - target.motionZ = 0.8 * dz; + target.motionZ = getProperty(REPULSION_VELOCITY).floatValue() * dz; // Player motion is handled on that player's client so needs packets if(target instanceof EntityPlayerMP){ @@ -80,8 +76,7 @@ public class LightningPulse extends Spell { } caster.swingArm(hand); - WizardryUtilities.playSoundAtPlayer(caster, WizardrySounds.SPELL_LIGHTNING, 1, 1); - WizardryUtilities.playSoundAtPlayer(caster, WizardrySounds.SPELL_SHOCKWAVE, 2, 1); + this.playSound(world, caster, ticksInUse, -1, modifiers); return true; } return false; diff --git a/src/main/java/electroblob/wizardry/spell/LightningRay.java b/src/main/java/electroblob/wizardry/spell/LightningRay.java index ce6ddd15..21bb5c0b 100644 --- a/src/main/java/electroblob/wizardry/spell/LightningRay.java +++ b/src/main/java/electroblob/wizardry/spell/LightningRay.java @@ -1,9 +1,5 @@ package electroblob.wizardry.spell; -import electroblob.wizardry.constants.Element; -import electroblob.wizardry.constants.SpellType; -import electroblob.wizardry.constants.Tier; -import electroblob.wizardry.registry.WizardrySounds; import electroblob.wizardry.util.MagicDamage; import electroblob.wizardry.util.MagicDamage.DamageType; import electroblob.wizardry.util.ParticleBuilder; @@ -11,100 +7,90 @@ import electroblob.wizardry.util.ParticleBuilder.Type; import electroblob.wizardry.util.SpellModifiers; import electroblob.wizardry.util.WizardryUtilities; import net.minecraft.entity.Entity; -import net.minecraft.entity.EntityLiving; import net.minecraft.entity.EntityLivingBase; import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.item.EnumAction; import net.minecraft.util.EnumFacing; -import net.minecraft.util.EnumHand; +import net.minecraft.util.SoundEvent; import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.Vec3d; import net.minecraft.util.text.TextComponentTranslation; import net.minecraft.world.World; public class LightningRay extends SpellRay { - - private static final float BASE_DAMAGE = 3; public LightningRay(){ - super("lightning_ray", Tier.APPRENTICE, Element.LIGHTNING, SpellType.ATTACK, 5, 0, true, 10, null); - } - - @Override - public boolean cast(World world, EntityPlayer caster, EnumHand hand, int ticksInUse, SpellModifiers modifiers){ - // TODO: Temporary solution until I implement a better continuous sound system - boolean flag = super.cast(world, caster, hand, ticksInUse, modifiers); - if(flag){ - if(ticksInUse == 1){ - WizardryUtilities.playSoundAtPlayer(caster, WizardrySounds.SPELL_LIGHTNING, 1, 1); - }else if(ticksInUse > 0 && ticksInUse % 20 == 0){ - WizardryUtilities.playSoundAtPlayer(caster, WizardrySounds.SPELL_LOOP_LIGHTNING, 1, 1); - } - } - return flag; + super("lightning_ray", true, EnumAction.NONE); + this.aimAssist(0.6f); + addProperties(DAMAGE); } @Override - public boolean cast(World world, EntityLiving caster, EnumHand hand, int ticksInUse, EntityLivingBase target, SpellModifiers modifiers){ - boolean flag = super.cast(world, caster, hand, ticksInUse, target, modifiers); - if(flag){ - if(ticksInUse == 1){ - caster.playSound(WizardrySounds.SPELL_LIGHTNING, 1, 1); - }else if(ticksInUse > 0 && ticksInUse % 20 == 0){ - caster.playSound(WizardrySounds.SPELL_LOOP_LIGHTNING, 1, 1); - } - } - return flag; + protected SoundEvent[] createSounds(){ + return this.createContinuousSpellSounds(); } @Override - protected boolean onEntityHit(World world, Entity target, EntityLivingBase caster, int ticksInUse, SpellModifiers modifiers){ - + protected void playSound(World world, EntityLivingBase entity, int ticksInUse, int duration, SpellModifiers modifiers, String... sounds){ + this.playSoundLoop(world, entity, ticksInUse); + } + + @Override + protected void playSound(World world, double x, double y, double z, int ticksInUse, int duration, SpellModifiers modifiers, String... sounds){ + this.playSoundLoop(world, x, y, z, ticksInUse, duration); + } + + @Override + protected boolean onEntityHit(World world, Entity target, Vec3d hit, EntityLivingBase caster, Vec3d origin, int ticksInUse, SpellModifiers modifiers){ + if(WizardryUtilities.isLiving(target)){ if(MagicDamage.isEntityImmune(DamageType.SHOCK, target)){ if(!world.isRemote && ticksInUse == 1 && caster instanceof EntityPlayer) ((EntityPlayer)caster).sendStatusMessage(new TextComponentTranslation("spell.resist", target.getName(), this.getNameForTranslationFormatted()), true); - }else{ + // This now only damages in line with the maxHurtResistantTime. Some mods don't play nicely and fiddle + // with this mechanic for their own purposes, so this line makes sure that doesn't affect wizardry. + }else if(ticksInUse % ((EntityLivingBase)target).maxHurtResistantTime == 1){ WizardryUtilities.attackEntityWithoutKnockback(target, MagicDamage.causeDirectMagicDamage(caster, DamageType.SHOCK), - BASE_DAMAGE * modifiers.get(SpellModifiers.POTENCY)); + getProperty(DAMAGE).floatValue() * modifiers.get(SpellModifiers.POTENCY)); } if(world.isRemote){ - + if(ticksInUse % 3 == 0) ParticleBuilder.create(Type.LIGHTNING).entity(caster) .pos(caster != null ? origin.subtract(caster.getPositionVector()) : origin).target(target).spawn(world); - + // Particle effect for(int i=0; i<5; i++){ ParticleBuilder.create(Type.SPARK, target).spawn(world); } } - - return true; } - + + return true; + } + + @Override + protected boolean onBlockHit(World world, BlockPos pos, EnumFacing side, Vec3d hit, EntityLivingBase caster, Vec3d origin, int ticksInUse, SpellModifiers modifiers){ return false; } @Override - protected boolean onBlockHit(World world, BlockPos pos, EnumFacing side, EntityLivingBase caster, int ticksInUse, SpellModifiers modifiers){ - return false; - } - - @Override - protected boolean onMiss(World world, EntityLivingBase caster, int ticksInUse, SpellModifiers modifiers){ + protected boolean onMiss(World world, EntityLivingBase caster, Vec3d origin, Vec3d direction, int ticksInUse, SpellModifiers modifiers){ // This is a nice example of when onMiss is used for more than just returning a boolean if(world.isRemote && ticksInUse % 4 == 0){ - - if(caster != null) origin = origin.subtract(0, Y_OFFSET, 0); - - double freeRange = 0.8 * baseRange; // The arc does not reach full range when it has a free end - Vec3d endpoint = origin.add(direction.scale(freeRange)); - - ParticleBuilder.create(Type.LIGHTNING).entity(caster) - .pos(caster != null ? origin.subtract(caster.getPositionVector()) : origin).target(endpoint).spawn(world); + + // The arc does not reach full range when it has a free end + double freeRange = 0.8 * getRange(world, origin, direction, caster, ticksInUse, modifiers); + + if(caster != null){ + ParticleBuilder.create(Type.LIGHTNING).entity(caster).pos(origin.subtract(caster.getPositionVector())) + .length(freeRange).spawn(world); + }else{ + ParticleBuilder.create(Type.LIGHTNING).pos(origin).target(origin.add(direction.scale(freeRange))).spawn(world); + } } return true; diff --git a/src/main/java/electroblob/wizardry/spell/LightningWeb.java b/src/main/java/electroblob/wizardry/spell/LightningWeb.java index cdc11ea2..759ea581 100644 --- a/src/main/java/electroblob/wizardry/spell/LightningWeb.java +++ b/src/main/java/electroblob/wizardry/spell/LightningWeb.java @@ -1,146 +1,138 @@ package electroblob.wizardry.spell; -import java.util.List; - -import electroblob.wizardry.constants.Element; -import electroblob.wizardry.constants.SpellType; -import electroblob.wizardry.constants.Tier; -import electroblob.wizardry.registry.WizardrySounds; -import electroblob.wizardry.util.MagicDamage; +import electroblob.wizardry.util.*; import electroblob.wizardry.util.MagicDamage.DamageType; -import electroblob.wizardry.util.ParticleBuilder; import electroblob.wizardry.util.ParticleBuilder.Type; -import electroblob.wizardry.util.SpellModifiers; -import electroblob.wizardry.util.WizardryUtilities; import net.minecraft.entity.Entity; -import net.minecraft.entity.EntityLiving; import net.minecraft.entity.EntityLivingBase; import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.item.EnumAction; import net.minecraft.util.EnumFacing; -import net.minecraft.util.EnumHand; +import net.minecraft.util.SoundEvent; import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.Vec3d; import net.minecraft.util.text.TextComponentTranslation; import net.minecraft.world.World; -public class LightningWeb extends SpellRay { - - private static final float PRIMARY_DAMAGE = 5; - private static final float SECONDARY_DAMAGE = 4; - private static final float TERTIARY_DAMAGE = 3; +import java.util.List; - private static final double PRIMARY_RANGE = 10; - private static final double SECONDARY_RANGE = 5; - private static final double TERTIARY_RANGE = 5; - - private static final int SECONDARY_MAX_TARGETS = 5; - private static final int TERTIARY_MAX_TARGETS = 2; // This is per secondary target, giving 10 in total +public class LightningWeb extends SpellRay { + + public static final String PRIMARY_DAMAGE = "primary_damage"; + public static final String SECONDARY_DAMAGE = "secondary_damage"; + public static final String TERTIARY_DAMAGE = "tertiary_damage"; + + public static final String SECONDARY_RANGE = "secondary_range"; + public static final String TERTIARY_RANGE = "tertiary_range"; + + public static final String SECONDARY_MAX_TARGETS = "secondary_max_targets"; + public static final String TERTIARY_MAX_TARGETS = "tertiary_max_targets"; // This is per secondary target public LightningWeb(){ - super("lightning_web", Tier.MASTER, Element.LIGHTNING, SpellType.ATTACK, 15, 0, true, PRIMARY_RANGE, null); - } - - @Override - public boolean cast(World world, EntityPlayer caster, EnumHand hand, int ticksInUse, SpellModifiers modifiers){ - // TODO: Temporary solution until I implement a better continuous sound system - boolean flag = super.cast(world, caster, hand, ticksInUse, modifiers); - if(flag){ - if(ticksInUse == 1){ - WizardryUtilities.playSoundAtPlayer(caster, WizardrySounds.SPELL_LIGHTNING, 1, 1); - }else if(ticksInUse > 0 && ticksInUse % 20 == 0){ - WizardryUtilities.playSoundAtPlayer(caster, WizardrySounds.SPELL_LOOP_LIGHTNING, 1, 1); - } - } - return flag; + super("lightning_web", true, EnumAction.NONE); + this.aimAssist(0.6f); + addProperties(PRIMARY_DAMAGE, SECONDARY_DAMAGE, TERTIARY_DAMAGE, SECONDARY_RANGE, TERTIARY_RANGE, + SECONDARY_MAX_TARGETS, TERTIARY_MAX_TARGETS); } @Override - public boolean cast(World world, EntityLiving caster, EnumHand hand, int ticksInUse, EntityLivingBase target, SpellModifiers modifiers){ - boolean flag = super.cast(world, caster, hand, ticksInUse, target, modifiers); - if(flag){ - if(ticksInUse == 1){ - caster.playSound(WizardrySounds.SPELL_LIGHTNING, 1, 1); - }else if(ticksInUse > 0 && ticksInUse % 20 == 0){ - caster.playSound(WizardrySounds.SPELL_LOOP_LIGHTNING, 1, 1); - } - } - return flag; + protected SoundEvent[] createSounds(){ + return this.createContinuousSpellSounds(); + } + + @Override + protected void playSound(World world, EntityLivingBase entity, int ticksInUse, int duration, SpellModifiers modifiers, String... sounds){ + this.playSoundLoop(world, entity, ticksInUse); + } + + @Override + protected void playSound(World world, double x, double y, double z, int ticksInUse, int duration, SpellModifiers modifiers, String... sounds){ + this.playSoundLoop(world, x, y, z, ticksInUse, duration); } @Override - protected boolean onEntityHit(World world, Entity target, EntityLivingBase caster, int ticksInUse, SpellModifiers modifiers){ + protected boolean onEntityHit(World world, Entity target, Vec3d hit, EntityLivingBase caster, Vec3d origin, int ticksInUse, SpellModifiers modifiers){ if(WizardryUtilities.isLiving(target)){ - - electrocute(world, caster, caster, target, PRIMARY_DAMAGE * modifiers.get(SpellModifiers.POTENCY), ticksInUse); + + electrocute(world, caster, origin, target, getProperty(PRIMARY_DAMAGE).floatValue() + * modifiers.get(SpellModifiers.POTENCY), ticksInUse); // Secondary chaining effect - List secondaryTargets = WizardryUtilities.getEntitiesWithinRadius(SECONDARY_RANGE, - target.posX, target.posY + target.height / 2, target.posZ, world); + List secondaryTargets = WizardryUtilities.getEntitiesWithinRadius( + getProperty(SECONDARY_RANGE).floatValue(), target.posX, target.posY + target.height / 2, + target.posZ, world); secondaryTargets.remove(target); secondaryTargets.removeIf(e -> !WizardryUtilities.isLiving(e)); - secondaryTargets.removeIf(e -> !WizardryUtilities.isValidTarget(caster, e)); - if(secondaryTargets.size() > SECONDARY_MAX_TARGETS) secondaryTargets = secondaryTargets.subList(0, SECONDARY_MAX_TARGETS); + secondaryTargets.removeIf(e -> !AllyDesignationSystem.isValidTarget(caster, e)); + if(secondaryTargets.size() > getProperty(SECONDARY_MAX_TARGETS).intValue()) + secondaryTargets = secondaryTargets.subList(0, getProperty(SECONDARY_MAX_TARGETS).intValue()); for(EntityLivingBase secondaryTarget : secondaryTargets){ - electrocute(world, caster, target, secondaryTarget, - SECONDARY_DAMAGE * modifiers.get(SpellModifiers.POTENCY), ticksInUse); + electrocute(world, caster, target.getPositionVector().add(0, target.height/2, 0), secondaryTarget, + getProperty(SECONDARY_DAMAGE).floatValue() * modifiers.get(SpellModifiers.POTENCY), ticksInUse); // Tertiary chaining effect - List tertiaryTargets = WizardryUtilities.getEntitiesWithinRadius(TERTIARY_RANGE, - secondaryTarget.posX, secondaryTarget.posY + secondaryTarget.height / 2, - secondaryTarget.posZ, world); + List tertiaryTargets = WizardryUtilities.getEntitiesWithinRadius( + getProperty(TERTIARY_RANGE).floatValue(), secondaryTarget.posX, + secondaryTarget.posY + secondaryTarget.height / 2, secondaryTarget.posZ, world); tertiaryTargets.remove(target); tertiaryTargets.removeAll(secondaryTargets); tertiaryTargets.removeIf(e -> !WizardryUtilities.isLiving(e)); - tertiaryTargets.removeIf(e -> !WizardryUtilities.isValidTarget(caster, e)); - if(tertiaryTargets.size() > TERTIARY_MAX_TARGETS) tertiaryTargets = tertiaryTargets.subList(0, TERTIARY_MAX_TARGETS); + tertiaryTargets.removeIf(e -> !AllyDesignationSystem.isValidTarget(caster, e)); + if(tertiaryTargets.size() > getProperty(TERTIARY_MAX_TARGETS).intValue()) + tertiaryTargets = tertiaryTargets.subList(0, getProperty(TERTIARY_MAX_TARGETS).intValue()); for(EntityLivingBase tertiaryTarget : tertiaryTargets){ - electrocute(world, caster, secondaryTarget, tertiaryTarget, - TERTIARY_DAMAGE * modifiers.get(SpellModifiers.POTENCY), ticksInUse); + electrocute(world, caster, secondaryTarget.getPositionVector().add(0, secondaryTarget.height/2, 0), + tertiaryTarget, getProperty(TERTIARY_DAMAGE).floatValue() * modifiers.get(SpellModifiers.POTENCY), ticksInUse); } } } + return true; + } + + @Override + protected boolean onBlockHit(World world, BlockPos pos, EnumFacing side, Vec3d hit, EntityLivingBase caster, Vec3d origin, int ticksInUse, SpellModifiers modifiers){ return false; } @Override - protected boolean onBlockHit(World world, BlockPos pos, EnumFacing side, EntityLivingBase caster, int ticksInUse, SpellModifiers modifiers){ - return false; - } - - @Override - protected boolean onMiss(World world, EntityLivingBase caster, int ticksInUse, SpellModifiers modifiers){ + protected boolean onMiss(World world, EntityLivingBase caster, Vec3d origin, Vec3d direction, int ticksInUse, SpellModifiers modifiers){ // This is a nice example of when onMiss is used for more than just returning a boolean if(world.isRemote){ - - if(caster != null) origin = origin.subtract(0, Y_OFFSET, 0); - - double freeRange = 0.8 * baseRange; // The arc does not reach full range when it has a free end - Vec3d endpoint = origin.add(direction.scale(freeRange)); - - ParticleBuilder.create(Type.BEAM).entity(caster).clr(0.2f, 0.6f, 1) - .pos(caster != null ? origin.subtract(caster.getPositionVector()) : origin).target(endpoint).spawn(world); - - if(ticksInUse % 2 == 0){ - ParticleBuilder.create(Type.LIGHTNING).entity(caster) - .pos(caster != null ? origin.subtract(caster.getPositionVector()) : origin).target(endpoint).spawn(world); - + // The arc does not reach full range when it has a free end + double freeRange = 0.8 * getRange(world, origin, direction, caster, ticksInUse, modifiers); + + if(caster != null){ + ParticleBuilder.create(Type.BEAM).entity(caster).pos(origin.subtract(caster.getPositionVector())) + .length(freeRange).clr(0.2f, 0.6f, 1).spawn(world); + }else{ + ParticleBuilder.create(Type.BEAM).pos(origin).target(origin.add(direction.scale(freeRange))) + .clr(0.2f, 0.6f, 1).spawn(world); + } + + if(ticksInUse % 4 == 0){ + if(caster != null){ + ParticleBuilder.create(Type.LIGHTNING).entity(caster).pos(origin.subtract(caster.getPositionVector())) + .length(freeRange).spawn(world); + }else{ + ParticleBuilder.create(Type.LIGHTNING).pos(origin).target(origin.add(direction.scale(freeRange))).spawn(world); + } } } return true; } - private void electrocute(World world, Entity caster, Entity origin, Entity target, float damage, int ticksInUse){ + private void electrocute(World world, Entity caster, Vec3d origin, Entity target, float damage, int ticksInUse){ if(MagicDamage.isEntityImmune(DamageType.SHOCK, target)){ if(!world.isRemote && ticksInUse == 1 && caster instanceof EntityPlayer) diff --git a/src/main/java/electroblob/wizardry/spell/Metamorphosis.java b/src/main/java/electroblob/wizardry/spell/Metamorphosis.java index 174e28ef..77f4fbee 100644 --- a/src/main/java/electroblob/wizardry/spell/Metamorphosis.java +++ b/src/main/java/electroblob/wizardry/spell/Metamorphosis.java @@ -2,35 +2,18 @@ package electroblob.wizardry.spell; import com.google.common.collect.BiMap; import com.google.common.collect.HashBiMap; - import electroblob.wizardry.Wizardry; -import electroblob.wizardry.constants.Element; -import electroblob.wizardry.constants.SpellType; -import electroblob.wizardry.constants.Tier; -import electroblob.wizardry.entity.living.EntitySkeletonMinion; -import electroblob.wizardry.entity.living.EntityWitherSkeletonMinion; -import electroblob.wizardry.registry.WizardrySounds; +import electroblob.wizardry.entity.living.*; +import electroblob.wizardry.util.NBTExtras; import electroblob.wizardry.util.ParticleBuilder; import electroblob.wizardry.util.ParticleBuilder.Type; import electroblob.wizardry.util.SpellModifiers; import electroblob.wizardry.util.WizardryUtilities; import net.minecraft.entity.Entity; import net.minecraft.entity.EntityLivingBase; -import net.minecraft.entity.monster.EntityCaveSpider; -import net.minecraft.entity.monster.EntityHusk; -import net.minecraft.entity.monster.EntityMagmaCube; -import net.minecraft.entity.monster.EntityPigZombie; -import net.minecraft.entity.monster.EntitySkeleton; -import net.minecraft.entity.monster.EntitySlime; -import net.minecraft.entity.monster.EntitySpider; -import net.minecraft.entity.monster.EntityStray; -import net.minecraft.entity.monster.EntityWitherSkeleton; -import net.minecraft.entity.monster.EntityZombie; -import net.minecraft.entity.passive.EntityBat; -import net.minecraft.entity.passive.EntityChicken; -import net.minecraft.entity.passive.EntityCow; -import net.minecraft.entity.passive.EntityMooshroom; -import net.minecraft.entity.passive.EntityPig; +import net.minecraft.entity.monster.*; +import net.minecraft.entity.passive.*; +import net.minecraft.item.EnumAction; import net.minecraft.nbt.NBTTagCompound; import net.minecraft.util.EnumFacing; import net.minecraft.util.math.BlockPos; @@ -46,10 +29,11 @@ public class Metamorphosis extends SpellRay { addTransformation(EntityCow.class, EntityMooshroom.class); addTransformation(EntityChicken.class, EntityBat.class); addTransformation(EntityZombie.class, EntityHusk.class); - addTransformation(EntitySkeleton.class, EntityWitherSkeleton.class, EntityStray.class); + addTransformation(EntitySkeleton.class, EntityStray.class, EntityWitherSkeleton.class); addTransformation(EntitySpider.class, EntityCaveSpider.class); addTransformation(EntitySlime.class, EntityMagmaCube.class); - addTransformation(EntitySkeletonMinion.class, EntityWitherSkeletonMinion.class); + addTransformation(EntityZombieMinion.class, EntityHuskMinion.class); + addTransformation(EntitySkeletonMinion.class, EntityStrayMinion.class, EntityWitherSkeletonMinion.class); } /** Adds circular mappings between the given entity classes to the transformations map. In other words, given an @@ -64,23 +48,24 @@ public class Metamorphosis extends SpellRay { } public Metamorphosis(){ - super("metamorphosis", Tier.APPRENTICE, Element.NECROMANCY, SpellType.UTILITY, 15, 30, false, 10, WizardrySounds.SPELL_DEFLECTION); - this.soundValues(0.5f, 0.8f, 0); + super("metamorphosis", false, EnumAction.NONE); + this.soundValues(0.5f, 1f, 0); } @Override public boolean canBeCastByNPCs() { return false; } @Override - protected boolean onEntityHit(World world, Entity target, EntityLivingBase caster, int ticksInUse, SpellModifiers modifiers){ - + protected boolean onEntityHit(World world, Entity target, Vec3d hit, EntityLivingBase caster, Vec3d origin, int ticksInUse, SpellModifiers modifiers){ + if(WizardryUtilities.isLiving(target)){ - + double xPos = target.posX; double yPos = target.posY; double zPos = target.posZ; // Sneaking allows the entities to be cycled through in the other direction. - Class newEntityClass = caster.isSneaking() ? + // Dispensers always cycle through entities in the normal direction. + Class newEntityClass = caster != null && caster.isSneaking() ? TRANSFORMATIONS.inverse().get(target.getClass()) : TRANSFORMATIONS.get(target.getClass()); if(newEntityClass == null) return false; @@ -103,7 +88,7 @@ public class Metamorphosis extends SpellRay { NBTTagCompound tag = new NBTTagCompound(); target.writeToNBT(tag); // Remove the UUID because keeping it the same causes the entity to disappear - WizardryUtilities.removeUniqueId(tag, "UUID"); + NBTExtras.removeUniqueId(tag, "UUID"); newEntity.readFromNBT(tag); target.setDead(); @@ -111,22 +96,27 @@ public class Metamorphosis extends SpellRay { world.spawnEntity(newEntity); }else{ - for(int i=0; i<5; i++){ - ParticleBuilder.create(Type.DARK_MAGIC).pos(xPos, yPos, zPos).clr(0.1f, 0, 0).spawn(world); + for(int i=0; i<20; i++){ + ParticleBuilder.create(Type.DARK_MAGIC, world.rand, xPos, yPos + 1, zPos, 1, false) + .clr(0.1f, 0, 0).spawn(world); } + ParticleBuilder.create(Type.BUFF).pos(xPos, yPos, zPos).clr(0xd363cb).spawn(world); } + + this.playSound(world, (EntityLivingBase)target, ticksInUse, -1, modifiers); + return true; } return false; } @Override - protected boolean onBlockHit(World world, BlockPos pos, EnumFacing side, EntityLivingBase caster, int ticksInUse, SpellModifiers modifiers){ + protected boolean onBlockHit(World world, BlockPos pos, EnumFacing side, Vec3d hit, EntityLivingBase caster, Vec3d origin, int ticksInUse, SpellModifiers modifiers){ return false; } @Override - protected boolean onMiss(World world, EntityLivingBase caster, int ticksInUse, SpellModifiers modifiers){ + protected boolean onMiss(World world, EntityLivingBase caster, Vec3d origin, Vec3d direction, int ticksInUse, SpellModifiers modifiers){ return false; } diff --git a/src/main/java/electroblob/wizardry/spell/Meteor.java b/src/main/java/electroblob/wizardry/spell/Meteor.java index e309762e..a89f1173 100644 --- a/src/main/java/electroblob/wizardry/spell/Meteor.java +++ b/src/main/java/electroblob/wizardry/spell/Meteor.java @@ -1,41 +1,44 @@ package electroblob.wizardry.spell; -import electroblob.wizardry.constants.Element; -import electroblob.wizardry.constants.SpellType; -import electroblob.wizardry.constants.Tier; import electroblob.wizardry.entity.EntityMeteor; import electroblob.wizardry.registry.WizardryItems; -import electroblob.wizardry.registry.WizardrySounds; import electroblob.wizardry.util.SpellModifiers; +import electroblob.wizardry.util.WizardryUtilities; import net.minecraft.entity.Entity; import net.minecraft.entity.EntityLivingBase; +import net.minecraft.item.EnumAction; import net.minecraft.util.EnumFacing; import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.Vec3d; import net.minecraft.world.World; public class Meteor extends SpellRay { + // It doesn't really make sense to have a blast radius when the explosion is measured by strength + public static final String BLAST_STRENGTH = "blast_strength"; + public Meteor(){ - super("meteor", Tier.MASTER, Element.FIRE, SpellType.ATTACK, 100, 200, false, 40, WizardrySounds.SPELL_SUMMONING); + super("meteor", false, EnumAction.NONE); this.soundValues(3, 1, 0); - this.ignoreEntities(true); + this.ignoreLivingEntities(true); + addProperties(BLAST_STRENGTH); } - @Override public boolean doesSpellRequirePacket(){ return false; } + @Override public boolean requiresPacket(){ return false; } @Override - protected boolean onEntityHit(World world, Entity target, EntityLivingBase caster, int ticksInUse, SpellModifiers modifiers){ + protected boolean onEntityHit(World world, Entity target, Vec3d hit, EntityLivingBase caster, Vec3d origin, int ticksInUse, SpellModifiers modifiers){ return false; } @Override - protected boolean onBlockHit(World world, BlockPos pos, EnumFacing side, EntityLivingBase caster, int ticksInUse, SpellModifiers modifiers){ + protected boolean onBlockHit(World world, BlockPos pos, EnumFacing side, Vec3d hit, EntityLivingBase caster, Vec3d origin, int ticksInUse, SpellModifiers modifiers){ if(world.canBlockSeeSky(pos.up())){ if(!world.isRemote){ EntityMeteor meteor = new EntityMeteor(world, pos.getX(), pos.getY() + 50, pos.getZ(), - modifiers.get(WizardryItems.blast_upgrade)); + modifiers.get(WizardryItems.blast_upgrade), WizardryUtilities.canDamageBlocks(caster, world)); world.spawnEntity(meteor); } @@ -46,7 +49,7 @@ public class Meteor extends SpellRay { } @Override - protected boolean onMiss(World world, EntityLivingBase caster, int ticksInUse, SpellModifiers modifiers){ + protected boolean onMiss(World world, EntityLivingBase caster, Vec3d origin, Vec3d direction, int ticksInUse, SpellModifiers modifiers){ return false; } diff --git a/src/main/java/electroblob/wizardry/spell/MindControl.java b/src/main/java/electroblob/wizardry/spell/MindControl.java index a472cf92..caa03f9d 100644 --- a/src/main/java/electroblob/wizardry/spell/MindControl.java +++ b/src/main/java/electroblob/wizardry/spell/MindControl.java @@ -1,31 +1,27 @@ package electroblob.wizardry.spell; -import java.util.Arrays; -import java.util.List; - import electroblob.wizardry.Wizardry; -import electroblob.wizardry.constants.Element; -import electroblob.wizardry.constants.SpellType; -import electroblob.wizardry.constants.Tier; import electroblob.wizardry.entity.living.EntityEvilWizard; import electroblob.wizardry.registry.WizardryItems; import electroblob.wizardry.registry.WizardryPotions; import electroblob.wizardry.registry.WizardrySounds; +import electroblob.wizardry.util.AllyDesignationSystem; import electroblob.wizardry.util.ParticleBuilder; import electroblob.wizardry.util.ParticleBuilder.Type; import electroblob.wizardry.util.SpellModifiers; import electroblob.wizardry.util.WizardryUtilities; -import net.minecraft.entity.Entity; -import net.minecraft.entity.EntityList; -import net.minecraft.entity.EntityLiving; -import net.minecraft.entity.EntityLivingBase; -import net.minecraft.entity.INpc; -import net.minecraft.entity.SharedMonsterAttributes; +import net.minecraft.entity.*; import net.minecraft.entity.item.EntityArmorStand; +import net.minecraft.entity.passive.EntitySheep; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.init.SoundEvents; +import net.minecraft.item.EnumAction; +import net.minecraft.item.EnumDyeColor; import net.minecraft.nbt.NBTTagCompound; import net.minecraft.potion.PotionEffect; import net.minecraft.util.EnumFacing; import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.Vec3d; import net.minecraft.util.text.TextComponentTranslation; import net.minecraft.world.World; import net.minecraftforge.event.entity.living.LivingEvent.LivingUpdateEvent; @@ -33,45 +29,57 @@ import net.minecraftforge.event.entity.living.LivingSetAttackTargetEvent; import net.minecraftforge.fml.common.Mod; import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; +import java.util.Arrays; +import java.util.List; + @Mod.EventBusSubscriber public class MindControl extends SpellRay { /** The NBT tag name for storing the controlling entity's UUID in the target's tag compound. */ public static final String NBT_KEY = "controllingEntity"; - - private static final int BASE_DURATION = 600; public MindControl(){ - super("mind_control", Tier.ADVANCED, Element.NECROMANCY, SpellType.ATTACK, 40, 150, false, 8, WizardrySounds.SPELL_SUMMONING); + super("mind_control", false, EnumAction.NONE); + addProperties(EFFECT_DURATION); } + @Override public boolean canBeCastByNPCs() { return false; } + @Override public boolean canBeCastByDispensers() { return false; } + @Override - protected boolean onEntityHit(World world, Entity target, EntityLivingBase caster, int ticksInUse, SpellModifiers modifiers){ + protected boolean onEntityHit(World world, Entity target, Vec3d hit, EntityLivingBase caster, Vec3d origin, int ticksInUse, SpellModifiers modifiers){ if(WizardryUtilities.isLiving(target)){ - - if(!world.isRemote){ - if(!canControl(target)){ - // Adds a message saying that the player/boss entity/wizard resisted mind control - ((EntityPlayer)caster).sendStatusMessage(new TextComponentTranslation("spell.resist", target.getName(), - this.getNameForTranslationFormatted()), true); - - }else if(target instanceof EntityLiving){ - + if(!canControl(target)){ + if(!world.isRemote){ + if(caster instanceof EntityPlayer){ + // Adds a message saying that the player/boss entity/wizard resisted mind control + ((EntityPlayer)caster).sendStatusMessage(new TextComponentTranslation("spell.resist", target.getName(), + this.getNameForTranslationFormatted()), true); + } + } + + }else if(target instanceof EntityLiving){ + + if(!world.isRemote){ if(!MindControl.findMindControlTarget((EntityLiving)target, caster, world)){ // If no valid target was found, this just acts like mind trick. ((EntityLiving)target).setAttackTarget(null); } - - NBTTagCompound entityNBT = target.getEntityData(); - if(entityNBT != null) entityNBT.setUniqueId(NBT_KEY, caster.getUniqueID()); - - ((EntityLiving)target).addPotionEffect(new PotionEffect(WizardryPotions.mind_control, - (int)(BASE_DURATION * modifiers.get(WizardryItems.duration_upgrade)), 0)); } - - }else{ + + if(target instanceof EntitySheep && ((EntitySheep)target).getFleeceColor() == EnumDyeColor.BLUE + && WizardryUtilities.canDamageBlocks(caster, world)){ + if(!world.isRemote) ((EntitySheep)target).setFleeceColor(EnumDyeColor.RED); // Wololo! + world.playSound(caster.posX, caster.posY, caster.posZ, SoundEvents.EVOCATION_ILLAGER_PREPARE_WOLOLO, WizardrySounds.SPELLS, 1, 1, false); + } + + if(!world.isRemote) startControlling((EntityLiving)target, caster, + (int)(getProperty(EFFECT_DURATION).floatValue() * modifiers.get(WizardryItems.duration_upgrade))); + } + + if(world.isRemote){ for(int i=0; i<10; i++){ ParticleBuilder.create(Type.DARK_MAGIC, world.rand, target.posX, @@ -90,12 +98,12 @@ public class MindControl extends SpellRay { } @Override - protected boolean onBlockHit(World world, BlockPos pos, EnumFacing side, EntityLivingBase caster, int ticksInUse, SpellModifiers modifiers){ + protected boolean onBlockHit(World world, BlockPos pos, EnumFacing side, Vec3d hit, EntityLivingBase caster, Vec3d origin, int ticksInUse, SpellModifiers modifiers){ return false; } @Override - protected boolean onMiss(World world, EntityLivingBase caster, int ticksInUse, SpellModifiers modifiers){ + protected boolean onMiss(World world, EntityLivingBase caster, Vec3d origin, Vec3d direction, int ticksInUse, SpellModifiers modifiers){ return false; } @@ -106,6 +114,11 @@ public class MindControl extends SpellRay { .contains(EntityList.getKey(target.getClass())); } + public static void startControlling(EntityLiving target, EntityLivingBase controller, int duration){ + target.getEntityData().setUniqueId(NBT_KEY, controller.getUniqueID()); + target.addPotionEffect(new PotionEffect(WizardryPotions.mind_control, duration, 0)); + } + /** * Finds the nearest creature to the given target which it is allowed to attack according to the given caster and * sets it as the target's attack target. Handles both new and old AI and takes follow range into account. Defined @@ -122,7 +135,7 @@ public class MindControl extends SpellRay { // no longer lasts until the creature dies; instead it is a potion effect which continues to // set the target until it wears off. List possibleTargets = WizardryUtilities.getEntitiesWithinRadius( - ((EntityLiving)target).getEntityAttribute(SharedMonsterAttributes.FOLLOW_RANGE).getAttributeValue(), + target.getEntityAttribute(SharedMonsterAttributes.FOLLOW_RANGE).getAttributeValue(), target.posX, target.posY, target.posZ, world); possibleTargets.remove(target); @@ -131,7 +144,7 @@ public class MindControl extends SpellRay { EntityLivingBase newAITarget = null; for(EntityLivingBase possibleTarget : possibleTargets){ - if(WizardryUtilities.isValidTarget(caster, possibleTarget) && (newAITarget == null + if(AllyDesignationSystem.isValidTarget(caster, possibleTarget) && (newAITarget == null || target.getDistance(possibleTarget) < target.getDistance(newAITarget))){ newAITarget = possibleTarget; } @@ -140,7 +153,7 @@ public class MindControl extends SpellRay { if(newAITarget != null){ // From 1.7.10 - this seems not to work quite right; the entity appears to continue attacking this target // after it gets killed (not noticeable in survival since it will target the player again immediately.) - ((EntityLiving)target).setAttackTarget(newAITarget); + target.setAttackTarget(newAITarget); return true; } @@ -163,7 +176,7 @@ public class MindControl extends SpellRay { if(caster instanceof EntityLivingBase){ // If the current target is already a valid mind control target, nothing happens. - if(WizardryUtilities.isValidTarget(caster, currentTarget)) return; + if(AllyDesignationSystem.isValidTarget(caster, currentTarget)) return; if(MindControl.findMindControlTarget(entity, (EntityLivingBase)caster, world)){ // If it worked, skip setting the target to null. diff --git a/src/main/java/electroblob/wizardry/spell/MindTrick.java b/src/main/java/electroblob/wizardry/spell/MindTrick.java index 739d585f..7aeb5cde 100644 --- a/src/main/java/electroblob/wizardry/spell/MindTrick.java +++ b/src/main/java/electroblob/wizardry/spell/MindTrick.java @@ -1,11 +1,7 @@ package electroblob.wizardry.spell; -import electroblob.wizardry.constants.Element; -import electroblob.wizardry.constants.SpellType; -import electroblob.wizardry.constants.Tier; import electroblob.wizardry.registry.WizardryItems; import electroblob.wizardry.registry.WizardryPotions; -import electroblob.wizardry.registry.WizardrySounds; import electroblob.wizardry.util.ParticleBuilder; import electroblob.wizardry.util.ParticleBuilder.Type; import electroblob.wizardry.util.SpellModifiers; @@ -15,9 +11,11 @@ import net.minecraft.entity.EntityLiving; import net.minecraft.entity.EntityLivingBase; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.init.MobEffects; +import net.minecraft.item.EnumAction; import net.minecraft.potion.PotionEffect; import net.minecraft.util.EnumFacing; import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.Vec3d; import net.minecraft.world.World; import net.minecraftforge.event.entity.living.LivingAttackEvent; import net.minecraftforge.event.entity.living.LivingSetAttackTargetEvent; @@ -26,16 +24,15 @@ import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; @Mod.EventBusSubscriber public class MindTrick extends SpellRay { - - private static final int BASE_DURATION = 300; public MindTrick(){ - super("mind_trick", Tier.BASIC, Element.NECROMANCY, SpellType.ATTACK, 10, 40, false, 8, WizardrySounds.SPELL_DEFLECTION); + super("mind_trick", false, EnumAction.NONE); this.soundValues(0.7f, 1, 0.4f); + addProperties(EFFECT_DURATION); } @Override - protected boolean onEntityHit(World world, Entity target, EntityLivingBase caster, int ticksInUse, SpellModifiers modifiers){ + protected boolean onEntityHit(World world, Entity target, Vec3d hit, EntityLivingBase caster, Vec3d origin, int ticksInUse, SpellModifiers modifiers){ if(WizardryUtilities.isLiving(target)){ @@ -44,13 +41,13 @@ public class MindTrick extends SpellRay { if(target instanceof EntityPlayer){ ((EntityLivingBase)target).addPotionEffect(new PotionEffect(MobEffects.NAUSEA, - (int)(BASE_DURATION * modifiers.get(WizardryItems.duration_upgrade)), 0)); + (int)(getProperty(EFFECT_DURATION).floatValue() * modifiers.get(WizardryItems.duration_upgrade)), 0)); }else if(target instanceof EntityLiving){ ((EntityLiving)target).setAttackTarget(null); ((EntityLivingBase)target).addPotionEffect(new PotionEffect(WizardryPotions.mind_trick, - (int)(BASE_DURATION * modifiers.get(WizardryItems.duration_upgrade)), 0)); + (int)(getProperty(EFFECT_DURATION).floatValue() * modifiers.get(WizardryItems.duration_upgrade)), 0)); } }else{ @@ -68,12 +65,12 @@ public class MindTrick extends SpellRay { } @Override - protected boolean onBlockHit(World world, BlockPos pos, EnumFacing side, EntityLivingBase caster, int ticksInUse, SpellModifiers modifiers){ + protected boolean onBlockHit(World world, BlockPos pos, EnumFacing side, Vec3d hit, EntityLivingBase caster, Vec3d origin, int ticksInUse, SpellModifiers modifiers){ return false; } @Override - protected boolean onMiss(World world, EntityLivingBase caster, int ticksInUse, SpellModifiers modifiers){ + protected boolean onMiss(World world, EntityLivingBase caster, Vec3d origin, Vec3d direction, int ticksInUse, SpellModifiers modifiers){ return false; } diff --git a/src/main/java/electroblob/wizardry/spell/Mine.java b/src/main/java/electroblob/wizardry/spell/Mine.java new file mode 100644 index 00000000..30389fb9 --- /dev/null +++ b/src/main/java/electroblob/wizardry/spell/Mine.java @@ -0,0 +1,157 @@ +package electroblob.wizardry.spell; + +import electroblob.wizardry.constants.Constants; +import electroblob.wizardry.item.ISpellCastingItem; +import electroblob.wizardry.item.ItemArtefact; +import electroblob.wizardry.registry.WizardryItems; +import electroblob.wizardry.util.ParticleBuilder; +import electroblob.wizardry.util.ParticleBuilder.Type; +import electroblob.wizardry.util.SpellModifiers; +import electroblob.wizardry.util.WizardryUtilities; +import net.minecraft.block.Block; +import net.minecraft.block.state.IBlockState; +import net.minecraft.entity.Entity; +import net.minecraft.entity.EntityLivingBase; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.entity.player.EntityPlayerMP; +import net.minecraft.item.EnumAction; +import net.minecraft.item.Item; +import net.minecraft.item.ItemStack; +import net.minecraft.util.EnumFacing; +import net.minecraft.util.EnumHand; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.Vec3d; +import net.minecraft.world.World; +import net.minecraftforge.common.ForgeHooks; +import net.minecraftforge.event.ForgeEventFactory; + +import java.util.List; + +public class Mine extends SpellRay { + + public Mine(){ + super("mine", false, EnumAction.NONE); + this.ignoreLivingEntities(true); + this.particleSpacing(0.5); + } + + @Override + protected boolean onEntityHit(World world, Entity target, Vec3d hit, EntityLivingBase caster, Vec3d origin, int ticksInUse, SpellModifiers modifiers){ + return false; + } + + @Override + protected boolean onBlockHit(World world, BlockPos pos, EnumFacing side, Vec3d hit, EntityLivingBase caster, Vec3d origin, int ticksInUse, SpellModifiers modifiers){ + + // Needs to be outside because it gets run on the client-side + if(caster instanceof EntityPlayer){ + if(caster.getHeldItemMainhand().getItem() instanceof ISpellCastingItem){ + caster.swingArm(EnumHand.MAIN_HAND); + }else if(caster.getHeldItemOffhand().getItem() instanceof ISpellCastingItem){ + caster.swingArm(EnumHand.OFF_HAND); + } + } + + if(!world.isRemote){ + + if(WizardryUtilities.isBlockUnbreakable(world, pos)) return false; + // The mine spell ignores the block damage setting for players, since that's the entire point of the spell + // Instead, it triggers block break events at the appropriate points, which protection mods should be able to + // pick up and allow/disallow accordingly + // For the time being, dispensers respect the mobGriefing gamerule + if(!(caster instanceof EntityPlayer) && !WizardryUtilities.canDamageBlocks(caster, world)) return false; + // Can't mine arcane-locked blocks + if(world.getTileEntity(pos) != null && world.getTileEntity(pos).getTileData().hasUniqueId(ArcaneLock.NBT_KEY)) return false; + + IBlockState state = world.getBlockState(pos); + // The maximum harvest level as determined by the potency multiplier. The + 0.5f is so that + // weird float processing doesn't incorrectly round it down. + int harvestLevel = (int)((modifiers.get(SpellModifiers.POTENCY) - 1) / Constants.POTENCY_INCREASE_PER_TIER + 0.5f); + + if(harvestLevel > 0) harvestLevel--; // Shifts them all down one since normally novice wands give some potency + + // The >= 3 is to allow master earth wands to break anything. + if(state.getBlock().getHarvestLevel(state) <= harvestLevel || harvestLevel >= 3){ + + boolean flag = false; + + int blastUpgradeCount = (int)((modifiers.get(WizardryItems.blast_upgrade) - 1) / Constants.RANGE_INCREASE_PER_LEVEL + 0.5f); + // Results in the following patterns: + // 0 blast upgrades: single block + // 1 blast upgrade: 3x3 without corners or edges + // 2 blast upgrades: 3x3 with corners + // 3 blast upgrades: 5x5 without corners or edges + float radius = 0.5f + 0.73f * blastUpgradeCount; + + List sphere = WizardryUtilities.getBlockSphere(pos, radius); + + for(BlockPos pos1 : sphere){ + + if(WizardryUtilities.isBlockUnbreakable(world, pos1)) continue; + + IBlockState state1 = world.getBlockState(pos1); + + if(state1.getBlock().getHarvestLevel(state1) <= harvestLevel || harvestLevel >= 3){ + + if(caster instanceof EntityPlayerMP){ // Everything in here is server-side only so this is fine + + boolean silkTouch = state1.getBlock().canSilkHarvest(world, pos1, state1, (EntityPlayer)caster) + && ItemArtefact.isArtefactActive((EntityPlayer)caster, WizardryItems.charm_silk_touch); + + // Some protection mods seem to use this event instead so let's trigger it to check + if(ForgeEventFactory.getBreakSpeed((EntityPlayer)caster, state1, 1, pos1) <= 0) continue; + + int xp = ForgeHooks.onBlockBreakEvent(world, + ((EntityPlayerMP)caster).interactionManager.getGameType(), (EntityPlayerMP)caster, pos1); + + if(xp == -1) continue; // Event was cancelled + + if(silkTouch){ + flag = world.destroyBlock(pos1, false); + if(flag) Block.spawnAsEntity(world, pos1, getSilkTouchDrop(state1)); + }else{ + flag = world.destroyBlock(pos1, true); + if(flag) state1.getBlock().dropXpOnBlockBreak(world, pos1, xp); + } + + }else{ + // NPCs can dig the block under the target's feet + flag = world.destroyBlock(pos1, true) || flag; + } + } + } + + return flag; + } + }else{ + return true; + } + + return false; + } + + @Override + protected boolean onMiss(World world, EntityLivingBase caster, Vec3d origin, Vec3d direction, int ticksInUse, SpellModifiers modifiers){ + return false; + } + + @Override + protected void spawnParticle(World world, double x, double y, double z, double vx, double vy, double vz){ + ParticleBuilder.create(Type.DUST).pos(x, y, z).time(20 + world.rand.nextInt(5)).clr(0.9f, 0.95f, 1) + .shaded(false).spawn(world); + } + + // Copied from Block, where (for some reason) it's protected + private static ItemStack getSilkTouchDrop(IBlockState state){ + + Item item = Item.getItemFromBlock(state.getBlock()); + int i = 0; + + if(item.getHasSubtypes()){ + i = state.getBlock().getMetaFromState(state); + } + + return new ItemStack(item, 1, i); + } + +} diff --git a/src/main/java/electroblob/wizardry/spell/None.java b/src/main/java/electroblob/wizardry/spell/None.java index 95e82045..c627002d 100644 --- a/src/main/java/electroblob/wizardry/spell/None.java +++ b/src/main/java/electroblob/wizardry/spell/None.java @@ -1,8 +1,5 @@ package electroblob.wizardry.spell; -import electroblob.wizardry.constants.Element; -import electroblob.wizardry.constants.SpellType; -import electroblob.wizardry.constants.Tier; import electroblob.wizardry.util.SpellModifiers; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.item.EnumAction; @@ -17,11 +14,11 @@ import net.minecraft.world.World; public class None extends Spell { public None(){ - super("none", Tier.BASIC, Element.MAGIC, SpellType.UTILITY, 0, 0, EnumAction.NONE, false); + super("none", EnumAction.NONE, false); } @Override - public boolean doesSpellRequirePacket(){ + public boolean requiresPacket(){ return false; } diff --git a/src/main/java/electroblob/wizardry/spell/Paralysis.java b/src/main/java/electroblob/wizardry/spell/Paralysis.java new file mode 100644 index 00000000..795a884a --- /dev/null +++ b/src/main/java/electroblob/wizardry/spell/Paralysis.java @@ -0,0 +1,123 @@ +package electroblob.wizardry.spell; + +import electroblob.wizardry.registry.Spells; +import electroblob.wizardry.registry.WizardryItems; +import electroblob.wizardry.registry.WizardryPotions; +import electroblob.wizardry.util.MagicDamage; +import electroblob.wizardry.util.MagicDamage.DamageType; +import electroblob.wizardry.util.ParticleBuilder; +import electroblob.wizardry.util.ParticleBuilder.Type; +import electroblob.wizardry.util.SpellModifiers; +import electroblob.wizardry.util.WizardryUtilities; +import net.minecraft.entity.Entity; +import net.minecraft.entity.EntityLiving; +import net.minecraft.entity.EntityLivingBase; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.item.EnumAction; +import net.minecraft.potion.PotionEffect; +import net.minecraft.util.EnumFacing; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.Vec3d; +import net.minecraft.util.text.TextComponentTranslation; +import net.minecraft.world.World; +import net.minecraftforge.event.entity.living.LivingEvent.LivingUpdateEvent; +import net.minecraftforge.event.entity.living.LivingHurtEvent; +import net.minecraftforge.fml.common.Mod; +import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; + +@Mod.EventBusSubscriber +public class Paralysis extends SpellRay { + + /** Creatures with this much health or less will snap out of paralysis - but only when they take damage, so a + * creature on critical health may still be paralysed, but if it takes any damage at all the paralysis effect + * will end. */ + private static final String CRITICAL_HEALTH = "critical_health"; + + public Paralysis(){ + super("paralysis", false, EnumAction.NONE); + addProperties(DAMAGE, EFFECT_DURATION, CRITICAL_HEALTH); + } + + @Override + protected boolean onEntityHit(World world, Entity target, Vec3d hit, EntityLivingBase caster, Vec3d origin, int ticksInUse, SpellModifiers modifiers){ + + if(WizardryUtilities.isLiving(target)){ + + if(world.isRemote){ + // Rather neatly, the entity can be set here and if it's null nothing will happen. + ParticleBuilder.create(Type.BEAM).entity(caster).clr(0.2f, 0.6f, 1) + .pos(caster != null ? origin.subtract(caster.getPositionVector()) : origin).target(target).spawn(world); + ParticleBuilder.create(Type.LIGHTNING).entity(caster) + .pos(caster != null ? origin.subtract(caster.getPositionVector()) : origin).target(target).spawn(world); + } + + // This is a lot neater than it was, thanks to the damage type system. + if(MagicDamage.isEntityImmune(DamageType.SHOCK, target)){ + if(!world.isRemote && caster instanceof EntityPlayer) ((EntityPlayer)caster).sendStatusMessage( + new TextComponentTranslation("spell.resist", + target.getName(), this.getNameForTranslationFormatted()), true); + }else{ + target.attackEntityFrom(MagicDamage.causeDirectMagicDamage(caster, DamageType.SHOCK), + getProperty(DAMAGE).floatValue() * modifiers.get(SpellModifiers.POTENCY)); + } + + ((EntityLivingBase)target).addPotionEffect(new PotionEffect(WizardryPotions.paralysis, + (int)(getProperty(EFFECT_DURATION).floatValue() * modifiers.get(WizardryItems.duration_upgrade)), 0)); + } + + return false; + } + + @Override + protected boolean onBlockHit(World world, BlockPos pos, EnumFacing side, Vec3d hit, EntityLivingBase caster, Vec3d origin, int ticksInUse, SpellModifiers modifiers){ + + if(world.isRemote){ + + if(world.getBlockState(pos).getMaterial().isSolid()){ + Vec3d vec = hit.add(new Vec3d(side.getDirectionVec()).scale(WizardryUtilities.ANTI_Z_FIGHTING_OFFSET)); + ParticleBuilder.create(Type.SCORCH).pos(vec).face(side).clr(0.4f, 0.8f, 1).spawn(world); + } + } + + return false; + } + + @Override + protected boolean onMiss(World world, EntityLivingBase caster, Vec3d origin, Vec3d direction, int ticksInUse, SpellModifiers modifiers){ + // This is first because we want the endpoint to be unaffected by the offset + Vec3d endpoint = origin.add(direction.scale(getProperty(RANGE).floatValue() * modifiers.get(WizardryItems.range_upgrade))); + + if(world.isRemote){ + ParticleBuilder.create(Type.LIGHTNING).time(4).pos(origin).target(endpoint).scale(0.5f).spawn(world); + ParticleBuilder.create(Type.BEAM).clr(0.2f, 0.6f, 1).time(4).pos(origin) + .target(endpoint).spawn(world); + } + + return true; + } + + // See WizardryClientEventHandler for prevention of players' movement under the effects of paralysis + + // TODO: (Animated?) screen overlay effect for paralysed players in first-person + + @SubscribeEvent + public static void onLivingUpdateEvent(LivingUpdateEvent event){ + // Disables entities' AI when under the effects of paralysis and re-enables it on the last update of the effect + // - this can't be in the potion class because it requires access to the duration and hence the actual + // PotionEffect instance + if(event.getEntity() instanceof EntityLiving && event.getEntityLiving().isPotionActive(WizardryPotions.paralysis)){ + int timeLeft = event.getEntityLiving().getActivePotionEffect(WizardryPotions.paralysis).getDuration(); + ((EntityLiving)event.getEntity()).setNoAI(timeLeft > 1); + } + } + + @SubscribeEvent + public static void onLivingHurtEvent(LivingHurtEvent event){ + // Paralysed creatures snap out of paralysis when they take critical damage + if(event.getEntityLiving().isPotionActive(WizardryPotions.paralysis) && event.getEntityLiving().getHealth() + - event.getAmount() <= Spells.paralysis.getProperty(CRITICAL_HEALTH).floatValue()){ + event.getEntityLiving().removePotionEffect(WizardryPotions.paralysis); + } + } + +} diff --git a/src/main/java/electroblob/wizardry/spell/Petrify.java b/src/main/java/electroblob/wizardry/spell/Petrify.java index 757d9f29..de5e6d4b 100644 --- a/src/main/java/electroblob/wizardry/spell/Petrify.java +++ b/src/main/java/electroblob/wizardry/spell/Petrify.java @@ -1,9 +1,6 @@ package electroblob.wizardry.spell; import electroblob.wizardry.block.BlockStatue; -import electroblob.wizardry.constants.Element; -import electroblob.wizardry.constants.SpellType; -import electroblob.wizardry.constants.Tier; import electroblob.wizardry.registry.WizardryBlocks; import electroblob.wizardry.registry.WizardryItems; import electroblob.wizardry.util.ParticleBuilder; @@ -12,42 +9,43 @@ import electroblob.wizardry.util.SpellModifiers; import net.minecraft.entity.Entity; import net.minecraft.entity.EntityLiving; import net.minecraft.entity.EntityLivingBase; -import net.minecraft.init.SoundEvents; +import net.minecraft.item.EnumAction; import net.minecraft.util.EnumFacing; import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.Vec3d; import net.minecraft.world.World; public class Petrify extends SpellRay { - private static final int BASE_DURATION = 900; + // This is more descriptive and more accurate than the standard "effect_duration" in this case + public static final String MINIMUM_EFFECT_DURATION = "minimum_effect_duration"; public Petrify(){ - super("petrify", Tier.ADVANCED, Element.SORCERY, SpellType.ATTACK, 40, 100, false, 10, SoundEvents.ENTITY_WITHER_SPAWN); + super("petrify", false, EnumAction.NONE); this.soundValues(1, 1.1f, 0.2f); + addProperties(MINIMUM_EFFECT_DURATION); } @Override - protected boolean onEntityHit(World world, Entity target, EntityLivingBase caster, int ticksInUse, SpellModifiers modifiers){ + protected boolean onEntityHit(World world, Entity target, Vec3d hit, EntityLivingBase caster, Vec3d origin, int ticksInUse, SpellModifiers modifiers){ if(target instanceof EntityLiving && !world.isRemote){ // Unchecked cast is fine because the block is a static final field if(((BlockStatue)WizardryBlocks.petrified_stone).convertToStatue((EntityLiving)target, - (int)(BASE_DURATION * modifiers.get(WizardryItems.duration_upgrade)))){ - - return true; + (int)(getProperty(MINIMUM_EFFECT_DURATION).floatValue() * modifiers.get(WizardryItems.duration_upgrade)))){ } } + return true; + } + + @Override + protected boolean onBlockHit(World world, BlockPos pos, EnumFacing side, Vec3d hit, EntityLivingBase caster, Vec3d origin, int ticksInUse, SpellModifiers modifiers){ return false; } @Override - protected boolean onBlockHit(World world, BlockPos pos, EnumFacing side, EntityLivingBase caster, int ticksInUse, SpellModifiers modifiers){ - return false; - } - - @Override - protected boolean onMiss(World world, EntityLivingBase caster, int ticksInUse, SpellModifiers modifiers){ + protected boolean onMiss(World world, EntityLivingBase caster, Vec3d origin, Vec3d direction, int ticksInUse, SpellModifiers modifiers){ return true; } diff --git a/src/main/java/electroblob/wizardry/spell/PhaseStep.java b/src/main/java/electroblob/wizardry/spell/PhaseStep.java index 05f9a9f1..18926341 100644 --- a/src/main/java/electroblob/wizardry/spell/PhaseStep.java +++ b/src/main/java/electroblob/wizardry/spell/PhaseStep.java @@ -2,73 +2,39 @@ package electroblob.wizardry.spell; import electroblob.wizardry.Wizardry; import electroblob.wizardry.constants.Constants; -import electroblob.wizardry.constants.Element; -import electroblob.wizardry.constants.SpellType; -import electroblob.wizardry.constants.Tier; import electroblob.wizardry.registry.WizardryItems; +import electroblob.wizardry.util.RayTracer; import electroblob.wizardry.util.SpellModifiers; import electroblob.wizardry.util.WizardryUtilities; import net.minecraft.entity.player.EntityPlayer; -import net.minecraft.init.SoundEvents; import net.minecraft.item.EnumAction; +import net.minecraft.util.EnumFacing; import net.minecraft.util.EnumHand; import net.minecraft.util.EnumParticleTypes; import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.RayTraceResult; +import net.minecraft.util.math.Vec3d; import net.minecraft.world.World; public class PhaseStep extends Spell { + public static final String WALL_THICKNESS = "wall_thickness"; + public PhaseStep(){ - super("phase_step", Tier.ADVANCED, Element.SORCERY, SpellType.UTILITY, 35, 40, EnumAction.NONE, false); + super("phase_step", EnumAction.NONE, false); + addProperties(RANGE, WALL_THICKNESS); } @Override public boolean cast(World world, EntityPlayer caster, EnumHand hand, int ticksInUse, SpellModifiers modifiers){ - // Phase step does not gain range from range multiplier, instead it increases the thickness - // of the wall you can teleport through. - RayTraceResult rayTrace = WizardryUtilities.standardBlockRayTrace(world, caster, 5, false); - - if(rayTrace != null && rayTrace.typeOfHit == RayTraceResult.Type.BLOCK){ - - BlockPos pos = new BlockPos(rayTrace.getBlockPos().getX(), (int)caster.posY, rayTrace.getBlockPos().getZ()); - - // The maximum wall thickness as determined by the range multiplier. The + 0.5f is so that - // weird float processing doesn't incorrectly round it down. - int maxThickness = 1 + (int)((modifiers.get(WizardryItems.range_upgrade) - 1) / Constants.RANGE_INCREASE_PER_LEVEL + 0.5f); - - if(rayTrace.sideHit.getAxis().isHorizontal()){ - - // i represents how far the player needs to teleport to get through the wall - for(int i = 0; i <= maxThickness; i++){ - - BlockPos pos1 = pos.offset(rayTrace.sideHit.getOpposite(), i); - - // Prevents the player from teleporting through unbreakable blocks, so they cannot cheat in other - // mods' mazes and dungeons. - if((WizardryUtilities.isBlockUnbreakable(world, pos1) || WizardryUtilities.isBlockUnbreakable(world, pos1.up())) - && !Wizardry.settings.teleportThroughUnbreakableBlocks) - return false; - - if(!world.getBlockState(pos1).getMaterial().blocksMovement() - && !world.getBlockState(pos1.up()).getMaterial().blocksMovement()){ - - if(!world.isRemote){ - caster.setPositionAndUpdate(pos1.getX() + 0.5, caster.posY, pos1.getZ() + 0.5); - } - - caster.swingArm(hand); - WizardryUtilities.playSoundAtPlayer(caster, SoundEvents.ENTITY_ENDERMEN_TELEPORT, 1.0F, 1.0f); - return true; - } - } - } - } + double range = getProperty(RANGE).floatValue() * modifiers.get(WizardryItems.range_upgrade); + RayTraceResult rayTrace = RayTracer.standardBlockRayTrace(world, caster, range, false); // This is here because the conditions are false on the client for whatever reason. (see the Javadoc for cast() // for an explanation) if(world.isRemote){ + for(int i = 0; i < 10; i++){ double dx1 = caster.posX; double dy1 = caster.getEntityBoundingBox().minY + 2 * world.rand.nextFloat(); @@ -76,12 +42,94 @@ public class PhaseStep extends Spell { world.spawnParticle(EnumParticleTypes.PORTAL, dx1, dy1, dz1, world.rand.nextDouble() - 0.5, world.rand.nextDouble() - 0.5, world.rand.nextDouble() - 0.5); } - + // Can't be bothered to route this through the proxies! electroblob.wizardry.client.WizardryClientEventHandler.playBlinkEffect(); } - return false; + if(rayTrace != null && rayTrace.typeOfHit == RayTraceResult.Type.BLOCK){ + + BlockPos pos = rayTrace.getBlockPos(); + + // The maximum wall thickness as determined by the range multiplier. The + 0.5f is so that + // weird float processing doesn't incorrectly round it down. + int maxThickness = getProperty(WALL_THICKNESS).intValue() + + (int)((modifiers.get(WizardryItems.range_upgrade) - 1) / Constants.RANGE_INCREASE_PER_LEVEL + 0.5f); + + if(rayTrace.sideHit == EnumFacing.UP) maxThickness++; // Allow space for the player's head + + // i represents how far the player needs to teleport to get through the wall + for(int i = 0; i <= maxThickness; i++){ + + BlockPos pos1 = pos.offset(rayTrace.sideHit.getOpposite(), i); + + // Prevents the player from teleporting through unbreakable blocks, so they cannot cheat in other + // mods' mazes and dungeons. + if((WizardryUtilities.isBlockUnbreakable(world, pos1) || WizardryUtilities.isBlockUnbreakable(world, pos1.up())) + && !Wizardry.settings.teleportThroughUnbreakableBlocks) + break; // Don't return false yet, there are other possible outcomes below now + + if(!world.getBlockState(pos1).getMaterial().blocksMovement() + && !world.getBlockState(pos1.up()).getMaterial().blocksMovement()){ + + // Plays before and after so it is heard from both positions + this.playSound(world, caster, ticksInUse, -1, modifiers); + + if(!world.isRemote){ + caster.setPositionAndUpdate(pos1.getX() + 0.5, pos1.getY() + 0.5, pos1.getZ() + 0.5); + } + + caster.swingArm(hand); + this.playSound(world, caster, ticksInUse, -1, modifiers); + return true; + } + } + + // If no suitable position was found on the other side of the wall, works like blink instead + + // Leave space for the player's head + if(rayTrace.sideHit == EnumFacing.DOWN) pos = pos.down(); + + // This means stuff like snow layers is ignored, meaning when on snow-covered ground the player does + // not teleport 1 block above the ground. + if(rayTrace.sideHit == EnumFacing.UP && !world.getBlockState(pos).getMaterial().blocksMovement()){ + pos = pos.down(); + } + + pos = pos.offset(rayTrace.sideHit); + + // Prevents the player from teleporting into blocks and suffocating + if(world.getBlockState(pos).getMaterial().blocksMovement() + || world.getBlockState(pos.up()).getMaterial().blocksMovement()){ + return false; + } + + // Plays before and after so it is heard from both positions + this.playSound(world, caster, ticksInUse, -1, modifiers); + + if(!world.isRemote) caster.setPositionAndUpdate(pos.getX() + 0.5, pos.getY(), pos.getZ() + 0.5); + + this.playSound(world, caster, ticksInUse, -1, modifiers); + caster.swingArm(hand); + return true; + + }else{ // The ray trace missed + + Vec3d destination = caster.getPositionVector().add(caster.getLookVec().scale(range)); + BlockPos pos = new BlockPos(destination); + + // Prevents the player from teleporting into blocks and suffocating. + if(world.getBlockState(pos).getMaterial().blocksMovement() + || world.getBlockState(pos.up()).getMaterial().blocksMovement()){ + return false; + } + + if(!world.isRemote) caster.setPositionAndUpdate(destination.x, destination.y, destination.z); + + this.playSound(world, caster, ticksInUse, -1, modifiers); + caster.swingArm(hand); + return true; + } } } diff --git a/src/main/java/electroblob/wizardry/spell/PlagueOfDarkness.java b/src/main/java/electroblob/wizardry/spell/PlagueOfDarkness.java index e1d71f41..bf1c9d32 100644 --- a/src/main/java/electroblob/wizardry/spell/PlagueOfDarkness.java +++ b/src/main/java/electroblob/wizardry/spell/PlagueOfDarkness.java @@ -1,54 +1,48 @@ package electroblob.wizardry.spell; -import java.util.List; - -import electroblob.wizardry.constants.Element; -import electroblob.wizardry.constants.SpellType; -import electroblob.wizardry.constants.Tier; import electroblob.wizardry.registry.WizardryItems; -import electroblob.wizardry.util.MagicDamage; +import electroblob.wizardry.util.*; import electroblob.wizardry.util.MagicDamage.DamageType; -import electroblob.wizardry.util.ParticleBuilder; import electroblob.wizardry.util.ParticleBuilder.Type; -import electroblob.wizardry.util.SpellModifiers; -import electroblob.wizardry.util.WizardryUtilities; import net.minecraft.block.Block; import net.minecraft.block.state.IBlockState; import net.minecraft.entity.EntityLivingBase; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.init.MobEffects; -import net.minecraft.init.SoundEvents; import net.minecraft.item.EnumAction; import net.minecraft.potion.PotionEffect; import net.minecraft.util.EnumHand; import net.minecraft.util.EnumParticleTypes; import net.minecraft.world.World; +import java.util.List; + public class PlagueOfDarkness extends Spell { - - private static final double BASE_RADIUS = 5; - private static final float BASE_DAMAGE = 8; - private static final int BASE_DURATION = 140; public PlagueOfDarkness(){ - super("plague_of_darkness", Tier.MASTER, Element.NECROMANCY, SpellType.ATTACK, 75, 200, EnumAction.BOW, false); + super("plague_of_darkness", EnumAction.BOW, false); + addProperties(EFFECT_RADIUS, DAMAGE, EFFECT_DURATION, EFFECT_STRENGTH); + soundValues(1, 1.1f, 0.2f); } @Override public boolean cast(World world, EntityPlayer caster, EnumHand hand, int ticksInUse, SpellModifiers modifiers){ - List targets = WizardryUtilities.getEntitiesWithinRadius( - BASE_RADIUS * modifiers.get(WizardryItems.blast_upgrade), caster.posX, caster.posY, caster.posZ, world); + double radius = getProperty(EFFECT_RADIUS).floatValue() * modifiers.get(WizardryItems.blast_upgrade); + + List targets = WizardryUtilities.getEntitiesWithinRadius(radius, caster.posX, caster.posY, caster.posZ, world); for(EntityLivingBase target : targets){ - if(WizardryUtilities.isValidTarget(caster, target) + if(AllyDesignationSystem.isValidTarget(caster, target) && !MagicDamage.isEntityImmune(DamageType.WITHER, target)){ target.attackEntityFrom(MagicDamage.causeDirectMagicDamage(caster, DamageType.WITHER), - BASE_DAMAGE * modifiers.get(SpellModifiers.POTENCY)); + getProperty(DAMAGE).floatValue() * modifiers.get(SpellModifiers.POTENCY)); target.addPotionEffect(new PotionEffect(MobEffects.WITHER, - (int)(BASE_DURATION * modifiers.get(WizardryItems.duration_upgrade)), 2)); + (int)(getProperty(EFFECT_DURATION).floatValue() * modifiers.get(WizardryItems.duration_upgrade)), + getProperty(EFFECT_STRENGTH).intValue() + SpellBuff.getStandardBonusAmplifier(modifiers.get(SpellModifiers.POTENCY)))); } } + if(world.isRemote){ double particleX, particleZ; @@ -74,10 +68,16 @@ public class PlagueOfDarkness extends Spell { particleZ, particleX - caster.posX, 0, particleZ - caster.posZ, Block.getStateId(block)); } } + + ParticleBuilder.create(Type.SPHERE) + .pos(caster.posX, caster.getEntityBoundingBox().minY + 0.1, caster.posZ) + .scale((float)radius * 0.8f) + .clr(0.8f, 0, 0.05f) + .spawn(world); } caster.swingArm(hand); - WizardryUtilities.playSoundAtPlayer(caster, SoundEvents.ENTITY_WITHER_DEATH, 1, 1 + 0.2f * world.rand.nextFloat()); + this.playSound(world, caster, ticksInUse, -1, modifiers); return true; } diff --git a/src/main/java/electroblob/wizardry/spell/PocketFurnace.java b/src/main/java/electroblob/wizardry/spell/PocketFurnace.java index dbcb7312..4b9afbc1 100644 --- a/src/main/java/electroblob/wizardry/spell/PocketFurnace.java +++ b/src/main/java/electroblob/wizardry/spell/PocketFurnace.java @@ -1,29 +1,31 @@ package electroblob.wizardry.spell; -import electroblob.wizardry.constants.Element; -import electroblob.wizardry.constants.SpellType; -import electroblob.wizardry.constants.Tier; +import electroblob.wizardry.Wizardry; import electroblob.wizardry.util.SpellModifiers; import electroblob.wizardry.util.WizardryUtilities; import net.minecraft.entity.player.EntityPlayer; -import net.minecraft.init.SoundEvents; -import net.minecraft.item.EnumAction; -import net.minecraft.item.ItemStack; +import net.minecraft.item.*; import net.minecraft.item.crafting.FurnaceRecipes; import net.minecraft.util.EnumHand; import net.minecraft.util.EnumParticleTypes; import net.minecraft.world.World; +import java.util.Arrays; + public class PocketFurnace extends Spell { + public static final String ITEMS_SMELTED = "items_smelted"; + public PocketFurnace(){ - super("pocket_furnace", Tier.APPRENTICE, Element.FIRE, SpellType.UTILITY, 30, 40, EnumAction.BOW, false); + super("pocket_furnace", EnumAction.BOW, false); + addProperties(ITEMS_SMELTED); + soundValues(1, 0.75f, 0); } @Override public boolean cast(World world, EntityPlayer caster, EnumHand hand, int ticksInUse, SpellModifiers modifiers){ - int usesLeft = 5; + int usesLeft = (int)(getProperty(ITEMS_SMELTED).floatValue() * modifiers.get(SpellModifiers.POTENCY)); ItemStack stack, result; @@ -31,11 +33,14 @@ public class PocketFurnace extends Spell { stack = caster.inventory.getStackInSlot(i); - if(!stack.isEmpty()){ + if(!stack.isEmpty() && !world.isRemote){ result = FurnaceRecipes.instance().getSmeltingResult(stack); - if(!result.isEmpty()){ + if(!result.isEmpty() && !(result.getItem() instanceof ItemTool) && !(result.getItem() instanceof ItemSword) + && !(result.getItem() instanceof ItemArmor) + && !Arrays.asList(Wizardry.settings.pocketFurnaceItemBlacklist).contains(result.getItem().getRegistryName())){ + if(stack.getCount() <= usesLeft){ ItemStack stack2 = new ItemStack(result.getItem(), stack.getCount(), result.getItemDamage()); if(WizardryUtilities.doesPlayerHaveItem(caster, result.getItem())){ @@ -55,7 +60,7 @@ public class PocketFurnace extends Spell { } } - WizardryUtilities.playSoundAtPlayer(caster, SoundEvents.BLOCK_FURNACE_FIRE_CRACKLE, 1, 0.75f); + this.playSound(world, caster, ticksInUse, -1, modifiers); if(world.isRemote){ for(int i = 0; i < 10; i++){ diff --git a/src/main/java/electroblob/wizardry/spell/PocketWorkbench.java b/src/main/java/electroblob/wizardry/spell/PocketWorkbench.java index fc5e9e6a..fb4ea0d1 100644 --- a/src/main/java/electroblob/wizardry/spell/PocketWorkbench.java +++ b/src/main/java/electroblob/wizardry/spell/PocketWorkbench.java @@ -2,12 +2,7 @@ package electroblob.wizardry.spell; import electroblob.wizardry.Wizardry; import electroblob.wizardry.WizardryGuiHandler; -import electroblob.wizardry.constants.Element; -import electroblob.wizardry.constants.SpellType; -import electroblob.wizardry.constants.Tier; -import electroblob.wizardry.registry.WizardrySounds; import electroblob.wizardry.util.SpellModifiers; -import electroblob.wizardry.util.WizardryUtilities; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.item.EnumAction; import net.minecraft.util.EnumHand; @@ -16,11 +11,11 @@ import net.minecraft.world.World; public class PocketWorkbench extends Spell { public PocketWorkbench(){ - super("pocket_workbench", Tier.APPRENTICE, Element.SORCERY, SpellType.UTILITY, 30, 40, EnumAction.BOW, false); + super("pocket_workbench", EnumAction.BOW, false); } @Override - public boolean doesSpellRequirePacket(){ + public boolean requiresPacket(){ return false; } @@ -33,7 +28,7 @@ public class PocketWorkbench extends Spell { (int)caster.posY, (int)caster.posZ); } - WizardryUtilities.playSoundAtPlayer(caster, WizardrySounds.SPELL_CONJURATION, 1, 1); + this.playSound(world, caster, ticksInUse, -1, modifiers); return true; } diff --git a/src/main/java/electroblob/wizardry/spell/Poison.java b/src/main/java/electroblob/wizardry/spell/Poison.java index a08a5920..5cf6a5f9 100644 --- a/src/main/java/electroblob/wizardry/spell/Poison.java +++ b/src/main/java/electroblob/wizardry/spell/Poison.java @@ -1,10 +1,6 @@ package electroblob.wizardry.spell; -import electroblob.wizardry.constants.Element; -import electroblob.wizardry.constants.SpellType; -import electroblob.wizardry.constants.Tier; import electroblob.wizardry.registry.WizardryItems; -import electroblob.wizardry.registry.WizardrySounds; import electroblob.wizardry.util.MagicDamage; import electroblob.wizardry.util.MagicDamage.DamageType; import electroblob.wizardry.util.ParticleBuilder; @@ -13,20 +9,22 @@ import electroblob.wizardry.util.SpellModifiers; import electroblob.wizardry.util.WizardryUtilities; import net.minecraft.entity.Entity; import net.minecraft.entity.EntityLivingBase; +import net.minecraft.entity.player.EntityPlayer; import net.minecraft.init.MobEffects; +import net.minecraft.item.EnumAction; import net.minecraft.potion.PotionEffect; import net.minecraft.util.EnumFacing; import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.Vec3d; import net.minecraft.util.text.TextComponentTranslation; import net.minecraft.world.World; public class Poison extends SpellRay { - - private static final int BASE_DURATION = 200; public Poison(){ - super("poison", Tier.APPRENTICE, Element.EARTH, SpellType.ATTACK, 10, 20, false, 10, WizardrySounds.SPELL_ICE); + super("poison", false, EnumAction.NONE); this.soundValues(1, 1.1f, 0.2f); + addProperties(DAMAGE, EFFECT_DURATION, EFFECT_STRENGTH); } @Override @@ -35,7 +33,7 @@ public class Poison extends SpellRay { } @Override - protected boolean onEntityHit(World world, Entity target, EntityLivingBase caster, int ticksInUse, SpellModifiers modifiers){ + protected boolean onEntityHit(World world, Entity target, Vec3d hit, EntityLivingBase caster, Vec3d origin, int ticksInUse, SpellModifiers modifiers){ if(WizardryUtilities.isLiving(target)){ @@ -45,24 +43,23 @@ public class Poison extends SpellRay { new TextComponentTranslation("spell.resist", target.getName(), this.getNameForTranslationFormatted()), true); }else{ target.attackEntityFrom(MagicDamage.causeDirectMagicDamage(caster, DamageType.POISON), - 1 * modifiers.get(SpellModifiers.POTENCY)); + getProperty(DAMAGE).floatValue() * modifiers.get(SpellModifiers.POTENCY)); ((EntityLivingBase)target).addPotionEffect(new PotionEffect(MobEffects.POISON, - (int)(BASE_DURATION * modifiers.get(WizardryItems.duration_upgrade)), 1)); + (int)(getProperty(EFFECT_DURATION).floatValue() * modifiers.get(WizardryItems.duration_upgrade)), + getProperty(EFFECT_STRENGTH).intValue() + SpellBuff.getStandardBonusAmplifier(modifiers.get(SpellModifiers.POTENCY)))); } - - return true; } + return true; + } + + @Override + protected boolean onBlockHit(World world, BlockPos pos, EnumFacing side, Vec3d hit, EntityLivingBase caster, Vec3d origin, int ticksInUse, SpellModifiers modifiers){ return false; } @Override - protected boolean onBlockHit(World world, BlockPos pos, EnumFacing side, EntityLivingBase caster, int ticksInUse, SpellModifiers modifiers){ - return false; - } - - @Override - protected boolean onMiss(World world, EntityLivingBase caster, int ticksInUse, SpellModifiers modifiers){ + protected boolean onMiss(World world, EntityLivingBase caster, Vec3d origin, Vec3d direction, int ticksInUse, SpellModifiers modifiers){ return true; } diff --git a/src/main/java/electroblob/wizardry/spell/Possession.java b/src/main/java/electroblob/wizardry/spell/Possession.java new file mode 100644 index 00000000..a7bad811 --- /dev/null +++ b/src/main/java/electroblob/wizardry/spell/Possession.java @@ -0,0 +1,714 @@ +package electroblob.wizardry.spell; + +import com.google.common.collect.HashMultimap; +import com.google.common.collect.ImmutableMap; +import com.google.common.collect.Multimap; +import electroblob.wizardry.Wizardry; +import electroblob.wizardry.data.IVariable; +import electroblob.wizardry.data.IVariable.Variable; +import electroblob.wizardry.data.Persistence; +import electroblob.wizardry.data.WizardData; +import electroblob.wizardry.entity.living.*; +import electroblob.wizardry.entity.projectile.*; +import electroblob.wizardry.integration.DamageSafetyChecker; +import electroblob.wizardry.packet.PacketControlInput; +import electroblob.wizardry.packet.PacketPossession; +import electroblob.wizardry.packet.WizardryPacketHandler; +import electroblob.wizardry.registry.Spells; +import electroblob.wizardry.registry.WizardryItems; +import electroblob.wizardry.util.ParticleBuilder; +import electroblob.wizardry.util.ParticleBuilder.Type; +import electroblob.wizardry.util.SpellModifiers; +import electroblob.wizardry.util.WizardryUtilities; +import net.minecraft.enchantment.Enchantment; +import net.minecraft.enchantment.EnchantmentHelper; +import net.minecraft.entity.*; +import net.minecraft.entity.ai.EntityAIAttackMelee; +import net.minecraft.entity.ai.attributes.AttributeModifier; +import net.minecraft.entity.ai.attributes.IAttribute; +import net.minecraft.entity.ai.attributes.IAttributeInstance; +import net.minecraft.entity.monster.*; +import net.minecraft.entity.passive.EntityChicken; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.entity.player.EntityPlayerMP; +import net.minecraft.entity.projectile.EntityPotion; +import net.minecraft.entity.projectile.EntitySnowball; +import net.minecraft.init.Enchantments; +import net.minecraft.init.Items; +import net.minecraft.init.PotionTypes; +import net.minecraft.inventory.EntityEquipmentSlot; +import net.minecraft.item.EnumAction; +import net.minecraft.item.ItemBow; +import net.minecraft.item.ItemStack; +import net.minecraft.nbt.NBTTagList; +import net.minecraft.potion.PotionEffect; +import net.minecraft.potion.PotionUtils; +import net.minecraft.util.*; +import net.minecraft.util.math.AxisAlignedBB; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.Vec3d; +import net.minecraft.util.text.TextComponentTranslation; +import net.minecraft.world.World; +import net.minecraftforge.common.util.Constants.NBT; +import net.minecraftforge.event.entity.item.ItemTossEvent; +import net.minecraftforge.event.entity.living.LivingAttackEvent; +import net.minecraftforge.event.entity.living.LivingDamageEvent; +import net.minecraftforge.event.entity.living.LivingDeathEvent; +import net.minecraftforge.event.entity.living.LivingSetAttackTargetEvent; +import net.minecraftforge.event.entity.player.AttackEntityEvent; +import net.minecraftforge.event.entity.player.EntityItemPickupEvent; +import net.minecraftforge.event.entity.player.PlayerInteractEvent; +import net.minecraftforge.event.world.BlockEvent; +import net.minecraftforge.fml.common.Mod; +import net.minecraftforge.fml.common.eventhandler.EventPriority; +import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; +import net.minecraftforge.fml.common.gameevent.PlayerEvent; +import net.minecraftforge.fml.common.gameevent.TickEvent; + +import javax.annotation.Nullable; +import java.util.HashMap; +import java.util.Map; +import java.util.UUID; +import java.util.function.BiConsumer; +import java.util.function.Function; + +@Mod.EventBusSubscriber +public class Possession extends SpellRay { + + /** A {@code ResourceLocation} representing the shader file used when possessing an entity. */ + public static final ResourceLocation SHADER = new ResourceLocation(Wizardry.MODID, "shaders/post/possession.json"); + + /** The NBT tag name for storing the possessing entity's UUID in the target's tag compound. */ + public static final String NBT_KEY = "possessor"; + /** The NBT tag name for storing the possessor's previous inventory in their tag compound. */ + public static final String INVENTORY_NBT_KEY = "prevInventory"; + + /** The health (in half-hearts) below or equal to which the possessor will automatically stop possessing. */ + public static final String CRITICAL_HEALTH = "critical_health"; + + private static final int PROJECTILE_COOLDOWN = 30; + + public static final IVariable TIMER_KEY = new Variable(Persistence.DIMENSION_CHANGE).withTicker(Possession::update); + public static final IVariable POSSESSEE_KEY = new Variable<>(Persistence.DIMENSION_CHANGE); + public static final IVariable SHOOT_COOLDOWN_KEY = new Variable(Persistence.DIMENSION_CHANGE).withTicker((p, n) -> Math.max(n-1, 0)); + + private static final Multimap, BiConsumer> abilities = HashMultimap.create(); + private static final Map, Function> projectiles = new HashMap<>(); + + private static final Map INHERITED_ATTRIBUTES; + + static { + + INHERITED_ATTRIBUTES = ImmutableMap.of( + SharedMonsterAttributes.MOVEMENT_SPEED, UUID.fromString("f65cfcaf-e7ec-4dfb-aa6c-711735d007e3"), + SharedMonsterAttributes.ATTACK_DAMAGE, UUID.fromString("ab67c89e-74a5-4e27-9621-40bffb4f7a03"), + SharedMonsterAttributes.KNOCKBACK_RESISTANCE, UUID.fromString("05529535-9bcf-42bb-8822-45f5ce6a8f08")); + + addAbility(EntitySpider.class, (spider, player) -> { if(player.collidedHorizontally) player.motionY = 0.2; }); + addAbility(EntityChicken.class, (chicken, player) -> { if(!player.onGround && player.motionY < 0) player.motionY *= 0.6D; }); + addAbility(EntityLiving.class, (entity, player) -> { if(!entity.isImmuneToFire() && player.isBurning()) player.extinguish(); }); + + addProjectile(EntitySnowman.class, EntitySnowball::new); // Woooo snowballs! + addProjectile(EntityBlaze.class, EntityMagicFireball::new); // Ugh normal fireballs don't fit so let's just use mine! + addProjectile(EntityGhast.class, EntityLargeMagicFireball::new); + addProjectile(EntityIceWraith.class, EntityIceShard::new); + addProjectile(EntityShadowWraith.class, EntityDarknessOrb::new); + addProjectile(EntityStormElemental.class, EntityLightningDisc::new); + addProjectile(EntityWitch.class, EntityPotion::new); + + } + + public Possession(){ + super("possession", false, EnumAction.NONE); + addProperties(EFFECT_DURATION, CRITICAL_HEALTH); + } + + @Override public boolean canBeCastByNPCs() { return false; } + @Override public boolean canBeCastByDispensers() { return false; } + + @Override + public boolean requiresPacket(){ + return false; // Has its own packet + } + + @Override + protected SoundEvent[] createSounds(){ + return createSoundsWithSuffixes("possess", "end"); + } + + @Override + public boolean cast(World world, EntityPlayer caster, EnumHand hand, int ticksInUse, SpellModifiers modifiers){ + + Vec3d look = caster.getLookVec(); + Vec3d origin = new Vec3d(caster.posX, caster.getEntityBoundingBox().minY + caster.getEyeHeight() - Y_OFFSET, caster.posZ); + + if(!shootSpell(world, origin, look, caster, ticksInUse, modifiers)) return false; + + if(casterSwingsArm(world, caster, hand, ticksInUse, modifiers)) caster.swingArm(hand); + this.playSound(world, caster, ticksInUse, -1, modifiers, "possess"); // TODO: There must be a better way... + return true; + } + + @Override + protected boolean onEntityHit(World world, Entity target, Vec3d hit, EntityLivingBase caster, Vec3d origin, int ticksInUse, + SpellModifiers modifiers){ + + if(target instanceof EntityLiving && caster instanceof EntityPlayer && !isPossessing((EntityPlayer)caster)){ + + EntityPlayer player = (EntityPlayer)caster; + + if(!player.isCreative() && player.getHealth() <= getProperty(CRITICAL_HEALTH).floatValue()){ + player.sendStatusMessage(new TextComponentTranslation( + "spell." + this.getRegistryName() + ".insufficienthealth"), true); + return false; + } + + if(!world.isRemote){ + int duration = (int)(getProperty(EFFECT_DURATION).floatValue() * modifiers.get(WizardryItems.duration_upgrade)); + if(possess(player, (EntityLiving)target, duration)){ + return true; + } + } + } + + return false; + } + + @Override + protected boolean onBlockHit(World world, BlockPos pos, EnumFacing side, Vec3d hit, EntityLivingBase caster, Vec3d origin, int ticksInUse, + SpellModifiers modifiers){ + return false; + } + + @Override + protected boolean onMiss(World world, EntityLivingBase caster, Vec3d origin, Vec3d direction, int ticksInUse, SpellModifiers modifiers){ + return false; + } + + // ================================================ Helper methods ================================================ + + /** + * Causes the given player to start possessing the given target for the given duration, and sets all relevant data + * for both entities accordingly. Also takes care of sending packets to update clients. + * @param possessor The player doing the possessing. + * @param target The entity being possessed. + * @param duration The number of ticks for which the possession should last. Pass in a negative integer to make the + * possession last indefinitely (until manually ended with the dismount key). + * @return True if the possession succeeded, false if for some reason it did not (only happens if the player's + * {@link WizardData} is null). + */ + public boolean possess(EntityPlayer possessor, EntityLiving target, int duration){ + + if(WizardData.get(possessor) != null){ + + WizardData.get(possessor).setVariable(POSSESSEE_KEY, target); + WizardData.get(possessor).setVariable(TIMER_KEY, duration); + + possessor.setPositionAndRotation(target.posX, target.posY, target.posZ, target.rotationYaw, target.rotationPitch); + possessor.eyeHeight = target.getEyeHeight(); + setSize(possessor, target.width, target.height); + + target.setDead(); + target.setNoAI(true); + target.setAttackTarget(null); + + // Attributes + + if(target instanceof EntityFlying || target instanceof net.minecraft.entity.passive.EntityFlying){ + possessor.capabilities.allowFlying = true; + possessor.capabilities.isFlying = true; + } + + // Apply attribute modifiers which change the player's attribute value to the target's value + // Uses predefined UUIDs so we can easily remove them later + attributes: + for(IAttribute attribute : INHERITED_ATTRIBUTES.keySet()){ + + IAttributeInstance instance = target.getAttributeMap().getAttributeInstance(attribute); + + if(instance != null){ + + double targetValue = instance.getAttributeValue(); + double currentValue = possessor.getAttributeMap().getAttributeInstance(attribute).getAttributeValue(); + // Don't ask me why, but the player's base movement speed seems to be 0.1 + if(attribute == SharedMonsterAttributes.MOVEMENT_SPEED) currentValue /= possessor.capabilities.getWalkSpeed(); + + for(EntityEquipmentSlot slot : EntityEquipmentSlot.values()){ + if(target.getItemStackFromSlot(slot).getAttributeModifiers(slot).containsKey(attribute.getName())){ + // If the mob has equipment, use the modifiers for that equipment instead of the mob's normal ones + // Not doing this results in the player being able to one-hit most mobs when possessing a zombie pigman! + continue attributes; + } + } + + possessor.getAttributeMap().getAttributeInstance(attribute).applyModifier(new AttributeModifier( + INHERITED_ATTRIBUTES.get(attribute), "possessionModifier", targetValue / currentValue, + WizardryUtilities.Operations.MULTIPLY_FLAT)); + } + } + + if(possessor.world.isRemote){ + // Shaders and effects + if(Wizardry.settings.useShaders) net.minecraft.client.Minecraft.getMinecraft().entityRenderer.loadShader(SHADER); + electroblob.wizardry.client.WizardryClientEventHandler.playBlinkEffect(); // Looks quite nice... + + }else{ + + // Targeting + + for(EntityLiving creature : WizardryUtilities.getEntitiesWithinRadius(16, possessor.posX, + possessor.posY, possessor.posZ, possessor.world, EntityLiving.class)){ + // Mobs are dumb, if a player possesses something they're like "Huh?! Where'd you go?" + // Of course, this won't last long if the player attacks them, since they'll revenge-target them + if(creature.getAttackTarget() == possessor && !creature.canAttackClass(target.getClass())) + creature.setAttackTarget(null); + } + + // Inventory and items + + if(possessor.getEntityData() != null){ + possessor.getEntityData().setTag(INVENTORY_NBT_KEY, possessor.inventory.writeToNBT(new NBTTagList())); + } + + possessor.inventory.clear(); + possessor.inventoryContainer.detectAndSendChanges(); + + ItemStack stack = target.getHeldItemMainhand().copy(); + + if(target instanceof EntityEnderman && ((EntityEnderman)target).getHeldBlockState() != null){ + stack = new ItemStack(((EntityEnderman)target).getHeldBlockState().getBlock()); + + }else if(stack.getItem() instanceof ItemBow){ + Map enchantments = EnchantmentHelper.getEnchantments(stack); + enchantments.put(Enchantments.INFINITY, 1); + EnchantmentHelper.setEnchantments(enchantments, stack); + ItemStack arrow = new ItemStack(Items.ARROW); + if(target instanceof EntityStray || target instanceof EntityStrayMinion){ + arrow = new ItemStack(Items.TIPPED_ARROW); + PotionUtils.addPotionToItemStack(arrow, PotionTypes.SLOWNESS); + } + possessor.setHeldItem(EnumHand.OFF_HAND, arrow); + } + + possessor.setItemStackToSlot(EntityEquipmentSlot.MAINHAND, stack); + + // Packets + + WizardryPacketHandler.net.sendToAllTracking(new PacketPossession.Message(possessor, target, duration), possessor); + if(possessor instanceof EntityPlayerMP){ + WizardryPacketHandler.net.sendTo(new PacketPossession.Message(possessor, target, duration), (EntityPlayerMP)possessor); + } + } + + return true; + } + + return false; + } + + /** Causes the given player to stop possessing their current possessee, if any, and resets all relevant data for + * both entities. Also takes care of sending packets to update clients. */ + public void endPossession(EntityPlayer player){ + + // Reverts the possessed entity back to normal + + EntityLiving victim = getPossessee(player); + + if(victim != null){ + + victim.isDead = false; + victim.setNoAI(false); + victim.setPosition(player.posX, player.posY, player.posZ); + if(!player.world.isRemote) player.world.spawnEntity(victim); + + for(PotionEffect effect : player.getActivePotionEffects()){ + victim.addPotionEffect(effect); + } + } + + // Reverts the player back to normal + + player.clearActivePotions(); + + player.eyeHeight = player.getDefaultEyeHeight(); // How convenient! + + if(WizardData.get(player) != null){ + WizardData.get(player).setVariable(TIMER_KEY, 0); + WizardData.get(player).setVariable(POSSESSEE_KEY, null); + } + + if(!player.capabilities.isCreativeMode){ + player.capabilities.allowFlying = false; + player.capabilities.isFlying = false; + } + + if(player.world.isRemote){ + net.minecraft.client.Minecraft.getMinecraft().entityRenderer.stopUseShader(); + electroblob.wizardry.client.WizardryClientEventHandler.playBlinkEffect(); // Looks quite nice... + } + + for(IAttribute attribute : INHERITED_ATTRIBUTES.keySet()){ + player.getAttributeMap().getAttributeInstance(attribute).removeModifier(INHERITED_ATTRIBUTES.get(attribute)); + } + + if(player instanceof EntityPlayerMP){ + + player.inventory.clear(); + + if(player.getEntityData() != null){ + player.inventory.readFromNBT(player.getEntityData().getTagList(INVENTORY_NBT_KEY, NBT.TAG_COMPOUND)); + } + + player.inventoryContainer.detectAndSendChanges(); + } + + this.playSound(player.world, player, 0, -1, null, "end"); + + if(!player.world.isRemote && player instanceof EntityPlayerMP){ + WizardryPacketHandler.net.sendToAllTracking(new PacketPossession.Message(player, null, 0), player); + WizardryPacketHandler.net.sendTo(new PacketPossession.Message(player, null, 0), (EntityPlayerMP)player); + } + } + + /** Returns the {@code EntityLiving} that is currently being possessed by the given player, or null if the player is + * not currently possessing an entity. */ + @Nullable + public static EntityLiving getPossessee(EntityPlayer player){ + return WizardData.get(player) == null ? null : WizardData.get(player).getVariable(POSSESSEE_KEY); + } + + /** Returns true if the given player is currently possessing an entity, false otherwise. Just a shortcut for + * {@code Possession.getPossessee(player) != null}. */ + public static boolean isPossessing(EntityPlayer player){ + return getPossessee(player) != null; + } + + private static int update(EntityPlayer player, Integer possessionTimer){ + + if(possessionTimer == null) possessionTimer = 0; + + if(possessionTimer > 0){ + + if(isPossessing(player) && !player.isSneaking()){ + + possessionTimer--; + + if(player.world.isRemote){ + ParticleBuilder.create(Type.DARK_MAGIC, player).clr(0.1f, 0, 0.3f).spawn(player.world); + // TODO: This (and a few other similar uses) needs ClientProxy-ing. + if(!net.minecraft.client.Minecraft.getMinecraft().entityRenderer.isShaderActive()) + if(Wizardry.settings.useShaders) net.minecraft.client.Minecraft.getMinecraft().entityRenderer.loadShader(SHADER); + } + + }else{ + ((Possession)Spells.possession).endPossession(player); + return 0; + } + + }else if(isPossessing(player)){ + ((Possession)Spells.possession).endPossession(player); + } + + return possessionTimer; + } + + /** Adds the given {@link BiConsumer} to the list of abilities. An ability is an entity-specific action or + * effect that happens when a certain type of entity is possessed. For example, spiders can climb walls, endermen + * can pick up blocks, creepers explode, etc. Other mods may use this method to */ + public static void addAbility(Class entityType, BiConsumer ability){ + abilities.put(entityType, ability); + } + + @SuppressWarnings("unchecked") // Guess what? Type erasure again! + private static void performAbilities(EntityLiving entity, EntityPlayer player){ + // Now we have a type parameter T to work with we can ram the entity into the consumer without a compiler error + for(Class entityType : abilities.keySet()){ + if(entityType.isAssignableFrom(entity.getClass())){ + abilities.get(entityType).forEach(a -> ((BiConsumer)a).accept((T)entity, player)); + } + } + } + + /** Adds the given factory to the list of projectiles. When a player right-clicks while possessing an entity of the + * given type, the given projectile factory will be invoked to create a projectile, which is then aimed and spawned. */ + public static void addProjectile(Class entityType, Function factory){ + projectiles.put(entityType, factory); + } + + /** Copied from Entity#setSize, with the call to move(...) removed. This is presumably also better than reflecting + * into Entity#setSize, which is protected. */ + private static void setSize(Entity entity, float width, float height){ + + if(width != entity.width || height != entity.height){ + + entity.width = width; + entity.height = height; + + double halfWidth = (double)width / 2.0D; + entity.setEntityBoundingBox(new AxisAlignedBB(entity.posX - halfWidth, entity.posY, entity.posZ - halfWidth, entity.posX + halfWidth, entity.posY + (double)entity.height, entity.posZ + halfWidth)); + } + } + + // ================================================ Event Handlers ================================================ + // We got every kind of event handler goin', folks! + + @SubscribeEvent + public static void onPlayerTickEvent(TickEvent.PlayerTickEvent event){ + + if(event.phase == TickEvent.Phase.START){ + + EntityLiving possessee = getPossessee(event.player); + + if(possessee != null){ + // Updating these to the player's variables won't have an effect on player movement, but it will + // affect various bits of mob-specific logic + possessee.setPosition(event.player.posX, event.player.posY, event.player.posZ); + possessee.motionX = event.player.motionX; + possessee.motionY = event.player.motionY; + possessee.motionZ = event.player.motionZ; + possessee.onGround = event.player.onGround; + + possessee.onUpdate(); // Event though it's not in the world, it still needs updating + possessee.ticksExisted++; // Normally gets updated from World + + if(possessee.getHealth() <= 0){ + ((Possession)Spells.possession).endPossession(event.player); + } + + performAbilities(possessee, event.player); + } + } + + // Right at the end of EntityPlayer#onUpdate() it calls EntityPlayer#updateSize(), which resets the player's + // size (and is also where this event is fired from, oddly enough) ... but not on my watch! + if(event.phase == TickEvent.Phase.END){ + EntityLiving possessee = getPossessee(event.player); + if(possessee != null){ + setSize(event.player, possessee.width, possessee.height); + } + } + } + + // When possessing, attacks are diverted to the possessed entity for armour, immunity, resistance calculations + // and so on, then when the damage is actually applied, the player is also damaged via onLivingDamageEvent below + @SubscribeEvent(priority = EventPriority.HIGH) + public static void onLivingAttackEvent(LivingAttackEvent event){ + + if(event.getEntity() instanceof EntityPlayer && event.getSource() != DamageSource.OUT_OF_WORLD){ + + EntityLiving possessee = getPossessee((EntityPlayer)event.getEntity()); + + if(possessee != null){ + DamageSafetyChecker.attackEntitySafely(possessee, event.getSource(), event.getAmount(), event.getSource().getDamageType()); + event.setCanceled(true); + } + } + } + + // LivingDamageEvent used in preference to LivingHurtEvent because the player is 'inside' the possessed entity, so + // any damage should come through that entity (and any armour, potions, enchantments etc. it has) first. + @SubscribeEvent + public static void onLivingDamageEvent(LivingDamageEvent event){ + + for(EntityPlayer player : event.getEntity().world.playerEntities){ + + EntityLiving possessee = getPossessee(player); + + if(possessee == event.getEntity()){ + // Possessors take half of all damage taken by the entity they are possessing. If the possessor receives + // fatal/critical damage (i.e. damage that takes them to half a heart or less), their health is reset to half + // a heart and the possession ends. + if(!player.capabilities.isCreativeMode){ + // TODO: Make this a proper DamageSource? + DamageSafetyChecker.attackEntitySafely(player, DamageSource.OUT_OF_WORLD, event.getAmount() / 2, + DamageSource.OUT_OF_WORLD.getDamageType()); + } + + if(player.getHealth() <= Spells.possession.getProperty(CRITICAL_HEALTH).floatValue()){ + player.setHealth(Spells.possession.getProperty(CRITICAL_HEALTH).floatValue()); + ((Possession)Spells.possession).endPossession(player); + } + } + } + } + + // Prevents possessing players from interacting with blocks and controls projectile shooting + @SubscribeEvent + public static void onPlayerInteractEvent(PlayerInteractEvent event){ + + if(event instanceof PlayerInteractEvent.RightClickItem) return; // Can always do this + + EntityLiving possessee = getPossessee(event.getEntityPlayer()); + + if(possessee != null){ + + // Let endermen interact with blocks + if(possessee instanceof EntityEnderman && ( + (event instanceof PlayerInteractEvent.RightClickBlock && ((EntityEnderman)possessee).getHeldBlockState() != null) + || (event instanceof PlayerInteractEvent.LeftClickBlock && ((EntityEnderman)possessee).getHeldBlockState() == null))) + return; + + if(WizardData.get(event.getEntityPlayer()) != null && event.getWorld().isRemote + && (event instanceof PlayerInteractEvent.RightClickEmpty + || event instanceof PlayerInteractEvent.EntityInteract + || event instanceof PlayerInteractEvent.RightClickBlock)){ + + Integer cooldown = WizardData.get(event.getEntityPlayer()).getVariable(SHOOT_COOLDOWN_KEY); + + if(cooldown == null || cooldown == 0){ + + WizardryPacketHandler.net.sendToServer(new PacketControlInput.Message(PacketControlInput.ControlType.POSSESSION_PROJECTILE)); + WizardData.get(event.getEntityPlayer()).setVariable(SHOOT_COOLDOWN_KEY, PROJECTILE_COOLDOWN); + + if(possessee instanceof EntityLightningWraith){ + Spells.arc.cast(event.getWorld(), event.getEntityPlayer(), EnumHand.MAIN_HAND, 0, new SpellModifiers()); + } + + if(possessee instanceof EntityCreeper){ + ((EntityCreeper)possessee).ignite(); + } + } + } + + if(event.isCancelable()) event.setCanceled(true); + } + } + + /** Called via packets to shoot a projectile if the entity currently possessed by the given player can do so. */ + public static void shootProjectile(EntityPlayer possessor){ + + if(WizardData.get(possessor) != null){ + + Integer cooldown = WizardData.get(possessor).getVariable(SHOOT_COOLDOWN_KEY); + + if(cooldown == null || cooldown == 0){ + + EntityLiving possessee = getPossessee(possessor); + + if(possessee != null){ + + if(possessee instanceof EntityLightningWraith){ + Spells.arc.cast(possessor.world, possessor, EnumHand.MAIN_HAND, 0, new SpellModifiers()); + } + + if(possessee instanceof EntityCreeper){ + ((Possession)Spells.possession).endPossession(possessor); + ((EntityCreeper)possessee).ignite(); // Aaaaaaand.... RUN! + } + + Function factory = projectiles.get(possessee.getClass()); + + if(factory != null){ + + IProjectile projectile = factory.apply(possessor.world); + Vec3d look = possessor.getLookVec(); + ((Entity)projectile).setPosition(possessor.posX + look.x, possessor.posY + possessor.getEyeHeight() + look.y, possessor.posZ + look.z); + projectile.shoot(look.x, look.y, look.z, 1.6f, WizardryUtilities.getDefaultAimingError(possessor.world.getDifficulty())); + + if(projectile instanceof EntityMagicProjectile) ((EntityMagicProjectile)projectile).setCaster(possessor); + else if(projectile instanceof EntityMagicArrow) ((EntityMagicArrow)projectile).setCaster(possessor); + + possessor.world.spawnEntity((Entity)projectile); + + } + + WizardData.get(possessor).setVariable(SHOOT_COOLDOWN_KEY, PROJECTILE_COOLDOWN); + } + } + } + } + + @SubscribeEvent + public static void onLivingSetAttackTargetEvent(LivingSetAttackTargetEvent event){ // Not fired for revenge-targeting + if(event.getTarget() instanceof EntityPlayer && event.getEntityLiving() instanceof EntityLiving){ + EntityLiving possessee = getPossessee((EntityPlayer)event.getTarget()); + EntityLiving attacker = (EntityLiving)event.getEntityLiving(); + if(possessee != null && !attacker.canAttackClass(possessee.getClass())){ + event.setCanceled(true); // Mobs can't target a player possessing an entity they don't normally attack + } + } + } + + // With these two methods I'm pretty sure it's watertight + + @SubscribeEvent + public static void onLivingDeathEvent(LivingDeathEvent event){ + if(event.getEntity() instanceof EntityPlayer && isPossessing((EntityPlayer)event.getEntity())){ + ((Possession)Spells.possession).endPossession((EntityPlayer)event.getEntity()); // Just in case, to make sure the player drops their items + } + } + + @SubscribeEvent + public static void onPlayerLoggedOutEvent(PlayerEvent.PlayerLoggedOutEvent event){ + if(isPossessing(event.player)) ((Possession)Spells.possession).endPossession(event.player); + } + + @SubscribeEvent + public static void onBlockBreakEvent(BlockEvent.BreakEvent event){ + + EntityLiving possessee = getPossessee(event.getPlayer()); + + if(possessee instanceof EntityEnderman){ + if(((EntityEnderman)possessee).getHeldBlockState() == null){ + ((EntityEnderman)possessee).setHeldBlockState(event.getState()); + event.getPlayer().setHeldItem(EnumHand.MAIN_HAND, new ItemStack(event.getState().getBlock())); + event.setExpToDrop(0); + event.getWorld().setBlockToAir(event.getPos()); // Remove block before it can drop + }else{ + event.setCanceled(true); + } + } + } + + @SubscribeEvent + public static void onBlockPlaceEvent(BlockEvent.PlaceEvent event){ + + EntityLiving possessee = getPossessee(event.getPlayer()); + + if(possessee instanceof EntityEnderman){ + if(((EntityEnderman)possessee).getHeldBlockState() == event.getState()){ + ((EntityEnderman)possessee).setHeldBlockState(null); + }else{ + event.setCanceled(true); + } + } + } + + @SubscribeEvent + public static void onEntityItemPickupEvent(EntityItemPickupEvent event){ // Why are there two item pickup events? + + EntityLiving possessee = getPossessee(event.getEntityPlayer()); + + if(possessee != null){ + + if(possessee.canPickUpLoot() && possessee.getHeldItemMainhand().isEmpty()){ + possessee.setHeldItem(EnumHand.MAIN_HAND, event.getItem().getItem()); + }else{ + event.setCanceled(true); + } + } + } + + @SubscribeEvent + static void onItemTossEvent(ItemTossEvent event){ + if(isPossessing(event.getPlayer())){ // Can't drop items while possessing + event.setCanceled(true); + event.getPlayer().inventory.addItemStackToInventory(event.getEntityItem().getItem()); + } + } + + @SubscribeEvent + public static void onAttackEntityEvent(AttackEntityEvent event){ + + EntityLiving possessee = getPossessee(event.getEntityPlayer()); + + if(possessee == null) return; + + if(possessee instanceof EntityCreeper){ + event.setCanceled(true); // Why do creepers have a melee AI?! + }else if(possessee.tasks.taskEntries.stream().noneMatch(t -> t.action instanceof EntityAIAttackMelee)){ + event.setCanceled(true); // Can't melee with a non-melee mob + } + } + +} diff --git a/src/main/java/electroblob/wizardry/spell/RayOfPurification.java b/src/main/java/electroblob/wizardry/spell/RayOfPurification.java new file mode 100644 index 00000000..4367fd39 --- /dev/null +++ b/src/main/java/electroblob/wizardry/spell/RayOfPurification.java @@ -0,0 +1,103 @@ +package electroblob.wizardry.spell; + +import electroblob.wizardry.registry.WizardryItems; +import electroblob.wizardry.util.MagicDamage; +import electroblob.wizardry.util.MagicDamage.DamageType; +import electroblob.wizardry.util.ParticleBuilder; +import electroblob.wizardry.util.ParticleBuilder.Type; +import electroblob.wizardry.util.SpellModifiers; +import electroblob.wizardry.util.WizardryUtilities; +import net.minecraft.entity.Entity; +import net.minecraft.entity.EntityLivingBase; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.init.MobEffects; +import net.minecraft.item.EnumAction; +import net.minecraft.potion.PotionEffect; +import net.minecraft.util.EnumFacing; +import net.minecraft.util.SoundEvent; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.MathHelper; +import net.minecraft.util.math.Vec3d; +import net.minecraft.util.text.TextComponentTranslation; +import net.minecraft.world.World; + +public class RayOfPurification extends SpellRay { + + /** The number by which this spell's damage is multiplied for undead entities. */ + public static final String UNDEAD_DAMAGE_MULTIPLIER = "undead_damage_multiplier"; + + public RayOfPurification(){ + super("ray_of_purification", true, EnumAction.NONE); + addProperties(DAMAGE, EFFECT_DURATION, BURN_DURATION, UNDEAD_DAMAGE_MULTIPLIER); + } + + // The following three methods serve as a good example of how to implement continuous spell sounds (hint: it's easy) + + @Override + protected SoundEvent[] createSounds(){ + return this.createContinuousSpellSounds(); + } + + @Override + protected void playSound(World world, EntityLivingBase entity, int ticksInUse, int duration, SpellModifiers modifiers, String... sounds){ + this.playSoundLoop(world, entity, ticksInUse); + } + + @Override + protected void playSound(World world, double x, double y, double z, int ticksInUse, int duration, SpellModifiers modifiers, String... sounds){ + this.playSoundLoop(world, x, y, z, ticksInUse, duration); + } + + @Override + protected boolean onEntityHit(World world, Entity target, Vec3d hit, EntityLivingBase caster, Vec3d origin, int ticksInUse, SpellModifiers modifiers){ + + if(WizardryUtilities.isLiving(target)){ + + if(MagicDamage.isEntityImmune(DamageType.RADIANT, target)){ + if(!world.isRemote && ticksInUse == 1 && caster instanceof EntityPlayer) ((EntityPlayer)caster) + .sendStatusMessage(new TextComponentTranslation("spell.resist", target.getName(), + this.getNameForTranslationFormatted()), true); + }else{ + + float damage = getProperty(DAMAGE).floatValue() * modifiers.get(SpellModifiers.POTENCY); + // Fire + if(((EntityLivingBase)target).isEntityUndead()){ + target.setFire((int)(getProperty(BURN_DURATION).floatValue() * modifiers.get(WizardryItems.duration_upgrade))); + damage *= getProperty(UNDEAD_DAMAGE_MULTIPLIER).floatValue(); + } + // Damage + WizardryUtilities.attackEntityWithoutKnockback(target, + MagicDamage.causeDirectMagicDamage(caster, DamageType.RADIANT), damage); + // Blindness + ((EntityLivingBase)target).addPotionEffect(new PotionEffect(MobEffects.BLINDNESS, + (int)(getProperty(EFFECT_DURATION).floatValue() * modifiers.get(WizardryItems.duration_upgrade)))); + } + } + + return true; + } + + @Override + protected boolean onBlockHit(World world, BlockPos pos, EnumFacing side, Vec3d hit, EntityLivingBase caster, Vec3d origin, int ticksInUse, SpellModifiers modifiers){ + return false; + } + + @Override + protected boolean onMiss(World world, EntityLivingBase caster, Vec3d origin, Vec3d direction, int ticksInUse, SpellModifiers modifiers){ + return true; + } + + @Override + protected void spawnParticleRay(World world, Vec3d origin, Vec3d direction, EntityLivingBase caster, double distance){ + + if(caster != null){ + ParticleBuilder.create(Type.BEAM).entity(caster).pos(origin.subtract(caster.getPositionVector())) + .length(distance).clr(1, 0.6f + 0.3f * world.rand.nextFloat(), 0.2f) + .scale(MathHelper.sin(world.getTotalWorldTime() * 0.2f) * 0.1f + 1.4f).spawn(world); + }else{ + ParticleBuilder.create(Type.BEAM).pos(origin).target(origin.add(direction.scale(distance))) + .clr(1, 0.6f + 0.3f * world.rand.nextFloat(), 0.2f) + .scale(MathHelper.sin(world.getTotalWorldTime() * 0.2f) * 0.1f + 1.4f).spawn(world); + } + } +} diff --git a/src/main/java/electroblob/wizardry/spell/RemoveCurse.java b/src/main/java/electroblob/wizardry/spell/RemoveCurse.java new file mode 100644 index 00000000..927d0b3a --- /dev/null +++ b/src/main/java/electroblob/wizardry/spell/RemoveCurse.java @@ -0,0 +1,53 @@ +package electroblob.wizardry.spell; + +import electroblob.wizardry.potion.Curse; +import electroblob.wizardry.util.ParticleBuilder; +import electroblob.wizardry.util.ParticleBuilder.Type; +import electroblob.wizardry.util.SpellModifiers; +import net.minecraft.entity.EntityLivingBase; +import net.minecraft.potion.PotionEffect; +import net.minecraft.world.World; + +public class RemoveCurse extends SpellBuff { + + public RemoveCurse(){ + super("remove_curse", 1, 1, 0.3f); + this.soundValues(0.7f, 1.2f, 0.4f); + } + + @Override + protected boolean applyEffects(EntityLivingBase caster, SpellModifiers modifiers){ + + if(!caster.getActivePotionEffects().isEmpty()){ + + boolean flag = false; + + for(PotionEffect effect : caster.getActivePotionEffects()){ + // The PotionEffect version (as opposed to Potion) does not call cleanup callbacks + if(effect.getPotion() instanceof Curse){ + caster.removePotionEffect(effect.getPotion()); + flag = true; + } + } + + return flag; + } + + return false; + } + + @Override + protected void spawnParticles(World world, EntityLivingBase caster, SpellModifiers modifiers){ + + super.spawnParticles(world, caster, modifiers); + + for(int i = 0; i < particleCount*2; i++){ + double x = caster.posX + world.rand.nextDouble() * 2 - 1; + double y = caster.getEntityBoundingBox().minY + caster.getEyeHeight() - 0.5 + world.rand.nextDouble(); + double z = caster.posZ + world.rand.nextDouble() * 2 - 1; + ParticleBuilder.create(Type.SPARKLE).pos(x, y, z).vel(0, 0.14, 0).clr(0x0f001b) + .time(20 + world.rand.nextInt(12)).spawn(world); + ParticleBuilder.create(Type.DARK_MAGIC).pos(x, y, z).clr(0x0f001b).spawn(world); + } + } +} diff --git a/src/main/java/electroblob/wizardry/spell/ReplenishHunger.java b/src/main/java/electroblob/wizardry/spell/ReplenishHunger.java index d5aa5028..f2ec06c2 100644 --- a/src/main/java/electroblob/wizardry/spell/ReplenishHunger.java +++ b/src/main/java/electroblob/wizardry/spell/ReplenishHunger.java @@ -1,9 +1,5 @@ package electroblob.wizardry.spell; -import electroblob.wizardry.constants.Element; -import electroblob.wizardry.constants.SpellType; -import electroblob.wizardry.constants.Tier; -import electroblob.wizardry.registry.WizardrySounds; import electroblob.wizardry.util.SpellModifiers; import net.minecraft.entity.EntityLivingBase; import net.minecraft.entity.player.EntityPlayer; @@ -12,9 +8,13 @@ import net.minecraft.world.World; public class ReplenishHunger extends SpellBuff { + public static final String HUNGER_POINTS = "hunger_points"; + public static final String SATURATION_MODIFIER = "saturation_modifier"; + public ReplenishHunger(){ - super("replenish_hunger", Tier.APPRENTICE, Element.HEALING, SpellType.BUFF, 10, 30, WizardrySounds.SPELL_HEAL, 1, 0.7f, 0.3f); + super("replenish_hunger", 1, 0.7f, 0.3f); this.soundValues(0.7f, 1.2f, 0.4f); + addProperties(HUNGER_POINTS, SATURATION_MODIFIER); } @Override public boolean canBeCastByNPCs(){ return false; } @@ -28,9 +28,9 @@ public class ReplenishHunger extends SpellBuff { public boolean cast(World world, EntityPlayer caster, EnumHand hand, int ticksInUse, SpellModifiers modifiers){ if(caster.getFoodStats().needFood()){ - int foodAmount = (int)(4 * modifiers.get(SpellModifiers.POTENCY)); + int foodAmount = (int)(getProperty(HUNGER_POINTS).floatValue() * modifiers.get(SpellModifiers.POTENCY)); // Fixed issue #6: Changed to addStats, since setFoodLevel is client-side only - caster.getFoodStats().addStats(foodAmount, foodAmount * 0.1f); + caster.getFoodStats().addStats(foodAmount, getProperty(SATURATION_MODIFIER).floatValue()); return super.cast(world, caster, hand, ticksInUse, modifiers); } diff --git a/src/main/java/electroblob/wizardry/spell/Resurrection.java b/src/main/java/electroblob/wizardry/spell/Resurrection.java new file mode 100644 index 00000000..1809e07b --- /dev/null +++ b/src/main/java/electroblob/wizardry/spell/Resurrection.java @@ -0,0 +1,111 @@ +package electroblob.wizardry.spell; + +import electroblob.wizardry.data.WizardData; +import electroblob.wizardry.item.ISpellCastingItem; +import electroblob.wizardry.packet.PacketResurrection; +import electroblob.wizardry.packet.WizardryPacketHandler; +import electroblob.wizardry.registry.Spells; +import electroblob.wizardry.registry.WizardryItems; +import electroblob.wizardry.util.ParticleBuilder; +import electroblob.wizardry.util.SpellModifiers; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.entity.player.EntityPlayerMP; +import net.minecraft.item.EnumAction; +import net.minecraft.item.ItemStack; +import net.minecraft.util.EnumHand; +import net.minecraft.util.math.MathHelper; +import net.minecraft.util.text.TextComponentTranslation; +import net.minecraft.world.World; +import net.minecraftforge.fml.common.network.simpleimpl.IMessage; + +import java.util.Arrays; +import java.util.Comparator; + +public class Resurrection extends Spell { + + public static final String WAIT_TIME = "wait_time"; + + public Resurrection(){ + super("resurrection", EnumAction.NONE, false); + addProperties(EFFECT_RADIUS, WAIT_TIME); + } + + @Override + public boolean requiresPacket(){ + return false; // Has its own packets + } + + @Override + public boolean cast(World world, EntityPlayer caster, EnumHand hand, int ticksInUse, SpellModifiers modifiers){ + + WizardData data = WizardData.get(caster); + + double radius = getProperty(EFFECT_RADIUS).doubleValue() * modifiers.get(WizardryItems.range_upgrade); + + if(!world.isRemote && caster.getServer() != null){ + // Potency reduces the time you have to wait to resurrect an ally + int waitTime = (int)(getProperty(WAIT_TIME).floatValue() / modifiers.get(SpellModifiers.POTENCY)); + + EntityPlayerMP nearestDeadAlly = caster.getServer().getPlayerList().getPlayers().stream() + .filter(p -> !p.isEntityAlive() && p.deathTime > waitTime && (data.isPlayerAlly(p) || caster == p) + && p.getDistanceSq(caster) < radius * radius) + .min(Comparator.comparingDouble(caster::getDistanceSq)) + .orElse(null); + + if(nearestDeadAlly != null){ + // When the player entity dies, it is removed from world#loadedEntityList. However, it is NOT removed + // from playerEntityList (and probably a few other places) until respawn is clicked, and since that + // never happens here we need to clean up those references or the player will have duplicate entries + // in some entity lists - and weirdness will ensue! + world.removeEntity(nearestDeadAlly); // Clean up the old entity references + resurrect(nearestDeadAlly); // Reset isDead, must be before spawning the player again + world.spawnEntity(nearestDeadAlly); // Re-add the player to all the relevant entity lists + + // Notify clients to reset the appropriate fields, spawn particles and play sounds + IMessage msg = new PacketResurrection.Message(nearestDeadAlly.getEntityId()); + WizardryPacketHandler.net.sendToDimension(msg, caster.dimension); + + if(caster == nearestDeadAlly){ + caster.getServer().getPlayerList().sendMessage(new TextComponentTranslation( + "spell." + this.getRegistryName() + ".resurrect_self", caster.getDisplayName())); + }else{ + caster.getServer().getPlayerList().sendMessage(new TextComponentTranslation( + "spell." + this.getRegistryName() + ".resurrect_ally", nearestDeadAlly.getDisplayName(), caster.getDisplayName())); + } + + return true; + } + } + + return false; + } + + /** Sets the given player back to alive, sets their health to half-full and (on the client) spawns particles. */ + public void resurrect(EntityPlayer player){ + + player.isDead = false; + player.setHealth(player.getMaxHealth() / 2); + // Experience doesn't normally get reset until respawn, so we need to do that here too + player.deathTime = 0; + player.experience = 0; + player.experienceLevel = 0; + player.experienceTotal = 0; + + if(player.world.isRemote){ + ParticleBuilder.spawnHealParticles(player.world, player); + this.playSound(player.world, player, 0, -1, null); // We know the modifiers parameter isn't used + } + } + + public static int getRemainingWaitTime(int timeSinceDeath){ + return Math.max(0, MathHelper.ceil((Spells.resurrection.getProperty(Resurrection.WAIT_TIME).floatValue() - timeSinceDeath) / 20)); + } + + /** Helper method for detecting if a stack can be used to cast the resurrection spell. */ + public static boolean canStackResurrect(ItemStack stack, EntityPlayer player){ + return stack.getItem() instanceof ISpellCastingItem + && Arrays.asList(((ISpellCastingItem)stack.getItem()).getSpells(stack)).contains(Spells.resurrection) + && ((ISpellCastingItem)stack.getItem()).canCast(stack, Spells.resurrection, player, EnumHand.MAIN_HAND, 0, new SpellModifiers()); + } + +} diff --git a/src/main/java/electroblob/wizardry/spell/Reversal.java b/src/main/java/electroblob/wizardry/spell/Reversal.java new file mode 100644 index 00000000..f8c79376 --- /dev/null +++ b/src/main/java/electroblob/wizardry/spell/Reversal.java @@ -0,0 +1,83 @@ +package electroblob.wizardry.spell; + +import electroblob.wizardry.constants.Constants; +import electroblob.wizardry.util.ParticleBuilder; +import electroblob.wizardry.util.ParticleBuilder.Type; +import electroblob.wizardry.util.SpellModifiers; +import net.minecraft.entity.Entity; +import net.minecraft.entity.EntityLivingBase; +import net.minecraft.item.EnumAction; +import net.minecraft.potion.PotionEffect; +import net.minecraft.util.EnumFacing; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.Vec3d; +import net.minecraft.world.World; + +import javax.annotation.Nullable; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +public class Reversal extends SpellRay { + + public static final String REVERSED_EFFECTS = "reversed_effects"; + + public Reversal(){ + super("reversal", false, EnumAction.NONE); + addProperties(REVERSED_EFFECTS); + } + + @Override + public boolean canBeCastByDispensers(){ + return false; + } + + @Override + protected boolean onEntityHit(World world, Entity target, Vec3d hit, @Nullable EntityLivingBase caster, Vec3d origin, int ticksInUse, SpellModifiers modifiers){ + + // Naturally, this spell won't work unless it has a living caster and target + if(caster != null && target instanceof EntityLivingBase){ + + List negativePotions = new ArrayList<>(caster.getActivePotionEffects()); + negativePotions.removeIf(p -> !p.getPotion().isBadEffect()); + + if(!world.isRemote){ + + if(negativePotions.isEmpty()) return false; // Needs potion effects to reverse! + + // 1 effect for non-necromancy wands, 2 for apprentice necromancy wands, 3 for advanced and 4 for master + int bonusEffects = (int)((modifiers.get(SpellModifiers.POTENCY) - 1) / Constants.POTENCY_INCREASE_PER_TIER + 0.5f) - 1; + int n = getProperty(REVERSED_EFFECTS).intValue() + bonusEffects; + + // Chooses n random negative potion effects, where n is the potency level + Collections.shuffle(negativePotions); + negativePotions = negativePotions.subList(0, negativePotions.size() < n ? negativePotions.size() : n); + + // Now reverse them! + negativePotions.forEach(p -> caster.removePotionEffect(p.getPotion())); + negativePotions.forEach(((EntityLivingBase)target)::addPotionEffect); + + }else{ + ParticleBuilder.create(Type.BUFF).entity(caster).clr(1, 1, 0.3f).spawn(world); + } + } + + return true; + } + + @Override + protected boolean onBlockHit(World world, BlockPos pos, EnumFacing side, Vec3d hit, @Nullable EntityLivingBase caster, Vec3d origin, int ticksInUse, SpellModifiers modifiers){ + return false; + } + + @Override + protected boolean onMiss(World world, @Nullable EntityLivingBase caster, Vec3d origin, Vec3d direction, int ticksInUse, SpellModifiers modifiers){ + return true; + } + + @Override + protected void spawnParticle(World world, double x, double y, double z, double vx, double vy, double vz){ + ParticleBuilder.create(Type.DARK_MAGIC).pos(x, y, z).clr(0.1f, 0, 0).spawn(world); + ParticleBuilder.create(Type.SPARKLE).pos(x, y, z).time(12 + world.rand.nextInt(8)).clr(0.1f, 0, 0.05f).spawn(world); + } +} diff --git a/src/main/java/electroblob/wizardry/spell/Satiety.java b/src/main/java/electroblob/wizardry/spell/Satiety.java new file mode 100644 index 00000000..8f3ce6e4 --- /dev/null +++ b/src/main/java/electroblob/wizardry/spell/Satiety.java @@ -0,0 +1,40 @@ +package electroblob.wizardry.spell; + +import electroblob.wizardry.util.SpellModifiers; +import net.minecraft.entity.EntityLivingBase; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.util.EnumHand; +import net.minecraft.world.World; + +public class Satiety extends SpellBuff { + + public static final String HUNGER_POINTS = "hunger_points"; + public static final String SATURATION_MODIFIER = "saturation_modifier"; + + public Satiety(){ + super("satiety", 1, 0.7f, 0.3f); + this.soundValues(0.7f, 1.2f, 0.4f); + addProperties(HUNGER_POINTS, SATURATION_MODIFIER); + } + + @Override public boolean canBeCastByNPCs(){ return false; } + + @Override + protected boolean applyEffects(EntityLivingBase caster, SpellModifiers modifiers){ + return true; // In this case the best solution is to remove the functionality of this method and override cast. + } + + @Override + public boolean cast(World world, EntityPlayer caster, EnumHand hand, int ticksInUse, SpellModifiers modifiers){ + + if(caster.getFoodStats().needFood()){ + int foodAmount = (int)(getProperty(HUNGER_POINTS).floatValue() * modifiers.get(SpellModifiers.POTENCY)); + // Fixed issue #6: Changed to addStats, since setFoodLevel is client-side only + caster.getFoodStats().addStats(foodAmount, getProperty(SATURATION_MODIFIER).floatValue()); + return super.cast(world, caster, hand, ticksInUse, modifiers); + } + + return false; + } + +} diff --git a/src/main/java/electroblob/wizardry/spell/ShadowWard.java b/src/main/java/electroblob/wizardry/spell/ShadowWard.java index 7d2736ea..60e42bf2 100644 --- a/src/main/java/electroblob/wizardry/spell/ShadowWard.java +++ b/src/main/java/electroblob/wizardry/spell/ShadowWard.java @@ -1,24 +1,20 @@ package electroblob.wizardry.spell; -import electroblob.wizardry.constants.Element; -import electroblob.wizardry.constants.SpellType; -import electroblob.wizardry.constants.Tier; -import electroblob.wizardry.item.ItemWand; import electroblob.wizardry.integration.DamageSafetyChecker; +import electroblob.wizardry.registry.Spells; import electroblob.wizardry.util.IElementalDamage; import electroblob.wizardry.util.MagicDamage; import electroblob.wizardry.util.MagicDamage.DamageType; import electroblob.wizardry.util.SpellModifiers; -import electroblob.wizardry.util.WandHelper; import electroblob.wizardry.util.WizardryUtilities; import net.minecraft.entity.EntityLivingBase; import net.minecraft.entity.player.EntityPlayer; -import net.minecraft.init.SoundEvents; import net.minecraft.item.EnumAction; -import net.minecraft.item.ItemStack; import net.minecraft.util.DamageSource; import net.minecraft.util.EnumHand; import net.minecraft.util.EnumParticleTypes; +import net.minecraft.util.SoundEvent; +import net.minecraft.util.math.MathHelper; import net.minecraft.world.World; import net.minecraftforge.event.entity.living.LivingAttackEvent; import net.minecraftforge.fml.common.Mod; @@ -27,8 +23,27 @@ import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; @Mod.EventBusSubscriber public class ShadowWard extends Spell { + public static final String REFLECTED_FRACTION = "reflected_fraction"; + public ShadowWard(){ - super("shadow_ward", Tier.ADVANCED, Element.NECROMANCY, SpellType.DEFENCE, 10, 0, EnumAction.BLOCK, true); + super("shadow_ward", EnumAction.BLOCK, true); + addProperties(REFLECTED_FRACTION); + soundValues(0.6f, 1, 0); + } + + @Override + protected SoundEvent[] createSounds(){ + return this.createContinuousSpellSounds(); + } + + @Override + protected void playSound(World world, EntityLivingBase entity, int ticksInUse, int duration, SpellModifiers modifiers, String... sounds){ + this.playSoundLoop(world, entity, ticksInUse); + } + + @Override + protected void playSound(World world, double x, double y, double z, int ticksInUse, int duration, SpellModifiers modifiers, String... sounds){ + this.playSoundLoop(world, x, y, z, ticksInUse, duration); } @Override @@ -42,7 +57,7 @@ public class ShadowWard extends Spell { } if(ticksInUse % 50 == 0){ - WizardryUtilities.playSoundAtPlayer(caster, SoundEvents.BLOCK_PORTAL_AMBIENT, 0.6f, 1.5f); + this.playSound(world, caster, ticksInUse, -1, modifiers); } return true; @@ -50,22 +65,24 @@ public class ShadowWard extends Spell { @SubscribeEvent public static void onLivingAttackEvent(LivingAttackEvent event){ + if(event.getSource() != null && event.getSource().getTrueSource() instanceof EntityLivingBase){ - // There used to be a check that the target was a player here, but I don't see any reason for it. - ItemStack wand = event.getEntityLiving().getActiveItemStack(); - if(wand.getItemDamage() < wand.getMaxDamage() && wand.getItem() instanceof ItemWand - && WandHelper.getCurrentSpell(wand) instanceof ShadowWard && !event.getSource().isUnblockable() + if(WizardryUtilities.isCasting(event.getEntityLiving(), Spells.shadow_ward) && !event.getSource().isUnblockable() && !(event.getSource() instanceof IElementalDamage && ((IElementalDamage)event.getSource()).isRetaliatory())){ event.setCanceled(true); + + float reflectedFraction = MathHelper.clamp(Spells.shadow_ward.getProperty(REFLECTED_FRACTION).floatValue(), 0, 1); + // Now we can preserve the original damage source (sort of) as long as we make it retaliatory. // For some reason this isn't working, so I've reverted to plain old magic damage for now. //event.getEntityLiving().attackEntityFrom( // MagicDamage.causeDirectMagicDamage(event.getSource().getTrueSource(), DamageType.MAGIC, true), event.getAmount() * 0.5f); - DamageSafetyChecker.attackEntitySafely(event.getEntity(), DamageSource.MAGIC, event.getAmount() * 0.5f, event.getSource().getDamageType()); - ((EntityLivingBase)event.getSource().getTrueSource()).attackEntityFrom( - MagicDamage.causeDirectMagicDamage(event.getEntityLiving(), DamageType.MAGIC, true), event.getAmount() * 0.5f); + DamageSafetyChecker.attackEntitySafely(event.getEntity(), DamageSource.MAGIC, event.getAmount() + * (1 - reflectedFraction), event.getSource().getDamageType()); + event.getSource().getTrueSource().attackEntityFrom(MagicDamage.causeDirectMagicDamage( + event.getEntityLiving(), DamageType.MAGIC, true), event.getAmount() * reflectedFraction); } } } diff --git a/src/main/java/electroblob/wizardry/spell/Shield.java b/src/main/java/electroblob/wizardry/spell/Shield.java index dac072c6..759ee3ed 100644 --- a/src/main/java/electroblob/wizardry/spell/Shield.java +++ b/src/main/java/electroblob/wizardry/spell/Shield.java @@ -1,40 +1,60 @@ package electroblob.wizardry.spell; -import electroblob.wizardry.WizardData; -import electroblob.wizardry.constants.Element; -import electroblob.wizardry.constants.SpellType; -import electroblob.wizardry.constants.Tier; +import electroblob.wizardry.data.IVariable; +import electroblob.wizardry.data.Persistence; +import electroblob.wizardry.data.WizardData; import electroblob.wizardry.entity.EntityShield; -import electroblob.wizardry.registry.WizardrySounds; import electroblob.wizardry.util.SpellModifiers; -import electroblob.wizardry.util.WizardryUtilities; +import net.minecraft.entity.EntityLivingBase; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.init.MobEffects; import net.minecraft.item.EnumAction; import net.minecraft.potion.PotionEffect; import net.minecraft.util.EnumHand; +import net.minecraft.util.SoundEvent; import net.minecraft.world.World; public class Shield extends Spell { + public static final IVariable SHIELD_KEY = new IVariable.Variable<>(Persistence.NEVER); + public Shield(){ - super("shield", Tier.APPRENTICE, Element.HEALING, SpellType.DEFENCE, 5, 0, EnumAction.BLOCK, true); + super("shield", EnumAction.BLOCK, true); + addProperties(EFFECT_STRENGTH); + } + + @Override + protected SoundEvent[] createSounds(){ + return this.createContinuousSpellSounds(); + } + + @Override + protected void playSound(World world, EntityLivingBase entity, int ticksInUse, int duration, SpellModifiers modifiers, String... sounds){ + this.playSoundLoop(world, entity, ticksInUse); + } + + @Override + protected void playSound(World world, double x, double y, double z, int ticksInUse, int duration, SpellModifiers modifiers, String... sounds){ + this.playSoundLoop(world, x, y, z, ticksInUse, duration); } @Override public boolean cast(World world, EntityPlayer caster, EnumHand hand, int ticksInUse, SpellModifiers modifiers){ - caster.addPotionEffect(new PotionEffect(MobEffects.RESISTANCE, 10, 0, false, false)); + caster.addPotionEffect(new PotionEffect(MobEffects.RESISTANCE, 10, + getProperty(EFFECT_STRENGTH).intValue(), false, false)); - if(WizardData.get(caster).shield == null){ - WizardData.get(caster).shield = new EntityShield(world, caster); + if(WizardData.get(caster).getVariable(SHIELD_KEY) == null){ + + EntityShield shield = new EntityShield(world, caster); + + WizardData.get(caster).setVariable(SHIELD_KEY, shield); if(!world.isRemote){ - world.spawnEntity(WizardData.get(caster).shield); + world.spawnEntity(shield); } } - if(ticksInUse == 0){ - WizardryUtilities.playSoundAtPlayer(caster, WizardrySounds.SPELL_CONJURATION, 1.0f, 1.0f); - } + + this.playSound(world, caster, ticksInUse, -1, modifiers); return true; } diff --git a/src/main/java/electroblob/wizardry/spell/Shockwave.java b/src/main/java/electroblob/wizardry/spell/Shockwave.java index 5b970204..abfd6767 100644 --- a/src/main/java/electroblob/wizardry/spell/Shockwave.java +++ b/src/main/java/electroblob/wizardry/spell/Shockwave.java @@ -1,18 +1,11 @@ package electroblob.wizardry.spell; -import java.util.List; - -import electroblob.wizardry.constants.Element; -import electroblob.wizardry.constants.SpellType; -import electroblob.wizardry.constants.Tier; +import electroblob.wizardry.Wizardry; +import electroblob.wizardry.item.ItemArtefact; import electroblob.wizardry.registry.WizardryItems; -import electroblob.wizardry.registry.WizardrySounds; -import electroblob.wizardry.util.MagicDamage; +import electroblob.wizardry.util.*; import electroblob.wizardry.util.MagicDamage.DamageType; -import electroblob.wizardry.util.ParticleBuilder; import electroblob.wizardry.util.ParticleBuilder.Type; -import electroblob.wizardry.util.SpellModifiers; -import electroblob.wizardry.util.WizardryUtilities; import net.minecraft.block.Block; import net.minecraft.block.state.IBlockState; import net.minecraft.entity.EntityLivingBase; @@ -22,39 +15,59 @@ import net.minecraft.item.EnumAction; import net.minecraft.network.play.server.SPacketEntityVelocity; import net.minecraft.util.EnumHand; import net.minecraft.util.EnumParticleTypes; +import net.minecraft.util.text.TextComponentTranslation; import net.minecraft.world.World; +import java.util.List; + public class Shockwave extends Spell { - private static final double BASE_RADIUS = 5; - private static final float BASE_DAMAGE = 8; + public static final String MAX_REPULSION_VELOCITY = "max_repulsion_velocity"; + /** The radius within which maximum damage is dealt and maximum repulsion velocity is applied. */ + private static final double EPICENTRE_RADIUS = 1; public Shockwave(){ - super("shockwave", Tier.MASTER, Element.SORCERY, SpellType.ATTACK, 65, 150, EnumAction.BOW, false); + super("shockwave", EnumAction.BOW, false); + this.soundValues(2, 0.5f, 0); + addProperties(BLAST_RADIUS, DAMAGE, MAX_REPULSION_VELOCITY); } @Override public boolean cast(World world, EntityPlayer caster, EnumHand hand, int ticksInUse, SpellModifiers modifiers){ - List targets = WizardryUtilities.getEntitiesWithinRadius( - BASE_RADIUS * modifiers.get(WizardryItems.blast_upgrade), caster.posX, caster.posY, caster.posZ, world); + double radius = getProperty(BLAST_RADIUS).floatValue() * modifiers.get(WizardryItems.blast_upgrade); + + List targets = WizardryUtilities.getEntitiesWithinRadius(radius, caster.posX, caster.posY, caster.posZ, world); for(EntityLivingBase target : targets){ - if(WizardryUtilities.isValidTarget(caster, target)){ + + if(target instanceof EntityPlayer && (!Wizardry.settings.playersMoveEachOther + || ItemArtefact.isArtefactActive((EntityPlayer)target, WizardryItems.amulet_anchoring))){ + + if(!world.isRemote) caster.sendStatusMessage(new TextComponentTranslation("spell.resist", + target.getName(), this.getNameForTranslationFormatted()), true); + return false; + } + + if(AllyDesignationSystem.isValidTarget(caster, target)){ + + // Produces a linear profile from 0 at the edge of the radius to 1 at the epicentre radius, then + // a constant value of 1 within the epicentre radius. + float proximity = (float)(1 - (Math.max(target.getDistance(caster) - EPICENTRE_RADIUS, 0))/(radius - EPICENTRE_RADIUS)); + // Damage increases closer to player up to a maximum of 4 hearts (at 1 block distance). - float damage = Math.min(BASE_DAMAGE / target.getDistance(caster), BASE_DAMAGE); target.attackEntityFrom(MagicDamage.causeDirectMagicDamage(caster, DamageType.BLAST), - damage * modifiers.get(SpellModifiers.POTENCY)); + getProperty(DAMAGE).floatValue() * proximity * modifiers.get(SpellModifiers.POTENCY)); if(!world.isRemote){ // Entity speed increases closer to the player to a maximum of 3 (at 1 block distance). // This is the entity's speed compared to its distance from the player. Used for a similar triangles // based x, y and z speed calculation. - double velocityFactor = Math.min(5 / target.getDistanceSq(caster), 3.0d); + double velocityFactor = proximity * getProperty(MAX_REPULSION_VELOCITY).floatValue(); double dx = target.posX - caster.posX; - double dy = target.posY + 1 - caster.posY; + double dy = target.getEntityBoundingBox().minY + 1 - caster.posY; double dz = target.posZ - caster.posZ; target.motionX = velocityFactor * dx; @@ -74,17 +87,17 @@ public class Shockwave extends Spell { double particleX, particleZ; for(int i = 0; i < 40; i++){ - - particleX = caster.posX - 1.0d + 2 * world.rand.nextDouble(); - particleZ = caster.posZ - 1.0d + 2 * world.rand.nextDouble(); - ParticleBuilder.create(Type.SPARKLE).pos(particleX, caster.getEntityBoundingBox().minY, particleZ) - .vel(particleX - caster.posX, 0, particleZ - caster.posZ).time(30).clr(0.8f, 0.8f, 1).spawn(world); - - particleX = caster.posX - 1.0d + 2 * world.rand.nextDouble(); - particleZ = caster.posZ - 1.0d + 2 * world.rand.nextDouble(); - ParticleBuilder.create(Type.SPARKLE).pos(particleX, caster.getEntityBoundingBox().minY, particleZ) - .vel(particleX - caster.posX, 0, particleZ - caster.posZ).time(30).clr(0.9f, 0.9f, 0.9f).spawn(world); - + +// particleX = caster.posX - 1.0d + 2 * world.rand.nextDouble(); +// particleZ = caster.posZ - 1.0d + 2 * world.rand.nextDouble(); +// ParticleBuilder.create(Type.SPARKLE).pos(particleX, caster.getEntityBoundingBox().minY, particleZ) +// .vel(particleX - caster.posX, 0, particleZ - caster.posZ).time(30).clr(0.8f, 0.8f, 1).spawn(world); +// +// particleX = caster.posX - 1.0d + 2 * world.rand.nextDouble(); +// particleZ = caster.posZ - 1.0d + 2 * world.rand.nextDouble(); +// ParticleBuilder.create(Type.SPARKLE).pos(particleX, caster.getEntityBoundingBox().minY, particleZ) +// .vel(particleX - caster.posX, 0, particleZ - caster.posZ).time(30).clr(0.9f, 0.9f, 0.9f).spawn(world); + particleX = caster.posX - 1.0d + 2 * world.rand.nextDouble(); particleZ = caster.posZ - 1.0d + 2 * world.rand.nextDouble(); IBlockState block = WizardryUtilities.getBlockEntityIsStandingOn(caster); @@ -95,14 +108,19 @@ public class Shockwave extends Spell { } } + ParticleBuilder.create(Type.SPHERE) + .pos(caster.posX, caster.getEntityBoundingBox().minY + 0.1, caster.posZ) + .scale((float)radius * 0.8f) + .clr(0.8f, 0.9f, 1) + .spawn(world); + world.spawnParticle(EnumParticleTypes.EXPLOSION_LARGE, caster.posX, caster.getEntityBoundingBox().minY + 0.1, caster.posZ, 0, 0, 0); } caster.swingArm(hand); - WizardryUtilities.playSoundAtPlayer(caster, WizardrySounds.SPELL_SHOCKWAVE, 1.0f, 0.7f); - WizardryUtilities.playSoundAtPlayer(caster, WizardrySounds.SPELL_SHOCKWAVE, 2.0f, 0.3f); + playSound(world, caster, ticksInUse, -1, modifiers); return true; } diff --git a/src/main/java/electroblob/wizardry/spell/ShulkerBullet.java b/src/main/java/electroblob/wizardry/spell/ShulkerBullet.java new file mode 100644 index 00000000..8b59fdf4 --- /dev/null +++ b/src/main/java/electroblob/wizardry/spell/ShulkerBullet.java @@ -0,0 +1,101 @@ +package electroblob.wizardry.spell; + +import electroblob.wizardry.registry.WizardryItems; +import electroblob.wizardry.util.SpellModifiers; +import electroblob.wizardry.util.WizardryUtilities; +import net.minecraft.entity.Entity; +import net.minecraft.entity.EntityLiving; +import net.minecraft.entity.EntityLivingBase; +import net.minecraft.entity.item.EntityArmorStand; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.entity.projectile.EntityShulkerBullet; +import net.minecraft.item.EnumAction; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.nbt.NBTUtil; +import net.minecraft.util.EnumFacing; +import net.minecraft.util.EnumHand; +import net.minecraft.util.math.BlockPos; +import net.minecraft.world.World; + +import javax.annotation.Nullable; +import java.util.Comparator; +import java.util.List; + +public class ShulkerBullet extends Spell { + + public ShulkerBullet(){ + super("shulker_bullet", EnumAction.NONE, false); + this.soundValues(2, 1, 0.3f); + addProperties(RANGE); + } + + @Override public boolean canBeCastByNPCs(){ return true; } + + @Override public boolean canBeCastByDispensers(){ return true; } + + @Override + public boolean cast(World world, EntityPlayer caster, EnumHand hand, int ticksInUse, SpellModifiers modifiers){ + if(!shoot(world, caster, caster.posX, caster.posY, caster.posZ, EnumFacing.UP, modifiers)) return false; + this.playSound(world, caster, ticksInUse, -1, modifiers); + return true; + } + + @Override + public boolean cast(World world, EntityLiving caster, EnumHand hand, int ticksInUse, EntityLivingBase target, SpellModifiers modifiers){ + if(!shoot(world, caster, caster.posX, caster.posY, caster.posZ, EnumFacing.UP, modifiers)) return false; + this.playSound(world, caster, ticksInUse, -1, modifiers); + return true; + } + + @Override + public boolean cast(World world, double x, double y, double z, EnumFacing direction, int duration, int ticksInUse, SpellModifiers modifiers){ + if(!shoot(world, null, x, y, z, direction, modifiers)) return false; + this.playSound(world, x, y, z, ticksInUse, -1, modifiers); + return true; + } + + private boolean shoot(World world, @Nullable EntityLivingBase caster, double x, double y, double z, EnumFacing direction, SpellModifiers modifiers){ + + if(!world.isRemote){ + + double range = getProperty(RANGE).floatValue() * modifiers.get(WizardryItems.range_upgrade); + + List possibleTargets = WizardryUtilities.getEntitiesWithinRadius(range, x, y, z, world); + + possibleTargets.remove(caster); + possibleTargets.removeIf(t -> t instanceof EntityArmorStand); + + if(possibleTargets.isEmpty()) return false; + + // getDistanceSq doesn't require square-rooting so it's faster when only comparing + possibleTargets.sort(Comparator.comparingDouble(t -> t.getDistanceSq(x, y, z))); + + Entity target = possibleTargets.get(0); + + // Y axis because the player is always upright + if(caster != null){ + world.spawnEntity(new EntityShulkerBullet(world, caster, target, direction.getAxis())); + }else{ + // Can't use the normal constructor because doesn't accept null for the owner + EntityShulkerBullet bullet = new EntityShulkerBullet(world); + bullet.setLocationAndAngles(x, y, z, bullet.rotationYaw, bullet.rotationPitch); + + // Where there's a will there's a way... + NBTTagCompound nbt = new NBTTagCompound(); + bullet.writeToNBT(nbt); + nbt.setInteger("Dir", direction.getIndex()); + BlockPos pos = new BlockPos(target); + NBTTagCompound targetTag = NBTUtil.createUUIDTag(target.getUniqueID()); + targetTag.setInteger("X", pos.getX()); + targetTag.setInteger("Y", pos.getY()); + targetTag.setInteger("Z", pos.getZ()); + nbt.setTag("Target", targetTag); + bullet.readFromNBT(nbt); // LOL I just modified private fields without reflection + + world.spawnEntity(bullet); + } + } + + return true; + } +} diff --git a/src/main/java/electroblob/wizardry/spell/SixthSense.java b/src/main/java/electroblob/wizardry/spell/SixthSense.java index a7d731bf..b311c7cb 100644 --- a/src/main/java/electroblob/wizardry/spell/SixthSense.java +++ b/src/main/java/electroblob/wizardry/spell/SixthSense.java @@ -1,43 +1,60 @@ package electroblob.wizardry.spell; +import electroblob.wizardry.Wizardry; import electroblob.wizardry.constants.Constants; -import electroblob.wizardry.constants.Element; -import electroblob.wizardry.constants.SpellType; -import electroblob.wizardry.constants.Tier; import electroblob.wizardry.registry.WizardryItems; import electroblob.wizardry.registry.WizardryPotions; import electroblob.wizardry.util.SpellModifiers; -import electroblob.wizardry.util.WizardryUtilities; import net.minecraft.entity.player.EntityPlayer; -import net.minecraft.init.SoundEvents; import net.minecraft.item.EnumAction; import net.minecraft.potion.PotionEffect; import net.minecraft.util.EnumHand; +import net.minecraft.util.ResourceLocation; import net.minecraft.world.World; +import net.minecraftforge.event.entity.living.PotionEvent; +import net.minecraftforge.fml.common.Mod; +import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; +@Mod.EventBusSubscriber public class SixthSense extends Spell { + /** A {@code ResourceLocation} representing the shader file used when under the effects of sixth sense. */ + public static final ResourceLocation SHADER = new ResourceLocation(Wizardry.MODID, "shaders/post/sixth_sense.json"); + public SixthSense(){ - super("sixth_sense", Tier.APPRENTICE, Element.EARTH, SpellType.BUFF, 20, 100, EnumAction.BOW, false); + super("sixth_sense", EnumAction.BOW, false); + addProperties(EFFECT_DURATION, EFFECT_RADIUS); + soundValues(1, 1.1f, 0.2f); } @Override - public boolean doesSpellRequirePacket(){ + public boolean requiresPacket(){ return false; } @Override public boolean cast(World world, EntityPlayer caster, EnumHand hand, int ticksInUse, SpellModifiers modifiers){ - // Cannot be cast when it has already been cast - if(!world.isRemote){ - caster.addPotionEffect(new PotionEffect(WizardryPotions.sixth_sense, - (int)(400 * modifiers.get(WizardryItems.duration_upgrade)), - (int)((modifiers.get(WizardryItems.range_upgrade) - 1f) / Constants.RANGE_INCREASE_PER_LEVEL))); + caster.addPotionEffect(new PotionEffect(WizardryPotions.sixth_sense, + (int)(getProperty(EFFECT_DURATION).floatValue() * modifiers.get(WizardryItems.duration_upgrade)), + (int)((modifiers.get(WizardryItems.range_upgrade) - 1f) / Constants.RANGE_INCREASE_PER_LEVEL))); + + if(world.isRemote && caster == net.minecraft.client.Minecraft.getMinecraft().player){ + if(Wizardry.settings.useShaders) net.minecraft.client.Minecraft.getMinecraft().entityRenderer.loadShader(SHADER); + electroblob.wizardry.client.WizardryClientEventHandler.playBlinkEffect(); } - WizardryUtilities.playSoundAtPlayer(caster, SoundEvents.ENTITY_WITHER_SHOOT, 1.0F, - world.rand.nextFloat() * 0.2F + 1.0F); + + this.playSound(world, caster, ticksInUse, -1, modifiers); return true; } + @SubscribeEvent + public static void onPotionAddedEvent(PotionEvent.PotionAddedEvent event){ + if(event.getEntity().world.isRemote && event.getPotionEffect().getPotion() == WizardryPotions.sixth_sense + && event.getEntity() == net.minecraft.client.Minecraft.getMinecraft().player){ + if(Wizardry.settings.useShaders) net.minecraft.client.Minecraft.getMinecraft().entityRenderer.loadShader(SHADER); + electroblob.wizardry.client.WizardryClientEventHandler.playBlinkEffect(); + } + } + } diff --git a/src/main/java/electroblob/wizardry/spell/Slime.java b/src/main/java/electroblob/wizardry/spell/Slime.java index 9b9e53fe..14bbfaf0 100644 --- a/src/main/java/electroblob/wizardry/spell/Slime.java +++ b/src/main/java/electroblob/wizardry/spell/Slime.java @@ -1,55 +1,32 @@ package electroblob.wizardry.spell; -import electroblob.wizardry.constants.Element; -import electroblob.wizardry.constants.SpellType; -import electroblob.wizardry.constants.Tier; import electroblob.wizardry.entity.living.EntityMagicSlime; -import electroblob.wizardry.registry.WizardryAdvancementTriggers; import electroblob.wizardry.registry.WizardryItems; -import electroblob.wizardry.registry.WizardrySounds; import electroblob.wizardry.util.ParticleBuilder; import electroblob.wizardry.util.ParticleBuilder.Type; import electroblob.wizardry.util.SpellModifiers; import electroblob.wizardry.util.WizardryUtilities; import net.minecraft.entity.Entity; -import net.minecraft.entity.EntityLiving; import net.minecraft.entity.EntityLivingBase; -import net.minecraft.entity.monster.EntitySkeleton; import net.minecraft.entity.monster.EntitySlime; import net.minecraft.entity.player.EntityPlayer; -import net.minecraft.init.SoundEvents; +import net.minecraft.item.EnumAction; import net.minecraft.util.EnumFacing; -import net.minecraft.util.EnumHand; import net.minecraft.util.EnumParticleTypes; import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.Vec3d; import net.minecraft.util.text.TextComponentTranslation; import net.minecraft.world.World; public class Slime extends SpellRay { - - private static final int BASE_DURATION = 200; public Slime(){ - super("slime", Tier.ADVANCED, Element.EARTH, SpellType.ATTACK, 20, 50, false, 8, WizardrySounds.SPELL_ICE); + super("slime", false, EnumAction.NONE); + addProperties(DURATION); } @Override - public boolean cast(World world, EntityPlayer caster, EnumHand hand, int ticksInUse, SpellModifiers modifiers){ - // This spell uses more than one sound, so this is required... - boolean flag = super.cast(world, caster, hand, ticksInUse, modifiers); - if(flag) WizardryUtilities.playSoundAtPlayer(caster, SoundEvents.ENTITY_SLIME_ATTACK, 1.0F, 0.5F); - return flag; - } - - @Override - public boolean cast(World world, EntityLiving caster, EnumHand hand, int ticksInUse, EntityLivingBase target, SpellModifiers modifiers){ - boolean flag = super.cast(world, caster, hand, ticksInUse, target, modifiers); - if(flag) caster.playSound(SoundEvents.ENTITY_SLIME_ATTACK, 1.0F, 0.5F); - return flag; - } - - @Override - protected boolean onEntityHit(World world, Entity target, EntityLivingBase caster, int ticksInUse, SpellModifiers modifiers){ + protected boolean onEntityHit(World world, Entity target, Vec3d hit, EntityLivingBase caster, Vec3d origin, int ticksInUse, SpellModifiers modifiers){ if(WizardryUtilities.isLiving(target) && !(target instanceof EntityMagicSlime)){ @@ -58,29 +35,24 @@ public class Slime extends SpellRay { new TextComponentTranslation("spell.resist", target.getName(), this.getNameForTranslationFormatted()), true); }else{ - if(target instanceof EntitySkeleton && caster instanceof EntityPlayer) - WizardryAdvancementTriggers.slime_skeleton.triggerFor((EntityPlayer)caster); - if(!world.isRemote){ EntityMagicSlime slime = new EntityMagicSlime(world, caster, (EntityLivingBase)target, - (int)(BASE_DURATION * modifiers.get(WizardryItems.duration_upgrade))); + (int)(getProperty(DURATION).floatValue() * modifiers.get(WizardryItems.duration_upgrade))); world.spawnEntity(slime); } } - - return true; } + return true; + } + + @Override + protected boolean onBlockHit(World world, BlockPos pos, EnumFacing side, Vec3d hit, EntityLivingBase caster, Vec3d origin, int ticksInUse, SpellModifiers modifiers){ return false; } @Override - protected boolean onBlockHit(World world, BlockPos pos, EnumFacing side, EntityLivingBase caster, int ticksInUse, SpellModifiers modifiers){ - return false; - } - - @Override - protected boolean onMiss(World world, EntityLivingBase caster, int ticksInUse, SpellModifiers modifiers){ + protected boolean onMiss(World world, EntityLivingBase caster, Vec3d origin, Vec3d direction, int ticksInUse, SpellModifiers modifiers){ return true; } diff --git a/src/main/java/electroblob/wizardry/spell/SlowTime.java b/src/main/java/electroblob/wizardry/spell/SlowTime.java new file mode 100644 index 00000000..04ce8150 --- /dev/null +++ b/src/main/java/electroblob/wizardry/spell/SlowTime.java @@ -0,0 +1,46 @@ +package electroblob.wizardry.spell; + +import electroblob.wizardry.Wizardry; +import electroblob.wizardry.registry.WizardryPotions; +import electroblob.wizardry.util.SpellModifiers; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.util.EnumHand; +import net.minecraft.util.ResourceLocation; +import net.minecraft.world.World; + +public class SlowTime extends SpellBuff { + + /** A {@code ResourceLocation} representing the shader file used when possessing an entity. */ + public static final ResourceLocation SHADER = new ResourceLocation(Wizardry.MODID, "shaders/post/slow_time.json"); + + public SlowTime(){ + super("slow_time", 0.2f, 0.8f, 0.8f, () -> WizardryPotions.slow_time); + addProperties(EFFECT_RADIUS); + soundValues(0.6f, 1.5f, 0); + } + + @Override + public boolean cast(World world, EntityPlayer caster, EnumHand hand, int ticksInUse, SpellModifiers modifiers){ + + if(caster.world.isRemote && caster == net.minecraft.client.Minecraft.getMinecraft().player){ + if(Wizardry.settings.useShaders) net.minecraft.client.Minecraft.getMinecraft().entityRenderer.loadShader(SHADER); + } + + return super.cast(world, caster, hand, ticksInUse, modifiers); + } + + @Override + public boolean requiresPacket(){ + return false; + } + + @Override + public boolean canBeCastByDispensers(){ + return false; + } + + @Override + public boolean canBeCastByNPCs(){ + return false; + } +} diff --git a/src/main/java/electroblob/wizardry/spell/Snare.java b/src/main/java/electroblob/wizardry/spell/Snare.java index fa2259ea..4b70e60d 100644 --- a/src/main/java/electroblob/wizardry/spell/Snare.java +++ b/src/main/java/electroblob/wizardry/spell/Snare.java @@ -1,8 +1,5 @@ package electroblob.wizardry.spell; -import electroblob.wizardry.constants.Element; -import electroblob.wizardry.constants.SpellType; -import electroblob.wizardry.constants.Tier; import electroblob.wizardry.registry.WizardryBlocks; import electroblob.wizardry.tileentity.TileEntityPlayerSave; import electroblob.wizardry.util.ParticleBuilder; @@ -11,26 +8,28 @@ import electroblob.wizardry.util.SpellModifiers; import electroblob.wizardry.util.WizardryUtilities; import net.minecraft.entity.Entity; import net.minecraft.entity.EntityLivingBase; -import net.minecraft.init.SoundEvents; +import net.minecraft.item.EnumAction; import net.minecraft.util.EnumFacing; import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.Vec3d; import net.minecraft.world.World; public class Snare extends SpellRay { public Snare(){ - super("snare", Tier.BASIC, Element.EARTH, SpellType.ATTACK, 10, 10, false, 10, SoundEvents.BLOCK_GRASS_PLACE); + super("snare", false, EnumAction.NONE); this.soundValues(1, 1.4f, 0.4f); - this.ignoreEntities(true); + this.ignoreLivingEntities(true); + addProperties(DAMAGE, EFFECT_DURATION, EFFECT_STRENGTH); } @Override - protected boolean onEntityHit(World world, Entity target, EntityLivingBase caster, int ticksInUse, SpellModifiers modifiers){ + protected boolean onEntityHit(World world, Entity target, Vec3d hit, EntityLivingBase caster, Vec3d origin, int ticksInUse, SpellModifiers modifiers){ return false; } @Override - protected boolean onBlockHit(World world, BlockPos pos, EnumFacing side, EntityLivingBase caster, int ticksInUse, SpellModifiers modifiers){ + protected boolean onBlockHit(World world, BlockPos pos, EnumFacing side, Vec3d hit, EntityLivingBase caster, Vec3d origin, int ticksInUse, SpellModifiers modifiers){ if(side == EnumFacing.UP && world.isSideSolid(pos, EnumFacing.UP) && WizardryUtilities.canBlockBeReplaced(world, pos.up())){ @@ -47,7 +46,7 @@ public class Snare extends SpellRay { } @Override - protected boolean onMiss(World world, EntityLivingBase caster, int ticksInUse, SpellModifiers modifiers){ + protected boolean onMiss(World world, EntityLivingBase caster, Vec3d origin, Vec3d direction, int ticksInUse, SpellModifiers modifiers){ return false; } diff --git a/src/main/java/electroblob/wizardry/spell/Snowball.java b/src/main/java/electroblob/wizardry/spell/Snowball.java index 1e4e901a..500488fd 100644 --- a/src/main/java/electroblob/wizardry/spell/Snowball.java +++ b/src/main/java/electroblob/wizardry/spell/Snowball.java @@ -1,25 +1,24 @@ package electroblob.wizardry.spell; -import electroblob.wizardry.constants.Element; -import electroblob.wizardry.constants.SpellType; -import electroblob.wizardry.constants.Tier; +import electroblob.wizardry.registry.WizardryItems; import electroblob.wizardry.util.SpellModifiers; -import electroblob.wizardry.util.WizardryUtilities; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.entity.projectile.EntitySnowball; -import net.minecraft.init.SoundEvents; import net.minecraft.item.EnumAction; import net.minecraft.util.EnumHand; +import net.minecraft.util.math.MathHelper; import net.minecraft.world.World; public class Snowball extends Spell { public Snowball(){ - super("snowball", Tier.BASIC, Element.ICE, SpellType.ATTACK, 1, 1, EnumAction.NONE, false); + super("snowball", EnumAction.NONE, false); + addProperties(RANGE); + soundValues(0.5f, 0.4f, 0.2f); } @Override - public boolean doesSpellRequirePacket(){ + public boolean requiresPacket(){ return false; } @@ -27,13 +26,18 @@ public class Snowball extends Spell { public boolean cast(World world, EntityPlayer caster, EnumHand hand, int ticksInUse, SpellModifiers modifiers){ if(!world.isRemote){ + // Trajectory calculation - see SpellProjectile for a more detailed explanation + float g = 0.03f; + float launchHeight = caster.getEyeHeight(); + float range = getProperty(RANGE).floatValue() * modifiers.get(WizardryItems.range_upgrade); + float velocity = MathHelper.sqrt(MathHelper.sqrt(g*g * (launchHeight*launchHeight + range*range)) - g*launchHeight); + EntitySnowball snowball = new EntitySnowball(world, caster); - snowball.shoot(caster, caster.rotationPitch, caster.rotationYaw, 0.0f, 1.5f, 1.0f); + snowball.shoot(caster, caster.rotationPitch, caster.rotationYaw, 0.0f, velocity, 1.0f); world.spawnEntity(snowball); } - WizardryUtilities.playSoundAtPlayer(caster, SoundEvents.ENTITY_SNOWBALL_THROW, 0.5F, - 0.4F / (world.rand.nextFloat() * 0.4F + 0.8F)); + this.playSound(world, caster, ticksInUse, -1, modifiers); caster.swingArm(hand); return true; } diff --git a/src/main/java/electroblob/wizardry/spell/SpectralPathway.java b/src/main/java/electroblob/wizardry/spell/SpectralPathway.java index 5591448b..adc6c73d 100644 --- a/src/main/java/electroblob/wizardry/spell/SpectralPathway.java +++ b/src/main/java/electroblob/wizardry/spell/SpectralPathway.java @@ -1,11 +1,7 @@ package electroblob.wizardry.spell; -import electroblob.wizardry.constants.Element; -import electroblob.wizardry.constants.SpellType; -import electroblob.wizardry.constants.Tier; import electroblob.wizardry.registry.WizardryBlocks; import electroblob.wizardry.registry.WizardryItems; -import electroblob.wizardry.registry.WizardrySounds; import electroblob.wizardry.tileentity.TileEntityTimer; import electroblob.wizardry.util.SpellModifiers; import electroblob.wizardry.util.WizardryUtilities; @@ -19,13 +15,17 @@ import net.minecraft.util.math.BlockPos; import net.minecraft.world.World; public class SpectralPathway extends Spell { + + /** The base length of the conjured bridge, in blocks. */ + public static final String LENGTH = "length"; public SpectralPathway(){ - super("spectral_pathway", Tier.ADVANCED, Element.SORCERY, SpellType.UTILITY, 40, 300, EnumAction.BOW, false); + super("spectral_pathway", EnumAction.BOW, false); + addProperties(LENGTH, DURATION); } @Override - public boolean doesSpellRequirePacket(){ + public boolean requiresPacket(){ return false; } @@ -44,8 +44,6 @@ public class SpectralPathway extends Spell { if(!world.isRemote){ - int baseLength = 15; - // Gets the coordinates of the nearest block intersection to the player's feet. // Remember that a block always takes the coordinates of its northwestern corner. BlockPos origin = new BlockPos(Math.round(caster.posX), (int)caster.getEntityBoundingBox().minY - 1, @@ -53,7 +51,7 @@ public class SpectralPathway extends Spell { int startPoint = direction.getAxisDirection() == AxisDirection.POSITIVE ? -1 : 0; - for(int i = 0; i < (int)(baseLength * modifiers.get(WizardryItems.range_upgrade)); i++){ + for(int i = 0; i < (int)(getProperty(LENGTH).floatValue() * modifiers.get(WizardryItems.range_upgrade)); i++){ // If either a block gets placed or one has already been placed, flag is set to true. flag = placePathwayBlockIfPossible(world, origin.offset(direction, startPoint + i), modifiers.get(WizardryItems.duration_upgrade)) || flag; @@ -63,17 +61,17 @@ public class SpectralPathway extends Spell { modifiers.get(WizardryItems.duration_upgrade)) || flag; } } - // TODO: There may be some client/server discrepancies here. - WizardryUtilities.playSoundAtPlayer(caster, WizardrySounds.SPELL_CONJURATION_LARGE, 1.0f, 1.0f); + + this.playSound(world, caster, ticksInUse, -1, modifiers); return flag; } - private static boolean placePathwayBlockIfPossible(World world, BlockPos pos, float durationMultiplier){ - if(WizardryUtilities.canBlockBeReplacedB(world, pos)){ + private boolean placePathwayBlockIfPossible(World world, BlockPos pos, float durationMultiplier){ + if(WizardryUtilities.canBlockBeReplaced(world, pos, true)){ world.setBlockState(pos, WizardryBlocks.spectral_block.getDefaultState()); if(world.getTileEntity(pos) instanceof TileEntityTimer){ - ((TileEntityTimer)world.getTileEntity(pos)).setLifetime((int)(1200 * durationMultiplier)); + ((TileEntityTimer)world.getTileEntity(pos)).setLifetime((int)(getProperty(DURATION).floatValue() * durationMultiplier)); } return true; } diff --git a/src/main/java/electroblob/wizardry/spell/SpeedTime.java b/src/main/java/electroblob/wizardry/spell/SpeedTime.java new file mode 100644 index 00000000..4692b176 --- /dev/null +++ b/src/main/java/electroblob/wizardry/spell/SpeedTime.java @@ -0,0 +1,133 @@ +package electroblob.wizardry.spell; + +import electroblob.wizardry.Wizardry; +import electroblob.wizardry.registry.WizardryItems; +import electroblob.wizardry.util.ParticleBuilder; +import electroblob.wizardry.util.SpellModifiers; +import electroblob.wizardry.util.WizardryUtilities; +import net.minecraft.entity.Entity; +import net.minecraft.entity.EntityLivingBase; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.item.EnumAction; +import net.minecraft.tileentity.TileEntity; +import net.minecraft.util.EnumHand; +import net.minecraft.util.ITickable; +import net.minecraft.util.SoundEvent; +import net.minecraft.util.math.BlockPos; +import net.minecraft.world.World; + +import java.util.ArrayList; +import java.util.List; + +/** + * This class represents a blank spell used to fill empty slots on wands. It is unobtainable in-game, except via + * commands, and does nothing when the player attempts to cast it. Its instance can be referenced directly using + * {@link electroblob.wizardry.registry.Spells#none Spells.none} + */ +public class SpeedTime extends Spell { + + /** The base number of ticks to add to the world time for each tick the spell is cast. */ + public static final String TIME_INCREMENT = "time_increment"; + /** The number of extra times to tick each nearby block, entity and tile entity each tick the spell is cast. */ + public static final String EXTRA_TICKS = "extra_ticks"; + + public SpeedTime(){ + super("speed_time", EnumAction.BOW, true); + addProperties(EFFECT_RADIUS, TIME_INCREMENT, EXTRA_TICKS); + } + + @Override + protected SoundEvent[] createSounds(){ + return this.createContinuousSpellSounds(); + } + + @Override + protected void playSound(World world, EntityLivingBase entity, int ticksInUse, int duration, SpellModifiers modifiers, String... sounds){ + this.playSoundLoop(world, entity, ticksInUse); + } + + @Override + protected void playSound(World world, double x, double y, double z, int ticksInUse, int duration, SpellModifiers modifiers, String... sounds){ + this.playSoundLoop(world, x, y, z, ticksInUse, duration); + } + + @Override + public boolean cast(World world, EntityPlayer caster, EnumHand hand, int ticksInUse, SpellModifiers modifiers){ + + boolean flag = false; + + // Hold onto your hats ladies and gentlemen, this effect scales with potency modifiers! Speeeeeeeeed! + if(Wizardry.settings.worldTimeManipulation){ + world.setWorldTime(world.getWorldTime() + (long)(getProperty(TIME_INCREMENT).floatValue() * modifiers.get(SpellModifiers.POTENCY))); + flag = true; + } + + double radius = getProperty(EFFECT_RADIUS).floatValue() * modifiers.get(WizardryItems.blast_upgrade); + + // Doubles the normal effect of the modifier + float potencyLevel = ((modifiers.get(SpellModifiers.POTENCY) - 1) * 2 + 1) * getProperty(EXTRA_TICKS).floatValue(); + + // Ticks all the entities near the caster + List entities = new ArrayList<>(world.loadedEntityList); + entities.removeIf(e -> e instanceof EntityPlayer); + entities.removeIf(e -> caster.getDistance(e) > radius); + + if(!entities.isEmpty()){ + for(int i = 0; i < potencyLevel; i++){ + entities.forEach(Entity::onUpdate); + } + flag = true; + } + + // Ticks all the tile entities near the caster + // Copy the list first! + List tileentities = new ArrayList<>(world.tickableTileEntities); + tileentities.removeIf(t -> caster.getDistanceSq(t.getPos()) > radius*radius); + + if(!tileentities.isEmpty()){ + for(int i = 0; i < potencyLevel; i++){ + tileentities.forEach(t -> ((ITickable)t).update()); + } + flag = true; + } + + if(!world.isRemote){ + + List sphere = WizardryUtilities.getBlockSphere(caster.getPosition(), radius); + + for(BlockPos pos : sphere){ + + if(world.getBlockState(pos).getBlock().getTickRandomly()){ + for(int i = 0; i < potencyLevel; i++){ + world.getBlockState(pos).getBlock().randomTick(world, pos, world.getBlockState(pos), world.rand); + flag = true; + } + } + } + } + + // Particle effects + if(world.isRemote){ + + for(int i=1; i<3; i++){ + + double particleSpread = 2; + double x = caster.posX + 2; + double y = caster.getEntityBoundingBox().minY + caster.height / 2; + double z = caster.posZ; + + ParticleBuilder.create(ParticleBuilder.Type.SPARKLE, world.rand, x, y, z, particleSpread, false) + .vel(-0.25, 0, 0).time(16).clr(1f, 1f, 1f).spawn(world); + + ParticleBuilder.create(ParticleBuilder.Type.FLASH, world.rand, x, y, z, particleSpread, false) + .vel(-0.25, 0, 0).time(16).scale(0.5f).clr(0.6f + world.rand.nextFloat() * 0.4f, + 0.6f + world.rand.nextFloat() * 0.4f, 0.6f + world.rand.nextFloat() * 0.4f).spawn(world); + } + } + + if(flag) playSound(world, caster, ticksInUse, -1, modifiers); + // Always return true if the world time was changed, otherwise return false if nothing was ticked. + return flag; + } + +} diff --git a/src/main/java/electroblob/wizardry/spell/Spell.java b/src/main/java/electroblob/wizardry/spell/Spell.java index e90f14b6..8ed6516e 100644 --- a/src/main/java/electroblob/wizardry/spell/Spell.java +++ b/src/main/java/electroblob/wizardry/spell/Spell.java @@ -1,26 +1,28 @@ package electroblob.wizardry.spell; -import java.util.Collection; -import java.util.HashSet; -import java.util.List; -import java.util.Set; -import java.util.function.Predicate; -import java.util.stream.Collectors; - import electroblob.wizardry.Wizardry; import electroblob.wizardry.constants.Element; import electroblob.wizardry.constants.SpellType; import electroblob.wizardry.constants.Tier; import electroblob.wizardry.entity.living.EntityWizard; +import electroblob.wizardry.item.ItemScroll; +import electroblob.wizardry.item.ItemSpellBook; +import electroblob.wizardry.packet.PacketSpellProperties; +import electroblob.wizardry.packet.WizardryPacketHandler; import electroblob.wizardry.registry.Spells; +import electroblob.wizardry.registry.WizardrySounds; import electroblob.wizardry.util.SpellModifiers; -import net.minecraft.client.resources.I18n; +import electroblob.wizardry.util.SpellProperties; import net.minecraft.entity.EntityLiving; import net.minecraft.entity.EntityLivingBase; import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.entity.player.EntityPlayerMP; import net.minecraft.item.EnumAction; +import net.minecraft.util.EnumFacing; import net.minecraft.util.EnumHand; import net.minecraft.util.ResourceLocation; +import net.minecraft.util.SoundEvent; +import net.minecraft.util.math.Vec3d; import net.minecraft.util.text.ITextComponent; import net.minecraft.util.text.TextComponentTranslation; import net.minecraft.world.World; @@ -31,24 +33,30 @@ import net.minecraftforge.registries.ForgeRegistry; import net.minecraftforge.registries.IForgeRegistry; import net.minecraftforge.registries.IForgeRegistryEntry; +import javax.annotation.Nonnull; +import javax.annotation.Nullable; +import java.util.*; +import java.util.function.Predicate; +import java.util.stream.Collectors; + /** * Generic spell class which is the superclass to all spells in wizardry. When extending this class, you must do the * following: - *

    + *

    * - Have a constructor which passes all necessary constants into the super constructor. I define the constants here so * that the constructor for an individual spell has no parameters, but you may prefer to pass in the parameters when the * spell is registered, so all the mana costs etc. are in one place like a sort of sandbox. - *

    + *

    * - Implement the {@link Spell#cast(World, EntityPlayer, EnumHand, int, SpellModifiers)} method, in which you should * execute the code that makes the spell work, and return true or false depending on whether the spell succeeded and * therefore whether mana should be used up. - *

    + *

    * - Register the spell using {@link RegistryEvent.Register}, with {@link Spell} as the type parameter. Each spell * should have a single instance, like blocks and items. As of Wizardry 2.1, spells use the Forge registry system. - * Related methods such as {@link Spell#id()} and {@link Spell#get(int)} have been re-routed to use this system, leaving + * Related methods such as {@link Spell#metadata()} and {@link Spell#byMetadata(int)} have been re-routed to use this system, leaving * minimal external changes. Note also that the constructor automatically sets the registry name for you, though you may * change it afterwards if necessary. - *

    + *

    * Also note that you can override some other methods from this class. For example, to add a specific kind of formatting * to a spell name or description, you can override {@link Spell#getDisplayName()}, * {@link Spell#getDisplayNameWithFormatting()} or {@link Spell#getDescription()} and append the formatting code (though @@ -56,8 +64,8 @@ import net.minecraftforge.registries.IForgeRegistryEntry; * {@link SummonShadowWraith#getDescription()} for an example. *
    * This class is also home to some useful static methods for interacting with the spell registry: - *

    - * {@link Spell#get(int)} gets a spell instance from its integer id, which corresponds to the metadata of its spell + *

    + * {@link Spell#byMetadata(int)} gets a spell instance from its integer metadata, which corresponds to the metadata of its spell * book.
    * {@link Spell#get(String)} gets a spell instance from its unlocalised name.
    * {@link Spell#getSpells(Predicate)} returns a list of spell instances that match the given {@link Predicate}.
    @@ -68,31 +76,48 @@ import net.minecraftforge.registries.IForgeRegistryEntry; * the order of which is as defined in {@link Element} (i.e. magic, fire, ice, lightning, necromancy, earth, sorcery, * healing). *
    - * + * * @since Wizardry 1.0 - * @see electroblob.wizardry.item.ItemSpellBook ItemSpellBook - * @see electroblob.wizardry.item.ItemScroll ItemScroll + * @see ItemSpellBook ItemSpellBook + * @see ItemScroll ItemScroll * @see Spells */ public abstract class Spell extends IForgeRegistryEntry.Impl implements Comparable { + // Spell checklist: + // - Create and register spell, add texture and properties json file + // - Add name AND description to lang files + // - Add sound(s) to sounds.json + // - Add to advancements/all_spells.json + + // Common property identifiers + public static final String DAMAGE = "damage"; + public static final String RANGE = "range"; + public static final String DURATION = "duration"; + public static final String EFFECT_RADIUS = "effect_radius"; + public static final String BLAST_RADIUS = "blast_radius"; + public static final String EFFECT_DURATION = "effect_duration"; + public static final String EFFECT_STRENGTH = "effect_strength"; + public static final String BURN_DURATION = "burn_duration"; + public static final String DIRECT_DAMAGE = "direct_damage"; + public static final String SPLASH_DAMAGE = "splash_damage"; + public static final String HEALTH = "health"; + public static final String SEEKING_STRENGTH = "seeking_strength"; + public static final String DIRECT_EFFECT_DURATION = "direct_effect_duration"; + public static final String DIRECT_EFFECT_STRENGTH = "direct_effect_strength"; + public static final String SPLASH_EFFECT_DURATION = "splash_effect_duration"; + public static final String SPLASH_EFFECT_STRENGTH = "splash_effect_strength"; + /** Forge registry-based replacement for the internal spells list. */ public static IForgeRegistry registry; - /** Mod ID of the mod that added this spell; defaults to {@link Wizardry#MODID} if not specified. */ - private final String modID; /** The unlocalised name of the spell. */ private final String unlocalisedName; - /** The tier this spell belongs to. */ - public final Tier tier; - /** The element this spell belongs to. */ - public final Element element; - /** The type of spell this is classified as. */ - public final SpellType type; - /** Mana cost of the spell. If it is a continuous spell the cost is per second. */ - public final int cost; - /** Cooldown for the spell in ticks */ - public final int cooldown; + /** This spell's associated SpellProperties object. */ + private SpellProperties properties; + /** Used in initialisation. */ + private Set propertyKeys = new HashSet<>(); + /** The action the player does when this spell is cast. */ public final EnumAction action; /** Whether or not the spell is continuous (keeps going as long as the mouse button is held) */ @@ -101,32 +126,37 @@ public abstract class Spell extends IForgeRegistryEntry.Impl implements C /** ResourceLocation of the spell icon. */ private final ResourceLocation icon; - /** - * False if the spell has been disabled in the config file, true otherwise. This is now encapsulated to stop it - * being fiddled with. - */ + /** False if the spell has been disabled in the config file, true otherwise. This is now encapsulated to stop it + * being fiddled with. */ private boolean enabled = true; + /** The sound(s) played when this spell is cast. */ + @Nullable + protected final SoundEvent[] sounds; + /** The volume of the sound played when this spell is cast. Defaults to 1. */ + protected float volume = 1; + /** The pitch of the sound played when this spell is cast. Defaults to 1. */ + protected float pitch = 1; + /** The pitch variation of the sound played when this spell is cast. Defaults to 0. */ + protected float pitchVariation = 0; + + private static int nextSpellId = 0; + /** The spell's integer ID, mainly used for networking. */ + // This was added after I learnt the hard way why you can't assume Forge's registry IDs are sequential... + private final int id; + /** * This constructor should be called from any subclasses, either feeding in the constants directly or through their * own constructor from wherever the spell is registered. This is the constructor for wizardry's own spells; spells * added by other mods should use - * {@link Spell#Spell(String, String, Tier, Element, SpellType, int, int, EnumAction, boolean)}. + * {@link Spell#Spell(String, String, EnumAction, boolean)}. * @param name The registry name of the spell. This will also be the name of the icon file. The spell's * unlocalised name will be a resource location with the format [modid]:[name]. - * @param tier The tier this spell belongs to. - * @param element The element this spell belongs to. - * @param type The type of spell this is classified as. - * @param cost The amount of mana used to cast the spell. If this is a continuous spell, it represents mana cost per - * second and should be a multiple of 5. - * @param cooldown The cooldown time for this spell in ticks. * @param action The vanilla usage action to be displayed when casting this spell. * @param isContinuous Whether this spell is continuous, meaning you cast it for a length of time by holding the - * right mouse button. */ - public Spell(String name, Tier tier, Element element, SpellType type, int cost, int cooldown, EnumAction action, - boolean isContinuous){ - this(Wizardry.MODID, name, tier, element, type, cost, cooldown, action, isContinuous); + public Spell(String name, EnumAction action, boolean isContinuous){ + this(Wizardry.MODID, name, action, isContinuous); } /** @@ -136,46 +166,153 @@ public abstract class Spell extends IForgeRegistryEntry.Impl implements C * the spell icon, and also more generally to distinguish between original and addon spells. * @param name The registry name of the spell, excluding the mod id. This will also be the name of the icon * file. The spell's unlocalised name will be a resource location with the format [modid]:[name]. - * @param tier The tier this spell belongs to. - * @param element The element this spell belongs to. - * @param type The type of spell this is classified as. - * @param cost The amount of mana used to cast the spell. If this is a continuous spell, it represents mana cost per - * second and should be a multiple of 5. - * @param cooldown The cooldown time for this spell in ticks. * @param action The vanilla usage action to be displayed when casting this spell (see {@link}EnumAction) * @param isContinuous Whether this spell is continuous, meaning you cast it for a length of time by holding the - * right mouse button. */ - public Spell(String modID, String name, Tier tier, Element element, SpellType type, int cost, int cooldown, - EnumAction action, boolean isContinuous){ - this.modID = modID; + public Spell(String modID, String name, EnumAction action, boolean isContinuous){ this.setRegistryName(modID, name); this.unlocalisedName = this.getRegistryName().toString(); - this.tier = tier; - this.element = element; - this.type = type; - this.cost = cost; - this.cooldown = cooldown; this.action = action; this.isContinuous = isContinuous; - this.icon = new ResourceLocation(this.modID, "textures/spells/" + name + ".png"); + this.icon = new ResourceLocation(modID, "textures/spells/" + name + ".png"); + this.sounds = createSounds(); + this.id = nextSpellId++; } + // ========================================= Initialisation methods =========================================== + + /** Called from {@code init()} in the main mod class. Used to initialise spell fields and properties that depend on + * other things being registered (e.g. potions). Always initialise things in the constructor wherever possible. */ + public void init(){} + + /** + * Called from the constructor to initialise this spell's sounds. By default, this creates and returns a 1-element + * array containing a single sound event called {@code spell.[unlocalised name]}. Override this to add a custom + * sound array, perhaps using one of the convenience methods (see below). + * @return An array of sound events played by this spell. + * @see Spell#createSoundWithSuffix(String) + * @see Spell#createContinuousSpellSounds + * @see Spell#playSound(World, double, double, double, int, int, SpellModifiers, String...) + */ + protected SoundEvent[] createSounds(){ + return new SoundEvent[]{WizardrySounds.createSound("spell." + this.getRegistryName().getPath())}; + } + + // Note 1: The aim here is conciseness. Keeping the identifiers in the spell classes means we don't usually have to + // qualify them with a class name, we can simply type RANGE or whatever. + // Note 2: Identifiers should be named concisely but descriptively. Usually, "range" will suffice, but "duration" + // is somewhat ambiguous - is it the duration of a potion effect, a conjured item, a summoned mob or the casting + // itself? This is why it is qualified as "effect_duration", "minion_lifetime", etc. + + /** + * Adds the given JSON identifiers to the configurable base properties of this spell. This should be called from + * the constructor or {@link Spell#init()}. It is highly recommended that property keys be defined as constants, + * as they will be needed later to retrieve the properties during the casting methods. + *

    + * General spell classes will call this method to set any properties they require in order to work properly, and + * the relevant keys will be public constants. + * @param keys One or more spell property keys to add to the spell. By convention, these are lowercase_with_underscores. + * If any of these already exists, a warning will be printed to the console. + * @return The spell instance, allowing this method to be chained onto the constructor. + * @throws IllegalStateException if this method is called after the spell properties have been initialised. + */ + // Nobody can remove property keys, which guarantees that spell classes always have the properties they need. + // It also means that subclasses need not worry about properties already defined and used in their superclass. + // Conversely, general spell classes ONLY EVER define the properties they ACTUALLY USE. + public final Spell addProperties(String... keys){ + + if(properties != null) throw new IllegalStateException("Tried to add spell properties after they were initialised"); + + for(String key : keys) if(propertyKeys.contains(key)) Wizardry.logger.warn("Tried to add a duplicate property key '" + + key + "' to spell " + this.getRegistryName()); + + Collections.addAll(propertyKeys, keys); + + return this; + } + + /** Internal, do not use. */ + public final String[] getPropertyKeys(){ + return propertyKeys.toArray(new String[0]); + } + + /** Sets this spell's properties to the given {@link SpellProperties} object, but only if it doesn't already + * have one. This prevents spell properties from being changed after initialisation. */ + public void setProperties(@Nonnull SpellProperties properties){ + + if(this.properties == null){ + this.properties = properties; + }else{ + Wizardry.logger.info("A mod attempted to set a spell's properties, but they were already initialised."); + } + } + + /** Called from the event handler when a player logs in. */ + public static void syncProperties(EntityPlayer player){ + if(player instanceof EntityPlayerMP){ + // On the server side, send a packet to the player to synchronise their spell properties + // To avoid sending extra data unnecessarily, the spell properties are sent in order of spell ID + List spells = new ArrayList<>(registry.getValuesCollection()); + spells.sort(Comparator.comparingInt(Spell::networkID)); + WizardryPacketHandler.net.sendToAll(new PacketSpellProperties.Message(spells.stream() + .map(s -> s.properties).toArray(SpellProperties[]::new))); + }else{ + // On the client side, wipe the spell properties so the new ones can be set + for(Spell spell : registry){ + spell.properties = null; // TESTME: Can we guarantee this happens before the packet arrives? + } + } + } + + // These three methods are final because they are for use by subclasses (and are pseudo-static, so to speak). + + /** + * Convenience method that generates a sound event for this spell, with the given suffix. + * @param suffix The suffix to use in the name of the returned sound event (excluding the dot) + * @return A sound event called {@code spell.[unlocalised name].[suffix]}, where [suffix] is the given string. + * @see Spell#createSoundsWithSuffixes(String[]) + */ + public final SoundEvent createSoundWithSuffix(String suffix){ + return WizardrySounds.createSound("spell." + this.getRegistryName().getPath() + "." + suffix); + } + + /** + * Compact version of {@link Spell#createSoundWithSuffix(String)} which accepts multiple suffixes and packs them + * into an array. + * @param suffixes 1 or more suffixes to use in the names of the returned sound events (excluding dots) + * @return An array of the resulting sound events. + */ + public final SoundEvent[] createSoundsWithSuffixes(String... suffixes){ + return Arrays.stream(suffixes).map(this::createSoundWithSuffix).toArray(SoundEvent[]::new); + } + + /** + * Convenience method that generates an array of 3 sound events which can be fed directly into either of the + * continuous spell sound classes' constructors. + * @return An array of three sound events called {@code spell.[unlocalised name].start}, + * {@code spell.[unlocalised name].loop} and {@code spell.[unlocalised name].end} respectively. + */ + public final SoundEvent[] createContinuousSpellSounds(){ + return createSoundsWithSuffixes("start", "loop", "end"); + } + + // ============================================ Casting methods ============================================== + /** * Casts the spell. Each subclass must override this method and within it execute the code to make the spell work. * Returns a boolean so that the main onItemRightClick or onUsingItemTick method can check if the spell was actually * cast or whether a spell specific condition caused it not to be (for example, heal won't work if the player is on * full health), preventing unfair drain of mana. - *

    + *

    * Each spell must return true when it works or the spell will not use up mana. Note that (!world.isRemote) does not * count as a condition; return true should be outside it - in other words, return a value on both the client and * the server. - *

    + *

    * It's worth noting that on the client side, this method only gets called if the server side cast() method * succeeded, so you can put any particle spawning code outside of any success conditions if there are discrepancies * between client and server. - * - * @param world A reference to the world object. Again this is for convenience, you can also use caster.world. + * + * @param world The world in which the spell is being cast. * @param caster The EntityPlayer that cast the spell. * @param hand The hand that is holding the item used to cast the spell. If no item was used, this will be the main * hand. @@ -194,21 +331,21 @@ public abstract class Spell extends IForgeRegistryEntry.Impl implements C * within it execute the code to make the spell work. Returns a boolean to allow whatever calls this method to check * if the spell was actually cast or whether a spell specific condition caused it not to be (for example, heal won't * work if the caster is on full health). - *

    + *

    * This method is intended for use by NPCs (see {@link EntityWizard}) so that they can cast spells. Override it if * you want a spell to be cast by wizards. Note that you must also override {@link Spell#canBeCastByNPCs()} to * return true to allow wizards to select the spell. For some spells, this method may well be exactly the same as * the regular cast method; for others it won't be - for example, projectile-based spells are normally done using * the player's look vector, but NPCs need to use a target-based method instead. - *

    + *

    * Each spell must return true when it works. Note that (!world.isRemote) does not count as a condition; return true * should be outside it - in other words, return a value on both the client and the server. - *

    + *

    * It's worth noting that on the client side, this method only gets called if the server side cast() method * succeeded, so you can put any particle spawning code outside of any success conditions if there are discrepancies * between client and server. - * - * @param world A reference to the world object. This is for convenience, you can also use caster.world. + * + * @param world The world in which the spell is being cast. * @param caster The EntityLiving that cast the spell. * @param hand The hand that is holding the item used to cast the spell. This will almost certainly be the main * hand. @@ -225,6 +362,69 @@ public abstract class Spell extends IForgeRegistryEntry.Impl implements C return false; } + /** + * Casts the spell, but with an origin and a direction instead of a caster. Each subclass can optionally override this + * method and within it execute the code to make the spell work. Returns a boolean to allow whatever calls this method + * to check if the spell was actually cast or whether a spell specific condition caused it not to be (for example, heal + * won't work if the caster is on full health). + *

    + * This method is intended for use by dispensers and command blocks so that they can cast spells. Override it if + * you want a spell to be cast by dispensers. Note that you must also override {@link Spell#canBeCastByDispensers()} to + * return true to allow dispensers to select the spell. For some spells, this method may well be exactly the same as + * the regular cast method; for others it won't be - for example, projectile-based spells are normally done using + * the player's look vector, but dispensers need to use a facing-based method instead. + *

    + * Each spell must return true when it works. Note that (!world.isRemote) does not count as a condition; return true + * should be outside it - in other words, return a value on both the client and the server. + *

    + * It's worth noting that on the client side, this method only gets called if the server side cast() method + * succeeded, so you can put any particle spawning code outside of any success conditions if there are discrepancies + * between client and server. + * + * @param world The world in which the spell is being cast. + * @param x The x coordinate of the origin point of the spell. + * @param y The y coordinate of the origin point of the spell. + * @param z The z coordinate of the origin point of the spell. + * @param direction The cardinal (UDNSEW) direction in which the spell is being cast. + * @param ticksInUse The number of ticks the spell has already been cast for. For all non-continuous spells, this is + * 0 and is not used. + * @param duration The duration this spell will be cast for, or -1 if it will be cast indefinitely. For all + * non-continuous spells, this is 0 and is not used. This is intended for use in sound loops; there + * should be no need to use it for anything else. + * @param modifiers A {@link SpellModifiers} object containing the modifiers that have been applied to the spell. + * See the javadoc for that class for more information. If no modifiers are required, pass in + * {@code new SpellModifiers()}. + * @return True if the spell succeeded, false if not. Returns false by default. + */ + public boolean cast(World world, double x, double y, double z, EnumFacing direction, int ticksInUse, int duration, SpellModifiers modifiers){ + return false; + } + + /** + * Called when the spell stops being cast, either from running out of mana, being stopped by the caster, or due + * to a stack of scrolls running out. Only ever called for continuous spells. This method is mostly used + * for adding particle effects and sounds on spell finish. + *

    + * Because this method is not used in the majority of cases, it was deemed excessive to have three separate + * methods for players, NPCs and dispensers. Instead, some parameters may be null depending on the circumstances, + * similar to the implementation in {@link electroblob.wizardry.event.SpellCastEvent SpellCastEvent}. + * Be sure to check for this before using them! + * + * @param world The world in which the spell was cast. + * @param caster The player or NPC that cast the spell, or null if it was cast from a dispenser. + * @param x The x coordinate of the origin point of the spell, or NaN if the spell wasn't cast from a dispenser. + * @param y The y coordinate of the origin point of the spell, or NaN if the spell wasn't cast from a dispenser. + * @param z The z coordinate of the origin point of the spell, or NaN if the spell wasn't cast from a dispenser. + * @param direction The cardinal (UDNSEW) direction in which the spell was cast, or null if the spell wasn't cast + * from a dispenser. + * @param duration The number of ticks the spell was cast for. + * @param modifiers The modifiers the spell was cast with. + */ + // Conveniently, we can't always get a reference to the target for NPC casting once the spell ends (because it + // might have died or run off, or the NPC might have lost interest...) - so let's just not bother! + public void finishCasting(World world, @Nullable EntityLivingBase caster, double x, double y, double z, + @Nullable EnumFacing direction, int duration, SpellModifiers modifiers){} + /** * Whether NPCs such as wizards can cast this spell. If you have overridden * {@link Spell#cast(World, EntityLiving, EnumHand, int, EntityLivingBase, SpellModifiers)}, you should override @@ -234,13 +434,22 @@ public abstract class Spell extends IForgeRegistryEntry.Impl implements C return false; } + /** + * Whether dispensers can cast this spell. If you have overridden + * {@link Spell#cast(World, double, double, double, EnumFacing, int, int, SpellModifiers)}, you should override this + * to return true. + */ + public boolean canBeCastByDispensers(){ + return false; + } + /** * Whether this spell requires a packet to be sent when it is cast. Returns true by default, but can be overridden * to return false if the spell's cast() method does not use any code that must be executed client-side (i.e. - * particle spawning). Does nothing for continuous spells, because they never need to send packets. - *

    + * particle spawning). This is not checked for continuous spells, because they never need to send packets. + *

    * If in doubt, leave this method as is; it is purely an optimisation. - * + * * @return false if the spell code should only be run on the server and the client of the player casting * it
    * true if the spell code should be run on the server and all clients in the dimension @@ -250,26 +459,29 @@ public abstract class Spell extends IForgeRegistryEntry.Impl implements C // Also, now I think about it, this method isn't going to make the slightest bit of difference to the item usage // actions since setItemInUse() is called in ItemWand, not the spell class - so the only thing that matters here is // the particles. - public boolean doesSpellRequirePacket(){ + public boolean requiresPacket(){ return true; } - /** - * Returns this spell's id number, which now corresponds to its position in the spell registry. Returns -1 if the - * spell has not been registered. - */ - // This is final so nothing can override it, because that would cause all kinds of problems! - public final int id(){ + // ============================================ Getter methods ============================================== + + /** Returns the metadata for this spell, which corresponds to its registry ID, or -1 if the spell has not been + * registered.
    + *
    + * Because of how the registry system works, this won't change once assigned for a given world so is guaranteed to + * be backwards-compatible by design. However, for this reason if spells are removed there may be gaps in the ID + * numbers. If a continuous set of IDs is required (for networking), use {@link Spell#networkID()}. */ + public final int metadata(){ return ((ForgeRegistry)registry).getID(this); } - /** - * Returns the mod ID for this spell, which should be the ID of the mod that added it. The mod ID is used to tell - * wizardry which filepath to use for the spell's icon. As of Wizardry 1.2, the field itself is private, but this - * getter is provided for external use (though it is never called in the main Wizardry mod). - */ - public final String getModID(){ - return modID; + /** Returns this spell's network ID number, similar to mod-specific entity IDs.
    + *
    + * Unlike {@link Spell#metadata()}, this is guaranteed to be sequential so is suitable for indexed lookup. + * However, it may change if spells are removed so is not backwards-compatible. This means it should not be + * used for data storage. */ + public final int networkID(){ + return id; } /** Returns the {@code ResourceLocation} for this spell's icon. */ @@ -277,6 +489,70 @@ public abstract class Spell extends IForgeRegistryEntry.Impl implements C return icon; } + /** Returns the {@code SoundEvent}s for this spell's sound. */ + public final SoundEvent[] getSounds(){ + return sounds; + } + + // Property getters - these are final to force addon devs to use the JSON system instead of just overriding them + + /** Returns the tier that this spell belongs to. */ + public final Tier getTier(){ + return properties.tier; + } + + /** Returns the element that this spell belongs to. */ + public final Element getElement(){ + return properties.element; + } + + /** Returns the type of spell this is classified as. */ + public final SpellType getType(){ + return properties.type; + } + + /** Returns the mana cost of the spell. If it is a continuous spell the cost is per second. */ + public final int getCost(){ + return properties.cost; + } + + /** Returns the charge-up time for the spell in ticks. */ + public final int getChargeup(){ + return properties.chargeup; + } + + /** Returns the cooldown for the spell in ticks. */ + public final int getCooldown(){ + return properties.cooldown; + } + + /** + * Returns the base value specified in JSON for the given identifier. This may be used from within the spell + * class, or from elsewhere (entities, items, etc.) via the spell's instance. + * + * @param identifier The JSON identifier for the required property. This must have been defined using + * {@link Spell#addProperties(String...)} or an exception will be thrown. + * @return The base value of the property, as a {@code Number} object. Internally this is handled as a float, but + * it is passed through as a {@code Number} to avoid casting. Be careful with rounding when extracting integer + * values! The JSON parser cannot guarantee that the property file has an integer value. + * @throws IllegalArgumentException if no property was defined with the given identifier. */ + public final Number getProperty(String identifier){ + return properties.getBaseValue(identifier); + } + + /** Returns whether the spell is enabled in any of the given {@link electroblob.wizardry.util.SpellProperties.Context Context}s. + * A spell may be disabled globally in the config, or it may be disabled for one or more specific contexts in + * its JSON file using a resource pack. If called with no arguments, defaults to any context, i.e. only returns + * false if the spell is completely disabled in all contexts. */ + public final boolean isEnabled(SpellProperties.Context... contexts){ + return enabled && (contexts.length == 0 || properties.isEnabled(contexts)); + } + + /** Sets whether the spell is enabled or not. */ + public final void setEnabled(boolean isEnabled){ + this.enabled = isEnabled; + } + /** * Returns the unlocalised name of the spell, without any prefixes or suffixes, e.g. "flame_ray". This should * only be used for translation purposes. @@ -285,6 +561,8 @@ public abstract class Spell extends IForgeRegistryEntry.Impl implements C return unlocalisedName; } + // ========================================== Translation methods ============================================ + /* The general idea with translation is to use net.minecraft.client.resources.I18n directly on the client side (and * just prepend formatting codes where necessary), and to use TextComponentTranslation on the server (setting the * style as necessary). TextComponentTranslation effectively stores what needs to be translated, without actually @@ -297,14 +575,14 @@ public abstract class Spell extends IForgeRegistryEntry.Impl implements C */ @SideOnly(Side.CLIENT) public String getDisplayName(){ - return I18n.format("spell." + unlocalisedName); + return net.minecraft.client.resources.I18n.format("spell." + unlocalisedName); } /** * Returns a {@code TextComponentTranslation} which will be translated to the display name of the spell, without * formatting (i.e. not coloured). */ - public TextComponentTranslation getNameForTranslation(){ + public ITextComponent getNameForTranslation(){ return new TextComponentTranslation("spell." + unlocalisedName); } @@ -314,7 +592,7 @@ public abstract class Spell extends IForgeRegistryEntry.Impl implements C */ @SideOnly(Side.CLIENT) public String getDisplayNameWithFormatting(){ - return this.element.getFormattingCode() + I18n.format("spell." + unlocalisedName); + return this.getElement().getFormattingCode() + net.minecraft.client.resources.I18n.format("spell." + unlocalisedName); } /** @@ -322,7 +600,7 @@ public abstract class Spell extends IForgeRegistryEntry.Impl implements C * formatting (i.e. coloured). */ public ITextComponent getNameForTranslationFormatted(){ - return new TextComponentTranslation("spell." + unlocalisedName).setStyle(this.element.getColour()); + return new TextComponentTranslation("spell." + unlocalisedName).setStyle(this.getElement().getColour()); } /** @@ -331,17 +609,124 @@ public abstract class Spell extends IForgeRegistryEntry.Impl implements C */ @SideOnly(Side.CLIENT) public String getDescription(){ - return I18n.format("spell." + unlocalisedName + ".desc"); + return net.minecraft.client.resources.I18n.format("spell." + unlocalisedName + ".desc"); } - /** Returns whether the spell is enabled in the config. */ - public final boolean isEnabled(){ - return enabled; + // ============================================ Sound methods ============================================== + + /** + * Sets the sound parameters for this spell. + * @param volume The volume of the sound played by this spell, relative to 1. + * @param pitch The pitch of the sound played by this spell, relative to 1. + * @param pitchVariation The random variation in the pitch of the sound played by this spell. The pitch at which the + * sound is played will be randomly chosen from the range: {@code pitch +/- pitchVariation}. + * @return The spell instance, allowing this method to be chained onto the constructor. Note that since this method + * only returns a {@code Spell}, if you are chaining multiple methods onto the constructor this should be called last. + */ + public Spell soundValues(float volume, float pitch, float pitchVariation){ + this.volume = volume; + this.pitch = pitch; + this.pitchVariation = pitchVariation; + return this; } - /** Sets whether the spell is enabled or not. */ - public final void setEnabled(boolean isEnabled){ - this.enabled = isEnabled; + // The general motivation for the spell-based sound system is as follows: + // - There are a lot of spells, and each spell has at least one sound event, which means a lot of sounds! + // - Blocks and entities also define their own sounds, though this system is a bit half-hearted because they + // still have to be registered manually + // - Most spell sounds are used only from within their respective spells + // - I don't want hundreds of simple spell sounds that aren't referenced elsewhere cluttering up WizardrySounds, + // so I'm keeping them in the spell instead - if you really want them you can use getSounds, but really it's bad + // practice to reuse other sound events (something I found out the hard way!) + // - The pitch variation thing is annoying to keep repeating so it's also centralised here + + /** + * Plays this spell's sound at the given entity in the given world. This calls {@link Spell#playSound(World, double, double, double, int, int, SpellModifiers, String...)}, passing in the given entity's position as the xyz coordinates. Also checks if the given entity + * is silent, and if so, does not play the sound. + *

    + * If you are overriding the {@code Spell.playSound} methods, it is recommended that you override the xyz version + * instead of this one, since this method calls that one anyway - unless you want different behaviour for entities. + * @param world The world to play the sound in. + * @param entity The entity to play the sound at, provided it is not silent. + * @param ticksInUse The number of ticks this spell has already been cast for, passed in from the {@code cast(...)} + * methods. Not used in the base method, but included for use by subclasses overriding this method. + * @param duration The number of ticks this spell will be cast for, passed in from the {@code cast(...)} + * methods. Not used in the base method, but included for use by subclasses overriding this method. + * @param modifiers The modifiers this spell was cast with, passed in from the {@code cast(...)} methods. + * @param sounds A number of strings representing the sounds to be played. If omitted, all of this spell's sounds + * will be played at once. String format is as passed to {@link Spell#createSoundWithSuffix(String)}. + */ + protected void playSound(World world, EntityLivingBase entity, int ticksInUse, int duration, SpellModifiers modifiers, String... sounds){ + if(!entity.isSilent()){ + this.playSound(world, entity.posX, entity.posY, entity.posZ, ticksInUse, duration, modifiers, sounds); + } + } + + /** + * Plays this spell's sound at the given position in the given world. This is a vector-based wrapper for + * {@link Spell#playSound(World, double, double, double, int, int, SpellModifiers, String...)}. + *

    + * If you are overriding the {@code Spell.playSound} methods, it is recommended that you override the xyz version + * instead of this one, since this method calls that one anyway. + * @param world The world to play the sound in. + * @param pos A vector representing the position to play the sound at. + * @param ticksInUse The number of ticks this spell has already been cast for, passed in from the {@code cast(...)} + * methods. Not used in the base method, but included for use by subclasses overriding this method. + * @param duration The number of ticks this spell will be cast for, passed in from the {@code cast(...)} + * methods. Not used in the base method, but included for use by subclasses overriding this method. + * @param modifiers The modifiers this spell was cast with, passed in from the {@code cast(...)} methods. + */ + protected void playSound(World world, Vec3d pos, int ticksInUse, int duration, SpellModifiers modifiers, String... sounds){ + this.playSound(world, pos.x, pos.y, pos.z, ticksInUse, duration, modifiers, sounds); + } + + /** + * Plays this spell's sounds at the given position in the given world. This is not called automatically; subclasses + * should call it at the appropriate point(s) in the cast methods. By default, it checks whether each sound is null + * before playing, so callers shouldn't have to. + *

    + * Usually, this method will be called by the general spell classes; this is clearly stated in those classes. When + * extending such a class, it is also possible to override this method to add extra sounds or change the sound + * behaviour entirely (for example, playing a continuous spell sound). + * @param world The world to play the sound in. + * @param x The x position to play the sound at. + * @param y The y position to play the sound at. + * @param z The z position to play the sound at. + * @param ticksInUse The number of ticks this spell has already been cast for, passed in from the {@code cast(...)} + * methods. Not used in the base method, but included for use by subclasses overriding this method. + * @param duration The number of ticks this spell will be cast for, passed in from the {@code cast(...)} + * methods. Not used in the base method, but included for use by subclasses overriding this method. + * @param modifiers The modifiers this spell was cast with, passed in from the {@code cast(...)} methods. + */ + protected void playSound(World world, double x, double y, double z, int ticksInUse, int duration, SpellModifiers modifiers, String... sounds){ + + List identifiers = Arrays.stream(sounds).map(s -> "spell." + this.getRegistryName().getPath() + "." + s) + .collect(Collectors.toList()); + + if(this.sounds != null){ + for(SoundEvent sound : this.sounds){ + ResourceLocation soundName = SoundEvent.REGISTRY.getNameForObject(sound); + if(soundName != null && (identifiers.size() == 0 || identifiers.contains(soundName.getPath()))){ + world.playSound(null, x, y, z, sound, WizardrySounds.SPELLS, volume, pitch + pitchVariation * (world.rand.nextFloat() - 0.5f)); + } + } + } + } + + /** Helper method which plays a standard continuous spell sound loop on the first casting tick, which moves + * with the given entity. */ + protected final void playSoundLoop(World world, EntityLivingBase entity, int ticksInUse){ + if(ticksInUse == 0 && world.isRemote) Wizardry.proxy.playSpellSoundLoop(entity, this, this.sounds, + WizardrySounds.SPELLS, volume, pitch + pitchVariation * (world.rand.nextFloat() - 0.5f)); + } + + /** Helper method which plays a standard continuous spell sound loop on the first casting tick, at the given + * coordinates. If the given duration is -1, the coordinates must be those of a dispenser. */ + protected final void playSoundLoop(World world, double x, double y, double z, int ticksInUse, int duration){ + if(ticksInUse == 0 && world.isRemote){ + Wizardry.proxy.playSpellSoundLoop(world, x, y, z, this, this.sounds, + WizardrySounds.SPELLS, volume, pitch + pitchVariation * (world.rand.nextFloat() - 0.5f), duration); + } } // Spells are sorted according to tier and element. Where several spells have the same tier and element, @@ -349,22 +734,16 @@ public abstract class Spell extends IForgeRegistryEntry.Impl implements C @Override public final int compareTo(Spell spell){ - if(this.tier.ordinal() > spell.tier.ordinal()){ + if(this.getTier().ordinal() > spell.getTier().ordinal()){ return 1; - }else if(this.tier.ordinal() < spell.tier.ordinal()){ + }else if(this.getTier().ordinal() < spell.getTier().ordinal()){ return -1; }else{ - if(this.element.ordinal() > spell.element.ordinal()){ - return 1; - }else if(this.element.ordinal() < spell.element.ordinal()){ - return -1; - }else{ - return 0; - } + return Integer.compare(this.getElement().ordinal(), spell.getElement().ordinal()); } } - // ================================================ Static methods ================================================== + // ============================================ Static methods ============================================== /** * Returns the total number of registered spells, excluding the 'None' spell. Returns the same number that would be @@ -375,31 +754,34 @@ public abstract class Spell extends IForgeRegistryEntry.Impl implements C } /** - * Gets a spell instance from its integer id, which now corresponds to its id in the spell registry. If the given id - * has no spell (i.e. is less than 0 or greater than the total number of spells - 1) then it will return the - * {@link None} spell. - *

    - * If you are calling this from inside a loop in which you are iterating through the spells, there is probably a - * better way; see {@link Spell#getSpells(Predicate)}. + * Gets a spell instance from its integer metadata, which corresponds to its ID in the spell registry. If the given + * metadata has no spell assigned then the {@link None} spell will be returned. */ - public static Spell get(int id){ - if(id < 0 || id >= registry.getValuesCollection().size()){ - return Spells.none; - } - Spell spell = ((ForgeRegistry)registry).getValue(id); + public static Spell byMetadata(int metadata){ + Spell spell = ((ForgeRegistry)registry).getValue(metadata); return spell == null ? Spells.none : spell; } + /** Gets a spell instance from its network ID. Or the {@link None} spell if no such spell exists. */ + public static Spell byNetworkID(int id){ + if(id < 0 || id >= registry.getValuesCollection().size()){ + return Spells.none; + } + return registry.getValuesCollection().stream().filter(s -> s.id == id).findAny().orElse(Spells.none); + } + /** - * Returns the spell with the given registry name, or null if no such spell exists. - * + * Returns the spell with the given registry name, or null if no such spell exists. This is really only intended + * for cases where the user has input a name (currently commands and loot functions) and may have omitted the mod + * ID for spells in the base mod. Otherwise, use {@code Spell.registry.getValue(ResourceLocation)}. + * * @param name The registry name of the spell, in the form [mod id]:[spell name]. If no mod id is specified, it * defaults to {@link Wizardry#MODID}. */ public static Spell get(String name){ ResourceLocation key = new ResourceLocation(name); if(key.getNamespace().equals("minecraft")) key = new ResourceLocation(Wizardry.MODID, name); - return ((ForgeRegistry)registry).getValue(key); + return registry.getValue(key); } /** Returns a list of all registered spells' registry names, excluding the 'none' spell. Used in commands. */ @@ -415,34 +797,30 @@ public abstract class Spell extends IForgeRegistryEntry.Impl implements C * internal spells list; any changes you make to the returned list will have no effect on wizardry since the * returned list is local to this method. Never includes the {@link None} spell. For convenience, there are some * predefined predicates in the Spell class (some of these really aren't shortcuts any more): - *

    + *

    * {@link Spell#allSpells} will allow all spells to be returned
    - * {@link Spell#enabledSpells} will filter out any spells that are disabled in the config
    * {@link Spell#npcSpells} will only allow enabled spells that can be cast by NPCs (see * {@link Spell#canBeCastByNPCs()})
    * {@link Spell#nonContinuousSpells} will filter out continuous spells but not disabled spells
    - * {@link Spell.TierElementFilter} will only allow enabled spells of the specified tier and element - * + * {@link TierElementFilter} will only allow enabled spells of the specified tier and element + * * @param filter A Predicate<Spell> that the returned spells must satisfy. - * + * * @return A local, modifiable list of spells matching the given predicate. Note that this list may be * empty. */ public static List getSpells(Predicate filter){ - return registry.getValuesCollection().stream().filter(filter.and(p -> p != Spells.none)).collect(Collectors.toList()); + return registry.getValuesCollection().stream().filter(filter.and(s -> s != Spells.none)).collect(Collectors.toList()); } /** Predicate which allows all spells. */ public static Predicate allSpells = s -> true; - /** Predicate which allows all enabled spells. */ - public static Predicate enabledSpells = Spell::isEnabled; - /** Predicate which allows all non-continuous spells, even those that have been disabled. */ public static Predicate nonContinuousSpells = s -> !s.isContinuous; /** Predicate which allows all enabled spells for which {@link Spell#canBeCastByNPCs()} returns true. */ - public static Predicate npcSpells = s -> s.isEnabled() && s.canBeCastByNPCs(); + public static Predicate npcSpells = s -> s.isEnabled(SpellProperties.Context.NPCS) && s.canBeCastByNPCs(); /** * Predicate which allows all enabled spells of the given tier and element (create an instance of this class each @@ -453,23 +831,29 @@ public abstract class Spell extends IForgeRegistryEntry.Impl implements C private Tier tier; private Element element; + private SpellProperties.Context[] contexts; /** * Creates a new TierElementFilter that checks for the given tier and element. Does not allow spells that have - * been disabled in the config. - * + * been disabled in the config or in their JSON files. + * * @param tier The EnumTier to check for. Pass in null to allow all tiers. * @param element The EnumElement to check for. Pass in null to allow all elements. + * @param contexts The {@link electroblob.wizardry.util.SpellProperties.Context Context}s in which to check + * for enabled spells. The spell must be enabled in at least one of these contexts to pass + * the filter. If omitted, defaults to all contexts i.e. only completely disabled spells are + * filtered out. */ - public TierElementFilter(Tier tier, Element element){ + public TierElementFilter(Tier tier, Element element, SpellProperties.Context... contexts){ this.tier = tier; this.element = element; + this.contexts = contexts; } @Override public boolean test(Spell spell){ - return spell.isEnabled() && (this.tier == null || spell.tier == this.tier) - && (this.element == null || spell.element == this.element); + return spell.isEnabled(contexts) && (this.tier == null || spell.getTier() == this.tier) + && (this.element == null || spell.getElement() == this.element); } } } diff --git a/src/main/java/electroblob/wizardry/spell/SpellAreaEffect.java b/src/main/java/electroblob/wizardry/spell/SpellAreaEffect.java index 3194da2d..f310ee2f 100644 --- a/src/main/java/electroblob/wizardry/spell/SpellAreaEffect.java +++ b/src/main/java/electroblob/wizardry/spell/SpellAreaEffect.java @@ -1,67 +1,36 @@ package electroblob.wizardry.spell; -import java.util.List; - -import javax.annotation.Nullable; - import electroblob.wizardry.Wizardry; -import electroblob.wizardry.constants.Element; -import electroblob.wizardry.constants.SpellType; -import electroblob.wizardry.constants.Tier; import electroblob.wizardry.registry.WizardryItems; +import electroblob.wizardry.util.AllyDesignationSystem; import electroblob.wizardry.util.SpellModifiers; import electroblob.wizardry.util.WizardryUtilities; import net.minecraft.entity.EntityLivingBase; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.item.EnumAction; import net.minecraft.util.EnumHand; -import net.minecraft.util.SoundEvent; import net.minecraft.util.math.MathHelper; import net.minecraft.world.World; +import java.util.List; + +/** [NYI] */ public abstract class SpellAreaEffect extends Spell { // TODO: This class doesn't really work as it is right now, it needs rethinking. The aim is to try and have all the // different casting methods call a single (abstract) positional method to do the actual AoE. - - /** The base radius of this spell's area of effect. */ - protected final double baseRadius; - /** The sound that gets played when this spell is cast. */ - @Nullable - protected final SoundEvent sound; - + /** The average number of particles to spawn per block in this spell's area of effect. */ protected float particleDensity = 0.65f; - /** The volume of the sound played when this spell is cast. Defaults to 1. */ - protected float volume = 1; - /** The pitch of the sound played when this spell is cast. Defaults to 1. */ - protected float pitch = 1; - /** The pitch variation of the sound played when this spell is cast. Defaults to 0. */ - protected float pitchVariation = 0; - - public SpellAreaEffect(String name, Tier tier, Element element, SpellType type, int cost, int cooldown, EnumAction action, double baseRadius, SoundEvent sound){ - this(Wizardry.MODID, name, tier, element, type, cost, cooldown, action, baseRadius, sound); - } - - public SpellAreaEffect(String modID, String name, Tier tier, Element element, SpellType type, int cost, int cooldown, EnumAction action, double baseRadius, SoundEvent sound){ - super(modID, name, tier, element, type, cost, cooldown, action, false); - this.baseRadius = baseRadius; - this.sound = sound; - } - /** - * Sets the sound parameters for this spell. - * @param volume - * @param pitch - * @param pitchVariation - * @return The spell instance, allowing this method to be chained onto the constructor. - */ - public SpellAreaEffect soundValues(float volume, float pitch, float pitchVariation) { - this.volume = volume; - this.pitch = pitch; - this.pitchVariation = pitchVariation; - return this; - } + public SpellAreaEffect(String name, EnumAction action){ + this(Wizardry.MODID, name, action); + } + + public SpellAreaEffect(String modID, String name, EnumAction action){ + super(modID, name, action, false); + this.addProperties(EFFECT_RADIUS); + } /** * Sets the number of particles to spawn per block for this spell. @@ -76,10 +45,10 @@ public abstract class SpellAreaEffect extends Spell { @Override public boolean cast(World world, EntityPlayer caster, EnumHand hand, int ticksInUse, SpellModifiers modifiers){ - List targets = WizardryUtilities.getEntitiesWithinRadius( - baseRadius * modifiers.get(WizardryItems.blast_upgrade), caster.posX, caster.posY, caster.posZ, world); + List targets = WizardryUtilities.getEntitiesWithinRadius(getProperty(EFFECT_RADIUS).floatValue() + * modifiers.get(WizardryItems.blast_upgrade), caster.posX, caster.posY, caster.posZ, world); - targets.removeIf(target -> !WizardryUtilities.isValidTarget(caster, target)); + targets.removeIf(target -> !AllyDesignationSystem.isValidTarget(caster, target)); for(EntityLivingBase target : targets){ affectEntity(world, caster, target, modifiers); @@ -89,7 +58,7 @@ public abstract class SpellAreaEffect extends Spell { spawnParticleEffect(world, caster, modifiers); } - if(sound != null) WizardryUtilities.playSoundAtPlayer(caster, sound, volume, pitch + pitchVariation * (world.rand.nextFloat() - 0.5f)); + this.playSound(world, caster, ticksInUse, -1, modifiers); return true; } @@ -107,13 +76,13 @@ public abstract class SpellAreaEffect extends Spell { * Called to spawn the spell's particle effect. By default, this generates a set of random points within the spell's * area of effect and calls {@link SpellAreaEffect#spawnParticle(World, double, double, double)} at each to spawn * the individual particles. Only called client-side. Override to add a custom particle effect. - * @param world - * @param caster - * @param modifiers - */ + * @param world The world to spawn the particles in. + * @param caster The caster of the spell. + * @param modifiers The modifiers the spell was cast with. + */ protected void spawnParticleEffect(World world, EntityLivingBase caster, SpellModifiers modifiers){ - double maxRadius = baseRadius * modifiers.get(WizardryItems.blast_upgrade); + double maxRadius = getProperty(EFFECT_RADIUS).floatValue() * modifiers.get(WizardryItems.blast_upgrade); int particleCount = (int)Math.round(particleDensity * Math.PI * maxRadius * maxRadius); for(int i=0; i + *

    + * Properties added by this type of spell: {@link Spell#RANGE} + *

    * By default, this type of spell can be cast by NPCs. {@link Spell#canBeCastByNPCs()} - *

    - * By default, this type of spell does not require a packet to be sent. {@link Spell#doesSpellRequirePacket()} + *

    + * By default, this type of spell can be cast by dispensers. {@link Spell#canBeCastByDispensers()} + *

    + * By default, this type of spell does not require a packet to be sent. {@link Spell#requiresPacket()} * * @author Electroblob * @since Wizardry 4.2 */ -public class SpellArrow extends Spell { +public class SpellArrow extends Spell { + + private static final float DISPENSER_INACCURACY = 1; // This is the same as for players + private static final float FALLBACK_VELOCITY = 2; // 2 seems to be a pretty standard value // The general contract for these spell subtypes is that any required parameters are set via the constructor and are // final, whereas any non-critical parameters are set via chainable setters with sensible defaults if not. For example, // the actual sound to play is required, but it makes sense for its volume and pitch to default to 1 if unspecified. /** A factory that creates projectile entities. */ - protected final Function arrowFactory; - /** The base range (projectile speed) of this spell. */ - protected final float baseRange; - /** The sound that gets played when this spell is cast, or null if the spell plays no sound. */ - @Nullable - protected final SoundEvent sound; + protected final Function arrowFactory; - /** The volume of the sound played when this spell is cast. Defaults to 1. */ - protected float volume = 1; - /** The pitch of the sound played when this spell is cast. Defaults to 1. */ - protected float pitch = 1; - /** The pitch variation of the sound played when this spell is cast. Defaults to 0. */ - protected float pitchVariation = 0; - - public SpellArrow(String name, Tier tier, Element element, int cost, int cooldown, Function arrowFactory, float baseRange, SoundEvent sound) { - this(Wizardry.MODID, name, tier, element, cost, cooldown, arrowFactory, baseRange, sound); + public SpellArrow(String name, Function arrowFactory){ + this(Wizardry.MODID, name, arrowFactory); } - public SpellArrow(String modID, String name, Tier tier, Element element, int cost, int cooldown, Function arrowFactory, float baseRange, SoundEvent sound){ - super(modID, name, tier, element, SpellType.PROJECTILE, cost, cooldown, EnumAction.NONE, false); + public SpellArrow(String modID, String name, Function arrowFactory){ + super(modID, name, EnumAction.NONE, false); this.arrowFactory = arrowFactory; - this.baseRange = baseRange; - this.sound = sound; + this.addProperties(RANGE); } - /** - * Sets the sound parameters for this spell. - * @param volume - * @param pitch - * @param pitchVariation - * @return The spell instance, allowing this method to be chained onto the constructor. - */ - public SpellArrow soundValues(float volume, float pitch, float pitchVariation) { - this.volume = volume; - this.pitch = pitch; - this.pitchVariation = pitchVariation; - return this; - } - - @Override public boolean doesSpellRequirePacket(){ return false; } + @Override public boolean requiresPacket(){ return false; } @Override public boolean canBeCastByNPCs(){ return true; } + + @Override public boolean canBeCastByDispensers() { return true; } + + /** Computes the velocity the projectile should be launched at to achieve the required range. */ + // Long story short, it doesn't make much sense to me to have the JSON file specify the velocity - even less so if + // the velocity is masquerading under the tag 'range' - so we'll let the code do the heavy lifting so people can + // input something meaningful. + protected float calculateVelocity(EntityMagicArrow projectile, SpellModifiers modifiers, float launchHeight){ + // The required range + float range = getProperty(RANGE).floatValue() * modifiers.get(WizardryItems.range_upgrade); + + if(!projectile.doGravity()){ + // No sensible spell will do this - range is meaningless if the particle has no gravity or lifetime + if(projectile.getLifetime() <= 0) return FALLBACK_VELOCITY; + // Speed = distance/time (trivial, I know, but I've put it here for the sake of completeness) + return range / projectile.getLifetime(); + }else{ + // Arrows have gravity 0.05 + float g = 0.05f; + // Assume horizontal projection + return range / MathHelper.sqrt(2 * launchHeight/g); + } + } @Override public boolean cast(World world, EntityPlayer caster, EnumHand hand, int ticksInUse, SpellModifiers modifiers){ if(!world.isRemote){ // Creates a projectile from the supplied factory - EntityMagicArrow projectile = arrowFactory.apply(world); + T projectile = arrowFactory.apply(world); // Sets the necessary parameters - projectile.aim(caster, baseRange * modifiers.get(WizardryItems.range_upgrade)); + projectile.aim(caster, calculateVelocity(projectile, modifiers, caster.getEyeHeight() + - (float)EntityMagicArrow.LAUNCH_Y_OFFSET)); projectile.damageMultiplier = modifiers.get(SpellModifiers.POTENCY); + addArrowExtras(projectile, caster, modifiers); // Spawns the projectile in the world world.spawnEntity(projectile); } caster.swingArm(hand); - if(sound != null) WizardryUtilities.playSoundAtPlayer(caster, sound, volume, pitch + pitchVariation * (world.rand.nextFloat() - 0.5f)); + this.playSound(world, caster, ticksInUse, -1, modifiers); return true; } @@ -112,19 +116,21 @@ public class SpellArrow extends Spell { if(!world.isRemote){ // Creates a projectile from the supplied factory - EntityMagicArrow projectile = arrowFactory.apply(world); + T projectile = arrowFactory.apply(world); // Sets the necessary parameters int aimingError = caster instanceof ISpellCaster ? ((ISpellCaster)caster).getAimingError(world.getDifficulty()) : WizardryUtilities.getDefaultAimingError(world.getDifficulty()); - projectile.aim(caster, target, baseRange * modifiers.get(WizardryItems.range_upgrade), aimingError); + projectile.aim(caster, target, calculateVelocity(projectile, modifiers, caster.getEyeHeight() + - (float)EntityMagicProjectile.LAUNCH_Y_OFFSET), aimingError); projectile.damageMultiplier = modifiers.get(SpellModifiers.POTENCY); + addArrowExtras(projectile, caster, modifiers); // Spawns the projectile in the world world.spawnEntity(projectile); } caster.swingArm(hand); - if(sound != null) caster.playSound(sound, volume, pitch + pitchVariation * (world.rand.nextFloat() - 0.5f)); + this.playSound(world, caster, ticksInUse, -1, modifiers); return true; } @@ -132,4 +138,38 @@ public class SpellArrow extends Spell { return false; } + @Override + public boolean cast(World world, double x, double y, double z, EnumFacing direction, int ticksInUse, int duration, SpellModifiers modifiers){ + + if(!world.isRemote){ + // Creates a projectile from the supplied factory + T projectile = arrowFactory.apply(world); + // Sets the necessary parameters + projectile.setPosition(x, y, z); + Vec3i vec = direction.getDirectionVec(); + projectile.shoot(vec.getX(), vec.getY(), vec.getZ(), calculateVelocity(projectile, modifiers, + 0.375f), DISPENSER_INACCURACY); // 0.375 is the height of the hole in a dispenser + projectile.damageMultiplier = modifiers.get(SpellModifiers.POTENCY); + addArrowExtras(projectile, null, modifiers); + // Spawns the projectile in the world + world.spawnEntity(projectile); + } + + // This MUST be the coordinates of the actual dispenser, so we need to offset it + this.playSound(world, x - direction.getXOffset(), y - direction.getYOffset(), z - direction.getZOffset(), ticksInUse, duration, modifiers); + + return true; + } + + /** + * Called just before the arrow is spawned. Does nothing by default, but subclasses can override to call extra + * methods on the spawned arrow. This method is only called server-side so cannot be used to spawn particles directly. + * @param arrow The entity being spawned. + * @param caster The caster of this spell, or null if it was cast by a dispenser. + * @param modifiers The modifiers this spell was cast with. + */ + protected void addArrowExtras(T arrow, @Nullable EntityLivingBase caster, SpellModifiers modifiers){ + // Subclasses can put spell-specific stuff here + } + } diff --git a/src/main/java/electroblob/wizardry/spell/SpellBuff.java b/src/main/java/electroblob/wizardry/spell/SpellBuff.java index f4277c69..5a7273a5 100644 --- a/src/main/java/electroblob/wizardry/spell/SpellBuff.java +++ b/src/main/java/electroblob/wizardry/spell/SpellBuff.java @@ -1,96 +1,98 @@ package electroblob.wizardry.spell; -import java.util.Arrays; -import java.util.Set; -import java.util.stream.Collectors; - -import org.apache.commons.lang3.tuple.Triple; - import electroblob.wizardry.Wizardry; -import electroblob.wizardry.constants.Element; -import electroblob.wizardry.constants.SpellType; -import electroblob.wizardry.constants.Tier; import electroblob.wizardry.registry.WizardryItems; import electroblob.wizardry.util.ParticleBuilder; import electroblob.wizardry.util.ParticleBuilder.Type; import electroblob.wizardry.util.SpellModifiers; -import electroblob.wizardry.util.WizardryUtilities; import net.minecraft.entity.EntityLiving; import net.minecraft.entity.EntityLivingBase; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.item.EnumAction; import net.minecraft.potion.Potion; import net.minecraft.potion.PotionEffect; +import net.minecraft.util.EnumFacing; import net.minecraft.util.EnumHand; -import net.minecraft.util.SoundEvent; +import net.minecraft.util.math.AxisAlignedBB; +import net.minecraft.util.math.BlockPos; import net.minecraft.world.World; +import java.util.Arrays; +import java.util.List; +import java.util.Set; +import java.util.function.Supplier; +import java.util.stream.Collectors; + /** * Generic superclass for all spells which buff their caster. * This allows all the relevant code to be centralised, since these spells all work in the same way. Usually, a simple * instantiation of this class is sufficient to create a buff spell; if something extra needs to be done, such as * applying a non-potion buff, then methods can be overridden (perhaps using an anonymous class) to add the required * functionality. - *

    + *

    + * Properties added by this type of spell: {@link SpellBuff#getDurationKey(Potion)}, {@link SpellBuff#getStrengthKey(Potion)} + *

    * By default, this type of spell can be cast by NPCs. {@link Spell#canBeCastByNPCs()} - *

    - * By default, this type of spell requires a packet to be sent. {@link Spell#doesSpellRequirePacket()} + *

    + * By default, this type of spell can be cast by dispensers. {@link Spell#canBeCastByDispensers()} + *

    + * By default, this type of spell requires a packet to be sent. {@link Spell#requiresPacket()} * * @author Electroblob * @since Wizardry 4.2 */ public class SpellBuff extends Spell { - /** An array of triples representing the parameters of the status effects that this spell applies to its caster. - * These are of the form [effect, base duration, base amplifier]. */ - protected final Triple[] effects; - /** A set of all the different potions (status effects) that this spell applies to its caster. */ - protected final Set potionSet; - /** The sound that gets played when this spell is cast. */ - protected final SoundEvent sound; + /** An array of factories for the status effects that this spell applies to its caster. The effect factory + * avoids the issue of the potions being registered after the spell. */ + protected final Supplier[] effects; + /** A set of all the different potions (status effects) that this spell applies to its caster. Loaded during + * init(). */ + protected Set potionSet; /** The RGB colour values of the particles spawned when this spell is cast. */ protected final float r, g, b; - /** The volume of the sound played when this spell is cast. Defaults to 1. */ - protected float volume = 1; - /** The pitch of the sound played when this spell is cast. Defaults to 1. */ - protected float pitch = 1; - /** The pitch variation of the sound played when this spell is cast. Defaults to 0. */ - protected float pitchVariation = 0; - /** The number of sparkle particles spawned when this spell is cast. Defualts to 10. */ + /** The number of sparkle particles spawned when this spell is cast. Defaults to 10. */ protected float particleCount = 10; @SafeVarargs - public SpellBuff(String name, Tier tier, Element element, SpellType type, int cost, int cooldown, SoundEvent sound, float r, float g, float b, Triple... effects){ - this(Wizardry.MODID, name, tier, element, type, cost, cooldown, sound, r, g, b, effects); + public SpellBuff(String name, float r, float g, float b, Supplier... effects){ + this(Wizardry.MODID, name, r, g, b, effects); } @SafeVarargs - public SpellBuff(String modID, String name, Tier tier, Element element, SpellType type, int cost, int cooldown, SoundEvent sound, float r, float g, float b, Triple... effects){ - super(modID, name, tier, element, type, cost, cooldown, EnumAction.BOW, false); - this.sound = sound; + public SpellBuff(String modID, String name, float r, float g, float b, Supplier... effects){ + super(modID, name, EnumAction.BOW, false); this.effects = effects; this.r = r; this.g = g; this.b = b; - // Pretty sure this is better than iterating over (or streaming) all the elements each time the spell is cast. - this.potionSet = Arrays.stream(effects).map(Triple::getLeft).collect(Collectors.toSet()); } - - /** - * Sets the sound parameters for this spell. - * @param volume - * @param pitch - * @param pitchVariation - * @return The spell instance, allowing this method to be chained onto the constructor. - */ - public SpellBuff soundValues(float volume, float pitch, float pitchVariation) { - this.volume = volume; - this.pitch = pitch; - this.pitchVariation = pitchVariation; - return this; + + @Override + public void init(){ + // Loads the potion set + this.potionSet = Arrays.stream(effects).map(Supplier::get).collect(Collectors.toSet()); + + for(Potion potion : potionSet){ + // I don't like having this for all buff spells when some potions aren't affected by amplifiers + // TODO: Find a way of only adding the strength key if the potion is affected by amplifiers (dynamically if possible) + // BrewingRecipeRegistry#getOutput might be a good place to start + addProperties(getStrengthKey(potion)); + if(!potion.isInstant()) addProperties(getDurationKey(potion)); + } } - + + // Potion-specific equivalent to defining the identifiers as constants + + protected static String getDurationKey(Potion potion){ + return potion.getRegistryName().getPath() + "_duration"; + } + + protected static String getStrengthKey(Potion potion){ + return potion.getRegistryName().getPath() + "_strength"; + } + /** * Sets the number of sparkle particles spawned when this spell is cast. * @param particleCount The number of particles. @@ -102,13 +104,15 @@ public class SpellBuff extends Spell { } @Override public boolean canBeCastByNPCs(){ return true; } + + @Override public boolean canBeCastByDispensers() { return true; } @Override public boolean cast(World world, EntityPlayer caster, EnumHand hand, int ticksInUse, SpellModifiers modifiers){ - - if(!this.applyEffects(caster, modifiers)) return false; + // Only return on the server side or the client probably won't spawn particles + if(!this.applyEffects(caster, modifiers) && !world.isRemote) return false; if(world.isRemote) this.spawnParticles(world, caster, modifiers); - WizardryUtilities.playSoundAtPlayer(caster, sound, volume, pitch + pitchVariation * (world.rand.nextFloat() - 0.5f)); + this.playSound(world, caster, ticksInUse, -1, modifiers); return true; } @@ -116,9 +120,38 @@ public class SpellBuff extends Spell { public boolean cast(World world, EntityLiving caster, EnumHand hand, int ticksInUse, EntityLivingBase target, SpellModifiers modifiers){ // Wizards can only cast a buff spell if they don't already have its effects. if(caster.getActivePotionMap().keySet().containsAll(potionSet)) return false; - if(!this.applyEffects(caster, modifiers)) return false; + // Only return on the server side or the client probably won't spawn particles + if(!this.applyEffects(caster, modifiers) && !world.isRemote) return false; if(world.isRemote) this.spawnParticles(world, caster, modifiers); - caster.playSound(sound, volume, pitch + pitchVariation * (world.rand.nextFloat() - 0.5f)); + this.playSound(world, caster, ticksInUse, -1, modifiers); + return true; + } + + @Override + public boolean cast(World world, double x, double y, double z, EnumFacing direction, int ticksInUse, int duration, SpellModifiers modifiers){ + // Gets a 1x1x1 bounding box corresponding to the block in front of the dispenser + AxisAlignedBB boundingBox = new AxisAlignedBB(new BlockPos(x, y, z)); + List entities = world.getEntitiesWithinAABB(EntityLivingBase.class, boundingBox); + + float distance = -1; + EntityLivingBase nearestEntity = null; + // Finds the nearest entity within the bounding box + for(EntityLivingBase entity : entities){ + float newDistance = (float)entity.getDistance(x, y, z); + if(distance == -1 || newDistance < distance){ + distance = newDistance; + nearestEntity = entity; + } + } + + if(nearestEntity == null) return false; + + // Only return on the server side or the client probably won't spawn particles + if(!this.applyEffects(nearestEntity, modifiers) && !world.isRemote) return false; + if(world.isRemote) this.spawnParticles(world, nearestEntity, modifiers); + // This MUST be the coordinates of the actual dispenser, so we need to offset it + this.playSound(world, x - direction.getXOffset(), y - direction.getYOffset(), z - direction.getZOffset(), ticksInUse, duration, modifiers); + return true; } @@ -128,14 +161,34 @@ public class SpellBuff extends Spell { * Returns a boolean to allow subclasses to cause the spell to fail if for some reason the effect cannot be applied * (for example, {@link Heal} fails if the caster is on full health). */ protected boolean applyEffects(EntityLivingBase caster, SpellModifiers modifiers){ - // TODO: Find a good way (if any) of implementing potency modifiers - for(Triple effect : effects){ - caster.addPotionEffect(new PotionEffect(effect.getLeft(), (int)(effect.getMiddle() - * modifiers.get(WizardryItems.duration_upgrade)), effect.getRight(), false, false)); + // This will generate 0 for novice and apprentice, and 1 for advanced and master + // TODO: Once we've found a way of detecting if amplifiers actually affect the potion type, implement it here. + int bonusAmplifier = getBonusAmplifier(modifiers.get(SpellModifiers.POTENCY)); + + for(Potion potion : potionSet){ + caster.addPotionEffect(new PotionEffect(potion, potion.isInstant() ? 1 : + (int)(getProperty(getDurationKey(potion)).floatValue() * modifiers.get(WizardryItems.duration_upgrade)), + (int)getProperty(getStrengthKey(potion)).floatValue() + bonusAmplifier, + false, true)); } return true; } + + /** Returns the number to be added to the potion amplifier(s) based on the given potency modifier. Override + * to define custom modifier handling. Delegates to {@link SpellBuff#getStandardBonusAmplifier(float)} by + * default. */ + protected int getBonusAmplifier(float potencyModifier){ + return getStandardBonusAmplifier(potencyModifier); + } + + /** Returns a number to be added to potion amplifiers based on the given potency modifier. This method uses + * a standard calculation which results in zero extra levels for novice and apprentice wands and one extra + * level for advanced and master wands (this generally seems to give about the right weight to potency + * modifiers). This is public static because it is useful in a variety of places. */ + public static int getStandardBonusAmplifier(float potencyModifier){ + return (int)((potencyModifier - 1) / 0.4); + } /** Spawns buff particles around the caster. Override to add a custom particle effect. Only called client-side. */ protected void spawnParticles(World world, EntityLivingBase caster, SpellModifiers modifiers){ diff --git a/src/main/java/electroblob/wizardry/spell/SpellConjuration.java b/src/main/java/electroblob/wizardry/spell/SpellConjuration.java index c339932a..b982f9ea 100644 --- a/src/main/java/electroblob/wizardry/spell/SpellConjuration.java +++ b/src/main/java/electroblob/wizardry/spell/SpellConjuration.java @@ -1,12 +1,8 @@ package electroblob.wizardry.spell; import electroblob.wizardry.Wizardry; -import electroblob.wizardry.constants.Element; -import electroblob.wizardry.constants.SpellType; -import electroblob.wizardry.constants.Tier; import electroblob.wizardry.item.IConjuredItem; import electroblob.wizardry.registry.WizardryItems; -import electroblob.wizardry.registry.WizardrySounds; import electroblob.wizardry.util.ParticleBuilder; import electroblob.wizardry.util.ParticleBuilder.Type; import electroblob.wizardry.util.SpellModifiers; @@ -17,7 +13,6 @@ import net.minecraft.item.EnumAction; import net.minecraft.item.Item; import net.minecraft.item.ItemStack; import net.minecraft.util.EnumHand; -import net.minecraft.util.SoundEvent; import net.minecraft.world.World; /** @@ -26,53 +21,36 @@ import net.minecraft.world.World; * instantiation of this class is sufficient to create a conjuration spell; if something extra needs to be done, such as * a custom particle effect or conjuring the item in a specific slot, then methods can be overridden (perhaps using an * anonymous class) to add the required functionality. - *

    + *

    + * Properties added by this type of spell: {@link SpellConjuration#ITEM_LIFETIME} + *

    * By default, this type of spell cannot be cast by NPCs. {@link Spell#canBeCastByNPCs()} - *

    - * By default, this type of spell requires a packet to be sent. {@link Spell#doesSpellRequirePacket()} + *

    + * By default, this type of spell cannot be cast by dispensers. {@link Spell#canBeCastByDispensers()} + *

    + * By default, this type of spell requires a packet to be sent. {@link Spell#requiresPacket()} * * @author Electroblob * @since Wizardry 4.2 * @see IConjuredItem */ public class SpellConjuration extends Spell { - + + public static final String ITEM_LIFETIME = "item_lifetime"; + /** The item that is conjured by this spell. Should implement {@link IConjuredItem}. */ protected final Item item; - /** The sound that gets played when this spell is cast. */ - protected final SoundEvent sound; - /** The volume of the sound played when this spell is cast. Defaults to 1. */ - protected float volume = 1; - /** The pitch of the sound played when this spell is cast. Defaults to 1. */ - protected float pitch = 1; - /** The pitch variation of the sound played when this spell is cast. Defaults to 0. */ - protected float pitchVariation = 0; - - public SpellConjuration(String name, Tier tier, Element element, SpellType type, int cost, int cooldown, Item item, SoundEvent sound){ - this(Wizardry.MODID, name, tier, element, type, cost, cooldown, item, sound); + public SpellConjuration(String name, Item item){ + this(Wizardry.MODID, name, item); } - public SpellConjuration(String modID, String name, Tier tier, Element element, SpellType type, int cost, int cooldown, Item item, SoundEvent sound){ - super(modID, name, tier, element, type, cost, cooldown, EnumAction.BOW, false); + public SpellConjuration(String modID, String name, Item item){ + super(modID, name, EnumAction.BOW, false); this.item = item; - this.sound = sound; + addProperties(ITEM_LIFETIME); } - /** - * Sets the sound parameters for this spell. - * @param volume - * @param pitch - * @param pitchVariation - * @return The spell instance, allowing this method to be chained onto the constructor. - */ - public SpellConjuration soundValues(float volume, float pitch, float pitchVariation) { - this.volume = volume; - this.pitch = pitch; - this.pitchVariation = pitchVariation; - return this; - } - @Override public boolean cast(World world, EntityPlayer caster, EnumHand hand, int ticksInUse, SpellModifiers modifiers){ @@ -80,7 +58,7 @@ public class SpellConjuration extends Spell { if(world.isRemote) spawnParticles(world, caster, modifiers); - WizardryUtilities.playSoundAtPlayer(caster, WizardrySounds.SPELL_CONJURATION, 1, 1); + this.playSound(world, caster, ticksInUse, -1, modifiers); return true; } @@ -106,6 +84,7 @@ public class SpellConjuration extends Spell { ItemStack stack = new ItemStack(item); IConjuredItem.setDurationMultiplier(stack, modifiers.get(WizardryItems.duration_upgrade)); + IConjuredItem.setDamageMultiplier(stack, modifiers.get(SpellModifiers.POTENCY)); if(WizardryUtilities.doesPlayerHaveItem(caster, item)) return false; diff --git a/src/main/java/electroblob/wizardry/spell/SpellConstruct.java b/src/main/java/electroblob/wizardry/spell/SpellConstruct.java index dce473e5..62483f62 100644 --- a/src/main/java/electroblob/wizardry/spell/SpellConstruct.java +++ b/src/main/java/electroblob/wizardry/spell/SpellConstruct.java @@ -1,13 +1,6 @@ package electroblob.wizardry.spell; -import java.util.function.Function; - -import javax.annotation.Nullable; - import electroblob.wizardry.Wizardry; -import electroblob.wizardry.constants.Element; -import electroblob.wizardry.constants.SpellType; -import electroblob.wizardry.constants.Tier; import electroblob.wizardry.entity.construct.EntityMagicConstruct; import electroblob.wizardry.registry.WizardryItems; import electroblob.wizardry.util.SpellModifiers; @@ -16,23 +9,31 @@ import net.minecraft.entity.EntityLiving; import net.minecraft.entity.EntityLivingBase; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.item.EnumAction; +import net.minecraft.util.EnumFacing; import net.minecraft.util.EnumHand; -import net.minecraft.util.SoundEvent; +import net.minecraft.util.math.BlockPos; import net.minecraft.world.World; +import javax.annotation.Nullable; +import java.util.function.Function; + /** * Generic superclass for all spells which conjure constructs (i.e. instances of {@link EntityMagicConstruct}). * This allows all the relevant code to be centralised, since these spells all work in a similar way. Usually, a simple * instantiation of this class is sufficient to create a construct spell; if something extra needs to be done, such as * particle spawning, then methods can be overridden (perhaps using an anonymous class) to add the required functionality. * It is encouraged, however, to put extra functionality in the construct entity class instead whenever possible. - *

    + *

    * This class spawns the construct entity at the caster's feet, like ring of fire and healing aura. Use * {@link SpellConstructRanged} (which extends this class) for spells that spawn constructs at an aimed-at position. - *

    + *

    + * Properties added by this type of spell: {@link Spell#DURATION} (if the construct is not permanent) + *

    * By default, this type of spell can be cast by NPCs. {@link Spell#canBeCastByNPCs()} - *

    - * By default, this type of spell does not require a packet to be sent. {@link Spell#doesSpellRequirePacket()} + *

    + * By default, this type of spell can be cast by dispensers. {@link Spell#canBeCastByDispensers()} + *

    + * By default, this type of spell does not require a packet to be sent. {@link Spell#requiresPacket()} * * @author Electroblob * @since Wizardry 4.2 @@ -42,53 +43,30 @@ public class SpellConstruct extends Spell { /** A factory that creates construct entities. */ protected final Function constructFactory; - /** The base lifetime of the construct created by this spell, or -1 if the construct does not despawn. */ - protected final int baseDuration; - /** The sound that gets played when this spell is cast, or null if the spell plays no sound. */ - @Nullable - protected final SoundEvent sound; - - /** The volume of the sound played when this spell is cast. Defaults to 1. */ - protected float volume = 1; - /** The pitch of the sound played when this spell is cast. Defaults to 1. */ - protected float pitch = 1; - /** The pitch variation of the sound played when this spell is cast. Defaults to 0. */ - protected float pitchVariation = 0; + /** Whether the construct lasts indefinitely, i.e. does not disappear after a set time. */ + protected final boolean permanent; /** Whether the construct must be spawned on the ground. Defaults to false. */ protected boolean requiresFloor = false; /** Whether constructs spawned by this spell may overlap. Defaults to false. */ protected boolean allowOverlap = false; - public SpellConstruct(String name, Tier tier, Element element, SpellType type, int cost, int cooldown, EnumAction action, Function constructFactory, int baseDuration, SoundEvent sound){ - this(Wizardry.MODID, name, tier, element, type, cost, cooldown, action, constructFactory, baseDuration, sound); + public SpellConstruct(String name, EnumAction action, Function constructFactory, boolean permanent){ + this(Wizardry.MODID, name, action, constructFactory, permanent); } - public SpellConstruct(String modID, String name, Tier tier, Element element, SpellType type, int cost, int cooldown, EnumAction action, Function constructFactory, int baseDuration, SoundEvent sound){ - super(modID, name, tier, element, type, cost, cooldown, action, false); + public SpellConstruct(String modID, String name, EnumAction action, Function constructFactory, boolean permanent){ + super(modID, name, action, false); this.constructFactory = constructFactory; - this.baseDuration = baseDuration; - this.sound = sound; + this.permanent = permanent; + if(!permanent) this.addProperties(DURATION); } - /** - * Sets the sound parameters for this spell. - * @param volume The volume of the sound, relative to 1. - * @param pitch The pitch of the sound, relative to 1. - * @param pitchVariation The pitch variation. The pitch will be set to a random value within this range either side - * of the set pitch value. - * @return The spell instance, allowing this method to be chained onto the constructor. - */ - public SpellConstruct soundValues(float volume, float pitch, float pitchVariation) { - this.volume = volume; - this.pitch = pitch; - this.pitchVariation = pitchVariation; - return this; - } - - @Override public boolean doesSpellRequirePacket(){ return false; } + @Override public boolean requiresPacket(){ return false; } @Override public boolean canBeCastByNPCs(){ return true; } + @Override public boolean canBeCastByDispensers() { return true; } + /** * Sets whether the construct must be spawned on the ground. * @param requiresFloor True to require that the construct be spawned on the ground, false to allow it in mid-air. @@ -114,8 +92,9 @@ public class SpellConstruct extends Spell { public boolean cast(World world, EntityPlayer caster, EnumHand hand, int ticksInUse, SpellModifiers modifiers){ if(caster.onGround || !requiresFloor){ - if(!spawnConstruct(world, caster.posX, caster.posY, caster.posZ, caster, modifiers)) return false; - if(sound != null) WizardryUtilities.playSoundAtPlayer(caster, sound, volume, pitch + pitchVariation * (world.rand.nextFloat() - 0.5f)); + if(!spawnConstruct(world, caster.posX, caster.posY, caster.posZ, caster.onGround ? EnumFacing.UP : null, + caster, modifiers)) return false; + this.playSound(world, caster, ticksInUse, -1, modifiers); return true; } @@ -127,8 +106,9 @@ public class SpellConstruct extends Spell { if(target != null){ if(caster.onGround || !requiresFloor){ - if(!spawnConstruct(world, caster.posX, caster.posY, caster.posZ, caster, modifiers)) return false; - if(sound != null) caster.playSound(sound, volume, pitch + pitchVariation * (world.rand.nextFloat() - 0.5f)); + if(!spawnConstruct(world, caster.posX, caster.posY, caster.posZ, caster.onGround ? EnumFacing.UP : null, + caster, modifiers)) return false; + this.playSound(world, caster, ticksInUse, -1, modifiers); return true; } } @@ -136,6 +116,26 @@ public class SpellConstruct extends Spell { return false; } + @Override + public boolean cast(World world, double x, double y, double z, EnumFacing direction, int ticksInUse, int duration, SpellModifiers modifiers){ + + Integer floor = (int)y; + + if(requiresFloor){ + floor = WizardryUtilities.getNearestFloor(world, new BlockPos(x, y, z), 1); + direction = EnumFacing.UP; + } + + if(floor != null){ + if(!spawnConstruct(world, x, floor, z, direction, null, modifiers)) return false; + // This MUST be the coordinates of the actual dispenser, so we need to offset it + this.playSound(world, x - direction.getXOffset(), y - direction.getYOffset(), z - direction.getZOffset(), ticksInUse, duration, modifiers); + return true; + } + + return false; + } + /** * Actually spawns the construct. By default, spawns the construct at the position of the caster and always returns * true. Returning false will cause the spell to fail. @@ -143,27 +143,30 @@ public class SpellConstruct extends Spell { * @param x The x coordinate to spawn the construct at. * @param y The y coordinate to spawn the construct at. * @param z The z coordinate to spawn the construct at. + * @param side The side of a block that was hit, or null if the construct is being spawned in mid-air (only happens + * if {@link SpellConstruct#requiresFloor} is true). * @param caster The EntityLivingBase that cast this spell. * @param modifiers The modifiers with which the spell was cast. * @return false to cause the spell to fail, true to continue with casting. */ - protected boolean spawnConstruct(World world, double x, double y, double z, EntityLivingBase caster, SpellModifiers modifiers){ + protected boolean spawnConstruct(World world, double x, double y, double z, @Nullable EnumFacing side, EntityLivingBase caster, SpellModifiers modifiers){ if(!world.isRemote){ - // Creates a new constuct using the supplied factory + // Creates a new construct using the supplied factory T construct = constructFactory.apply(world); // Sets the position of the construct (and initialises its bounding box) construct.setPosition(x, y, z); + // Sets the various parameters + construct.setCaster(caster); + construct.lifetime = permanent ? -1 : (int)(getProperty(DURATION).floatValue() * modifiers.get(WizardryItems.duration_upgrade)); + construct.damageMultiplier = modifiers.get(SpellModifiers.POTENCY); + addConstructExtras(construct, side, caster, modifiers); // Prevents overlapping of multiple constructs of the same type. Since we have an instance here this is // very simple. The trade-off is that we have to create the entity before the spell fails, but unless // world.spawnEntity(...) is called, its scope is limited to this method so it should be fine. - if(!allowOverlap && !world.getEntitiesWithinAABB(construct.getClass(), caster.getEntityBoundingBox()).isEmpty()) return false; - // Sets the various parameters - construct.setCaster(caster); - construct.lifetime = baseDuration == -1 ? -1 : (int)(baseDuration * modifiers.get(WizardryItems.duration_upgrade)); - construct.damageMultiplier = modifiers.get(SpellModifiers.POTENCY); - addConstructExtras(construct, caster, modifiers); - // Spawns the construct in the world + // Needs to be last in case addConstructExtras modifies the bounding box + if(!allowOverlap && !world.getEntitiesWithinAABB(construct.getClass(), construct.getEntityBoundingBox()).isEmpty()) return false; + // Spawns the construct in the world world.spawnEntity(construct); } @@ -175,11 +178,13 @@ public class SpellConstruct extends Spell { * extra methods on the spawned entity. This method is only called server-side so cannot be used to spawn particles * directly. * @param construct The entity being spawned. - * @param caster The caster of this spell. + * @param side The side of a block that was hit, or null if the construct is being spawned in mid-air (only happens + * if {@link SpellConstruct#requiresFloor} is true). + * @param caster The caster of this spell, or null if it was cast by a dispenser. * @param modifiers The modifiers this spell was cast with. */ // This is the reason this class is generic: it allows subclasses to do whatever they want to their specific entity, // without needing to cast to it. - protected void addConstructExtras(T construct, EntityLivingBase caster, SpellModifiers modifiers){} + protected void addConstructExtras(T construct, EnumFacing side, @Nullable EntityLivingBase caster, SpellModifiers modifiers){} } diff --git a/src/main/java/electroblob/wizardry/spell/SpellConstructRanged.java b/src/main/java/electroblob/wizardry/spell/SpellConstructRanged.java index cac214de..05d1b618 100644 --- a/src/main/java/electroblob/wizardry/spell/SpellConstructRanged.java +++ b/src/main/java/electroblob/wizardry/spell/SpellConstructRanged.java @@ -1,13 +1,9 @@ package electroblob.wizardry.spell; -import java.util.function.Function; - import electroblob.wizardry.Wizardry; -import electroblob.wizardry.constants.Element; -import electroblob.wizardry.constants.SpellType; -import electroblob.wizardry.constants.Tier; import electroblob.wizardry.entity.construct.EntityMagicConstruct; import electroblob.wizardry.registry.WizardryItems; +import electroblob.wizardry.util.RayTracer; import electroblob.wizardry.util.SpellModifiers; import electroblob.wizardry.util.WizardryUtilities; import net.minecraft.entity.EntityLiving; @@ -16,12 +12,13 @@ import net.minecraft.entity.player.EntityPlayer; import net.minecraft.item.EnumAction; import net.minecraft.util.EnumFacing; import net.minecraft.util.EnumHand; -import net.minecraft.util.SoundEvent; import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.RayTraceResult; import net.minecraft.util.math.Vec3d; import net.minecraft.world.World; +import java.util.function.Function; + /** * Generic superclass for all spells which conjure constructs (i.e. instances of {@link EntityMagicConstruct}) at an * aimed-at position (players and dispensers) or target (non-player spell casters). @@ -29,40 +26,69 @@ import net.minecraft.world.World; * instantiation of this class is sufficient to create a construct spell; if something extra needs to be done, such as * particle spawning, then methods can be overridden (perhaps using an anonymous class) to add the required functionality. * It is encouraged, however, to put extra functionality in the construct entity class instead whenever possible. - *

    + *

    + * Properties added by this type of spell: {@link Spell#RANGE}, {@link Spell#DURATION} (if the construct is not + * permanent) + *

    * By default, this type of spell can be cast by NPCs. {@link Spell#canBeCastByNPCs()} - *

    - * By default, this type of spell does not require a packet to be sent. {@link Spell#doesSpellRequirePacket()} + *

    + * By default, this type of spell can be cast by dispensers. {@link Spell#canBeCastByDispensers()} + *

    + * By default, this type of spell does not require a packet to be sent. {@link Spell#requiresPacket()} * * @author Electroblob * @since Wizardry 4.2 * @see SpellConstruct */ public class SpellConstructRanged extends SpellConstruct { - - /** The base range of this spell. */ - protected final double baseRange; - public SpellConstructRanged(String name, Tier tier, Element element, SpellType type, int cost, int cooldown, - Function constructFactory, int baseDuration, double baseRange, SoundEvent sound){ - this(Wizardry.MODID, name, tier, element, type, cost, cooldown, constructFactory, baseDuration, baseRange, sound); + /** Whether liquids count as blocks when raytracing. Defaults to false. */ + protected boolean hitLiquids = false; + /** Whether to ignore uncollidable blocks when raytracing. Defaults to false. */ + protected boolean ignoreUncollidables = false; + + public SpellConstructRanged(String name, Function constructFactory, boolean permanent){ + this(Wizardry.MODID, name, constructFactory, permanent); } - public SpellConstructRanged(String modID, String name, Tier tier, Element element, SpellType type, int cost, int cooldown, - Function constructFactory, int baseDuration, double baseRange, SoundEvent sound){ - super(modID, name, tier, element, type, cost, cooldown, EnumAction.NONE, constructFactory, baseDuration, sound); - this.baseRange = baseRange; + public SpellConstructRanged(String modID, String name, Function constructFactory, boolean permanent){ + super(modID, name, EnumAction.NONE, constructFactory, permanent); + this.addProperties(RANGE); } - @Override public boolean doesSpellRequirePacket(){ return false; } + /** + * Sets whether liquids count as blocks when raytracing. + * @param hitLiquids Whether to hit liquids when raytracing. If this is false, the spell will pass through + * liquids as if they weren't there. + * @return The spell instance, allowing this method to be chained onto the constructor. + */ + public Spell hitLiquids(boolean hitLiquids){ + this.hitLiquids = hitLiquids; + return this; + } + + /** + * Sets whether uncollidable blocks are ignored when raytracing. + * @param ignoreUncollidables Whether to hit uncollidable blocks when raytracing. If this is false, the spell will + * pass through uncollidable blocks as if they weren't there. + * @return The spell instance, allowing this method to be chained onto the constructor. + */ + public Spell ignoreUncollidables(boolean ignoreUncollidables){ + this.ignoreUncollidables = ignoreUncollidables; + return this; + } + + @Override public boolean requiresPacket(){ return false; } @Override public boolean canBeCastByNPCs(){ return true; } + @Override public boolean canBeCastByDispensers() { return true; } + @Override public boolean cast(World world, EntityPlayer caster, EnumHand hand, int ticksInUse, SpellModifiers modifiers){ - double range = baseRange * modifiers.get(WizardryItems.range_upgrade); - RayTraceResult rayTrace = WizardryUtilities.standardBlockRayTrace(world, caster, range, false); + double range = getProperty(RANGE).doubleValue() * modifiers.get(WizardryItems.range_upgrade); + RayTraceResult rayTrace = RayTracer.standardBlockRayTrace(world, caster, range, hitLiquids, ignoreUncollidables, false); if(rayTrace != null && rayTrace.typeOfHit == RayTraceResult.Type.BLOCK && (rayTrace.sideHit == EnumFacing.UP || !requiresFloor)){ @@ -73,7 +99,7 @@ public class SpellConstructRanged extends SpellC double y = rayTrace.hitVec.y; double z = rayTrace.hitVec.z; - if(!spawnConstruct(world, x, y, z, caster, modifiers)) return false; + if(!spawnConstruct(world, x, y, z, rayTrace.sideHit, caster, modifiers)) return false; } }else if(!requiresFloor){ @@ -86,7 +112,7 @@ public class SpellConstructRanged extends SpellC double y = caster.getEntityBoundingBox().minY + caster.getEyeHeight() + look.y * range; double z = caster.posZ + look.z * range; - if(!spawnConstruct(world, x, y, z, caster, modifiers)) return false; + if(!spawnConstruct(world, x, y, z, null, caster, modifiers)) return false; } }else{ @@ -94,7 +120,7 @@ public class SpellConstructRanged extends SpellC } caster.swingArm(hand); - if(sound != null) WizardryUtilities.playSoundAtPlayer(caster, sound, volume, pitch + pitchVariation * (world.rand.nextFloat() - 0.5f)); + this.playSound(world, caster, ticksInUse, -1, modifiers); return true; } @@ -102,7 +128,7 @@ public class SpellConstructRanged extends SpellC public boolean cast(World world, EntityLiving caster, EnumHand hand, int ticksInUse, EntityLivingBase target, SpellModifiers modifiers){ - double range = baseRange * modifiers.get(WizardryItems.range_upgrade); + double range = getProperty(RANGE).doubleValue() * modifiers.get(WizardryItems.range_upgrade); if(target != null && caster.getDistance(target) <= range){ @@ -111,23 +137,63 @@ public class SpellConstructRanged extends SpellC double x = target.posX; double y = target.posY; double z = target.posZ; + + EnumFacing side = null; // If the target is not on the ground but the construct must be placed on the floor, searches for the // floor under the caster and returns false if it does not find one within 3 blocks. if(!target.onGround && requiresFloor){ - y = WizardryUtilities.getNearestFloorLevel(world, new BlockPos(x, y, z), 3); - if(y < 0) return false; + Integer floor = WizardryUtilities.getNearestFloor(world, new BlockPos(x, y, z), 3); + if(floor == null) return false; + y = floor; + side = EnumFacing.UP; } - if(!spawnConstruct(world, x, y, z, caster, modifiers)) return false; + if(!spawnConstruct(world, x, y, z, side, caster, modifiers)) return false; } caster.swingArm(hand); - if(sound != null) caster.playSound(sound, volume, pitch + pitchVariation * (world.rand.nextFloat() - 0.5f)); + this.playSound(world, caster, ticksInUse, -1, modifiers); return true; } return false; } + + @Override + public boolean cast(World world, double x, double y, double z, EnumFacing direction, int ticksInUse, int duration, SpellModifiers modifiers){ + + double range = getProperty(RANGE).doubleValue() * modifiers.get(WizardryItems.range_upgrade); + Vec3d origin = new Vec3d(x, y, z); + Vec3d endpoint = origin.add(new Vec3d(direction.getDirectionVec()).scale(range)); + RayTraceResult rayTrace = world.rayTraceBlocks(origin, endpoint, hitLiquids, ignoreUncollidables, false); + + if(rayTrace != null && rayTrace.typeOfHit == RayTraceResult.Type.BLOCK && (rayTrace.sideHit == EnumFacing.UP || + !requiresFloor)){ + + if(!world.isRemote){ + + double x1 = rayTrace.hitVec.x; + double y1 = rayTrace.hitVec.y; + double z1 = rayTrace.hitVec.z; + + if(!spawnConstruct(world, x1, y1, z1, rayTrace.sideHit, null, modifiers)) return false; + } + + }else if(!requiresFloor){ + + if(!world.isRemote){ + + if(!spawnConstruct(world, endpoint.x, endpoint.y, endpoint.z, null, null, modifiers)) return false; + } + + }else{ + return false; + } + + // This MUST be the coordinates of the actual dispenser, so we need to offset it + this.playSound(world, x - direction.getXOffset(), y - direction.getYOffset(), z - direction.getZOffset(), ticksInUse, duration, modifiers); + return true; + } } diff --git a/src/main/java/electroblob/wizardry/spell/SpellMinion.java b/src/main/java/electroblob/wizardry/spell/SpellMinion.java index d7971d27..f492b07a 100644 --- a/src/main/java/electroblob/wizardry/spell/SpellMinion.java +++ b/src/main/java/electroblob/wizardry/spell/SpellMinion.java @@ -1,114 +1,94 @@ package electroblob.wizardry.spell; -import java.util.function.Function; - import electroblob.wizardry.Wizardry; -import electroblob.wizardry.constants.Element; -import electroblob.wizardry.constants.SpellType; -import electroblob.wizardry.constants.Tier; import electroblob.wizardry.entity.living.ISummonedCreature; import electroblob.wizardry.registry.WizardryItems; import electroblob.wizardry.util.SpellModifiers; import electroblob.wizardry.util.WizardryUtilities; -import net.minecraft.entity.Entity; +import electroblob.wizardry.util.WizardryUtilities.Operations; import net.minecraft.entity.EntityLiving; import net.minecraft.entity.EntityLivingBase; +import net.minecraft.entity.IEntityLivingData; +import net.minecraft.entity.SharedMonsterAttributes; +import net.minecraft.entity.ai.attributes.AttributeModifier; +import net.minecraft.entity.ai.attributes.IAttributeInstance; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.item.EnumAction; +import net.minecraft.util.EnumFacing; import net.minecraft.util.EnumHand; -import net.minecraft.util.SoundEvent; import net.minecraft.util.math.BlockPos; +import net.minecraft.world.DifficultyInstance; import net.minecraft.world.World; +import javax.annotation.Nullable; +import java.util.function.Function; + /** * Generic superclass for all spells which summon minions (i.e. instances of {@link ISummonedCreature}). * This allows all the relevant code to be centralised, since these spells all work in the same way. Usually, a simple - * instantiation of this class is sufficient to create a projectile spell; if something extra needs to be done, such as + * instantiation of this class is sufficient to create a minion spell; if something extra needs to be done, such as * particle spawning, then methods can be overridden (perhaps using an anonymous class) to add the required functionality. * It is encouraged, however, to put extra functionality in the summoned creature class instead whenever possible. - *

    + *

    + * Properties added by this type of spell: {@link SpellMinion#MINION_LIFETIME} + *

    * By default, this type of spell can be cast by NPCs. {@link Spell#canBeCastByNPCs()} - *

    - * By default, this type of spell does not require a packet to be sent. {@link Spell#doesSpellRequirePacket()} + *

    + * By default, this type of spell can be cast by dispensers. {@link Spell#canBeCastByDispensers()} + *

    + * By default, this type of spell does not require a packet to be sent. {@link Spell#requiresPacket()} * * @author Electroblob * @since Wizardry 4.2 */ -// Adding a type parameter to this class seems to work very nicely! -public class SpellMinion extends Spell { +public class SpellMinion extends Spell { + + public static final String MINION_LIFETIME = "minion_lifetime"; + public static final String MINION_COUNT = "minion_count"; + public static final String SUMMON_RADIUS = "summon_radius"; + + /** The string identifier for the minion health spell modifier, which doubles as the identifier for the + * entity attribute modifier. */ + public static final String HEALTH_MODIFIER = "minion_health"; + /** The string identifier for the potency attribute modifier. */ + private static final String POTENCY_ATTRIBUTE_MODIFIER = "potency"; /** A factory that creates summoned creature entities. */ protected final Function minionFactory; - /** The base lifetime of the summoned creature. */ - protected final int baseDuration; - /** The sound that gets played when this spell is cast. */ - protected final SoundEvent sound; - - /** The volume of the sound played when this spell is cast. Defaults to 1. */ - protected float volume = 1; - /** The pitch of the sound played when this spell is cast. Defaults to 1. */ - protected float pitch = 1; - /** The pitch variation of the sound played when this spell is cast. Defaults to 0. */ - protected float pitchVariation = 0; - /** The number of minions to summon. Defaults to 1. */ - protected int quantity = 1; - /** The maximum number of blocks from the caster in a single direction that the minions can spawn, defaults to 2. */ - protected int range = 2; + /** Whether the minions are spawned in mid-air. Defaults to false. */ + protected boolean flying = false; - public SpellMinion(String name, Tier tier, Element element, int cost, int cooldown, Function minionFactory, int baseDuration, SoundEvent sound){ - this(Wizardry.MODID, name, tier, element, cost, cooldown, minionFactory, baseDuration, sound); + public SpellMinion(String name, Function minionFactory){ + this(Wizardry.MODID, name, minionFactory); } - public SpellMinion(String modID, String name, Tier tier, Element element, int cost, int cooldown, Function minionFactory, int baseDuration, SoundEvent sound){ - super(modID, name, tier, element, SpellType.MINION, cost, cooldown, EnumAction.BOW, false); + public SpellMinion(String modID, String name, Function minionFactory){ + super(modID, name, EnumAction.BOW, false); this.minionFactory = minionFactory; - this.baseDuration = baseDuration; - this.sound = sound; + addProperties(MINION_LIFETIME, MINION_COUNT, SUMMON_RADIUS); } - + /** - * Sets the sound parameters for this spell. - * @param volume - * @param pitch - * @param pitchVariation + * Sets whether the minions are spawned in mid-air. + * @param flying True to spawn the minions in mid-air, false to spawn them on the ground. * @return The spell instance, allowing this method to be chained onto the constructor. */ - public SpellMinion soundValues(float volume, float pitch, float pitchVariation) { - this.volume = volume; - this.pitch = pitch; - this.pitchVariation = pitchVariation; + public SpellMinion flying(boolean flying){ + this.flying = flying; return this; } - /** - * Sets the number of minions this spell will summon. - * @param quantity The number of minions to summon. - * @return The spell instance, allowing this method to be chained onto the constructor. - */ - public SpellMinion quantity(int quantity){ - this.quantity = quantity; - return this; - } - - /** - * Sets the range within which minions can spawn. - * @param range The maximum number of blocks from the caster that minions can be spawned. - * @return The spell instance, allowing this method to be chained onto the constructor. - */ - public SpellMinion range(int range){ - this.range = range; - return this; - } - - @Override public boolean doesSpellRequirePacket(){ return false; } + @Override public boolean requiresPacket(){ return false; } @Override public boolean canBeCastByNPCs(){ return true; } + + @Override public boolean canBeCastByDispensers() { return true; } @Override public boolean cast(World world, EntityPlayer caster, EnumHand hand, int ticksInUse, SpellModifiers modifiers){ if(!this.spawnMinions(world, caster, modifiers)) return false; - WizardryUtilities.playSoundAtPlayer(caster, sound, volume, pitch + pitchVariation * (world.rand.nextFloat() - 0.5f)); + this.playSound(world, caster, ticksInUse, -1, modifiers); return true; } @@ -117,31 +97,90 @@ public class SpellMinion extends Spell { SpellModifiers modifiers){ if(!this.spawnMinions(world, caster, modifiers)) return false; - caster.playSound(sound, volume, pitch + pitchVariation * (world.rand.nextFloat() - 0.5f)); + this.playSound(world, caster, ticksInUse, -1, modifiers); return true; } - /** Actually spawns the minions. By default, this spawns the number of minions specified by - * {@link SpellMinion#quantity} within a number of blocks of the caster specified by {@link SpellMinion#range}, - * returning false if there is no space to spawn the minions. Returning false from this method causes the spell to - * fail. Override to do something special, like spawning mnions in a specific position. - * @see SpellMinion#addMinionExtras(Entity, EntityLivingBase, SpellModifiers, int) */ + @Override + public boolean cast(World world, double x, double y, double z, EnumFacing direction, int ticksInUse, int duration, SpellModifiers modifiers){ + + BlockPos pos = new BlockPos(x, y, z); + + // In this case it looks nice to have them all explode out from one position! (It also makes the code simpler...) + if(!world.isRemote){ + for(int i=0; i extends Spell { return true; } + + /** + * Creates and returns a new instance of this spell's minion entity. By default, this simply calls the apply + * method in {@link SpellMinion#minionFactory}. Override to add logic for changing the type of entity summoned. + * + * @param world The world in which to spawn the minion. + * @param caster The entity that cast this spell, or null if it was cast by a dispenser. + * @param modifiers The spell modifiers this spell was cast with. + * @return The resulting minion entity. + */ + protected T createMinion(World world, @Nullable EntityLivingBase caster, SpellModifiers modifiers){ + return minionFactory.apply(world); + } /** - * Called just before each minion is spawned. Does nothing by default, but is provided to allow subclasses to call - * extra methods on the summoned entity, for example to add equipment. This method is only called server-side so - * cannot be used to spawn particles directly. + * Called just before each minion is spawned. Calls {@link EntityLiving#onInitialSpawn(DifficultyInstance, IEntityLivingData)} + * by default, but subclasses can override to call extra methods on the summoned entity, for example to add + * special equipment. This method is only called server-side so cannot be used to spawn particles directly. * @param minion The entity being spawned. - * @param caster The caster of this spell. + * @param pos The position at which the entity was spawned. + * @param caster The caster of this spell, or null if it was cast by a dispenser. * @param modifiers The modifiers this spell was cast with. - * @param alreadySpawned The number of minions already spawned, before this one. Always less than - * {@link SpellMinion#quantity}. + * @param alreadySpawned The number of minions already spawned, before this one. Always less than the property + * {@link SpellMinion#MINION_COUNT}. */ - protected void addMinionExtras(T minion, EntityLivingBase caster, SpellModifiers modifiers, int alreadySpawned){} + protected void addMinionExtras(T minion, BlockPos pos, @Nullable EntityLivingBase caster, SpellModifiers modifiers, int alreadySpawned){ + minion.onInitialSpawn(minion.world.getDifficultyForLocation(pos), null); + } } diff --git a/src/main/java/electroblob/wizardry/spell/SpellProjectile.java b/src/main/java/electroblob/wizardry/spell/SpellProjectile.java index 09f011ff..1e8562e0 100644 --- a/src/main/java/electroblob/wizardry/spell/SpellProjectile.java +++ b/src/main/java/electroblob/wizardry/spell/SpellProjectile.java @@ -1,11 +1,6 @@ package electroblob.wizardry.spell; -import java.util.function.Function; - import electroblob.wizardry.Wizardry; -import electroblob.wizardry.constants.Element; -import electroblob.wizardry.constants.SpellType; -import electroblob.wizardry.constants.Tier; import electroblob.wizardry.entity.living.ISpellCaster; import electroblob.wizardry.entity.projectile.EntityBomb; import electroblob.wizardry.entity.projectile.EntityMagicProjectile; @@ -16,90 +11,109 @@ import net.minecraft.entity.EntityLiving; import net.minecraft.entity.EntityLivingBase; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.item.EnumAction; +import net.minecraft.util.EnumFacing; import net.minecraft.util.EnumHand; -import net.minecraft.util.SoundEvent; +import net.minecraft.util.math.MathHelper; +import net.minecraft.util.math.Vec3i; import net.minecraft.world.World; +import javax.annotation.Nullable; +import java.util.function.Function; + /** * Generic superclass for all spells which launch non-directed projectiles (i.e. instances of {@link EntityMagicProjectile}). * This allows all the relevant code to be centralised, since these spells all work in the same way. Usually, a simple * instantiation of this class is sufficient to create a projectile spell; if something extra needs to be done, such as * particle spawning, then methods can be overridden (perhaps using an anonymous class) to add the required functionality. * It is encouraged, however, to put extra functionality in the projectile class instead whenever possible. - *

    + *

    + * Properties added by this type of spell: {@link Spell#RANGE} + *

    * By default, this type of spell can be cast by NPCs. {@link Spell#canBeCastByNPCs()} - *

    - * By default, this type of spell does not require a packet to be sent. {@link Spell#doesSpellRequirePacket()} + *

    + * By default, this type of spell can be cast by dispensers. {@link Spell#canBeCastByDispensers()} + *

    + * By default, this type of spell does not require a packet to be sent. {@link Spell#requiresPacket()} * * @author Electroblob * @since Wizardry 4.2 */ -public class SpellProjectile extends Spell { +public class SpellProjectile extends Spell { + private static final float DISPENSER_INACCURACY = 1; // This is the same as for players + private static final float FALLBACK_VELOCITY = 1.5f; // 1.5 seems to be a pretty standard value + // The general contract for these spell subtypes is that any required parameters are set via the constructor and are // final, whereas any non-critical parameters are set via chainable setters with sensible defaults if not. For example, // the actual sound to play is required, but it makes sense for its volume and pitch to default to 1 if unspecified. /** A factory that creates projectile entities. */ - protected final Function projectileFactory; - /** The base range (projectile speed) of this spell. */ - protected final float baseRange; - /** The sound that gets played when this spell is cast. */ - protected final SoundEvent sound; + protected final Function projectileFactory; - /** The volume of the sound played when this spell is cast. Defaults to 1. */ - protected float volume = 1; - /** The pitch of the sound played when this spell is cast. Defaults to 1. */ - protected float pitch = 1; - /** The pitch variation of the sound played when this spell is cast. Defaults to 0. */ - protected float pitchVariation = 0; - - public SpellProjectile(String name, Tier tier, Element element, int cost, int cooldown, Function projectileFactory, float baseRange, SoundEvent sound) { - this(Wizardry.MODID, name, tier, element, cost, cooldown, projectileFactory, baseRange, sound); + public SpellProjectile(String name, Function projectileFactory) { + this(Wizardry.MODID, name, projectileFactory); } - public SpellProjectile(String modID, String name, Tier tier, Element element, int cost, int cooldown, Function projectileFactory, float baseRange, SoundEvent sound){ - super(modID, name, tier, element, SpellType.PROJECTILE, cost, cooldown, EnumAction.NONE, false); + public SpellProjectile(String modID, String name, Function projectileFactory){ + super(modID, name, EnumAction.NONE, false); this.projectileFactory = projectileFactory; - this.baseRange = baseRange; - this.sound = sound; + addProperties(RANGE); } - /** - * Sets the sound parameters for this spell. - * @param volume - * @param pitch - * @param pitchVariation - * @return The spell instance, allowing this method to be chained onto the constructor. - */ - public SpellProjectile soundValues(float volume, float pitch, float pitchVariation) { - this.volume = volume; - this.pitch = pitch; - this.pitchVariation = pitchVariation; - return this; - } - - @Override public boolean doesSpellRequirePacket(){ return false; } + @Override public boolean requiresPacket(){ return false; } @Override public boolean canBeCastByNPCs(){ return true; } + + @Override public boolean canBeCastByDispensers() { return true; } + + /** Computes the velocity the projectile should be launched at to achieve the required range. */ + // Long story short, it doesn't make much sense to me to have the JSON file specify the velocity - even less so if + // the velocity is masquerading under the tag 'range' - so we'll let the code do the heavy lifting so people can + // input something meaningful. + protected float calculateVelocity(EntityMagicProjectile projectile, SpellModifiers modifiers, float launchHeight){ + // The required range + float range = getProperty(RANGE).floatValue() * modifiers.get(WizardryItems.range_upgrade); + + if(projectile.hasNoGravity()){ + // No sensible spell will do this - range is meaningless if the projectile has no gravity or lifetime + if(projectile.getLifetime() <= 0) return FALLBACK_VELOCITY; + // Speed = distance/time (trivial, I know, but I've put it here for the sake of completeness) + return range / projectile.getLifetime(); + }else{ + // It seems that in Minecraft, g is usually* 0.03 - the getter method is protected unfortunately + // * Potions and xp bottles seem to have more gravity (because that makes sense...) + float g = 0.03f; + // Assume horizontal projection + return range / MathHelper.sqrt(2 * launchHeight/g); + } + } + + // Previously we assumed the base range specified refers to the absolute maximum possible range + // when launched at the ideal angle of projection. See the following: + // https://math.stackexchange.com/questions/127300/maximum-range-of-a-projectile-launched-from-an-elevation + // The above link gives the formula: Rmax = u/g * sqrt(u^2 + 2gH), so u = sqrt(sqrt(g^2*(h^2+r^2)) - gh) + // This is probably overkill on the accuracy front, but... hey, I'm a perfectionist, what can I say? + //return MathHelper.sqrt(MathHelper.sqrt(g*g * (launchHeight*launchHeight + range*range)) - g*launchHeight); @Override public boolean cast(World world, EntityPlayer caster, EnumHand hand, int ticksInUse, SpellModifiers modifiers){ if(!world.isRemote){ // Creates a projectile from the supplied factory - EntityMagicProjectile projectile = projectileFactory.apply(world); + T projectile = projectileFactory.apply(world); // Sets the necessary parameters - projectile.aim(caster, baseRange * modifiers.get(WizardryItems.range_upgrade)); + projectile.aim(caster, calculateVelocity(projectile, modifiers, caster.getEyeHeight() + - (float)EntityMagicProjectile.LAUNCH_Y_OFFSET)); projectile.damageMultiplier = modifiers.get(SpellModifiers.POTENCY); if(projectile instanceof EntityBomb) ((EntityBomb)projectile).blastMultiplier = modifiers.get(WizardryItems.blast_upgrade); + addProjectileExtras(projectile, caster, modifiers); // Spawns the projectile in the world world.spawnEntity(projectile); } caster.swingArm(hand); - WizardryUtilities.playSoundAtPlayer(caster, sound, volume, pitch + pitchVariation * (world.rand.nextFloat() - 0.5f)); + this.playSound(world, caster, ticksInUse, -1, modifiers); return true; } @@ -111,20 +125,22 @@ public class SpellProjectile extends Spell { if(!world.isRemote){ // Creates a projectile from the supplied factory - EntityMagicProjectile projectile = projectileFactory.apply(world); + T projectile = projectileFactory.apply(world); // Sets the necessary parameters int aimingError = caster instanceof ISpellCaster ? ((ISpellCaster)caster).getAimingError(world.getDifficulty()) : WizardryUtilities.getDefaultAimingError(world.getDifficulty()); - projectile.aim(caster, target, baseRange * modifiers.get(WizardryItems.range_upgrade), aimingError); + projectile.aim(caster, target, calculateVelocity(projectile, modifiers, caster.getEyeHeight() + - (float)EntityMagicProjectile.LAUNCH_Y_OFFSET), aimingError); projectile.damageMultiplier = modifiers.get(SpellModifiers.POTENCY); if(projectile instanceof EntityBomb) ((EntityBomb)projectile).blastMultiplier = modifiers.get(WizardryItems.blast_upgrade); + addProjectileExtras(projectile, caster, modifiers); // Spawns the projectile in the world world.spawnEntity(projectile); } caster.swingArm(hand); - caster.playSound(sound, volume, pitch + pitchVariation * (world.rand.nextFloat() - 0.5f)); + this.playSound(world, caster, ticksInUse, -1, modifiers); return true; } @@ -132,4 +148,38 @@ public class SpellProjectile extends Spell { return false; } + @Override + public boolean cast(World world, double x, double y, double z, EnumFacing direction, int ticksInUse, int duration, SpellModifiers modifiers){ + + if(!world.isRemote){ + // Creates a projectile from the supplied factory + T projectile = projectileFactory.apply(world); + // Sets the necessary parameters + projectile.setPosition(x, y, z); + Vec3i vec = direction.getDirectionVec(); + projectile.shoot(vec.getX(), vec.getY(), vec.getZ(), calculateVelocity(projectile, modifiers, + 0.375f), DISPENSER_INACCURACY); // 0.375 is the height of the hole in a dispenser + projectile.damageMultiplier = modifiers.get(SpellModifiers.POTENCY); + if(projectile instanceof EntityBomb) ((EntityBomb)projectile).blastMultiplier = modifiers.get(WizardryItems.blast_upgrade); + addProjectileExtras(projectile, null, modifiers); + // Spawns the projectile in the world + world.spawnEntity(projectile); + } + // This MUST be the coordinates of the actual dispenser, so we need to offset it + this.playSound(world, x - direction.getXOffset(), y - direction.getYOffset(), z - direction.getZOffset(), ticksInUse, duration, modifiers); + + return true; + } + + /** + * Called just before the projectile is spawned. Does nothing by default, but subclasses can override to call extra + * methods on the spawned projectile. This method is only called server-side so cannot be used to spawn particles directly. + * @param projectile The entity being spawned. + * @param caster The caster of this spell, or null if it was cast by a dispenser. + * @param modifiers The modifiers this spell was cast with. + */ + protected void addProjectileExtras(T projectile, @Nullable EntityLivingBase caster, SpellModifiers modifiers){ + // Subclasses can put spell-specific stuff here + } + } diff --git a/src/main/java/electroblob/wizardry/spell/SpellRay.java b/src/main/java/electroblob/wizardry/spell/SpellRay.java index 0ac28b72..1dc46232 100644 --- a/src/main/java/electroblob/wizardry/spell/SpellRay.java +++ b/src/main/java/electroblob/wizardry/spell/SpellRay.java @@ -1,12 +1,8 @@ package electroblob.wizardry.spell; -import javax.annotation.Nullable; - import electroblob.wizardry.Wizardry; -import electroblob.wizardry.constants.Element; -import electroblob.wizardry.constants.SpellType; -import electroblob.wizardry.constants.Tier; import electroblob.wizardry.registry.WizardryItems; +import electroblob.wizardry.util.RayTracer; import electroblob.wizardry.util.SpellModifiers; import electroblob.wizardry.util.WizardryUtilities; import net.minecraft.entity.Entity; @@ -16,13 +12,14 @@ import net.minecraft.entity.player.EntityPlayer; import net.minecraft.item.EnumAction; import net.minecraft.util.EnumFacing; import net.minecraft.util.EnumHand; -import net.minecraft.util.SoundEvent; import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.MathHelper; import net.minecraft.util.math.RayTraceResult; import net.minecraft.util.math.Vec3d; import net.minecraft.world.World; +import javax.annotation.Nullable; + /** * Generic superclass for all spells which use a raytrace to do something and (optionally) spawn particles along that * trajectory. This is for both continuous ('stream') spells and non-continuous ('bolt') spells This allows all the @@ -30,111 +27,95 @@ import net.minecraft.world.World; * such must be subclassed to define what the spell actually does. This is because ray-like spells do a wider variety of * different things, so it does not make sense to define more specific functions in this class since they would be * redundant in the majority of cases. - *

    + *

    + * N.B. The three abstract methods in this class have a {@link Nullable} caster parameter (the caster is null when + * the spell is cast by a dispenser). When implementing these methods, be sure to check whether the caster is + * {@code null} and deal with it appropriately. + *

    + * Properties added by this type of spell: {@link Spell#RANGE} + *

    * By default, this type of spell can be cast by NPCs. {@link Spell#canBeCastByNPCs()} - *

    - * By default, this type of spell requires a packet to be sent. {@link Spell#doesSpellRequirePacket()} + *

    + * By default, this type of spell can be cast by dispensers. {@link Spell#canBeCastByDispensers()} + *

    + * By default, this type of spell requires a packet to be sent. {@link Spell#requiresPacket()} * * @author Electroblob * @since Wizardry 4.2 - * @see SpellStream */ public abstract class SpellRay extends Spell { - // TODO: Implement the 'aim assist' (borderSize) effect for rayTracing - /** The distance below the caster's eyes that the bolt particles start from. */ - private static final double Y_OFFSET = 0.4; - - /** The base range of this spell. */ - protected final double baseRange; - /** The sound that gets played when this spell is cast. */ - @Nullable - protected final SoundEvent sound; - - /** The volume of the sound played when this spell is cast. Defaults to 1. */ - protected float volume = 1; - /** The pitch of the sound played when this spell is cast. Defaults to 1. */ - protected float pitch = 1; - /** The pitch variation of the sound played when this spell is cast. Defaults to 0. */ - protected float pitchVariation = 0; + protected static final double Y_OFFSET = 0.25; + /** The distance between spawned particles. Defaults to 0.85. */ // 0.85 was chosen to keep it similar to the most common method used previously, which gave an effective spacing of // 10/12 = 0.8333 when the spell did not hit anything. protected double particleSpacing = 0.85; - /** The maximum dither (random position offset) for spawned particles. Defaults to 0.1. */ - protected double particleDither = 0.1; + /** The maximum jitter (random position offset) for spawned particles. Defaults to 0.1. */ + protected double particleJitter = 0.1; /** The velocity of spawned particles in the direction the caster is aiming, can be negative. Defaults to 0. */ protected double particleVelocity = 0; - /** Whether entities are ignored when raytracing. Defaults to false. */ - protected boolean ignoreEntities = false; + /** Whether living entities are ignored when raytracing. Defaults to false. */ + protected boolean ignoreLivingEntities = false; /** Whether liquids count as blocks when raytracing. Defaults to false. */ protected boolean hitLiquids = false; + /** Whether to ignore uncollidable blocks when raytracing. Defaults to true. */ + protected boolean ignoreUncollidables = true; /** The aim assist to use when raytracing. Defaults to 0. */ protected float aimAssist = 0; - public SpellRay(String name, Tier tier, Element element, SpellType type, int cost, int cooldown, boolean isContinuous, double baseRange, SoundEvent sound){ - this(Wizardry.MODID, name, tier, element, type, cost, cooldown, isContinuous, baseRange, sound); + public SpellRay(String name, boolean isContinuous, EnumAction action){ + this(Wizardry.MODID, name, isContinuous, action); } - public SpellRay(String modID, String name, Tier tier, Element element, SpellType type, int cost, int cooldown, boolean isContinuous, double baseRange, SoundEvent sound){ - super(modID, name, tier, element, type, cost, cooldown, EnumAction.NONE, isContinuous); - this.baseRange = baseRange; - this.sound = sound; + public SpellRay(String modID, String name, boolean isContinuous, EnumAction action){ + super(modID, name, action, isContinuous); + this.addProperties(RANGE); } - /** - * Sets the sound parameters for this spell. - * @param volume - * @param pitch - * @param pitchVariation - * @return The spell instance, allowing this method to be chained onto the constructor. - */ - public SpellRay soundValues(float volume, float pitch, float pitchVariation) { - this.volume = volume; - this.pitch = pitch; - this.pitchVariation = pitchVariation; - return this; - } + // Although this class is abstract, someone might instantiate one of its subclasses more than once to make two + // different spells, which may require different parameters. These methods allow such instances to neatly set any + // relevant parameters by chaining them onto the constructor. /** * Sets the distance between spawned particles. * @param particleSpacing The distance between particles in the ray effect. * @return The spell instance, allowing this method to be chained onto the constructor. */ - public SpellRay particleSpacing(double particleSpacing){ + public Spell particleSpacing(double particleSpacing){ this.particleSpacing = particleSpacing; return this; } /** - * Sets the maximum dither (random position offset) for spawned particles. - * @param particleDither The maximum dither for particles in the ray effect. + * Sets the maximum jitter (random position offset) for spawned particles. + * @param particleJitter The maximum jitter for particles in the ray effect. * @return The spell instance, allowing this method to be chained onto the constructor. */ - public SpellRay particleDither(double particleDither){ - this.particleDither = particleDither; + public Spell particleJitter(double particleJitter){ + this.particleJitter = particleJitter; return this; } /** - * Sets the velocity of spawned particles. + * Sets the velocity of spawned particles; usually used for continuous spells. * @param particleVelocity The velocity of spawned particles in the direction the caster is aiming, can be negative. * @return The spell instance, allowing this method to be chained onto the constructor. */ - public SpellRay particleVelocity(double particleVelocity){ + public Spell particleVelocity(double particleVelocity){ this.particleVelocity = particleVelocity; return this; } /** * Sets whether entities are ignored when raytracing. - * @param ignoreEntities Whether to ignore entities when raytracing. If this is true, the spell will pass through - * entities as if they weren't there. + * @param ignoreLivingEntities Whether to ignore living entities when raytracing. If this is true, the spell + * will pass through living entities as if they weren't there. * @return The spell instance, allowing this method to be chained onto the constructor. */ - public SpellRay ignoreEntities(boolean ignoreEntities){ - this.ignoreEntities = ignoreEntities; + public Spell ignoreLivingEntities(boolean ignoreLivingEntities){ + this.ignoreLivingEntities = ignoreLivingEntities; return this; } @@ -144,36 +125,47 @@ public abstract class SpellRay extends Spell { * liquids as if they weren't there. * @return The spell instance, allowing this method to be chained onto the constructor. */ - public SpellRay hitLiquids(boolean hitLiquids){ + public Spell hitLiquids(boolean hitLiquids){ this.hitLiquids = hitLiquids; return this; } + + /** + * Sets whether uncollidable blocks are ignored when raytracing. + * @param ignoreUncollidables Whether to hit uncollidable blocks when raytracing. If this is true, the spell will + * pass through uncollidable blocks as if they weren't there. + * @return The spell instance, allowing this method to be chained onto the constructor. + */ + public Spell ignoreUncollidables(boolean ignoreUncollidables){ + this.ignoreUncollidables = ignoreUncollidables; + return this; + } /** * Sets the aim assist to use when raytracing. - * @param particleVelocity The aim assist to use when raytracing. See {@link WizardryUtilities#rayTrace(World, Vec3d, - * Vec3d, float, boolean, Class, java.util.function.Predicate)} for more details. + * @param aimAssist The aim assist to use when raytracing. See {@link RayTracer#rayTrace(World, Vec3d, Vec3d, float, boolean, boolean, boolean, Class, java.util.function.Predicate)} for more details. * @return The spell instance, allowing this method to be chained onto the constructor. */ - public SpellRay aimAssist(float aimAssist){ + public Spell aimAssist(float aimAssist){ this.aimAssist = aimAssist; return this; } @Override public boolean canBeCastByNPCs(){ return true; } + + @Override public boolean canBeCastByDispensers() { return true; } // Finally everything in here is standardised and written in a form that's actually readable - it was long overdue! @Override public boolean cast(World world, EntityPlayer caster, EnumHand hand, int ticksInUse, SpellModifiers modifiers){ Vec3d look = caster.getLookVec(); - Vec3d origin = new Vec3d(caster.posX, caster.getEntityBoundingBox().minY + caster.getEyeHeight() - Y_OFFSET, - caster.posZ); + Vec3d origin = new Vec3d(caster.posX, caster.getEntityBoundingBox().minY + caster.getEyeHeight() - Y_OFFSET, caster.posZ); if(!shootSpell(world, origin, look, caster, ticksInUse, modifiers)) return false; - if(!isContinuous) caster.swingArm(hand); // Bit of a dirty fix but I don't think it'll be a problem! - if(sound != null) WizardryUtilities.playSoundAtPlayer(caster, sound, volume, pitch + pitchVariation * (world.rand.nextFloat() - 0.5f)); + if(casterSwingsArm(world, caster, hand, ticksInUse, modifiers)) caster.swingArm(hand); + this.playSound(world, caster, ticksInUse, -1, modifiers); return true; } @@ -187,7 +179,8 @@ public abstract class SpellRay extends Spell { if(target != null){ - if(!ignoreEntities && onEntityHit(world, target, caster, ticksInUse, modifiers)){ + if((!ignoreLivingEntities || !WizardryUtilities.isLiving(target)) + && onEntityHit(world, target, null, caster, origin, ticksInUse, modifiers)){ direction = new Vec3d(target.posX, target.getEntityBoundingBox().minY + target.height/2, target.posZ) .subtract(origin); @@ -203,7 +196,7 @@ public abstract class SpellRay extends Spell { // This works as if the NPC had actually aimed at the floor beneath the target, so it needs to check // that the block is not air and (optionally) not a liquid. if(!world.isAirBlock(pos) && (!world.getBlockState(pos).getMaterial().isLiquid() || hitLiquids) - && onBlockHit(world, pos, EnumFacing.UP, caster, ticksInUse, modifiers)){ + && onBlockHit(world, pos, EnumFacing.UP, null, caster, origin, ticksInUse, modifiers)){ direction = new Vec3d(x + 0.5, y + 1, z + 0.5).subtract(origin); flag = true; @@ -214,118 +207,196 @@ public abstract class SpellRay extends Spell { // Wizards don't miss... yet if(!flag) return false; - // Particle spawning (direction should never be null at this point but no harm in checking) - if(world.isRemote && direction != null){ - spawnParticleRay(world, origin, direction.normalize(), direction.lengthVector()); + // Particle spawning + if(world.isRemote){ + spawnParticleRay(world, origin, direction.normalize(), caster, direction.length()); } - - if(!isContinuous) caster.swingArm(hand); // Bit of a dirty fix but I don't think it'll be a problem! - if(sound != null) caster.playSound(sound, volume, pitch + pitchVariation * (world.rand.nextFloat() - 0.5f)); + + if(casterSwingsArm(world, caster, hand, ticksInUse, modifiers)) caster.swingArm(hand); + this.playSound(world, caster, ticksInUse, -1, modifiers); return true; } - /** Player and dispenser casting are almost identical so this takes care of the shared stuff. */ - private boolean shootSpell(World world, Vec3d origin, Vec3d direction, @Nullable EntityPlayer caster, int ticksInUse, SpellModifiers modifiers){ + @Override + public boolean cast(World world, double x, double y, double z, EnumFacing direction, int ticksInUse, int duration, SpellModifiers modifiers){ - double range = baseRange * modifiers.get(WizardryItems.range_upgrade); + Vec3d vec = new Vec3d(direction.getDirectionVec()); + Vec3d origin = new Vec3d(x, y, z); + + if(!shootSpell(world, origin, vec, null, ticksInUse, modifiers)) return false; + // This MUST be the coordinates of the actual dispenser, so we need to offset it + this.playSound(world, x - direction.getXOffset(), y - direction.getYOffset(), z - direction.getZOffset(), ticksInUse, duration, modifiers); + return true; + } + + /** + * Hook allowing subclasses to override the default range calculation on a per-cast basis. For example, grapple + * overrides this to change the range based on casting time so that its vine attaches to entities/blocks at the + * correct point and moves them accordingly. + * + * @param world The world in which the spell is being cast. + * @param origin A vector representing the coordinates of the origin point of the spell. + * @param direction A normalised vector representing the direction in which the spell is being cast. + * @param caster The entity casting the spell, or null if the spell is being cast from a dispenser. + * @param ticksInUse The number of ticks the spell has already been cast for. For all non-continuous spells, + * this is 0 and is not used. + * @param modifiers The SpellModifiers object with which this spell is being cast. + * @return The range to be used for this particular casting of the spell. + */ + // Technically you could alter the range in the SpellModifiers object by overriding the cast method but that + // would be a bit of a hack since it's not really what spell modifiers are for. + protected double getRange(World world, Vec3d origin, Vec3d direction, @Nullable EntityLivingBase caster, int ticksInUse, SpellModifiers modifiers){ + return getProperty(RANGE).doubleValue() * modifiers.get(WizardryItems.range_upgrade); + } + + /** + * Hook allowing subclasses to determine whether the caster swings their arm when casting the spell. By default, + * returns false for continuous spells and true for all others. + * + * @param world A reference to the world object. This is for convenience, you can also use caster.world. + * @param caster The EntityLivingBase that cast the spell. + * @param hand The hand that is holding the item used to cast the spell. If no item was used, this will be the + * main hand. + * @param ticksInUse The number of ticks the spell has already been cast for. For all non-continuous spells, this is + * 0 and is not used. For continuous spells, it is passed in as the maximum use duration of the item minus + * the count parameter in onUsingItemTick and therefore it increases by 1 each tick. + * @return True if the caster should swing their arm when casting this spell, false if not. + */ + protected boolean casterSwingsArm(World world, EntityLivingBase caster, EnumHand hand, int ticksInUse, SpellModifiers modifiers){ + return !this.isContinuous; + } + + /** Player and dispenser casting are almost identical so this takes care of the shared stuff. This is mainly for internal use. */ + protected boolean shootSpell(World world, Vec3d origin, Vec3d direction, @Nullable EntityPlayer caster, int ticksInUse, SpellModifiers modifiers){ + + double range = getRange(world, origin, direction, caster, ticksInUse, modifiers); Vec3d endpoint = origin.add(direction.scale(range)); - // The first method will hit the first block it touches, passing through entities as if they weren't there. - // The second method will hit the first thing it touches, whether that's a block or an entity. This method now - // returns the exact hit position for entities as well as blocks. - RayTraceResult rayTrace = WizardryUtilities.rayTrace(world, origin, endpoint, aimAssist, hitLiquids, Entity.class, e -> e == caster); + // Change the filter depending on whether living entities are ignored or not + RayTraceResult rayTrace = RayTracer.rayTrace(world, origin, endpoint, aimAssist, hitLiquids, + ignoreUncollidables, false, Entity.class, ignoreLivingEntities ? WizardryUtilities::isLiving + : RayTracer.ignoreEntityFilter(caster)); boolean flag = false; - + if(rayTrace != null){ // Doesn't matter which way round these are, they're mutually exclusive if(rayTrace.typeOfHit == RayTraceResult.Type.ENTITY){ // Do whatever the spell does when it hits an entity - flag = onEntityHit(world, rayTrace.entityHit, caster, ticksInUse, modifiers); + flag = onEntityHit(world, rayTrace.entityHit, rayTrace.hitVec, caster, origin, ticksInUse, modifiers); // If the spell succeeded, clip the particles to the correct distance so they don't go through the entity if(flag) range = origin.distanceTo(rayTrace.hitVec); }else if(rayTrace.typeOfHit == RayTraceResult.Type.BLOCK){ // Do whatever the spell does when it hits an block - flag = onBlockHit(world, rayTrace.getBlockPos(), rayTrace.sideHit, caster, ticksInUse, modifiers); - // If the spell succeeded, clip the particles to the correct distance so they don't go through the block - if(flag) range = origin.distanceTo(rayTrace.hitVec); + flag = onBlockHit(world, rayTrace.getBlockPos(), rayTrace.sideHit, rayTrace.hitVec, caster, origin, ticksInUse, modifiers); + // Clip the particles to the correct distance so they don't go through the block + // Unlike with entities, this is done regardless of whether the spell succeeded, since no spells go + // through blocks (and in fact, even the ray tracer itself doesn't do that) + range = origin.distanceTo(rayTrace.hitVec); } } // If flag is false, either the spell missed or the relevant entity/block hit method returned false - if(!flag && !onMiss(world, caster, ticksInUse, modifiers)) return false; + if(!flag && !onMiss(world, caster, origin, direction, ticksInUse, modifiers)) return false; // Particle spawning if(world.isRemote){ - spawnParticleRay(world, origin, direction, range); + spawnParticleRay(world, origin, direction, caster, range); } return true; } - // Private helper method, no-one will need to override it since it's pretty much the whole point of this class. - private void spawnParticleRay(World world, Vec3d origin, Vec3d direction, double distance){ - - Vec3d velocity = direction.scale(particleVelocity); - - for(double d = particleSpacing; d <= distance; d += particleSpacing){ - double x = origin.x + d*direction.x + particleDither * (world.rand.nextDouble()*2 - 1); - double y = origin.y + d*direction.y + particleDither * (world.rand.nextDouble()*2 - 1); - double z = origin.z + d*direction.z + particleDither * (world.rand.nextDouble()*2 - 1); - spawnParticle(world, x, y, z, velocity.x, velocity.y, velocity.z); - } - } // The exact behaviour of the returned values of the following three methods can be a little confusing. Normally, // either onEntityHit or onBlockHit (or both) will return true when the spell succeeded in hitting the block or // entity, and false if not (note that those two methods are mutually exclusive). If false is returned, onMiss will - // be called - onMiss will never be called if either of the other methods returns true. + // be called - if either of the other methods returns true, onMiss will only be called for a complete miss. /** - * Called when the spell hits an entity. Will never be called if ignoreEntities is true. + * Called when the spell hits an entity. Will never be called if ignoreLivingEntities is true. * @param world The world the entity is in. * @param target The entity that was hit. - * @param caster The caster of this spell, or null if this spell was cast from a dispenser. + * @param hit A vector representing the exact position at which the spell first hit the entity. Usually used for + * particle spawning. + * @param caster The caster of this spell, or null if this spell was cast from a dispenser. N.B. It is strongly + * recommended that the origin parameter is used instead of taking the caster's position directly. + * @param origin The position at which this spell originated. If the caster is not null, this will be at the caster's + * eyes. * @param ticksInUse The number of ticks the spell has already been cast for (used only for continuous spells). * @param modifiers The modifiers this spell was cast with. * @return True to continue with spell casting and spawn particles, false to trigger a miss (N.B. you will need to - * return false from {@link SpellRay#onMiss(World, EntityLivingBase, int, SpellModifiers)} if a miss should not consume - * mana). + * return false from {@link SpellRay#onMiss(World, EntityLivingBase, Vec3d, Vec3d, int, SpellModifiers)} if a miss + * should not consume mana). Returning false from this method will make it look as if the spell passed right + * through it, so if a spell spawns particles when it misses this method should return true even for non-living + * entities. */ - protected abstract boolean onEntityHit(World world, Entity target, @Nullable EntityLivingBase caster, int ticksInUse, SpellModifiers modifiers); + protected abstract boolean onEntityHit(World world, Entity target, Vec3d hit, @Nullable EntityLivingBase caster, Vec3d origin, int ticksInUse, SpellModifiers modifiers); /** * Called when the spell hits a block. * @param world The world the block is in. * @param pos The BlockPos of the block that was hit. * @param side The side of the block that was hit. + * @param hit A vector representing the exact position at which the spell first hit the block. Usually used for + * particle spawning. * @param caster The caster of this spell, or null if this spell was cast from a dispenser. + * @param origin The position at which this spell originated. If the caster is not null, this will be at the caster's + * eyes. * @param ticksInUse The number of ticks the spell has already been cast for (used only for continuous spells). * @param modifiers The modifiers this spell was cast with. * @return True to continue with spell casting and spawn particles, false to trigger a miss (N.B. you will need to - * return false from {@link SpellRay#onMiss(World, EntityLivingBase, int, SpellModifiers)} if a miss should not consume + * return false from {@link SpellRay#onMiss(World, EntityLivingBase, Vec3d, Vec3d, int, SpellModifiers)} if a miss should not consume * mana). */ - protected abstract boolean onBlockHit(World world, BlockPos pos, EnumFacing side, @Nullable EntityLivingBase caster, int ticksInUse, SpellModifiers modifiers); + protected abstract boolean onBlockHit(World world, BlockPos pos, EnumFacing side, Vec3d hit, @Nullable EntityLivingBase caster, Vec3d origin, int ticksInUse, SpellModifiers modifiers); /** * Called when the spell does not hit anything or when the spell hits something it has no effect on. Most of the time - * this will just return true or false, but some spells may, for example, display a chat readout. + * this will just return true or false, but some spells may, for example, display a chat readout or spawn custom + * particles. It is worth noting that this can affect how easy the spell is to identify. * @param world The world the spell is in. * @param caster The caster of this spell, or null if this spell was cast from a dispenser. + * @param origin The position at which this spell originated. If the caster is not null, this will be at the caster's + * eyes. + * @param direction A normalised vector in the direction this spell was cast (useful for custom particle effects). * @param ticksInUse The number of ticks the spell has already been cast for (used only for continuous spells). * @param modifiers The modifiers this spell was cast with. * @return True to continue with spell casting and spawn particles, false to cause the spell to fail. */ - protected abstract boolean onMiss(World world, @Nullable EntityLivingBase caster, int ticksInUse, SpellModifiers modifiers); + protected abstract boolean onMiss(World world, @Nullable EntityLivingBase caster, Vec3d origin, Vec3d direction, int ticksInUse, SpellModifiers modifiers); + + /** + * Highest-level particle spawning method, only called client-side. 'Normal' subclasses should not need to override + * this method; by default it spawns a line of particles, applying jitter and then calling + * {@link SpellRay#spawnParticle(World, double, double, double, double, double, double)} at each point. Override to replace this with + * an entirely custom particle effect - this is done by a few spells in the main mod to spawn beam-type particles. + * @param world The world in which to spawn the particles. + * @param origin A vector representing the start point of the line of particles. + * @param direction A normalised vector representing the direction of the line of particles. + * @param caster The entity that cast this spell, or null if it was cast by a dispenser. + * @param distance The length of the line of particles, already set to the appropriate distance based on the spell's + */ + // The caster argument is only really useful for spawning targeted particles continuously + protected void spawnParticleRay(World world, Vec3d origin, Vec3d direction, EntityLivingBase caster, double distance){ + + Vec3d velocity = direction.scale(particleVelocity); + + for(double d = particleSpacing; d <= distance; d += particleSpacing){ + double x = origin.x + d*direction.x + particleJitter * (world.rand.nextDouble()*2 - 1); + double y = origin.y + d*direction.y + particleJitter * (world.rand.nextDouble()*2 - 1); + double z = origin.z + d*direction.z + particleJitter * (world.rand.nextDouble()*2 - 1); + spawnParticle(world, x, y, z, velocity.x, velocity.y, velocity.z); + } + } /** * Called at each point along the spell trajectory to spawn one or more particles at that point. Only called * client-side. Does nothing by default. * @param world The world in which to spawn the particle. - * @param x The x-coordinate to spawn the particle at, with dither already applied. - * @param y The y-coordinate to spawn the particle at, with dither already applied. - * @param z The z-coordinate to spawn the particle at, with dither already applied. + * @param x The x-coordinate to spawn the particle at, with jitter already applied. + * @param y The y-coordinate to spawn the particle at, with jitter already applied. + * @param z The z-coordinate to spawn the particle at, with jitter already applied. * @param vx The x velocity to spawn the particle with. Usually this is only non-zero for continuous spells. * @param vy The y velocity to spawn the particle with. Usually this is only non-zero for continuous spells. * @param vz The z velocity to spawn the particle with. Usually this is only non-zero for continuous spells. diff --git a/src/main/java/electroblob/wizardry/spell/SummonIronGolem.java b/src/main/java/electroblob/wizardry/spell/SummonIronGolem.java index 5166d9ba..9feaca7d 100644 --- a/src/main/java/electroblob/wizardry/spell/SummonIronGolem.java +++ b/src/main/java/electroblob/wizardry/spell/SummonIronGolem.java @@ -1,15 +1,11 @@ package electroblob.wizardry.spell; -import electroblob.wizardry.constants.Element; -import electroblob.wizardry.constants.SpellType; -import electroblob.wizardry.constants.Tier; import electroblob.wizardry.util.ParticleBuilder; import electroblob.wizardry.util.ParticleBuilder.Type; import electroblob.wizardry.util.SpellModifiers; import electroblob.wizardry.util.WizardryUtilities; import net.minecraft.entity.monster.EntityIronGolem; import net.minecraft.entity.player.EntityPlayer; -import net.minecraft.init.SoundEvents; import net.minecraft.item.EnumAction; import net.minecraft.util.EnumHand; import net.minecraft.util.math.BlockPos; @@ -18,19 +14,24 @@ import net.minecraft.world.World; public class SummonIronGolem extends Spell { public SummonIronGolem(){ - super("summon_iron_golem", Tier.MASTER, Element.SORCERY, SpellType.MINION, 175, 400, EnumAction.BOW, false); + super("summon_iron_golem", EnumAction.BOW, false); + addProperties(SpellMinion.SUMMON_RADIUS); + soundValues(1, 1.1f, 0.2f); } @Override public boolean cast(World world, EntityPlayer caster, EnumHand hand, int ticksInUse, SpellModifiers modifiers){ - BlockPos pos = WizardryUtilities.findNearbyFloorSpace(caster, 2, 4); + BlockPos pos = WizardryUtilities.findNearbyFloorSpace(caster, getProperty(SpellMinion.SUMMON_RADIUS).intValue(), + getProperty(SpellMinion.SUMMON_RADIUS).intValue()); + if(pos == null) return false; if(!world.isRemote){ EntityIronGolem golem = new EntityIronGolem(world); golem.setPosition(pos.getX() + 0.5, pos.getY(), pos.getZ() + 0.5); + golem.setPlayerCreated(true); world.spawnEntity(golem); }else{ @@ -43,7 +44,7 @@ public class SummonIronGolem extends Spell { } } - WizardryUtilities.playSoundAtPlayer(caster, SoundEvents.ENTITY_WITHER_SPAWN, 1, 1 + 0.2f * world.rand.nextFloat()); + this.playSound(world, caster, ticksInUse, -1, modifiers); return true; } diff --git a/src/main/java/electroblob/wizardry/spell/SummonShadowWraith.java b/src/main/java/electroblob/wizardry/spell/SummonShadowWraith.java index 8dac0d1c..46f58165 100644 --- a/src/main/java/electroblob/wizardry/spell/SummonShadowWraith.java +++ b/src/main/java/electroblob/wizardry/spell/SummonShadowWraith.java @@ -1,16 +1,13 @@ package electroblob.wizardry.spell; -import electroblob.wizardry.constants.Element; -import electroblob.wizardry.constants.Tier; import electroblob.wizardry.entity.living.EntityShadowWraith; -import net.minecraft.init.SoundEvents; import net.minecraftforge.fml.relauncher.Side; import net.minecraftforge.fml.relauncher.SideOnly; public class SummonShadowWraith extends SpellMinion { public SummonShadowWraith(){ - super("summon_shadow_wraith", Tier.MASTER, Element.NECROMANCY, 100, 400, EntityShadowWraith::new, 600, SoundEvents.ENTITY_WITHER_AMBIENT); + super("summon_shadow_wraith", EntityShadowWraith::new); this.soundValues(1, 1.1f, 0.1f); } diff --git a/src/main/java/electroblob/wizardry/spell/SummonSkeleton.java b/src/main/java/electroblob/wizardry/spell/SummonSkeleton.java index 4bec5e60..095be078 100644 --- a/src/main/java/electroblob/wizardry/spell/SummonSkeleton.java +++ b/src/main/java/electroblob/wizardry/spell/SummonSkeleton.java @@ -1,24 +1,36 @@ package electroblob.wizardry.spell; -import electroblob.wizardry.constants.Element; -import electroblob.wizardry.constants.Tier; import electroblob.wizardry.entity.living.EntitySkeletonMinion; -import electroblob.wizardry.registry.WizardrySounds; +import electroblob.wizardry.entity.living.EntityStrayMinion; +import electroblob.wizardry.item.ItemArtefact; +import electroblob.wizardry.registry.WizardryItems; import electroblob.wizardry.util.SpellModifiers; import net.minecraft.entity.EntityLivingBase; +import net.minecraft.entity.player.EntityPlayer; import net.minecraft.init.Items; import net.minecraft.inventory.EntityEquipmentSlot; import net.minecraft.item.ItemStack; +import net.minecraft.util.math.BlockPos; +import net.minecraft.world.World; public class SummonSkeleton extends SpellMinion { public SummonSkeleton(){ - super("summon_skeleton", Tier.APPRENTICE, Element.NECROMANCY, 15, 50, EntitySkeletonMinion::new, 600, WizardrySounds.SPELL_SUMMONING); + super("summon_skeleton", EntitySkeletonMinion::new); this.soundValues(7, 0.6f, 0); } - + @Override - protected void addMinionExtras(EntitySkeletonMinion minion, EntityLivingBase caster, SpellModifiers modifiers, int alreadySpawned){ + protected EntitySkeletonMinion createMinion(World world, EntityLivingBase caster, SpellModifiers modifiers){ + if(caster instanceof EntityPlayer && ItemArtefact.isArtefactActive((EntityPlayer)caster, WizardryItems.charm_minion_variants)){ + return new EntityStrayMinion(world); + }else{ + return super.createMinion(world, caster, modifiers); + } + } + + @Override + protected void addMinionExtras(EntitySkeletonMinion minion, BlockPos pos, EntityLivingBase caster, SpellModifiers modifiers, int alreadySpawned){ minion.setItemStackToSlot(EntityEquipmentSlot.MAINHAND, new ItemStack(Items.BOW)); minion.setDropChance(EntityEquipmentSlot.MAINHAND, 0.0f); } diff --git a/src/main/java/electroblob/wizardry/spell/SummonSkeletonLegion.java b/src/main/java/electroblob/wizardry/spell/SummonSkeletonLegion.java index f7fb9c4c..72ecd26f 100644 --- a/src/main/java/electroblob/wizardry/spell/SummonSkeletonLegion.java +++ b/src/main/java/electroblob/wizardry/spell/SummonSkeletonLegion.java @@ -1,26 +1,36 @@ package electroblob.wizardry.spell; -import electroblob.wizardry.constants.Element; -import electroblob.wizardry.constants.Tier; import electroblob.wizardry.entity.living.EntitySkeletonMinion; +import electroblob.wizardry.entity.living.EntityStrayMinion; +import electroblob.wizardry.item.ItemArtefact; +import electroblob.wizardry.registry.WizardryItems; import electroblob.wizardry.util.SpellModifiers; import net.minecraft.entity.EntityLivingBase; +import net.minecraft.entity.player.EntityPlayer; import net.minecraft.init.Items; -import net.minecraft.init.SoundEvents; import net.minecraft.inventory.EntityEquipmentSlot; import net.minecraft.item.ItemStack; +import net.minecraft.util.math.BlockPos; +import net.minecraft.world.World; public class SummonSkeletonLegion extends SpellMinion { public SummonSkeletonLegion(){ - super("summon_skeleton_legion", Tier.MASTER, Element.NECROMANCY, 100, 400, EntitySkeletonMinion::new, 1200, SoundEvents.ENTITY_WITHER_SPAWN); + super("summon_skeleton_legion", EntitySkeletonMinion::new); this.soundValues(1, 1.1f, 0.1f); - this.quantity(3); - this.range(3); } - + @Override - protected void addMinionExtras(EntitySkeletonMinion minion, EntityLivingBase caster, SpellModifiers modifiers, int alreadySpawned){ + protected EntitySkeletonMinion createMinion(World world, EntityLivingBase caster, SpellModifiers modifiers){ + if(caster instanceof EntityPlayer && ItemArtefact.isArtefactActive((EntityPlayer)caster, WizardryItems.charm_minion_variants)){ + return new EntityStrayMinion(world); + }else{ + return super.createMinion(world, caster, modifiers); + } + } + + @Override + protected void addMinionExtras(EntitySkeletonMinion minion, BlockPos pos, EntityLivingBase caster, SpellModifiers modifiers, int alreadySpawned){ if(alreadySpawned % 2 == 0){ // Archers diff --git a/src/main/java/electroblob/wizardry/spell/SummonSnowGolem.java b/src/main/java/electroblob/wizardry/spell/SummonSnowGolem.java index 3be56349..2f77947c 100644 --- a/src/main/java/electroblob/wizardry/spell/SummonSnowGolem.java +++ b/src/main/java/electroblob/wizardry/spell/SummonSnowGolem.java @@ -1,9 +1,5 @@ package electroblob.wizardry.spell; -import electroblob.wizardry.constants.Element; -import electroblob.wizardry.constants.SpellType; -import electroblob.wizardry.constants.Tier; -import electroblob.wizardry.registry.WizardrySounds; import electroblob.wizardry.util.ParticleBuilder; import electroblob.wizardry.util.ParticleBuilder.Type; import electroblob.wizardry.util.SpellModifiers; @@ -18,7 +14,9 @@ import net.minecraft.world.World; public class SummonSnowGolem extends Spell { public SummonSnowGolem(){ - super("summon_snow_golem", Tier.APPRENTICE, Element.ICE, SpellType.MINION, 15, 20, EnumAction.BOW, false); + super("summon_snow_golem", EnumAction.BOW, false); + this.soundValues(1, 1, 0.4f); + addProperties(SpellMinion.SUMMON_RADIUS); } @Override @@ -43,7 +41,7 @@ public class SummonSnowGolem extends Spell { } } - WizardryUtilities.playSoundAtPlayer(caster, WizardrySounds.SPELL_HEAL, 0.7f, 1 + 0.4f * world.rand.nextFloat()); + playSound(world, caster, ticksInUse, -1, modifiers); return true; } diff --git a/src/main/java/electroblob/wizardry/spell/SummonSpiritHorse.java b/src/main/java/electroblob/wizardry/spell/SummonSpiritHorse.java index a256d880..a9f02984 100644 --- a/src/main/java/electroblob/wizardry/spell/SummonSpiritHorse.java +++ b/src/main/java/electroblob/wizardry/spell/SummonSpiritHorse.java @@ -1,53 +1,83 @@ package electroblob.wizardry.spell; -import electroblob.wizardry.WizardData; -import electroblob.wizardry.constants.Element; -import electroblob.wizardry.constants.SpellType; -import electroblob.wizardry.constants.Tier; +import electroblob.wizardry.data.IStoredVariable; +import electroblob.wizardry.data.Persistence; +import electroblob.wizardry.data.WizardData; import electroblob.wizardry.entity.living.EntitySpiritHorse; -import electroblob.wizardry.registry.WizardrySounds; import electroblob.wizardry.util.SpellModifiers; import electroblob.wizardry.util.WizardryUtilities; +import electroblob.wizardry.util.WizardryUtilities.Operations; +import net.minecraft.entity.Entity; +import net.minecraft.entity.SharedMonsterAttributes; +import net.minecraft.entity.ai.attributes.AttributeModifier; +import net.minecraft.entity.ai.attributes.IAttribute; +import net.minecraft.entity.passive.AbstractHorse; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.item.EnumAction; import net.minecraft.util.EnumHand; import net.minecraft.util.math.BlockPos; import net.minecraft.world.World; +import net.minecraftforge.fml.common.ObfuscationReflectionHelper; + +import java.util.UUID; public class SummonSpiritHorse extends Spell { + /** The string identifier for the potency attribute modifier. */ + private static final String POTENCY_ATTRIBUTE_MODIFIER = "potency"; + + private static final IAttribute JUMP_STRENGTH; + // Why is this protected? Doesn't that defeat the point of the attribute system? + static { + // Great, now I have to reflect into this class too. + JUMP_STRENGTH = ObfuscationReflectionHelper.getPrivateValue(AbstractHorse.class, null, "field_110271_bv"); + } + + public static final IStoredVariable UUID_KEY = IStoredVariable.StoredVariable.ofUUID("spiritHorseUUID", Persistence.ALWAYS); + public SummonSpiritHorse(){ - super("summon_spirit_horse", Tier.ADVANCED, Element.EARTH, SpellType.MINION, 50, 150, EnumAction.BOW, false); + super("summon_spirit_horse", EnumAction.BOW, false); + addProperties(SpellMinion.SUMMON_RADIUS); + soundValues(0.7f, 1.2f, 0.4f); + WizardData.registerStoredVariables(UUID_KEY); } @Override - public boolean doesSpellRequirePacket(){ + public boolean requiresPacket(){ return false; } @Override public boolean cast(World world, EntityPlayer caster, EnumHand hand, int ticksInUse, SpellModifiers modifiers){ - WizardData properties = WizardData.get(caster); + WizardData data = WizardData.get(caster); - if(!properties.hasSpiritHorse){ - if(!world.isRemote){ + if(!world.isRemote){ - BlockPos pos = WizardryUtilities.findNearbyFloorSpace(caster, 2, 4); - if(pos == null) return false; + Entity oldHorse = WizardryUtilities.getEntityByUUID(world, data.getVariable(UUID_KEY)); - EntitySpiritHorse horse = new EntitySpiritHorse(world); - horse.setPosition(pos.getX() + 0.5, pos.getY(), pos.getZ() + 0.5); - horse.setTamedBy(caster); - horse.setHorseSaddled(true); - world.spawnEntity(horse); - } - properties.hasSpiritHorse = true; - WizardryUtilities.playSoundAtPlayer(caster, WizardrySounds.SPELL_HEAL, 0.7F, - world.rand.nextFloat() * 0.4F + 1.0F); - return true; + if(oldHorse != null) oldHorse.setDead(); + + BlockPos pos = WizardryUtilities.findNearbyFloorSpace(caster, 2, 4); + if(pos == null) return false; + + EntitySpiritHorse horse = new EntitySpiritHorse(world); + horse.setPosition(pos.getX() + 0.5, pos.getY(), pos.getZ() + 0.5); + horse.setTamedBy(caster); + horse.setHorseSaddled(true); + world.spawnEntity(horse); + + horse.getEntityAttribute(SharedMonsterAttributes.MOVEMENT_SPEED).applyModifier( + new AttributeModifier(POTENCY_ATTRIBUTE_MODIFIER, modifiers.get(SpellModifiers.POTENCY) - 1, Operations.MULTIPLY_CUMULATIVE)); + // Jump strength increases ridiculously fast, so we're reducing the effect of the modifier by 75% + horse.getEntityAttribute(JUMP_STRENGTH).applyModifier(new AttributeModifier(POTENCY_ATTRIBUTE_MODIFIER, + modifiers.amplified(SpellModifiers.POTENCY, 0.25f) - 1, Operations.MULTIPLY_CUMULATIVE)); + + data.setVariable(UUID_KEY, horse.getUniqueID()); } - return false; + + this.playSound(world, caster, ticksInUse, -1, modifiers); + return true; } } diff --git a/src/main/java/electroblob/wizardry/spell/SummonSpiritWolf.java b/src/main/java/electroblob/wizardry/spell/SummonSpiritWolf.java index f3896c7f..f4a8d6eb 100644 --- a/src/main/java/electroblob/wizardry/spell/SummonSpiritWolf.java +++ b/src/main/java/electroblob/wizardry/spell/SummonSpiritWolf.java @@ -1,53 +1,75 @@ package electroblob.wizardry.spell; -import electroblob.wizardry.WizardData; -import electroblob.wizardry.constants.Element; -import electroblob.wizardry.constants.SpellType; -import electroblob.wizardry.constants.Tier; +import electroblob.wizardry.data.IStoredVariable; +import electroblob.wizardry.data.Persistence; +import electroblob.wizardry.data.WizardData; import electroblob.wizardry.entity.living.EntitySpiritWolf; -import electroblob.wizardry.registry.WizardrySounds; import electroblob.wizardry.util.SpellModifiers; import electroblob.wizardry.util.WizardryUtilities; +import electroblob.wizardry.util.WizardryUtilities.Operations; +import net.minecraft.entity.Entity; +import net.minecraft.entity.SharedMonsterAttributes; +import net.minecraft.entity.ai.attributes.AttributeModifier; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.item.EnumAction; import net.minecraft.util.EnumHand; import net.minecraft.util.math.BlockPos; import net.minecraft.world.World; +import java.util.UUID; + public class SummonSpiritWolf extends Spell { + /** The string identifier for the potency attribute modifier. */ + private static final String POTENCY_ATTRIBUTE_MODIFIER = "potency"; + + public static final IStoredVariable UUID_KEY = IStoredVariable.StoredVariable.ofUUID("spiritWolfUUID", Persistence.ALWAYS); + public SummonSpiritWolf(){ - super("summon_spirit_wolf", Tier.APPRENTICE, Element.EARTH, SpellType.MINION, 25, 100, EnumAction.BOW, false); + super("summon_spirit_wolf", EnumAction.BOW, false); + addProperties(SpellMinion.SUMMON_RADIUS); + soundValues(0.7f, 1.2f, 0.4f); + WizardData.registerStoredVariables(UUID_KEY); } @Override - public boolean doesSpellRequirePacket(){ + public boolean requiresPacket(){ return false; } @Override public boolean cast(World world, EntityPlayer caster, EnumHand hand, int ticksInUse, SpellModifiers modifiers){ - WizardData properties = WizardData.get(caster); + WizardData data = WizardData.get(caster); - if(!properties.hasSpiritWolf){ - if(!world.isRemote){ + if(!world.isRemote){ - BlockPos pos = WizardryUtilities.findNearbyFloorSpace(caster, 2, 4); - if(pos == null) return false; + Entity oldWolf = WizardryUtilities.getEntityByUUID(world, data.getVariable(UUID_KEY)); - EntitySpiritWolf wolf = new EntitySpiritWolf(world); - wolf.setPosition(pos.getX() + 0.5, pos.getY(), pos.getZ() + 0.5); - wolf.setTamed(true); - wolf.setOwnerId(caster.getUniqueID()); - world.spawnEntity(wolf); - } - properties.hasSpiritWolf = true; - WizardryUtilities.playSoundAtPlayer(caster, WizardrySounds.SPELL_HEAL, 0.7F, - world.rand.nextFloat() * 0.4F + 1.0F); - return true; + if(oldWolf != null) oldWolf.setDead(); + + BlockPos pos = WizardryUtilities.findNearbyFloorSpace(caster, 2, 4); + if(pos == null) return false; + + EntitySpiritWolf wolf = new EntitySpiritWolf(world); + wolf.setPosition(pos.getX() + 0.5, pos.getY(), pos.getZ() + 0.5); + wolf.setTamed(true); + wolf.setOwnerId(caster.getUniqueID()); + // Potency gives the wolf more strength AND more health + wolf.getEntityAttribute(SharedMonsterAttributes.ATTACK_DAMAGE).applyModifier( + new AttributeModifier(POTENCY_ATTRIBUTE_MODIFIER, modifiers.get(SpellModifiers.POTENCY) - 1, Operations.MULTIPLY_CUMULATIVE)); + wolf.getEntityAttribute(SharedMonsterAttributes.MAX_HEALTH).applyModifier( + new AttributeModifier(POTENCY_ATTRIBUTE_MODIFIER, modifiers.amplified(SpellModifiers.POTENCY, 1.5f) - 1, Operations.MULTIPLY_CUMULATIVE)); + wolf.setHealth(wolf.getMaxHealth()); + + world.spawnEntity(wolf); + + data.setVariable(UUID_KEY, wolf.getUniqueID()); } - return false; + + this.playSound(world, caster, ticksInUse, -1, modifiers); + return true; + } } diff --git a/src/main/java/electroblob/wizardry/spell/SummonWitherSkeleton.java b/src/main/java/electroblob/wizardry/spell/SummonWitherSkeleton.java new file mode 100644 index 00000000..d452c83c --- /dev/null +++ b/src/main/java/electroblob/wizardry/spell/SummonWitherSkeleton.java @@ -0,0 +1,24 @@ +package electroblob.wizardry.spell; + +import electroblob.wizardry.entity.living.EntityWitherSkeletonMinion; +import electroblob.wizardry.util.SpellModifiers; +import net.minecraft.entity.EntityLivingBase; +import net.minecraft.init.Items; +import net.minecraft.inventory.EntityEquipmentSlot; +import net.minecraft.item.ItemStack; +import net.minecraft.util.math.BlockPos; + +public class SummonWitherSkeleton extends SpellMinion { + + public SummonWitherSkeleton(){ + super("summon_wither_skeleton", EntityWitherSkeletonMinion::new); + this.soundValues(7, 0.6f, 0); + } + + @Override + protected void addMinionExtras(EntityWitherSkeletonMinion minion, BlockPos pos, EntityLivingBase caster, SpellModifiers modifiers, int alreadySpawned){ + minion.setItemStackToSlot(EntityEquipmentSlot.MAINHAND, new ItemStack(Items.STONE_SWORD)); + minion.setDropChance(EntityEquipmentSlot.MAINHAND, 0.0f); + } + +} diff --git a/src/main/java/electroblob/wizardry/spell/SummonZombie.java b/src/main/java/electroblob/wizardry/spell/SummonZombie.java new file mode 100644 index 00000000..1663b329 --- /dev/null +++ b/src/main/java/electroblob/wizardry/spell/SummonZombie.java @@ -0,0 +1,28 @@ +package electroblob.wizardry.spell; + +import electroblob.wizardry.entity.living.EntityHuskMinion; +import electroblob.wizardry.entity.living.EntityZombieMinion; +import electroblob.wizardry.item.ItemArtefact; +import electroblob.wizardry.registry.WizardryItems; +import electroblob.wizardry.util.SpellModifiers; +import net.minecraft.entity.EntityLivingBase; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.world.World; + +public class SummonZombie extends SpellMinion { + + public SummonZombie(){ + super("summon_zombie", EntityZombieMinion::new); + this.soundValues(7, 0.6f, 0); + } + + @Override + protected EntityZombieMinion createMinion(World world, EntityLivingBase caster, SpellModifiers modifiers){ + if(caster instanceof EntityPlayer && ItemArtefact.isArtefactActive((EntityPlayer)caster, WizardryItems.charm_minion_variants)){ + return new EntityHuskMinion(world); + }else{ + return super.createMinion(world, caster, modifiers); + } + } + +} diff --git a/src/main/java/electroblob/wizardry/spell/Telekinesis.java b/src/main/java/electroblob/wizardry/spell/Telekinesis.java index 13dbe35c..9d97aaa6 100644 --- a/src/main/java/electroblob/wizardry/spell/Telekinesis.java +++ b/src/main/java/electroblob/wizardry/spell/Telekinesis.java @@ -1,38 +1,36 @@ package electroblob.wizardry.spell; import electroblob.wizardry.Wizardry; -import electroblob.wizardry.constants.Element; -import electroblob.wizardry.constants.SpellType; -import electroblob.wizardry.constants.Tier; -import electroblob.wizardry.registry.WizardrySounds; import electroblob.wizardry.util.SpellModifiers; import net.minecraft.block.state.IBlockState; import net.minecraft.entity.Entity; import net.minecraft.entity.EntityLivingBase; import net.minecraft.entity.item.EntityItem; import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.item.EnumAction; import net.minecraft.item.ItemStack; import net.minecraft.util.EnumFacing; import net.minecraft.util.EnumHand; import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.Vec3d; import net.minecraft.world.World; public class Telekinesis extends SpellRay { public Telekinesis(){ - super("telekinesis", Tier.BASIC, Element.SORCERY, SpellType.UTILITY, 5, 5, false, 8, WizardrySounds.SPELL_CONJURATION); + super("telekinesis", false, EnumAction.NONE); } - @Override public boolean doesSpellRequirePacket(){ return false; } + @Override public boolean requiresPacket(){ return false; } @Override - protected boolean onEntityHit(World world, Entity target, EntityLivingBase caster, int ticksInUse, SpellModifiers modifiers){ + protected boolean onEntityHit(World world, Entity target, Vec3d hit, EntityLivingBase caster, Vec3d origin, int ticksInUse, SpellModifiers modifiers){ if(target instanceof EntityItem){ - target.motionX = (caster.posX - target.posX) / 6; - target.motionY = (caster.posY + caster.getEyeHeight() - target.posY) / 6; - target.motionZ = (caster.posZ - target.posZ) / 6; + target.motionX = (origin.x - target.posX) / 6; + target.motionY = (origin.y - target.posY) / 6; + target.motionZ = (origin.z - target.posZ) / 6; return true; }else if(target instanceof EntityPlayer && (Wizardry.settings.telekineticDisarmament || !(caster instanceof EntityPlayer))){ @@ -46,8 +44,8 @@ public class Telekinesis extends SpellRay { if(!world.isRemote){ EntityItem item = player.entityDropItem(player.getHeldItemMainhand(), 0); // Makes the item move towards the caster - item.motionX = (caster.posX - player.posX) / 20; - item.motionZ = (caster.posZ - player.posZ) / 20; + item.motionX = (origin.x - player.posX) / 20; + item.motionZ = (origin.z - player.posZ) / 20; } player.setHeldItem(EnumHand.MAIN_HAND, ItemStack.EMPTY); @@ -60,7 +58,7 @@ public class Telekinesis extends SpellRay { } @Override - protected boolean onBlockHit(World world, BlockPos pos, EnumFacing side, EntityLivingBase caster, int ticksInUse, SpellModifiers modifiers){ + protected boolean onBlockHit(World world, BlockPos pos, EnumFacing side, Vec3d hit, EntityLivingBase caster, Vec3d origin, int ticksInUse, SpellModifiers modifiers){ if(caster instanceof EntityPlayer){ @@ -76,7 +74,7 @@ public class Telekinesis extends SpellRay { } @Override - protected boolean onMiss(World world, EntityLivingBase caster, int ticksInUse, SpellModifiers modifiers){ + protected boolean onMiss(World world, EntityLivingBase caster, Vec3d origin, Vec3d direction, int ticksInUse, SpellModifiers modifiers){ return false; } diff --git a/src/main/java/electroblob/wizardry/spell/Thunderstorm.java b/src/main/java/electroblob/wizardry/spell/Thunderstorm.java index 06ca648b..05e7884f 100644 --- a/src/main/java/electroblob/wizardry/spell/Thunderstorm.java +++ b/src/main/java/electroblob/wizardry/spell/Thunderstorm.java @@ -1,18 +1,9 @@ package electroblob.wizardry.spell; -import java.util.List; - -import electroblob.wizardry.constants.Element; -import electroblob.wizardry.constants.SpellType; -import electroblob.wizardry.constants.Tier; import electroblob.wizardry.registry.WizardryItems; -import electroblob.wizardry.registry.WizardrySounds; -import electroblob.wizardry.util.MagicDamage; +import electroblob.wizardry.util.*; import electroblob.wizardry.util.MagicDamage.DamageType; -import electroblob.wizardry.util.ParticleBuilder; import electroblob.wizardry.util.ParticleBuilder.Type; -import electroblob.wizardry.util.SpellModifiers; -import electroblob.wizardry.util.WizardryUtilities; import net.minecraft.entity.EntityLiving; import net.minecraft.entity.EntityLivingBase; import net.minecraft.entity.effect.EntityLightningBolt; @@ -20,12 +11,31 @@ import net.minecraft.entity.player.EntityPlayer; import net.minecraft.item.EnumAction; import net.minecraft.util.EnumHand; import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.MathHelper; import net.minecraft.world.World; +import java.util.List; + public class Thunderstorm extends Spell { + public static final String LIGHTNING_BOLTS = "lightning_bolts"; + + public static final String SECONDARY_DAMAGE = "secondary_damage"; + public static final String TERTIARY_DAMAGE = "tertiary_damage"; + + public static final String SECONDARY_RANGE = "secondary_range"; + public static final String TERTIARY_RANGE = "tertiary_range"; + + public static final String SECONDARY_MAX_TARGETS = "secondary_max_targets"; + public static final String TERTIARY_MAX_TARGETS = "tertiary_max_targets"; // This is per secondary target + + private static final float CENTRE_RADIUS_FRACTION = 0.5f; + public Thunderstorm(){ - super("thunderstorm", Tier.MASTER, Element.LIGHTNING, SpellType.ATTACK, 100, 250, EnumAction.BOW, false); + super("thunderstorm", EnumAction.BOW, false); + this.soundValues(1, 1.7f, 0.2f); + addProperties(EFFECT_RADIUS, LIGHTNING_BOLTS, SECONDARY_DAMAGE, TERTIARY_DAMAGE, SECONDARY_RANGE, + TERTIARY_RANGE, SECONDARY_MAX_TARGETS, TERTIARY_MAX_TARGETS); } @Override @@ -43,77 +53,80 @@ public class Thunderstorm extends Spell { if(world.canBlockSeeSky(new BlockPos(caster))){ - for(int r = 0; r < 10; r++){ + double maxRadius = getProperty(EFFECT_RADIUS).doubleValue(); - double radius = 4 + world.rand.nextDouble() * 6 * modifiers.get(WizardryItems.blast_upgrade); - double angle = world.rand.nextDouble() * Math.PI * 2; + for(int i = 0; i < getProperty(LIGHTNING_BOLTS).intValue(); i++){ - double x = caster.posX + radius * Math.cos(angle); - double z = caster.posZ + radius * Math.sin(angle); - double y = WizardryUtilities.getNearestFloorLevel(world, new BlockPos(x, caster.posY, z), 10); + double radius = maxRadius * CENTRE_RADIUS_FRACTION + world.rand.nextDouble() * maxRadius + * (1 - CENTRE_RADIUS_FRACTION) * modifiers.get(WizardryItems.blast_upgrade); + float angle = world.rand.nextFloat() * (float)Math.PI * 2; - if(!world.isRemote){ - EntityLightningBolt entitylightning = new EntityLightningBolt(world, x, y, z, false); - world.addWeatherEffect(entitylightning); - } + double x = caster.posX + radius * MathHelper.cos(angle); + double z = caster.posZ + radius * MathHelper.sin(angle); + Integer y = WizardryUtilities.getNearestFloor(world, new BlockPos(x, caster.posY, z), (int)maxRadius); - // Code for eventhandler recognition; for achievements and such like. Left in for future use. - // NBTTagCompound entityNBT = entitylightning.getEntityData(); - // entityNBT.setInteger("summoningPlayer", entityplayer.entityId); + if(y != null){ - // Secondary chaining effect - double seekerRange = 10.0d; + if(!world.isRemote){ + EntityLightningBolt entitylightning = new EntityLightningBolt(world, x, y, z, false); + world.addWeatherEffect(entitylightning); + } - List secondaryTargets = WizardryUtilities.getEntitiesWithinRadius(seekerRange, x, - y + 1, z, world); + // Code for eventhandler recognition; for achievements and such like. Left in for future use. + // NBTTagCompound entityNBT = entitylightning.getEntityData(); + // entityNBT.setInteger("summoningPlayer", entityplayer.entityId); - // For this spell there is no limit to the amount of secondary targets! - for(EntityLivingBase secondaryTarget : secondaryTargets){ + // Secondary chaining effect + List secondaryTargets = WizardryUtilities.getEntitiesWithinRadius( + getProperty(SECONDARY_RANGE).doubleValue(), x, y + 1, z, world); - if(WizardryUtilities.isValidTarget(caster, secondaryTarget)){ + for(int j = 0; j < Math.min(secondaryTargets.size(), getProperty(SECONDARY_MAX_TARGETS).intValue()); j++){ - if(world.isRemote){ + EntityLivingBase secondaryTarget = secondaryTargets.get(j); - ParticleBuilder.create(Type.LIGHTNING).pos(x, y, z).target(secondaryTarget).spawn(world); - - ParticleBuilder.spawnShockParticles(world, secondaryTarget.posX, - secondaryTarget.getEntityBoundingBox().minY + secondaryTarget.height / 2, - secondaryTarget.posZ); - } + if(AllyDesignationSystem.isValidTarget(caster, secondaryTarget)){ - secondaryTarget.playSound(WizardrySounds.SPELL_SPARK, 1.0F, - world.rand.nextFloat() * 0.4F + 1.5F); + if(world.isRemote){ - secondaryTarget.attackEntityFrom(MagicDamage.causeDirectMagicDamage(caster, DamageType.SHOCK), - 10.0f * modifiers.get(SpellModifiers.POTENCY)); + ParticleBuilder.create(Type.LIGHTNING).pos(x, y, z).target(secondaryTarget).spawn(world); - // Tertiary chaining effect + ParticleBuilder.spawnShockParticles(world, secondaryTarget.posX, + secondaryTarget.getEntityBoundingBox().minY + secondaryTarget.height / 2, + secondaryTarget.posZ); + } - List tertiaryTargets = WizardryUtilities.getEntitiesWithinRadius(seekerRange, - secondaryTarget.posX, secondaryTarget.posY + secondaryTarget.height / 2, - secondaryTarget.posZ, world); + playSound(world, secondaryTarget, 0, -1, modifiers); - for(int j = 0; j < Math.min(tertiaryTargets.size(), 3); j++){ + secondaryTarget.attackEntityFrom(MagicDamage.causeDirectMagicDamage(caster, DamageType.SHOCK), + getProperty(SECONDARY_DAMAGE).floatValue() * modifiers.get(SpellModifiers.POTENCY)); - EntityLivingBase tertiaryTarget = (EntityLivingBase)tertiaryTargets.get(j); + // Tertiary chaining effect - if(!secondaryTargets.contains(tertiaryTarget) - && WizardryUtilities.isValidTarget(caster, tertiaryTarget)){ + List tertiaryTargets = WizardryUtilities.getEntitiesWithinRadius( + getProperty(TERTIARY_RANGE).doubleValue(), secondaryTarget.posX, + secondaryTarget.posY + secondaryTarget.height / 2, secondaryTarget.posZ, world); - if(world.isRemote){ - ParticleBuilder.create(Type.LIGHTNING).entity(secondaryTarget) - .pos(0, secondaryTarget.height/2, 0).target(tertiaryTarget).spawn(world); - ParticleBuilder.spawnShockParticles(world, tertiaryTarget.posX, - tertiaryTarget.getEntityBoundingBox().minY + tertiaryTarget.height / 2, - tertiaryTarget.posZ); + for(int k = 0; k < Math.min(tertiaryTargets.size(), getProperty(TERTIARY_MAX_TARGETS).intValue()); k++){ + + EntityLivingBase tertiaryTarget = tertiaryTargets.get(k); + + if(!secondaryTargets.contains(tertiaryTarget) + && AllyDesignationSystem.isValidTarget(caster, tertiaryTarget)){ + + if(world.isRemote){ + ParticleBuilder.create(Type.LIGHTNING).entity(secondaryTarget) + .pos(0, secondaryTarget.height / 2, 0).target(tertiaryTarget).spawn(world); + ParticleBuilder.spawnShockParticles(world, tertiaryTarget.posX, + tertiaryTarget.getEntityBoundingBox().minY + tertiaryTarget.height / 2, + tertiaryTarget.posZ); + } + + playSound(world, tertiaryTarget, 0, -1, modifiers); + + tertiaryTarget.attackEntityFrom( + MagicDamage.causeDirectMagicDamage(caster, DamageType.SHOCK), + getProperty(TERTIARY_DAMAGE).floatValue() * modifiers.get(SpellModifiers.POTENCY)); } - - tertiaryTarget.playSound(WizardrySounds.SPELL_SPARK, 1.0F, - world.rand.nextFloat() * 0.4F + 1.5F); - - tertiaryTarget.attackEntityFrom( - MagicDamage.causeDirectMagicDamage(caster, DamageType.SHOCK), - 8.0f * modifiers.get(SpellModifiers.POTENCY)); } } } diff --git a/src/main/java/electroblob/wizardry/spell/Tornado.java b/src/main/java/electroblob/wizardry/spell/Tornado.java index 166b071e..f5045b05 100644 --- a/src/main/java/electroblob/wizardry/spell/Tornado.java +++ b/src/main/java/electroblob/wizardry/spell/Tornado.java @@ -1,23 +1,25 @@ package electroblob.wizardry.spell; -import electroblob.wizardry.constants.Element; -import electroblob.wizardry.constants.SpellType; -import electroblob.wizardry.constants.Tier; import electroblob.wizardry.entity.construct.EntityTornado; -import electroblob.wizardry.registry.WizardrySounds; import electroblob.wizardry.util.SpellModifiers; import net.minecraft.entity.EntityLivingBase; import net.minecraft.item.EnumAction; +import net.minecraft.util.EnumFacing; public class Tornado extends SpellConstruct { + public static final String SPEED = "speed"; + public static final String UPWARD_ACCELERATION = "upward_acceleration"; + public Tornado(){ - super("tornado", Tier.ADVANCED, Element.EARTH, SpellType.ATTACK, 35, 80, EnumAction.NONE, EntityTornado::new, 200, WizardrySounds.SPELL_ICE); + super("tornado", EnumAction.NONE, EntityTornado::new, false); + addProperties(EFFECT_RADIUS, SPEED, DAMAGE, UPWARD_ACCELERATION); } @Override - protected void addConstructExtras(EntityTornado construct, EntityLivingBase caster, SpellModifiers modifiers){ - construct.setHorizontalVelocity(caster.getLookVec().x / 3, caster.getLookVec().z / 3); + protected void addConstructExtras(EntityTornado construct, EnumFacing side, EntityLivingBase caster, SpellModifiers modifiers){ + float speed = getProperty(SPEED).floatValue(); + construct.setHorizontalVelocity(caster.getLookVec().x * speed, caster.getLookVec().z * speed); } } diff --git a/src/main/java/electroblob/wizardry/spell/Transience.java b/src/main/java/electroblob/wizardry/spell/Transience.java index 07bcc516..b47fdfcf 100644 --- a/src/main/java/electroblob/wizardry/spell/Transience.java +++ b/src/main/java/electroblob/wizardry/spell/Transience.java @@ -1,48 +1,60 @@ package electroblob.wizardry.spell; -import electroblob.wizardry.constants.Element; -import electroblob.wizardry.constants.SpellType; -import electroblob.wizardry.constants.Tier; +import electroblob.wizardry.Wizardry; import electroblob.wizardry.registry.WizardryItems; import electroblob.wizardry.registry.WizardryPotions; -import electroblob.wizardry.registry.WizardrySounds; import electroblob.wizardry.util.SpellModifiers; -import electroblob.wizardry.util.WizardryUtilities; import net.minecraft.entity.EntityLivingBase; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.init.MobEffects; import net.minecraft.item.EnumAction; import net.minecraft.potion.PotionEffect; +import net.minecraft.util.DamageSource; import net.minecraft.util.EnumHand; +import net.minecraft.util.ResourceLocation; import net.minecraft.world.World; import net.minecraftforge.event.entity.living.LivingAttackEvent; -import net.minecraftforge.event.world.BlockEvent; +import net.minecraftforge.event.entity.living.PotionEvent; +import net.minecraftforge.event.entity.player.PlayerInteractEvent; import net.minecraftforge.fml.common.Mod; import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; @Mod.EventBusSubscriber public class Transience extends Spell { + /** A {@code ResourceLocation} representing the shader file used when under the effects of transience. */ + public static final ResourceLocation SHADER = new ResourceLocation(Wizardry.MODID, "shaders/post/transience.json"); + public Transience(){ - super("transience", Tier.ADVANCED, Element.HEALING, SpellType.BUFF, 50, 100, EnumAction.BOW, false); + super("transience", EnumAction.BOW, false); + addProperties(EFFECT_DURATION); } @Override - public boolean doesSpellRequirePacket(){ - return false; + public boolean requiresPacket(){ + return true; } @Override public boolean cast(World world, EntityPlayer caster, EnumHand hand, int ticksInUse, SpellModifiers modifiers){ + if(world.isRemote && caster == net.minecraft.client.Minecraft.getMinecraft().player){ + if(Wizardry.settings.useShaders) net.minecraft.client.Minecraft.getMinecraft().entityRenderer.loadShader(SHADER); + electroblob.wizardry.client.WizardryClientEventHandler.playBlinkEffect(); + } + if(!caster.isPotionActive(WizardryPotions.transience)){ + if(!world.isRemote){ - caster.addPotionEffect(new PotionEffect(WizardryPotions.transience, - (int)(400 * modifiers.get(WizardryItems.duration_upgrade)), 0)); - caster.addPotionEffect(new PotionEffect(MobEffects.INVISIBILITY, - (int)(400 * modifiers.get(WizardryItems.duration_upgrade)), 0, false, false)); - WizardryUtilities.playSoundAtPlayer(caster, WizardrySounds.SPELL_CONJURATION, 1.0f, 1.0f); + + int duration = (int)(getProperty(EFFECT_DURATION).floatValue() * modifiers.get(WizardryItems.duration_upgrade)); + + caster.addPotionEffect(new PotionEffect(WizardryPotions.transience, duration, 0)); + caster.addPotionEffect(new PotionEffect(MobEffects.INVISIBILITY, duration, 0, false, false)); + + this.playSound(world, caster, ticksInUse, duration, modifiers); } + return true; } return false; @@ -53,7 +65,7 @@ public class Transience extends Spell { if(event.getSource() != null){ // Prevents all blockable damage while transience is active if(event.getEntityLiving().isPotionActive(WizardryPotions.transience) - && !event.getSource().isUnblockable()){ + && event.getSource() != DamageSource.OUT_OF_WORLD){ event.setCanceled(true); } // Prevents transient entities from causing any damage @@ -65,20 +77,19 @@ public class Transience extends Spell { } @SubscribeEvent - public static void onBlockPlaceEvent(BlockEvent.PlaceEvent event){ - // Prevents transient players from placing blocks - if(event.getPlayer().isPotionActive(WizardryPotions.transience)){ + public static void onPlayerInteractEvent(PlayerInteractEvent event){ + // Prevents transient players from interacting with the world in any way + if(event.isCancelable() && event.getEntityPlayer().isPotionActive(WizardryPotions.transience)){ event.setCanceled(true); - return; } } @SubscribeEvent - public static void onBlockBreakEvent(BlockEvent.BreakEvent event){ - // Prevents transient players from breaking blocks - if(event.getPlayer().isPotionActive(WizardryPotions.transience)){ - event.setCanceled(true); - return; + public static void onPotionAddedEvent(PotionEvent.PotionAddedEvent event){ + if(event.getEntity().world.isRemote && event.getPotionEffect().getPotion() == WizardryPotions.transience + && event.getEntity() == net.minecraft.client.Minecraft.getMinecraft().player){ + if(Wizardry.settings.useShaders) net.minecraft.client.Minecraft.getMinecraft().entityRenderer.loadShader(SHADER); + electroblob.wizardry.client.WizardryClientEventHandler.playBlinkEffect(); } } diff --git a/src/main/java/electroblob/wizardry/spell/Transportation.java b/src/main/java/electroblob/wizardry/spell/Transportation.java index cbb838d0..07e7d9a6 100644 --- a/src/main/java/electroblob/wizardry/spell/Transportation.java +++ b/src/main/java/electroblob/wizardry/spell/Transportation.java @@ -1,63 +1,197 @@ package electroblob.wizardry.spell; -import electroblob.wizardry.WizardData; import electroblob.wizardry.block.BlockTransportationStone; -import electroblob.wizardry.constants.Element; -import electroblob.wizardry.constants.SpellType; -import electroblob.wizardry.constants.Tier; +import electroblob.wizardry.data.IStoredVariable; +import electroblob.wizardry.data.Persistence; +import electroblob.wizardry.data.WizardData; +import electroblob.wizardry.item.ItemArtefact; +import electroblob.wizardry.packet.PacketTransportation; +import electroblob.wizardry.packet.WizardryPacketHandler; +import electroblob.wizardry.registry.WizardryItems; +import electroblob.wizardry.util.Location; +import electroblob.wizardry.util.NBTExtras; import electroblob.wizardry.util.SpellModifiers; import electroblob.wizardry.util.WizardryUtilities; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.init.MobEffects; -import net.minecraft.init.SoundEvents; import net.minecraft.item.EnumAction; +import net.minecraft.nbt.NBTTagList; import net.minecraft.potion.PotionEffect; import net.minecraft.util.EnumHand; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.Vec3d; import net.minecraft.util.text.TextComponentTranslation; import net.minecraft.world.World; +import net.minecraftforge.fml.common.network.simpleimpl.IMessage; + +import java.util.ArrayList; +import java.util.Comparator; +import java.util.List; +import java.util.stream.Collectors; public class Transportation extends Spell { + public static final String TELEPORT_COUNTDOWN = "teleport_countdown"; + + public static final int MAX_REMEMBERED_LOCATIONS = 4; + + // For some reason 'the diamond' doesn't work if I chain methods onto this. Type inference is weird. + public static final IStoredVariable> LOCATIONS_KEY = new IStoredVariable.StoredVariable, NBTTagList>("stoneCirclePos", + s -> NBTExtras.listToNBT(s, Location::toNBT), t -> new ArrayList<>(NBTExtras.NBTToList(t, Location::fromNBT)), Persistence.ALWAYS).setSynced(); + public static final IStoredVariable COUNTDOWN_KEY = IStoredVariable.StoredVariable.ofInt("tpCountdown", Persistence.NEVER).withTicker(Transportation::update); + public Transportation(){ - super("transportation", Tier.ADVANCED, Element.SORCERY, SpellType.UTILITY, 100, 100, EnumAction.BOW, false); + super("transportation", EnumAction.BOW, false); + addProperties(TELEPORT_COUNTDOWN); + WizardData.registerStoredVariables(LOCATIONS_KEY, COUNTDOWN_KEY); } @Override - public boolean doesSpellRequirePacket(){ + public boolean requiresPacket(){ return false; } @Override public boolean cast(World world, EntityPlayer caster, EnumHand hand, int ticksInUse, SpellModifiers modifiers){ - WizardData properties = WizardData.get(caster); + WizardData data = WizardData.get(caster); // Fixes the sound not playing in first person. - if(world.isRemote) WizardryUtilities.playSoundAtPlayer(caster, SoundEvents.BLOCK_PORTAL_TRIGGER, 1.0f, 1.0f); + if(world.isRemote) this.playSound(world, caster, ticksInUse, -1, modifiers); // Only works when the caster is in the same dimension. - if(properties != null && properties.getTpCountdown() == 0){ - if(caster.dimension == properties.getStoneCircleDimension()){ - // Has to be y since x and z could reasonably be -1. - if(properties.getStoneCircleLocation() != null){ - if(BlockTransportationStone.testForCircle(world, properties.getStoneCircleLocation())){ - WizardryUtilities.playSoundAtPlayer(caster, SoundEvents.BLOCK_PORTAL_TRIGGER, 1.0f, 1.0f); - caster.addPotionEffect(new PotionEffect(MobEffects.NAUSEA, 150, 0)); - properties.setTpCountdown(75); - return true; - }else{ - if(!world.isRemote) - caster.sendStatusMessage(new TextComponentTranslation("spell." + this.getUnlocalisedName() + ".missing"), true); - } - }else{ - if(!world.isRemote) - caster.sendStatusMessage(new TextComponentTranslation("spell." + this.getUnlocalisedName() + ".undefined"), true); + if(data != null){ + + Integer countdown = data.getVariable(COUNTDOWN_KEY); + + if(countdown == null || countdown == 0){ + + List locations = data.getVariable(Transportation.LOCATIONS_KEY); + + if(locations == null) data.setVariable(Transportation.LOCATIONS_KEY, locations = new ArrayList<>(Transportation.MAX_REMEMBERED_LOCATIONS)); + + if(locations.isEmpty()){ + if(!world.isRemote) caster.sendStatusMessage(new TextComponentTranslation("spell." + this.getUnlocalisedName() + ".undefined"), true); + return false; + } + + if(ItemArtefact.isArtefactActive(caster, WizardryItems.charm_transportation)){ + + List locationsInDimension = locations.stream().filter(l -> l.dimension == caster.dimension).collect(Collectors.toList()); + + if(locationsInDimension.isEmpty()){ + if(!world.isRemote) caster.sendStatusMessage(new TextComponentTranslation("spell." + this.getUnlocalisedName() + ".wrongdimension"), true); + return false; + } + + Location destination = getLocationAimedAt(caster, locationsInDimension, 1); + + if(destination == null) return false; // None of them were aimed at + + if(attemptTravelTo(caster, world, destination.pos, modifiers)){ + // Move the selected destination to the end of the list, making it the 'most recent' one + // This makes my life easier in update() below, and is a kind of useful feature too + locations.remove(destination); + locations.add(destination); + if(!world.isRemote) data.sync(); + return true; + } + + }else{ + + Location destination = locations.get(locations.size() - 1); // The most recent one, or the only one + + if(destination.dimension == caster.dimension){ + return attemptTravelTo(caster, world, destination.pos, modifiers); + }else{ + if(!world.isRemote) caster.sendStatusMessage(new TextComponentTranslation("spell." + this.getUnlocalisedName() + ".wrongdimension"), true); + } + } - }else{ - if(!world.isRemote) - caster.sendStatusMessage(new TextComponentTranslation("spell." + this.getUnlocalisedName() + ".wrongdimension"), true); } } + return false; } + // The following four methods centralise and neaten up the code + // Since the deviation angle is also used by the UI renderer, this also ensures they use the same calculation + + /** Returns the location from the given list that the give player is aiming at, or null if they are not aiming + * at any of them. */ + public static Location getLocationAimedAt(EntityPlayer player, List locations, float partialTicks){ + return locations.stream() + .filter(l -> isLocationAimedAt(player, l.pos, partialTicks)) + .min(Comparator.comparingDouble(l -> getLookDeviationAngle(player, l.pos, partialTicks))) + .orElse(null); + } + + public static boolean isLocationAimedAt(EntityPlayer player, BlockPos pos, float partialTicks){ + + Vec3d origin = player.getPositionEyes(partialTicks); + Vec3d centre = WizardryUtilities.getCentre(pos); + Vec3d direction = centre.subtract(origin); + double distance = direction.length(); + + return getLookDeviationAngle(player, pos, partialTicks) < getIconSize(distance); + } + + public static double getLookDeviationAngle(EntityPlayer player, BlockPos pos, float partialTicks){ + + Vec3d origin = player.getPositionEyes(partialTicks); + Vec3d look = player.getLook(partialTicks); + Vec3d centre = WizardryUtilities.getCentre(pos); + Vec3d direction = centre.subtract(origin); + double distance = direction.length(); + + return Math.acos(direction.dotProduct(look) / distance); // Angle between a and b = acos((a.b) / (|a|*|b|)) + } + + public static double getIconSize(double distance){ + return 0.05 + 2/(distance + 5); + } + + private boolean attemptTravelTo(EntityPlayer player, World world, BlockPos destination, SpellModifiers modifiers){ + + WizardData data = WizardData.get(player); + + if(BlockTransportationStone.testForCircle(world, destination)){ + this.playSound(world, player, 0, -1, modifiers); + player.addPotionEffect(new PotionEffect(MobEffects.NAUSEA, 150, 0)); + data.setVariable(COUNTDOWN_KEY, getProperty(TELEPORT_COUNTDOWN).intValue()); + return true; + }else{ + if(!world.isRemote) player.sendStatusMessage(new TextComponentTranslation("spell." + this.getUnlocalisedName() + ".missing"), true); + return false; + } + } + + private static int update(EntityPlayer player, Integer countdown){ + + if(countdown == null) return 0; + + if(!player.world.isRemote){ + + WizardData data = WizardData.get(player); + + List locations = data.getVariable(Transportation.LOCATIONS_KEY); + if(locations == null || locations.isEmpty()) return 0; + + // If the location was selected, either it was already at the end of the list or it was moved there + Location destination = locations.get(locations.size() - 1); + + if(countdown == 1 && destination.dimension == player.dimension){ + player.setPositionAndUpdate(destination.pos.getX() + 0.5, destination.pos.getY(), destination.pos.getZ() + 0.5); + player.addPotionEffect(new PotionEffect(MobEffects.BLINDNESS, 50, 0)); + IMessage msg = new PacketTransportation.Message(player.getEntityId()); + WizardryPacketHandler.net.sendToDimension(msg, player.world.provider.getDimension()); + } + + if(countdown > 0){ + countdown--; + } + } + + return countdown; + } + } diff --git a/src/main/java/electroblob/wizardry/spell/VanishingBox.java b/src/main/java/electroblob/wizardry/spell/VanishingBox.java index 24ea13df..471450de 100644 --- a/src/main/java/electroblob/wizardry/spell/VanishingBox.java +++ b/src/main/java/electroblob/wizardry/spell/VanishingBox.java @@ -1,12 +1,7 @@ package electroblob.wizardry.spell; -import electroblob.wizardry.constants.Element; -import electroblob.wizardry.constants.SpellType; -import electroblob.wizardry.constants.Tier; import electroblob.wizardry.util.SpellModifiers; -import electroblob.wizardry.util.WizardryUtilities; import net.minecraft.entity.player.EntityPlayer; -import net.minecraft.init.SoundEvents; import net.minecraft.inventory.InventoryEnderChest; import net.minecraft.item.EnumAction; import net.minecraft.util.EnumHand; @@ -15,10 +10,10 @@ import net.minecraft.world.World; public class VanishingBox extends Spell { public VanishingBox(){ - super("vanishing_box", Tier.ADVANCED, Element.SORCERY, SpellType.UTILITY, 45, 70, EnumAction.BOW, false); + super("vanishing_box", EnumAction.BOW, false); } - @Override public boolean doesSpellRequirePacket(){ return false; } + @Override public boolean requiresPacket(){ return false; } @Override public boolean cast(World world, EntityPlayer caster, EnumHand hand, int ticksInUse, SpellModifiers modifiers){ @@ -32,7 +27,7 @@ public class VanishingBox extends Spell { } } - WizardryUtilities.playSoundAtPlayer(caster, SoundEvents.BLOCK_ENDERCHEST_OPEN, 1, 1); + this.playSound(world, caster, ticksInUse, -1, modifiers); return true; } diff --git a/src/main/java/electroblob/wizardry/spell/WallOfFrost.java b/src/main/java/electroblob/wizardry/spell/WallOfFrost.java index 1ab2670d..2c059bef 100644 --- a/src/main/java/electroblob/wizardry/spell/WallOfFrost.java +++ b/src/main/java/electroblob/wizardry/spell/WallOfFrost.java @@ -1,83 +1,69 @@ package electroblob.wizardry.spell; import electroblob.wizardry.block.BlockStatue; -import electroblob.wizardry.constants.Element; -import electroblob.wizardry.constants.SpellType; -import electroblob.wizardry.constants.Tier; import electroblob.wizardry.registry.WizardryBlocks; import electroblob.wizardry.registry.WizardryItems; import electroblob.wizardry.registry.WizardrySounds; -import electroblob.wizardry.tileentity.TileEntityStatue; import electroblob.wizardry.util.ParticleBuilder; +import electroblob.wizardry.util.ParticleBuilder.Type; import electroblob.wizardry.util.SpellModifiers; import electroblob.wizardry.util.WizardryUtilities; -import electroblob.wizardry.util.ParticleBuilder.Type; import net.minecraft.entity.Entity; import net.minecraft.entity.EntityLiving; import net.minecraft.entity.EntityLivingBase; -import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.item.EnumAction; import net.minecraft.util.EnumFacing; -import net.minecraft.util.EnumHand; +import net.minecraft.util.SoundEvent; import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.Vec3d; import net.minecraft.world.World; public class WallOfFrost extends SpellRay { - private static final int BASE_DURATION = 600; + private static final int MINIMUM_PLACEMENT_RANGE = 2; public WallOfFrost(){ - super("wall_of_frost", Tier.MASTER, Element.ICE, SpellType.UTILITY, 15, 0, true, 10, null); + super("wall_of_frost", true, EnumAction.NONE); this.particleVelocity(1); this.particleSpacing(0.5); - } - - @Override - public boolean cast(World world, EntityPlayer caster, EnumHand hand, int ticksInUse, SpellModifiers modifiers){ - // TODO: Temporary solution until I implement a better continuous sound system - boolean flag = super.cast(world, caster, hand, ticksInUse, modifiers); - if(flag){ - if(ticksInUse % 12 == 0){ - if(ticksInUse == 0) WizardryUtilities.playSoundAtPlayer(caster, WizardrySounds.SPELL_ICE, 0.5f, 1); - WizardryUtilities.playSoundAtPlayer(caster, WizardrySounds.SPELL_LOOP_ICE, 0.5f, 1); - } - } - return flag; + addProperties(DURATION); + soundValues(0.5f, 1, 0); } @Override - public boolean cast(World world, EntityLiving caster, EnumHand hand, int ticksInUse, EntityLivingBase target, SpellModifiers modifiers){ - boolean flag = super.cast(world, caster, hand, ticksInUse, target, modifiers); - if(flag){ - if(ticksInUse % 12 == 0){ - if(ticksInUse == 0) caster.playSound(WizardrySounds.SPELL_ICE, 0.5f, 1); - caster.playSound(WizardrySounds.SPELL_LOOP_ICE, 0.5f, 1); - } - } - return flag; + protected SoundEvent[] createSounds(){ + return this.createContinuousSpellSounds(); } @Override - protected boolean onEntityHit(World world, Entity target, EntityLivingBase caster, int ticksInUse, SpellModifiers modifiers){ + protected void playSound(World world, EntityLivingBase entity, int ticksInUse, int duration, SpellModifiers modifiers, String... sounds){ + this.playSoundLoop(world, entity, ticksInUse); + } + + @Override + protected void playSound(World world, double x, double y, double z, int ticksInUse, int duration, SpellModifiers modifiers, String... sounds){ + this.playSoundLoop(world, x, y, z, ticksInUse, duration); + } + + @Override + protected boolean onEntityHit(World world, Entity target, Vec3d hit, EntityLivingBase caster, Vec3d origin, int ticksInUse, SpellModifiers modifiers){ // Wall of frost now freezes entities solid too! if(target instanceof EntityLiving && !world.isRemote){ // Unchecked cast is fine because the block is a static final field if(((BlockStatue)WizardryBlocks.ice_statue).convertToStatue((EntityLiving)target, - (int)(BASE_DURATION * modifiers.get(WizardryItems.duration_upgrade)))){ + (int)(getProperty(DURATION).floatValue() * modifiers.get(WizardryItems.duration_upgrade)))){ - target.playSound(WizardrySounds.SPELL_FREEZE, 1.0F, world.rand.nextFloat() * 0.4F + 0.8F); - return true; + target.playSound(WizardrySounds.MISC_FREEZE, 1.0F, world.rand.nextFloat() * 0.4F + 0.8F); } } - return false; + return true; } @Override - protected boolean onBlockHit(World world, BlockPos pos, EnumFacing side, EntityLivingBase caster, int ticksInUse, SpellModifiers modifiers){ - - // IDEA: Use frosted ice instead of ice statue blocks - - if(!world.isRemote){ + protected boolean onBlockHit(World world, BlockPos pos, EnumFacing side, Vec3d hit, EntityLivingBase caster, Vec3d origin, int ticksInUse, SpellModifiers modifiers){ + + if(!world.isRemote && WizardryUtilities.canDamageBlocks(caster, world)){ // Stops the ice being placed floating above snow and grass. Directions other than up included for // completeness. @@ -86,20 +72,16 @@ public class WallOfFrost extends SpellRay { pos = pos.offset(side.getOpposite()); } - if(caster.getDistance(pos.getX(), pos.getY(), pos.getZ()) > 2 - && world.getBlockState(pos).getBlock() != WizardryBlocks.ice_statue){ + if(origin.squareDistanceTo(pos.getX(), pos.getY(), pos.getZ()) > MINIMUM_PLACEMENT_RANGE * MINIMUM_PLACEMENT_RANGE + && world.getBlockState(pos).getBlock() != WizardryBlocks.ice_statue && world.getBlockState(pos).getBlock() != WizardryBlocks.dry_frosted_ice){ pos = pos.offset(side); - int duration = (int)(BASE_DURATION * modifiers.get(WizardryItems.duration_upgrade)); + int duration = (int)(getProperty(DURATION).floatValue() * modifiers.get(WizardryItems.duration_upgrade)); if(WizardryUtilities.canBlockBeReplaced(world, pos)){ - - world.setBlockState(pos, WizardryBlocks.ice_statue.getDefaultState()); - - if(world.getTileEntity(pos) instanceof TileEntityStatue){ - ((TileEntityStatue)world.getTileEntity(pos)).setLifetime(duration); - } + world.setBlockState(pos, WizardryBlocks.dry_frosted_ice.getDefaultState()); + world.scheduleUpdate(pos.toImmutable(), WizardryBlocks.dry_frosted_ice, duration); } // Builds a 2 block high wall if it hits the ground @@ -107,12 +89,8 @@ public class WallOfFrost extends SpellRay { pos = pos.offset(side); if(WizardryUtilities.canBlockBeReplaced(world, pos)){ - - world.setBlockState(pos, WizardryBlocks.ice_statue.getDefaultState()); - - if(world.getTileEntity(pos) instanceof TileEntityStatue){ - ((TileEntityStatue)world.getTileEntity(pos)).setLifetime(duration); - } + world.setBlockState(pos, WizardryBlocks.dry_frosted_ice.getDefaultState()); + world.scheduleUpdate(pos.toImmutable(), WizardryBlocks.dry_frosted_ice, duration); } } } @@ -122,7 +100,7 @@ public class WallOfFrost extends SpellRay { } @Override - protected boolean onMiss(World world, EntityLivingBase caster, int ticksInUse, SpellModifiers modifiers){ + protected boolean onMiss(World world, EntityLivingBase caster, Vec3d origin, Vec3d direction, int ticksInUse, SpellModifiers modifiers){ return true; } diff --git a/src/main/java/electroblob/wizardry/spell/Whirlwind.java b/src/main/java/electroblob/wizardry/spell/Whirlwind.java index c3ff793e..733c891a 100644 --- a/src/main/java/electroblob/wizardry/spell/Whirlwind.java +++ b/src/main/java/electroblob/wizardry/spell/Whirlwind.java @@ -1,37 +1,55 @@ package electroblob.wizardry.spell; -import electroblob.wizardry.constants.Element; -import electroblob.wizardry.constants.SpellType; -import electroblob.wizardry.constants.Tier; -import electroblob.wizardry.registry.WizardrySounds; +import electroblob.wizardry.Wizardry; +import electroblob.wizardry.item.ItemArtefact; +import electroblob.wizardry.registry.WizardryItems; import electroblob.wizardry.util.SpellModifiers; import net.minecraft.entity.Entity; import net.minecraft.entity.EntityLivingBase; +import net.minecraft.entity.player.EntityPlayer; import net.minecraft.entity.player.EntityPlayerMP; +import net.minecraft.item.EnumAction; import net.minecraft.network.play.server.SPacketEntityVelocity; import net.minecraft.util.EnumFacing; import net.minecraft.util.EnumParticleTypes; import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.Vec3d; +import net.minecraft.util.text.TextComponentTranslation; import net.minecraft.world.World; public class Whirlwind extends SpellRay { + public static final String REPULSION_VELOCITY = "repulsion_velocity"; + public Whirlwind(){ - super("whirlwind", Tier.APPRENTICE, Element.EARTH, SpellType.DEFENCE, 10, 15, false, 10, WizardrySounds.SPELL_ICE); + super("whirlwind", false, EnumAction.NONE); this.soundValues(0.8f, 0.7f, 0.2f); + addProperties(REPULSION_VELOCITY); } @Override - protected boolean onEntityHit(World world, Entity target, EntityLivingBase caster, int ticksInUse, SpellModifiers modifiers){ - + protected boolean onEntityHit(World world, Entity target, Vec3d hit, EntityLivingBase caster, Vec3d origin, int ticksInUse, SpellModifiers modifiers){ + + if(target instanceof EntityPlayer && ((caster instanceof EntityPlayer && !Wizardry.settings.playersMoveEachOther) + || ItemArtefact.isArtefactActive((EntityPlayer)target, WizardryItems.amulet_anchoring))){ + + if(!world.isRemote && caster instanceof EntityPlayer) ((EntityPlayer)caster).sendStatusMessage( + new TextComponentTranslation("spell.resist", target.getName(), this.getNameForTranslationFormatted()), true); + return false; + } + // Left as EntityLivingBase because why not be able to move armour stands around? if(target instanceof EntityLivingBase){ + + Vec3d vec = target.getPositionVector().add(0, target.getEyeHeight(), 0).subtract(origin).normalize(); if(!world.isRemote){ - target.motionX = caster.getLookVec().x * 2; - target.motionY = caster.getLookVec().y * 2 + 1; - target.motionZ = caster.getLookVec().z * 2; + float velocity = getProperty(REPULSION_VELOCITY).floatValue() * modifiers.get(SpellModifiers.POTENCY); + + target.motionX = vec.x * velocity; + target.motionY = vec.y * velocity + 1; + target.motionZ = vec.z * velocity; // Player motion is handled on that player's client so needs packets if(target instanceof EntityPlayerMP){ @@ -40,15 +58,14 @@ public class Whirlwind extends SpellRay { } if(world.isRemote){ + + double distance = target.getDistance(origin.x, origin.y, origin.z); + for(int i = 0; i < 10; i++){ - double x = (double)(caster.posX + world.rand.nextFloat() - 0.5F - + caster.getLookVec().x * caster.getDistance(target) * 0.5); - double y = (double)(caster.getEntityBoundingBox().minY + caster.getEyeHeight() + world.rand.nextFloat() - 0.5F - + caster.getLookVec().y * caster.getDistance(target) * 0.5); - double z = (double)(caster.posZ + world.rand.nextFloat() - 0.5F - + caster.getLookVec().z * caster.getDistance(target) * 0.5); - world.spawnParticle(EnumParticleTypes.CLOUD, x, y, z, caster.getLookVec().x, - caster.getLookVec().y, caster.getLookVec().z); + double x = origin.x + world.rand.nextDouble() - 0.5 + vec.x * distance * 0.5; + double y = origin.y + world.rand.nextDouble() - 0.5 + vec.y * distance * 0.5; + double z = origin.z + world.rand.nextDouble() - 0.5 + vec.z * distance * 0.5; + world.spawnParticle(EnumParticleTypes.CLOUD, x, y, z, vec.x, vec.y, vec.z); } } @@ -59,12 +76,12 @@ public class Whirlwind extends SpellRay { } @Override - protected boolean onBlockHit(World world, BlockPos pos, EnumFacing side, EntityLivingBase caster, int ticksInUse, SpellModifiers modifiers){ + protected boolean onBlockHit(World world, BlockPos pos, EnumFacing side, Vec3d hit, EntityLivingBase caster, Vec3d origin, int ticksInUse, SpellModifiers modifiers){ return false; } @Override - protected boolean onMiss(World world, EntityLivingBase caster, int ticksInUse, SpellModifiers modifiers){ + protected boolean onMiss(World world, EntityLivingBase caster, Vec3d origin, Vec3d direction, int ticksInUse, SpellModifiers modifiers){ return false; } diff --git a/src/main/java/electroblob/wizardry/spell/Wither.java b/src/main/java/electroblob/wizardry/spell/Wither.java index 9055c0c4..f649d9b8 100644 --- a/src/main/java/electroblob/wizardry/spell/Wither.java +++ b/src/main/java/electroblob/wizardry/spell/Wither.java @@ -1,8 +1,5 @@ package electroblob.wizardry.spell; -import electroblob.wizardry.constants.Element; -import electroblob.wizardry.constants.SpellType; -import electroblob.wizardry.constants.Tier; import electroblob.wizardry.registry.WizardryItems; import electroblob.wizardry.util.MagicDamage; import electroblob.wizardry.util.MagicDamage.DamageType; @@ -12,26 +9,26 @@ import electroblob.wizardry.util.SpellModifiers; import electroblob.wizardry.util.WizardryUtilities; import net.minecraft.entity.Entity; import net.minecraft.entity.EntityLivingBase; +import net.minecraft.entity.player.EntityPlayer; import net.minecraft.init.MobEffects; -import net.minecraft.init.SoundEvents; +import net.minecraft.item.EnumAction; import net.minecraft.potion.PotionEffect; import net.minecraft.util.EnumFacing; import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.Vec3d; import net.minecraft.util.text.TextComponentTranslation; import net.minecraft.world.World; public class Wither extends SpellRay { - - private static final int BASE_DURATION = 200; - private static final int BASE_DAMAGE = 1; public Wither(){ - super("wither", Tier.APPRENTICE, Element.NECROMANCY, SpellType.ATTACK, 10, 20, false, 10, SoundEvents.ENTITY_WITHER_HURT); + super("wither", false, EnumAction.NONE); this.soundValues(1, 1.1f, 0.2f); + addProperties(DAMAGE, EFFECT_DURATION, EFFECT_STRENGTH); } @Override - protected boolean onEntityHit(World world, Entity target, EntityLivingBase caster, int ticksInUse, SpellModifiers modifiers){ + protected boolean onEntityHit(World world, Entity target, Vec3d hit, EntityLivingBase caster, Vec3d origin, int ticksInUse, SpellModifiers modifiers){ if(WizardryUtilities.isLiving(target)){ @@ -41,24 +38,23 @@ public class Wither extends SpellRay { new TextComponentTranslation("spell.resist", target.getName(), this.getNameForTranslationFormatted()), true); }else{ target.attackEntityFrom(MagicDamage.causeDirectMagicDamage(caster, DamageType.WITHER), - BASE_DAMAGE * modifiers.get(SpellModifiers.POTENCY)); + getProperty(DAMAGE).floatValue() * modifiers.get(SpellModifiers.POTENCY)); ((EntityLivingBase)target).addPotionEffect(new PotionEffect(MobEffects.WITHER, - (int)(BASE_DURATION * modifiers.get(WizardryItems.duration_upgrade)), 1)); + (int)(getProperty(EFFECT_DURATION).floatValue() * modifiers.get(WizardryItems.duration_upgrade)), + getProperty(EFFECT_STRENGTH).intValue() + SpellBuff.getStandardBonusAmplifier(modifiers.get(SpellModifiers.POTENCY)))); } - - return true; } + return true; + } + + @Override + protected boolean onBlockHit(World world, BlockPos pos, EnumFacing side, Vec3d hit, EntityLivingBase caster, Vec3d origin, int ticksInUse, SpellModifiers modifiers){ return false; } @Override - protected boolean onBlockHit(World world, BlockPos pos, EnumFacing side, EntityLivingBase caster, int ticksInUse, SpellModifiers modifiers){ - return false; - } - - @Override - protected boolean onMiss(World world, EntityLivingBase caster, int ticksInUse, SpellModifiers modifiers){ + protected boolean onMiss(World world, EntityLivingBase caster, Vec3d origin, Vec3d direction, int ticksInUse, SpellModifiers modifiers){ return true; } diff --git a/src/main/java/electroblob/wizardry/spell/WitherSkull.java b/src/main/java/electroblob/wizardry/spell/WitherSkull.java index 85a8b363..8370ad26 100644 --- a/src/main/java/electroblob/wizardry/spell/WitherSkull.java +++ b/src/main/java/electroblob/wizardry/spell/WitherSkull.java @@ -1,46 +1,63 @@ package electroblob.wizardry.spell; -import electroblob.wizardry.constants.Element; -import electroblob.wizardry.constants.SpellType; -import electroblob.wizardry.constants.Tier; +import electroblob.wizardry.Wizardry; +import electroblob.wizardry.registry.WizardryItems; import electroblob.wizardry.util.SpellModifiers; -import electroblob.wizardry.util.WizardryUtilities; import net.minecraft.entity.EntityLiving; import net.minecraft.entity.EntityLivingBase; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.entity.projectile.EntityWitherSkull; -import net.minecraft.init.SoundEvents; import net.minecraft.item.EnumAction; import net.minecraft.util.EnumHand; import net.minecraft.util.math.Vec3d; import net.minecraft.world.World; +import net.minecraftforge.event.entity.EntityMobGriefingEvent; +import net.minecraftforge.fml.common.Mod; +import net.minecraftforge.fml.common.eventhandler.Event; +import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; +@Mod.EventBusSubscriber public class WitherSkull extends Spell { + public static final String ACCELERATION = "acceleration"; + public WitherSkull(){ - super("wither_skull", Tier.ADVANCED, Element.NECROMANCY, SpellType.ATTACK, 20, 30, EnumAction.NONE, false); + super("wither_skull", EnumAction.NONE, false); + addProperties(ACCELERATION); + soundValues(1, 1.1f, 0.2f); } @Override - public boolean doesSpellRequirePacket(){ + public boolean requiresPacket(){ return false; } + @Override + public boolean canBeCastByNPCs(){ + return true; + } + @Override public boolean cast(World world, EntityPlayer caster, EnumHand hand, int ticksInUse, SpellModifiers modifiers){ Vec3d look = caster.getLookVec(); if(!world.isRemote){ + EntityWitherSkull witherskull = new EntityWitherSkull(world, caster, 1, 1, 1); - witherskull.setPosition(caster.posX + look.x, caster.posY + look.y + 1.3, - caster.posZ + look.z); - witherskull.accelerationX = look.x * 0.1; - witherskull.accelerationY = look.y * 0.1; - witherskull.accelerationZ = look.z * 0.1; + + witherskull.setPosition(caster.posX + look.x, caster.posY + look.y + 1.3, caster.posZ + look.z); + + double acceleration = getProperty(ACCELERATION).doubleValue() * modifiers.get(WizardryItems.range_upgrade); + + witherskull.accelerationX = look.x * acceleration; + witherskull.accelerationY = look.y * acceleration; + witherskull.accelerationZ = look.z * acceleration; + + witherskull.shootingEntity = caster; world.spawnEntity(witherskull); - WizardryUtilities.playSoundAtPlayer(caster, SoundEvents.ENTITY_WITHER_SHOOT, 1.0F, - world.rand.nextFloat() * 0.2F + 1.0F); + + this.playSound(world, caster, ticksInUse, -1, modifiers); } caster.swingArm(hand); return true; @@ -65,10 +82,11 @@ public class WitherSkull extends Spell { witherskull.accelerationY = dy / caster.getDistance(target) * 0.1; witherskull.accelerationZ = dz / caster.getDistance(target) * 0.1; + witherskull.shootingEntity = caster; witherskull.setPosition(caster.posX, caster.posY + caster.getEyeHeight(), caster.posZ); world.spawnEntity(witherskull); - caster.playSound(SoundEvents.ENTITY_WITHER_SHOOT, 1.0F, world.rand.nextFloat() * 0.2F + 1.0F); + this.playSound(world, caster, ticksInUse, -1, modifiers); } caster.swingArm(hand); @@ -78,9 +96,12 @@ public class WitherSkull extends Spell { return false; } - @Override - public boolean canBeCastByNPCs(){ - return true; + @SubscribeEvent + public static void onEntityMobGriefingEvent(EntityMobGriefingEvent event){ + if(event.getEntity() instanceof EntityPlayer){ + // If a player shot the wither skull, it should ignore the mob griefing gamerule and use playerBlockDamage instead + event.setResult(Wizardry.settings.playerBlockDamage ? Event.Result.ALLOW : Event.Result.DENY); + } } } diff --git a/src/main/java/electroblob/wizardry/tileentity/ContainerArcaneWorkbench.java b/src/main/java/electroblob/wizardry/tileentity/ContainerArcaneWorkbench.java index 8bd2d63f..7582ba0e 100644 --- a/src/main/java/electroblob/wizardry/tileentity/ContainerArcaneWorkbench.java +++ b/src/main/java/electroblob/wizardry/tileentity/ContainerArcaneWorkbench.java @@ -1,17 +1,14 @@ package electroblob.wizardry.tileentity; -import java.util.HashSet; -import java.util.Set; - import electroblob.wizardry.Wizardry; import electroblob.wizardry.event.SpellBindEvent; import electroblob.wizardry.item.IWorkbenchItem; -import electroblob.wizardry.item.ItemArcaneTome; -import electroblob.wizardry.item.ItemArmourUpgrade; import electroblob.wizardry.item.ItemSpellBook; +import electroblob.wizardry.registry.WizardryAdvancementTriggers; import electroblob.wizardry.registry.WizardryItems; import electroblob.wizardry.util.WandHelper; import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.entity.player.EntityPlayerMP; import net.minecraft.inventory.Container; import net.minecraft.inventory.IInventory; import net.minecraft.inventory.Slot; @@ -21,6 +18,9 @@ import net.minecraft.util.ResourceLocation; import net.minecraft.util.math.MathHelper; import net.minecraftforge.common.MinecraftForge; +import java.util.HashSet; +import java.util.Set; + public class ContainerArcaneWorkbench extends Container { /** The arcane workbench tile entity associated with this container. */ @@ -42,20 +42,21 @@ public class ContainerArcaneWorkbench extends Container { ItemStack wand = tileentity.getStackInSlot(CENTRE_SLOT); for(int i = 0; i < 8; i++){ - Slot slot = new SlotItemList(tileentity, i, -999, -999, 1, WizardryItems.spell_book); + Slot slot = new SlotItemClassList(tileentity, i, -999, -999, 1, ItemSpellBook.class); this.addSlotToContainer(slot); } - this.addSlotToContainer(new SlotItemList(tileentity, CRYSTAL_SLOT, 8, 88, 64, WizardryItems.magic_crystal)) + this.addSlotToContainer(new SlotItemList(tileentity, CRYSTAL_SLOT, 13, 101, 64, + WizardryItems.magic_crystal, WizardryItems.crystal_shard, WizardryItems.grand_crystal)) .setBackgroundName(EMPTY_SLOT_CRYSTAL.toString()); this.addSlotToContainer(new SlotWorkbenchItem(tileentity, CENTRE_SLOT, 80, 64, this)); - Set upgrades = new HashSet(WandHelper.getSpecialUpgrades()); // Can't be done statically. + Set upgrades = new HashSet<>(WandHelper.getSpecialUpgrades()); // Can't be done statically. upgrades.add(WizardryItems.arcane_tome); upgrades.add(WizardryItems.armour_upgrade); - this.addSlotToContainer(new SlotItemList(tileentity, UPGRADE_SLOT, 8, 106, 1, upgrades.toArray(new Item[0]))) + this.addSlotToContainer(new SlotItemList(tileentity, UPGRADE_SLOT, 147, 17, 1, upgrades.toArray(new Item[0]))) .setBackgroundName(EMPTY_SLOT_UPGRADE.toString()); for(int x = 0; x < 9; x++){ @@ -142,9 +143,9 @@ public class ContainerArcaneWorkbench extends Container { for(int i = 0; i < spellSlots; i++){ float angle = i * (2 * (float)Math.PI)/spellSlots; - int x = centreX + (int)(Math.round(SLOT_RADIUS * MathHelper.sin(angle))); + int x = centreX + Math.round(SLOT_RADIUS * MathHelper.sin(angle)); // -cos because +y is downwards - int y = centreY + (int)(Math.round(SLOT_RADIUS * -MathHelper.cos(angle))); + int y = centreY + Math.round(SLOT_RADIUS * -MathHelper.cos(angle)); showSlot(i, x, y); } @@ -159,17 +160,22 @@ public class ContainerArcaneWorkbench extends Container { } // FIXME: It only seems to be syncing correctly when a stack is put into the slot, not taken out. - // This is because markDirty isn't called in the tileentity, I think. + // This is because markDirty isn't called in the tileentity, I think. this.tileentity.sync(); } + // FIXME: Shift-clicking a stack of special upgrades when in the arcane workbench causes the whole stack to be + // transferred when it should be just one (this is a bug with vanilla as well - try putting a stack of + // bottles into a brewing stand). I have at least made it so only one gets used now, so it has no impact on + // the game. @Override public ItemStack transferStackInSlot(EntityPlayer player, int clickedSlotId){ ItemStack remainder = ItemStack.EMPTY; - Slot slot = (Slot)this.inventorySlots.get(clickedSlotId); + Slot slot = this.inventorySlots.get(clickedSlotId); if(slot != null && slot.getHasStack()){ + ItemStack stack = slot.getStack(); // The stack that was there originally remainder = stack.copy(); // A copy of that stack @@ -189,14 +195,13 @@ public class ContainerArcaneWorkbench extends Container { if(stack.getItem() instanceof ItemSpellBook){ minSlotId = 0; maxSlotId = CRYSTAL_SLOT - 1; - }else if(stack.getItem() == WizardryItems.magic_crystal){ + }else if(getSlot(CRYSTAL_SLOT).isItemValid(stack)){ minSlotId = CRYSTAL_SLOT; maxSlotId = CRYSTAL_SLOT; - }else if(stack.getItem() instanceof IWorkbenchItem){ + }else if(getSlot(CENTRE_SLOT).isItemValid(stack)){ minSlotId = CENTRE_SLOT; maxSlotId = CENTRE_SLOT; - }else if(stack.getItem() instanceof ItemArcaneTome || stack.getItem() instanceof ItemArmourUpgrade - || WandHelper.isWandUpgrade(stack.getItem())){ + }else if(getSlot(UPGRADE_SLOT).isItemValid(stack)){ minSlotId = UPGRADE_SLOT; maxSlotId = UPGRADE_SLOT; }else{ @@ -257,8 +262,10 @@ public class ContainerArcaneWorkbench extends Container { if(((IWorkbenchItem)centre.getStack().getItem()) .onApplyButtonPressed(player, centre, this.getSlot(CRYSTAL_SLOT), this.getSlot(UPGRADE_SLOT), spellBooks)){ - - // Probably don't need to do anything here, unless we're going to use packets to control the animation + + if(player instanceof EntityPlayerMP){ + WizardryAdvancementTriggers.arcane_workbench.trigger((EntityPlayerMP)player, centre.getStack()); + } } } } diff --git a/src/main/java/electroblob/wizardry/tileentity/SlotItemClassList.java b/src/main/java/electroblob/wizardry/tileentity/SlotItemClassList.java new file mode 100644 index 00000000..783249d9 --- /dev/null +++ b/src/main/java/electroblob/wizardry/tileentity/SlotItemClassList.java @@ -0,0 +1,40 @@ +package electroblob.wizardry.tileentity; + +import net.minecraft.inventory.IInventory; +import net.minecraft.inventory.Slot; +import net.minecraft.item.Item; +import net.minecraft.item.ItemStack; + +/** + * Simple extension of {@link Slot} which only accepts items from an array of item classes defined in the constructor. + * + * @author Electroblob + * @since Wizardry 1.0 + */ +public class SlotItemClassList extends Slot { + + private final Class[] itemClasses; + private int stackLimit; + + @SafeVarargs + public SlotItemClassList(IInventory inventory, int index, int x, int y, int stackLimit, Class... allowedItemClasses){ + super(inventory, index, x, y); + this.itemClasses = allowedItemClasses; + this.stackLimit = stackLimit; + } + + public int getSlotStackLimit(){ + return stackLimit; + } + + public boolean isItemValid(ItemStack stack){ + + for(Class itemClass : itemClasses){ + if(itemClass.isAssignableFrom(stack.getItem().getClass())){ + return true; + } + } + + return false; + } +} diff --git a/src/main/java/electroblob/wizardry/tileentity/SlotItemList.java b/src/main/java/electroblob/wizardry/tileentity/SlotItemList.java index 93115155..db95b5e0 100644 --- a/src/main/java/electroblob/wizardry/tileentity/SlotItemList.java +++ b/src/main/java/electroblob/wizardry/tileentity/SlotItemList.java @@ -6,18 +6,18 @@ import net.minecraft.item.Item; import net.minecraft.item.ItemStack; /** - * Simple extension of {@link Slot} which only accepts items from an array defined in the constructor. + * Simple extension of {@link Slot} which only accepts items from an array of items defined in the constructor. * * @author Electroblob * @since Wizardry 1.0 */ public class SlotItemList extends Slot { - private Item[] items; + private final Item[] items; private int stackLimit; - public SlotItemList(IInventory par1iInventory, int index, int x, int y, int stackLimit, Item... allowedItems){ - super(par1iInventory, index, x, y); + public SlotItemList(IInventory inventory, int index, int x, int y, int stackLimit, Item... allowedItems){ + super(inventory, index, x, y); this.items = allowedItems; this.stackLimit = stackLimit; } @@ -27,11 +27,13 @@ public class SlotItemList extends Slot { } public boolean isItemValid(ItemStack stack){ - for(int i = 0; i < items.length; i++){ - if(stack.getItem() == this.items[i]){ + + for(Item item : items){ + if(stack.getItem() == item){ return true; } } + return false; } } diff --git a/src/main/java/electroblob/wizardry/tileentity/SlotWorkbenchItem.java b/src/main/java/electroblob/wizardry/tileentity/SlotWorkbenchItem.java index c83673f0..0e0a2f7d 100644 --- a/src/main/java/electroblob/wizardry/tileentity/SlotWorkbenchItem.java +++ b/src/main/java/electroblob/wizardry/tileentity/SlotWorkbenchItem.java @@ -35,7 +35,7 @@ public class SlotWorkbenchItem extends Slot { @Override public int getSlotStackLimit(){ - return 1; + return 16; } @Override diff --git a/src/main/java/electroblob/wizardry/tileentity/TileEntityArcaneWorkbench.java b/src/main/java/electroblob/wizardry/tileentity/TileEntityArcaneWorkbench.java index a04d661c..991098b7 100644 --- a/src/main/java/electroblob/wizardry/tileentity/TileEntityArcaneWorkbench.java +++ b/src/main/java/electroblob/wizardry/tileentity/TileEntityArcaneWorkbench.java @@ -1,11 +1,10 @@ package electroblob.wizardry.tileentity; -import java.util.HashSet; -import java.util.Set; - import electroblob.wizardry.Wizardry; -import electroblob.wizardry.item.ItemWand; -import electroblob.wizardry.item.ItemWizardArmour; +import electroblob.wizardry.item.IManaStoringItem; +import electroblob.wizardry.item.IWorkbenchItem; +import electroblob.wizardry.item.ItemCrystal; +import electroblob.wizardry.item.ItemSpellBook; import electroblob.wizardry.registry.WizardryBlocks; import electroblob.wizardry.registry.WizardryItems; import electroblob.wizardry.util.WandHelper; @@ -26,16 +25,15 @@ import net.minecraftforge.common.util.Constants.NBT; import net.minecraftforge.fml.relauncher.Side; import net.minecraftforge.fml.relauncher.SideOnly; +import java.util.HashSet; +import java.util.Set; + public class TileEntityArcaneWorkbench extends TileEntity implements IInventory, ITickable { /** The inventory of the arcane workbench. */ private NonNullList inventory; - /** Controls the rotation of the rune. */ + /** Controls the rotating rune and floating wand animations. */ public float timer = 0; - /** Controls the change of yOffset. */ - public int yTimer = 0; - /** Controls the height of the wand. */ - public int yOffset = 300; public TileEntityArcaneWorkbench(){ inventory = NonNullList.withSize(ContainerArcaneWorkbench.UPGRADE_SLOT + 1, ItemStack.EMPTY); @@ -44,8 +42,6 @@ public class TileEntityArcaneWorkbench extends TileEntity implements IInventory, @Override public void onLoad(){ timer = 0; - yTimer = 0; - yOffset = 300; } /** Called to manually sync the tile entity with clients. */ @@ -56,29 +52,18 @@ public class TileEntityArcaneWorkbench extends TileEntity implements IInventory, @Override public void update(){ - ItemStack itemstack = this.getStackInSlot(ContainerArcaneWorkbench.CENTRE_SLOT); + ItemStack stack = this.getStackInSlot(ContainerArcaneWorkbench.CENTRE_SLOT); // Decrements wand damage (increases mana) every 1.5 seconds if it has a condenser upgrade - if(itemstack.getItem() instanceof ItemWand && !this.world.isRemote && itemstack.isItemDamaged() - && this.world.getWorldTime() % electroblob.wizardry.constants.Constants.CONDENSER_TICK_INTERVAL == 0){ + if(stack.getItem() instanceof IManaStoringItem && !this.world.isRemote && !((IManaStoringItem)stack.getItem()).isManaFull(stack) + && this.world.getTotalWorldTime() % electroblob.wizardry.constants.Constants.CONDENSER_TICK_INTERVAL == 0){ // If the upgrade level is 0, this does nothing anyway. - itemstack.setItemDamage( - itemstack.getItemDamage() - WandHelper.getUpgradeLevel(itemstack, WizardryItems.condenser_upgrade)); + ((IManaStoringItem)stack.getItem()).rechargeMana(stack, WandHelper.getUpgradeLevel(stack, WizardryItems.condenser_upgrade)); } // The server doesn't care what these are, and there's no need for them to be synced or saved. if(this.world.isRemote){ - if(timer < 359){ - timer++; - }else{ - timer = 0; - } - if(yOffset > 0){ - yTimer--; - }else{ - yTimer++; - } - yOffset += yTimer; + timer++; } } @@ -170,17 +155,16 @@ public class TileEntityArcaneWorkbench extends TileEntity implements IInventory, if(itemstack == ItemStack.EMPTY) return true; if(slotNumber >= 0 && slotNumber < ContainerArcaneWorkbench.CRYSTAL_SLOT){ - return itemstack.getItem() == WizardryItems.spell_book; + return itemstack.getItem() instanceof ItemSpellBook; }else if(slotNumber == ContainerArcaneWorkbench.CRYSTAL_SLOT){ - return itemstack.getItem() == WizardryItems.magic_crystal; + return itemstack.getItem() instanceof ItemCrystal; }else if(slotNumber == ContainerArcaneWorkbench.CENTRE_SLOT){ - return (itemstack.getItem() instanceof ItemWand || itemstack.getItem() instanceof ItemWizardArmour - || itemstack.getItem() == WizardryItems.blank_scroll); + return itemstack.getItem() instanceof IWorkbenchItem; }else if(slotNumber == ContainerArcaneWorkbench.UPGRADE_SLOT){ - Set upgrades = new HashSet(WandHelper.getSpecialUpgrades()); + Set upgrades = new HashSet<>(WandHelper.getSpecialUpgrades()); upgrades.add(WizardryItems.arcane_tome); upgrades.add(WizardryItems.armour_upgrade); return upgrades.contains(itemstack.getItem()); @@ -197,16 +181,12 @@ public class TileEntityArcaneWorkbench extends TileEntity implements IInventory, NBTTagList tagList = tagCompound.getTagList("Inventory", NBT.TAG_COMPOUND); for(int i = 0; i < tagList.tagCount(); i++){ - NBTTagCompound tag = (NBTTagCompound)tagList.getCompoundTagAt(i); + NBTTagCompound tag = tagList.getCompoundTagAt(i); byte slot = tag.getByte("Slot"); if(slot >= 0 && slot < getSizeInventory()){ setInventorySlotContents(slot, new ItemStack(tag)); } } - - // timer = tagCompound.getFloat("timer"); - // yTimer = tagCompound.getInteger("yTimer"); - // yOffset = tagCompound.getInteger("yOffset"); } @Override @@ -226,10 +206,6 @@ public class TileEntityArcaneWorkbench extends TileEntity implements IInventory, } tagCompound.setTag("Inventory", itemList); - // tagCompound.setFloat("timer", timer); - // tagCompound.setInteger("yTimer", yTimer); - // tagCompound.setInteger("yOffset", yOffset); - return tagCompound; } @@ -249,6 +225,7 @@ public class TileEntityArcaneWorkbench extends TileEntity implements IInventory, } @SideOnly(Side.CLIENT) + @Override public AxisAlignedBB getRenderBoundingBox(){ AxisAlignedBB bb = INFINITE_EXTENT_AABB; Block type = getBlockType(); diff --git a/src/main/java/electroblob/wizardry/tileentity/TileEntityMagicLight.java b/src/main/java/electroblob/wizardry/tileentity/TileEntityMagicLight.java index 7a43f568..2fa0ab68 100644 --- a/src/main/java/electroblob/wizardry/tileentity/TileEntityMagicLight.java +++ b/src/main/java/electroblob/wizardry/tileentity/TileEntityMagicLight.java @@ -19,6 +19,11 @@ public class TileEntityMagicLight extends TileEntityTimer { randomiser2[0] = -1; } + @Override + public boolean shouldRenderInPass(int pass){ + return pass == 1; + } + @Override public void update(){ diff --git a/src/main/java/electroblob/wizardry/tileentity/TileEntityPlayerSave.java b/src/main/java/electroblob/wizardry/tileentity/TileEntityPlayerSave.java index d9ff7e86..6e91f534 100644 --- a/src/main/java/electroblob/wizardry/tileentity/TileEntityPlayerSave.java +++ b/src/main/java/electroblob/wizardry/tileentity/TileEntityPlayerSave.java @@ -1,43 +1,26 @@ package electroblob.wizardry.tileentity; -import java.lang.ref.WeakReference; -import java.util.UUID; - +import electroblob.wizardry.Wizardry; import electroblob.wizardry.util.WizardryUtilities; import net.minecraft.entity.Entity; import net.minecraft.entity.EntityLivingBase; import net.minecraft.nbt.NBTTagCompound; import net.minecraft.tileentity.TileEntity; -import net.minecraft.util.ITickable; -public class TileEntityPlayerSave extends TileEntity implements ITickable { +import javax.annotation.Nullable; +import java.util.UUID; - /** The entity that created this construct */ - private WeakReference caster; +public class TileEntityPlayerSave extends TileEntity { - /** - * The UUID of the caster. Note that this is only for loading purposes; during normal updates the actual entity - * instance is stored (so that getEntityByUUID is not called constantly), so this will not always be synced (this is - * why it is private). - */ + /** The UUID of the caster. As of Wizardry 4.2, this is synced, and rather than storing the caster + * instance via a weak reference, it is fetched from the UUID each time it is needed in + * {@link TileEntityPlayerSave#getCaster()}. */ private UUID casterUUID; + public TileEntityPlayerSave(){} + public TileEntityPlayerSave(EntityLivingBase caster){ - this.caster = new WeakReference(caster); - } - - public TileEntityPlayerSave(){ - - } - - @Override - public void update(){ - if(this.getCaster() == null && this.casterUUID != null){ - Entity entity = WizardryUtilities.getEntityByUUID(world, casterUUID); - if(entity instanceof EntityLivingBase){ - this.caster = new WeakReference((EntityLivingBase)entity); - } - } + this.casterUUID = caster.getUniqueID(); } @Override @@ -52,7 +35,7 @@ public class TileEntityPlayerSave extends TileEntity implements ITickable { super.writeToNBT(tagCompound); if(this.getCaster() != null){ - tagCompound.setUniqueId("casterUUID", this.getCaster().getUniqueID()); + tagCompound.setUniqueId("casterUUID", casterUUID); } return tagCompound; @@ -63,12 +46,21 @@ public class TileEntityPlayerSave extends TileEntity implements ITickable { * may no longer exist are: entity died or was deleted, mob despawned, player logged out, entity teleported to * another dimension, or this construct simply had no caster in the first place. */ + @Nullable public EntityLivingBase getCaster(){ - return caster == null ? null : caster.get(); + + Entity entity = WizardryUtilities.getEntityByUUID(world, casterUUID); + + if(entity != null && !(entity instanceof EntityLivingBase)){ // Should never happen + Wizardry.logger.warn("{} has a non-living owner!", this); + entity = null; + } + + return (EntityLivingBase)entity; } - public void setCaster(EntityLivingBase caster){ - this.caster = new WeakReference(caster); + public void setCaster(@Nullable EntityLivingBase caster){ + this.casterUUID = caster == null ? null : caster.getUniqueID(); } } diff --git a/src/main/java/electroblob/wizardry/tileentity/TileEntityPlayerSaveTimed.java b/src/main/java/electroblob/wizardry/tileentity/TileEntityPlayerSaveTimed.java new file mode 100644 index 00000000..92f4ab37 --- /dev/null +++ b/src/main/java/electroblob/wizardry/tileentity/TileEntityPlayerSaveTimed.java @@ -0,0 +1,69 @@ +package electroblob.wizardry.tileentity; + +import electroblob.wizardry.block.BlockThorns; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.network.NetworkManager; +import net.minecraft.network.play.server.SPacketUpdateTileEntity; +import net.minecraft.util.ITickable; + +public class TileEntityPlayerSaveTimed extends TileEntityPlayerSave implements ITickable { + + public int timer = 0; + public int maxTimer; + + public TileEntityPlayerSaveTimed(int maxTimer){ + this.maxTimer = maxTimer; + } + + @Override + public void update(){ + + timer++; + + if(timer > maxTimer && !this.world.isRemote){ + this.world.destroyBlock(pos, false); + } + + if(timer % 2 == 0 && world.getBlockState(pos).getValue(BlockThorns.AGE) < BlockThorns.GROWTH_STAGES - 1){ + world.setBlockState(pos, world.getBlockState(pos).withProperty(BlockThorns.AGE, world.getBlockState(pos).getValue(BlockThorns.AGE) + 1), 2); + } + } + + public void setLifetime(int lifetime){ + this.maxTimer = lifetime; + } + + @Override + public void readFromNBT(NBTTagCompound tagCompound){ + super.readFromNBT(tagCompound); + timer = tagCompound.getInteger("timer"); + maxTimer = tagCompound.getInteger("maxTimer"); + } + + @Override + public NBTTagCompound writeToNBT(NBTTagCompound tagCompound){ + super.writeToNBT(tagCompound); + tagCompound.setInteger("timer", timer); + tagCompound.setInteger("maxTimer", maxTimer); + return tagCompound; + } + + @Override + public final NBTTagCompound getUpdateTag(){ + return this.writeToNBT(new NBTTagCompound()); + } + + @Override + public SPacketUpdateTileEntity getUpdatePacket(){ + NBTTagCompound tag = new NBTTagCompound(); + writeToNBT(tag); + return new SPacketUpdateTileEntity(pos, 1, tag); + } + + @Override + public void onDataPacket(NetworkManager net, SPacketUpdateTileEntity pkt){ + NBTTagCompound tag = pkt.getNbtCompound(); + readFromNBT(tag); + } + +} diff --git a/src/main/java/electroblob/wizardry/tileentity/TileEntityShrineCore.java b/src/main/java/electroblob/wizardry/tileentity/TileEntityShrineCore.java new file mode 100644 index 00000000..2fdd0393 --- /dev/null +++ b/src/main/java/electroblob/wizardry/tileentity/TileEntityShrineCore.java @@ -0,0 +1,218 @@ +package electroblob.wizardry.tileentity; + +import electroblob.wizardry.Wizardry; +import electroblob.wizardry.block.BlockPedestal; +import electroblob.wizardry.entity.living.EntityEvilWizard; +import electroblob.wizardry.entity.living.EntityWizard; +import electroblob.wizardry.packet.PacketConquerShrine; +import electroblob.wizardry.packet.WizardryPacketHandler; +import electroblob.wizardry.potion.PotionContainment; +import electroblob.wizardry.registry.WizardryBlocks; +import electroblob.wizardry.registry.WizardryPotions; +import electroblob.wizardry.registry.WizardrySounds; +import electroblob.wizardry.spell.ArcaneLock; +import electroblob.wizardry.util.NBTExtras; +import electroblob.wizardry.util.ParticleBuilder; +import electroblob.wizardry.util.ParticleBuilder.Type; +import electroblob.wizardry.util.WizardryUtilities; +import net.minecraft.entity.Entity; +import net.minecraft.entity.EntityLivingBase; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.nbt.NBTBase; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.nbt.NBTTagList; +import net.minecraft.nbt.NBTUtil; +import net.minecraft.potion.PotionEffect; +import net.minecraft.tileentity.TileEntity; +import net.minecraft.util.ITickable; +import net.minecraft.util.SoundCategory; +import net.minecraft.util.math.AxisAlignedBB; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.MathHelper; +import net.minecraftforge.common.util.Constants; +import net.minecraftforge.fml.common.network.NetworkRegistry; + +import java.util.Arrays; +import java.util.List; +import java.util.UUID; + +public class TileEntityShrineCore extends TileEntity implements ITickable { + + private static final double ACTIVATION_RADIUS = 5; + + private boolean activated = false; + private AxisAlignedBB containmentField; + private final UUID[] linkedWizards = new UUID[3]; + private TileEntity linkedContainer; + private BlockPos linkedContainerPos; // Temporary stores the container position read from NBT until the world is set + + @Override + public void setPos(BlockPos pos){ + super.setPos(pos); + initContainmentField(pos); + } + + private void initContainmentField(BlockPos pos){ + float r = PotionContainment.getContainmentDistance(0); + this.containmentField = new AxisAlignedBB(-r, -r, -r, r, r, r).offset(WizardryUtilities.getCentre(pos)); + } + + public void linkContainer(TileEntity container){ + this.linkedContainer = container; + } + + @Override + public void update(){ + + if(this.linkedContainer == null && this.linkedContainerPos != null){ + this.linkContainer(world.getTileEntity(this.linkedContainerPos)); + } + + double x = this.pos.getX() + 0.5; + double y = this.pos.getY() + 0.5; + double z = this.pos.getZ() + 0.5; + + if(!activated && world.getClosestPlayer(x, y, z, ACTIVATION_RADIUS, false) != null){ + + this.activated = true; + + if(world.isRemote){ + ParticleBuilder.create(Type.SPHERE).pos(x, y + 1, z).clr(0xf06495).scale(5).time(12).spawn(world); + } + + world.playSound(x, y, z, + WizardrySounds.BLOCK_PEDESTAL_ACTIVATE, SoundCategory.BLOCKS, 1.5f, 1, false); + + if(!world.isRemote){ + + EntityEvilWizard[] wizards = new EntityEvilWizard[linkedWizards.length]; + + for(int i = 0; i < linkedWizards.length; i++){ + + EntityEvilWizard wizard = new EntityEvilWizard(world); + + float angle = world.rand.nextFloat() * 2 * (float)Math.PI; + double x1 = this.pos.getX() + 0.5 + 5 * MathHelper.sin(angle); + double z1 = this.pos.getZ() + 0.5 + 5 * MathHelper.cos(angle); + Integer y1 = WizardryUtilities.getNearestFloor(world, new BlockPos(x1, this.pos.getY(), z1), 8); + if(y1 == null){ + // Fallback to the position of the shrine core if it failed to find a position (unlikely) + x1 = this.pos.getX() + 1; // Offset it so the wizard isn't inside the block + y1 = this.pos.getY(); + z1 = this.pos.getZ(); + } + + wizard.setLocationAndAngles(x1, y1 + 0.5, z1, 0, 0); + wizard.setElement(world.getBlockState(pos).getValue(BlockPedestal.ELEMENT)); + wizard.onInitialSpawn(world.getDifficultyForLocation(pos), null); + wizard.hasStructure = true; + + world.spawnEntity(wizard); + wizards[i] = wizard; + linkedWizards[i] = wizard.getUniqueID(); + } + + for(EntityEvilWizard wizard : wizards) wizard.groupUUIDs.addAll(Arrays.asList(linkedWizards)); + } + + containNearbyTargets(); + } + + if(activated && world.getTotalWorldTime() % 20L == 0) containNearbyTargets(); + + if(activated && areWizardsDead() && !world.isRemote){ + conquer(); + } + } + + private boolean areWizardsDead(){ + + for(UUID uuid : linkedWizards){ + Entity entity = WizardryUtilities.getEntityByUUID(world, uuid); + if(entity instanceof EntityEvilWizard && entity.isEntityAlive()) return false; + } + + return true; + } + + public void conquer(){ + + double x = this.pos.getX() + 0.5; + double y = this.pos.getY() + 0.5; + double z = this.pos.getZ() + 0.5; + + if(!world.isRemote){ + WizardryPacketHandler.net.sendToAllAround(new PacketConquerShrine.Message(this.pos), + new NetworkRegistry.TargetPoint(this.world.provider.getDimension(), x, y, z, 64)); + } + + world.setBlockState(pos, WizardryBlocks.runestone_pedestal.getDefaultState() + .withProperty(BlockPedestal.ELEMENT, world.getBlockState(pos).getValue(BlockPedestal.ELEMENT))); + + world.markTileEntityForRemoval(this); + + if(!world.isRemote){ + if(linkedContainer != null) NBTExtras.removeUniqueId(linkedContainer.getTileData(), ArcaneLock.NBT_KEY); + }else{ + TileEntity tileEntity = world.getTileEntity(this.pos.up()); + if(tileEntity != null){ // Bit of a dirty fix but it's only visual, so meh + NBTExtras.removeUniqueId(tileEntity.getTileData(), ArcaneLock.NBT_KEY); + } + } + + world.playSound(x, y, z, WizardrySounds.BLOCK_PEDESTAL_CONQUER, SoundCategory.BLOCKS, 1, 1, false); + + if(world.isRemote){ + ParticleBuilder.create(Type.SPHERE).scale(5).pos(x, y + 1, z).clr(0xf06495).time(12).spawn(world); + for(int i=0; i<5; i++){ + float brightness = 0.8f + world.rand.nextFloat() * 0.2f; + ParticleBuilder.create(Type.SPARKLE, world.rand, x, y + 1, z, 1, true) + .clr(1, brightness, brightness).spawn(world); + } + } + } + + private void containNearbyTargets(){ + + List entities = world.getEntitiesWithinAABB(EntityLivingBase.class, containmentField, + e -> e instanceof EntityPlayer || e instanceof EntityWizard || e instanceof EntityEvilWizard); + + for(EntityLivingBase entity : entities){ + entity.addPotionEffect(new PotionEffect(WizardryPotions.containment, 219)); + entity.getEntityData().setTag(PotionContainment.ENTITY_TAG, NBTUtil.createPosTag(this.pos)); + } + } + + @Override + public NBTTagCompound writeToNBT(NBTTagCompound compound){ + + compound.setBoolean("activated", this.activated); + if(linkedContainer != null) compound.setTag("linkedContainerPos", NBTUtil.createPosTag(linkedContainer.getPos())); + + NBTTagList tagList = new NBTTagList(); + for(UUID uuid : linkedWizards){ + if(uuid != null) tagList.appendTag(NBTUtil.createUUIDTag(uuid)); + } + compound.setTag("wizards", tagList); + + return super.writeToNBT(compound); + } + + @Override + public void readFromNBT(NBTTagCompound compound){ + + this.activated = compound.getBoolean("activated"); + this.linkedContainerPos = NBTUtil.getPosFromTag(compound.getCompoundTag("linkedContainerPos")); + + NBTTagList tagList = compound.getTagList("wizards", Constants.NBT.TAG_COMPOUND); + int i = 0; + for(NBTBase tag : tagList){ + if(tag instanceof NBTTagCompound) linkedWizards[i++] = NBTUtil.getUUIDFromTag((NBTTagCompound)tag); + else Wizardry.logger.warn("Unexpected tag type in NBT tag list of compound tags!"); + } + + super.readFromNBT(compound); + // Must be after super + initContainmentField(this.pos); + } +} diff --git a/src/main/java/electroblob/wizardry/tileentity/TileEntityStatue.java b/src/main/java/electroblob/wizardry/tileentity/TileEntityStatue.java index f93c7851..ab999d7d 100644 --- a/src/main/java/electroblob/wizardry/tileentity/TileEntityStatue.java +++ b/src/main/java/electroblob/wizardry/tileentity/TileEntityStatue.java @@ -18,7 +18,7 @@ public class TileEntityStatue extends TileEntity implements ITickable { public EntityLiving creature; private NBTTagCompound entityCompound; - private String entityName; + private ResourceLocation entityName; private float entityYawHead; private float entityYawOffset; public boolean isIce; @@ -95,8 +95,7 @@ public class TileEntityStatue extends TileEntity implements ITickable { // System.out.println(entityName); if(this.creature == null && entityName != null){ - this.creature = (EntityLiving)EntityList.createEntityByIDFromName(new ResourceLocation(this.entityName), - this.world); + this.creature = (EntityLiving)EntityList.createEntityByIDFromName(this.entityName, this.world); if(this.creature != null){ this.creature.readFromNBT(entityCompound); this.creature.rotationYawHead = this.entityYawHead; @@ -133,7 +132,7 @@ public class TileEntityStatue extends TileEntity implements ITickable { position = tagCompound.getInteger("position"); parts = tagCompound.getInteger("parts"); entityCompound = tagCompound.getCompoundTag("entity"); - entityName = tagCompound.getString("entityName"); + entityName = new ResourceLocation(tagCompound.getString("entityName")); timer = tagCompound.getInteger("timer"); lifetime = tagCompound.getInteger("lifetime"); isIce = tagCompound.getBoolean("isIce"); @@ -149,7 +148,7 @@ public class TileEntityStatue extends TileEntity implements ITickable { entityCompound = new NBTTagCompound(); if(creature != null){ creature.writeToNBT(entityCompound); - tagCompound.setString("entityName", EntityList.getEntityString(creature)); + tagCompound.setString("entityName", EntityList.getKey(creature).toString()); tagCompound.setFloat("entityYawHead", creature.rotationYawHead); tagCompound.setFloat("entityYawOffset", creature.renderYawOffset); } diff --git a/src/main/java/electroblob/wizardry/tileentity/TileEntityTimer.java b/src/main/java/electroblob/wizardry/tileentity/TileEntityTimer.java index c8eb6062..185bbd55 100644 --- a/src/main/java/electroblob/wizardry/tileentity/TileEntityTimer.java +++ b/src/main/java/electroblob/wizardry/tileentity/TileEntityTimer.java @@ -22,11 +22,10 @@ public class TileEntityTimer extends TileEntity implements ITickable { @Override public void update(){ + timer++; - if(!this.world.isRemote){ - // System.out.println("Timer: " + timer + "/" + maxTimer); - } - if(timer > maxTimer && !this.world.isRemote){// && this.world.getBlockId(xCoord, yCoord, zCoord) == + + if(maxTimer > 0 && timer > maxTimer && !this.world.isRemote){// && this.world.getBlockId(xCoord, yCoord, zCoord) == // Wizardry.magicLight.blockID){ if(this.getBlockType() instanceof BlockVanishingCobweb){ // destroyBlock breaks the block as if broken by a player, with sound and particles. diff --git a/src/main/java/electroblob/wizardry/util/AllyDesignationSystem.java b/src/main/java/electroblob/wizardry/util/AllyDesignationSystem.java new file mode 100644 index 00000000..a066a9eb --- /dev/null +++ b/src/main/java/electroblob/wizardry/util/AllyDesignationSystem.java @@ -0,0 +1,234 @@ +package electroblob.wizardry.util; + +import electroblob.wizardry.Wizardry; +import electroblob.wizardry.data.WizardData; +import electroblob.wizardry.registry.WizardryPotions; +import electroblob.wizardry.spell.MindControl; +import net.minecraft.entity.Entity; +import net.minecraft.entity.EntityLiving; +import net.minecraft.entity.EntityLivingBase; +import net.minecraft.entity.IEntityOwnable; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraftforge.common.util.FakePlayer; +import net.minecraftforge.event.entity.living.LivingAttackEvent; +import net.minecraftforge.fml.common.Mod; +import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; + +/** + * Contains some useful static methods for interacting with the ally designation system. Also handles the friendly fire + * setting. This was split off from {@link WizardryUtilities} as of wizardry 4.2 in an effort to make the code easier to + * navigate. + */ +@Mod.EventBusSubscriber +public final class AllyDesignationSystem { + + private AllyDesignationSystem(){} // No instances! + + /** Set of constants for each of the four friendly fire settings. */ + public enum FriendlyFire { + + ALL("All", false, false), + ONLY_PLAYERS("Only players", false, true), + ONLY_OWNED("Only summoned/tamed creatures", true, false), + NONE("None", true, true); + + /** Constant array storing the names of each of the constants, in the order they are declared. */ + public static final String[] names; + + static { + names = new String[values().length]; + for(FriendlyFire setting : values()){ + names[setting.ordinal()] = setting.name; + } + } + + /** The readable name for this friendly fire setting that will be displayed on the button in the config GUI. */ + public final String name; + public final boolean blockPlayers; + public final boolean blockOwned; + + FriendlyFire(String name, boolean blockPlayers, boolean blockOwned){ + this.name = name; + this.blockPlayers = blockPlayers; + this.blockOwned = blockOwned; + } + + /** + * Gets a friendly fire setting from its string name (ignoring case), or ALL if the given name is not a valid + * setting. + */ + public static FriendlyFire fromName(String name){ + + for(FriendlyFire setting : values()){ + if(setting.name.equalsIgnoreCase(name)) return setting; + } + + Wizardry.logger.info("Invalid string for the friendly fire setting. Using default (all) instead."); + return ALL; + } + + } + + /** + * Returns whether the given target can be attacked by the given attacker. It is up to the caller of this method to + * work out what this means; it doesn't necessarily mean the target is completely immune (for example, revenge + * targeting might reasonably bypass this). This method is intended for use where the damage is indirect and/or + * unavoidable; direct attacks should not check this method. Currently this means the following situations check + * this method: + *

    + * - AI targeting for summoned creatures
    + * - AI targeting for mind-controlled creatures
    + * - Constructs with an area of effect
    + * - Instantaneous spells with an area of effect around the caster (e.g. forest's curse, thunderstorm)
    + * - Any lightning chaining effects
    + * - Any projectiles which seek targets + *

    + * Also note that the friendly fire option is dealt with in the event handler. This method acts as a sort of wrapper + * for all the AllyDesignationSystem stuff in {@link WizardData}; more details about the ally designation system can be found there. + * + * @param attacker The entity that cast the spell originally + * @param target The entity being attacked + * + * @return False under any of the following circumstances, true otherwise: + *

    + * - The target is null + *

    + * - The target is the attacker (this isn't as stupid as it sounds - anything with an AoE might cause this + * to be true, as can summoned creatures) + *

    + * - The target and the attacker are both players and the target is an ally of the attacker (but the + * attacker need not be an ally of the target) + *

    + * - The target is a creature that was summoned/controlled by the attacker or by an ally of the attacker. + *

    + * - The target is a creature that was tamed by the attacker or by an ally of the attacker + * (see {@link net.minecraft.entity.IEntityOwnable}). + *

    + * As of wizardry 4.1.2, this method now returns true instead of false if the attacker is null. This + * is because in the vast majority of cases, it makes more sense this way: if a construct has no caster, it + * should affect all entities; if a minion has no caster it should target all entities; etc. + */ + public static boolean isValidTarget(Entity attacker, Entity target){ + + // Always return true if the attacker is null + if(attacker == null) return true; + + // Always return false if the target is null + if(target == null) return false; + + // Tests whether the target is the attacker + if(target == attacker) return false; + + // I really shouldn't need to do this, but fake players seem to break stuff... + if(target instanceof FakePlayer) return false; + + // Tests whether the target is a creature that was summoned by the attacker +// if(target instanceof ISummonedCreature && ((ISummonedCreature)target).getCaster() == attacker){ +// return false; +// } + + // Tests whether the target is a creature that was summoned/tamed (or is otherwise owned) by the attacker + if(target instanceof IEntityOwnable && ((IEntityOwnable)target).getOwner() == attacker){ + return false; + } + + // Tests whether the target is a creature that was mind controlled by the attacker + if(target instanceof EntityLiving && ((EntityLivingBase)target).isPotionActive(WizardryPotions.mind_control)){ + + NBTTagCompound entityNBT = target.getEntityData(); + + if(entityNBT != null && entityNBT.hasUniqueId(MindControl.NBT_KEY)){ + if(attacker == WizardryUtilities.getEntityByUUID(target.world, + entityNBT.getUniqueId(MindControl.NBT_KEY))){ + return false; + } + } + } + + // Ally section + if(attacker instanceof EntityPlayer && WizardData.get((EntityPlayer)attacker) != null){ + + if(target instanceof EntityPlayer){ + // Tests whether the target is an ally of the attacker + if(WizardData.get((EntityPlayer)attacker).isPlayerAlly((EntityPlayer)target)){ + return false; + } + +// }else if(target instanceof ISummonedCreature){ +// // Tests whether the target is a creature that was summoned by an ally of the attacker +// if(((ISummonedCreature)target).getCaster() instanceof EntityPlayer && WizardData.get((EntityPlayer)attacker) +// .isPlayerAlly((EntityPlayer)((ISummonedCreature)target).getCaster())){ +// return false; +// } + + }else if(target instanceof IEntityOwnable){ + // Tests whether the target is a creature that was summoned/tamed by an ally of the attacker + if(isOwnerAlly((EntityPlayer)attacker, (IEntityOwnable)target)); + + }else if(target instanceof EntityLiving && ((EntityLivingBase)target).isPotionActive(WizardryPotions.mind_control)){ + // Tests whether the target is a creature that was mind controlled by an ally of the attacker + NBTTagCompound entityNBT = target.getEntityData(); + + if(entityNBT != null && entityNBT.hasKey(MindControl.NBT_KEY)){ + + Entity controller = WizardryUtilities.getEntityByUUID(target.world, entityNBT.getUniqueId(MindControl.NBT_KEY)); + + if(controller instanceof EntityPlayer && WizardData.get((EntityPlayer)attacker).isPlayerAlly((EntityPlayer)controller)){ + return false; + } + } + } + } + + return true; + } + + /** Umbrella method that covers both {@link AllyDesignationSystem#isPlayerAlly(EntityPlayer, EntityPlayer)} and + * {@link AllyDesignationSystem#isOwnerAlly(EntityPlayer, IEntityOwnable)}, returning true if the given + * {@link EntityLivingBase} is either owned by the given player, an ally of the given player or owned by an ally + * of the given player. This is generally used to determine targets for healing or other group buffs. */ + public static boolean isAllied(EntityPlayer allyOf, EntityLivingBase possibleAlly){ + return (possibleAlly instanceof EntityPlayer && isPlayerAlly(allyOf, (EntityPlayer)possibleAlly)) + || (possibleAlly instanceof IEntityOwnable && (((IEntityOwnable)possibleAlly).getOwner() == allyOf + || isOwnerAlly(allyOf, (IEntityOwnable)possibleAlly))); + } + + /** Helper method for testing if the second player is an ally of the first player. Makes the code neater. + * @see AllyDesignationSystem#isOwnerAlly(EntityPlayer, IEntityOwnable) */ + public static boolean isPlayerAlly(EntityPlayer allyOf, EntityPlayer possibleAlly){ + WizardData data = WizardData.get(allyOf); + return data != null && data.isPlayerAlly(possibleAlly); + } + + /** Helper method for testing if the given {@link net.minecraft.entity.IEntityOwnable}'s owner is an ally of the + * given player. This works even when the owner is not logged in, though it may not correctly respect teams when + * that is the case. */ + public static boolean isOwnerAlly(EntityPlayer allyOf, IEntityOwnable ownable){ + WizardData data = WizardData.get(allyOf); + if(data == null) return false; + Entity owner = ownable.getOwner(); + return owner instanceof EntityPlayer ? data.isPlayerAlly((EntityPlayer)owner) : data.isPlayerAlly(ownable.getOwnerId()); + } + + @SubscribeEvent + public static void onLivingAttackEvent(LivingAttackEvent event){ + + if(event.getSource() != null && event.getSource().getTrueSource() instanceof EntityPlayer + && event.getSource() instanceof IElementalDamage){ + + if(event.getEntity() instanceof EntityPlayer){ + // Prevents any magic damage to allied players if friendly fire is disabled for players + if(Wizardry.settings.friendlyFire.blockPlayers && isPlayerAlly((EntityPlayer)event.getSource().getTrueSource(), (EntityPlayer)event.getEntity())){ + event.setCanceled(true); + } + }else{ + // Prevents any magic damage to entities owned by allied players if friendly fire is disabled for owned creatures + // Since we're dealing with players separately we might as well just use isAllied + if(Wizardry.settings.friendlyFire.blockOwned && isAllied((EntityPlayer)event.getSource().getTrueSource(), event.getEntityLiving())){ + event.setCanceled(true); + } + } + } + } +} diff --git a/src/main/java/electroblob/wizardry/util/CustomSoundCategory.java b/src/main/java/electroblob/wizardry/util/CustomSoundCategory.java new file mode 100644 index 00000000..a0fb1394 --- /dev/null +++ b/src/main/java/electroblob/wizardry/util/CustomSoundCategory.java @@ -0,0 +1,86 @@ +package electroblob.wizardry.util; + +import com.google.common.collect.Maps; +import net.minecraft.util.SoundCategory; +import net.minecraftforge.common.util.EnumHelper; +import net.minecraftforge.fml.common.ObfuscationReflectionHelper; +import net.minecraftforge.fml.relauncher.FMLLaunchHandler; +import net.minecraftforge.fml.relauncher.Side; +import net.minecraftforge.fml.relauncher.SideOnly; + +import java.util.Map; + +/** + * Add a new CONSTANT and reference name to net.minecraft.util.SoundCategory + * + * This allows the display of a volume control in the "Music & Sound Options" dialog. + * Unfortunately the GuiScreenOptionsSounds dialog does not auto size + * properly and move the Done button lower on the screen. + * + * To initialize the class create an instance during FMLPreInitializationEvent in + * the file with the @Mod annotation or your common proxy class. + * + * Usage example: static final SoundCategory SC_MXTUNE = MODSoundCategory.add("MXTUNE"); + * + * The language file key is "soundCategory.mxtune" + * The game settings "options.txt" key is "soundCategory_mxtune" + * + * To use the MXTUNE enum constant in code it must be referenced by name because + * SoundCategory.MXTUNE does not exist at compile time. + * e.g. SoundCategory.getByName("mxtune"); + * + * @author Paul Boese aka Aeronica (modified for 1.12.2 and for conciseness/clarity by Electroblob) + * @see + * www.minecraftforge.net/forum/topic/42439-adding-additional-soundcategorys/ + */ +public final class CustomSoundCategory { + + private static final String SRG_soundLevels = "field_186714_aM"; + private static final String SRG_SOUND_CATEGORIES = "field_187961_k"; + // >> Electroblob: Don't know why this was instantiated at all, surely it's a static helper class? + + private CustomSoundCategory(){} + + /** + * Adds a new custom sound category, performing the necessary changes to GameSettings and + * + * @param name A unique name for the sound category + * @return The resulting SoundCategory object + * @throws IllegalArgumentException if name is not unique + */ + public static SoundCategory add(String name){ + + Map SOUND_CATEGORIES; + + String constantName; + String referenceName; + SoundCategory soundCategory; + // >> Electroblob: Constructors were unnecessary since strings are immutable + constantName = name.toUpperCase().replace(" ", ""); + referenceName = constantName.toLowerCase(); + // >> Electroblob: Removed array surrounding varargs argument + soundCategory = EnumHelper.addEnum(SoundCategory.class , constantName, new Class[]{String.class}, referenceName); + SOUND_CATEGORIES = ObfuscationReflectionHelper.getPrivateValue(SoundCategory.class, SoundCategory.VOICE ,"SOUND_CATEGORIES", SRG_SOUND_CATEGORIES); + if (SOUND_CATEGORIES.containsKey(referenceName)) + // >> Electroblob: changed from Error to IllegalArgumentException + throw new IllegalArgumentException("Clash in Sound Category name pools! Cannot insert " + constantName); + SOUND_CATEGORIES.put(referenceName, soundCategory); + if (FMLLaunchHandler.side() == Side.CLIENT) setSoundLevels(); + + return soundCategory; + } + + /** Game sound level options settings only exist on the client side */ + @SideOnly(Side.CLIENT) + private static void setSoundLevels(){ + // SoundCategory now contains 'name' sound category so build a new map + // >> Electroblob: Converted to local variable + Map soundLevels = Maps.newEnumMap(SoundCategory.class); + // Replace the map in the GameSettings.class + // >> Electroblob: Fully qualified names, because this class gets loaded on both sides + ObfuscationReflectionHelper.setPrivateValue(net.minecraft.client.settings.GameSettings.class, + net.minecraft.client.Minecraft.getMinecraft().gameSettings, soundLevels, + "soundLevels", SRG_soundLevels); + } + +} \ No newline at end of file diff --git a/src/main/java/electroblob/wizardry/util/IElementalDamage.java b/src/main/java/electroblob/wizardry/util/IElementalDamage.java index 47fad34a..a3d12aeb 100644 --- a/src/main/java/electroblob/wizardry/util/IElementalDamage.java +++ b/src/main/java/electroblob/wizardry/util/IElementalDamage.java @@ -1,9 +1,7 @@ package electroblob.wizardry.util; -import electroblob.wizardry.registry.WizardryAdvancementTriggers; import electroblob.wizardry.util.MagicDamage.DamageType; import net.minecraft.entity.monster.EntityCreeper; -import net.minecraft.entity.player.EntityPlayer; import net.minecraftforge.event.entity.living.LivingAttackEvent; import net.minecraftforge.fml.common.Mod; import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; @@ -43,10 +41,6 @@ public interface IElementalDamage { && ((IElementalDamage)event.getSource()).getType() == DamageType.SHOCK){ // Charges creepers when they are hit by shock damage WizardryUtilities.chargeCreeper((EntityCreeper)event.getEntityLiving()); - // Gives the player that caused the shock damage the 'It's Gonna Blow' achievement - if(event.getSource().getTrueSource() instanceof EntityPlayer){ - WizardryAdvancementTriggers.charge_creeper.triggerFor((EntityPlayer)event.getSource().getTrueSource()); - } } } } diff --git a/src/main/java/electroblob/wizardry/util/Location.java b/src/main/java/electroblob/wizardry/util/Location.java new file mode 100644 index 00000000..dfeec264 --- /dev/null +++ b/src/main/java/electroblob/wizardry/util/Location.java @@ -0,0 +1,47 @@ +package electroblob.wizardry.util; + +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.nbt.NBTUtil; +import net.minecraft.util.math.BlockPos; + +import javax.annotation.concurrent.Immutable; + +/** Simple wrapper class that stores a {@link BlockPos} and an integer dimension ID. */ +@Immutable +public class Location { + + public final BlockPos pos; + public final int dimension; + + public Location(BlockPos pos, int dimension){ + this.pos = pos; + this.dimension = dimension; + } + + /** Returns true if the given location refers to the same coordinates and dimension as this one. */ + @Override + public boolean equals(Object that){ + + if(this == that) return true; + + if(that instanceof Location){ + return this.pos.equals(((Location)that).pos) && this.dimension == ((Location)that).dimension; + } + + return false; + } + + /** Creates and returns an {@link NBTTagCompound} representing this location. The returned compound tag is the + * same as that returned by {@link NBTUtil#createPosTag(BlockPos)}, but with an extra "dimension" key. */ + public NBTTagCompound toNBT(){ + NBTTagCompound nbt = NBTUtil.createPosTag(pos); + nbt.setInteger("dimension", dimension); + return nbt; + } + + /** Creates a new {@code Location} from the given {@link NBTTagCompound}. The given compound tag should be the + * same as that returned by {@link NBTUtil#createPosTag(BlockPos)}, but with an extra "dimension" key. */ + public static Location fromNBT(NBTTagCompound nbt){ + return new Location(NBTUtil.getPosFromTag(nbt), nbt.getInteger("dimension")); + } +} diff --git a/src/main/java/electroblob/wizardry/util/MagicDamage.java b/src/main/java/electroblob/wizardry/util/MagicDamage.java index 5055c9ff..80e3cf6c 100644 --- a/src/main/java/electroblob/wizardry/util/MagicDamage.java +++ b/src/main/java/electroblob/wizardry/util/MagicDamage.java @@ -1,37 +1,15 @@ package electroblob.wizardry.util; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import electroblob.wizardry.entity.living.EntityBlazeMinion; -import electroblob.wizardry.entity.living.EntityIceGiant; -import electroblob.wizardry.entity.living.EntityIceWraith; -import electroblob.wizardry.entity.living.EntityLightningWraith; -import electroblob.wizardry.entity.living.EntityPhoenix; -import electroblob.wizardry.entity.living.EntityShadowWraith; -import electroblob.wizardry.entity.living.EntitySkeletonMinion; -import electroblob.wizardry.entity.living.EntitySpiderMinion; -import electroblob.wizardry.entity.living.EntityStormElemental; -import electroblob.wizardry.entity.living.EntityZombieMinion; +import electroblob.wizardry.entity.living.*; import net.minecraft.entity.Entity; import net.minecraft.entity.boss.EntityDragon; import net.minecraft.entity.boss.EntityWither; -import net.minecraft.entity.monster.EntityBlaze; -import net.minecraft.entity.monster.EntityCaveSpider; -import net.minecraft.entity.monster.EntityGhast; -import net.minecraft.entity.monster.EntityMagmaCube; -import net.minecraft.entity.monster.EntityPigZombie; -import net.minecraft.entity.monster.EntitySkeleton; -import net.minecraft.entity.monster.EntitySnowman; -import net.minecraft.entity.monster.EntitySpider; -import net.minecraft.entity.monster.EntityWitherSkeleton; -import net.minecraft.entity.monster.EntityZombie; +import net.minecraft.entity.monster.*; import net.minecraft.util.DamageSource; import net.minecraft.util.EntityDamageSource; +import java.util.*; + // A note on the use of the vanilla damagesources: // When using indirect damage sources, the SECOND argument is the original entity (i.e. the caster), and the // FIRST argument is the actual projectile or whatever that does the damage. getTrueSource() will return @@ -47,12 +25,12 @@ import net.minecraft.util.EntityDamageSource; /** * "Ouch, that hurt!" - *

    + *

    * As of wizardry 1.1, this class has replaced the damagesource-related methods in WizardryUtilities, allowing a * {@link DamageType} to be specified with the damage. The main reason for this is so that damage sources can fit with * the vanilla behaviour on armour enchantments and such like whilst still being classified as wizardry damage for the * purposes of friendly fire, etc. - *

    + *

    * In the future, there is scope for an entirely standalone mod based on this idea. Perhaps 'Elemental Damage' could * be a config-only mod which allows its users to define any number of specific damage types, then give any creature a * resistance, immunity or vulnerability to each, as well as being able to specify the sources for each type, such as @@ -71,7 +49,7 @@ public class MagicDamage extends EntityDamageSource implements IElementalDamage /** The name of the damagesource for indirect magic damage from the wizardry mod. */ public static final String INDIRECT_MAGIC_DAMAGE = "indirect_wizardry_magic"; // Technically, I don't need to specify that the classes in this map must extend entity, but it's good practice to. - private static final Map, DamageType[]> immunityMapping = new HashMap, DamageType[]>(); + private static final Map, DamageType[]> immunityMapping = new HashMap<>(); private final DamageType type; private final boolean isRetaliatory; @@ -82,29 +60,29 @@ public class MagicDamage extends EntityDamageSource implements IElementalDamage * them. */ public enum DamageType { - /** Generic magic damage from the wizardry mod. Like vanilla magic damage, except it doesn't bypass armour. */ + /** Generic magic damage from wizardry. Like vanilla magic damage, except it doesn't bypass armour. */ MAGIC, - /** Fire damage from the wizardry mod. Counts as fire damage in the vanilla system, so is blocked by any mobs + /** Fire damage from wizardry. Counts as fire damage in the vanilla system, so is blocked by any mobs * that are immune to fire and entities with the fire resistance effect, and is affected by the fire protection * enchantment. */ FIRE, - /** Frost (ice) damage from the wizardry mod. Snow golems, ice wraiths and ice giants are immune. */ + /** Frost (ice) damage from wizardry. Snow golems, ice wraiths and ice giants are immune. */ FROST, - /** Shock (lightning) damage from the wizardry mod. Lightning wraiths and storm elementals are immune. */ + /** Shock (lightning) damage from wizardry. Lightning wraiths and storm elementals are immune. */ SHOCK, - /** Wither damage from the wizardry mod. Withers, wither skeletons and shadow wraiths are immune. */ + /** Wither damage from wizardry. Withers, wither skeletons and shadow wraiths are immune. */ WITHER, - /** Poison damage from the wizardry mod. Spiders, cave spiders and undead mobs are immune. */ + /** Poison damage from wizardry. Spiders, cave spiders and undead mobs are immune. */ POISON, - /** Force damage from the wizardry mod. */ // Insubstantial creatures (ghast, shadow wraith, etc.) are immune? + /** Force damage from wizardry. */ // Insubstantial creatures (ghast, shadow wraith, etc.) are immune? FORCE, - /** Blast damage from the wizardry mod. Affected by the blast protection enchantment. */ + /** Blast damage from wizardry. Affected by the blast protection enchantment. */ BLAST, - /** Radiant damage from the wizardry mod. */ - RADIANT; + /** Radiant damage from wizardry. */ + RADIANT } - static{ + static { // Of course, the entities that are immune to fire already are since there's a vanilla system for that, but // they're included here anyway for completeness and in case anyone wants to check if an entity is immune to // an unspecified element for reasons other than dealing damage. @@ -118,6 +96,7 @@ public class MagicDamage extends EntityDamageSource implements IElementalDamage setEntityImmunities(EntityStormElemental.class, DamageType.FIRE, DamageType.SHOCK); setEntityImmunities(EntityWither.class, DamageType.FIRE, DamageType.WITHER); setEntityImmunities(EntitySnowman.class, DamageType.FROST); + setEntityImmunities(EntityPolarBear.class, DamageType.FROST); setEntityImmunities(EntityIceWraith.class, DamageType.FROST); setEntityImmunities(EntityIceGiant.class, DamageType.FROST); setEntityImmunities(EntityLightningWraith.class, DamageType.SHOCK); @@ -165,7 +144,7 @@ public class MagicDamage extends EntityDamageSource implements IElementalDamage /** Adds the passed in damage type to the list of damage types to which the given entity is immune. */ public static void addEntityImmunity(Class entityType, DamageType immunity){ - List immunities = immunityMapping.get(entityType) == null ? new ArrayList() + List immunities = immunityMapping.get(entityType) == null ? new ArrayList<>() : Arrays.asList(immunityMapping.get(entityType)); immunities.add(immunity); // Apparently putting 0 here works just fine. @@ -178,7 +157,7 @@ public class MagicDamage extends EntityDamageSource implements IElementalDamage * not bypass armour and has a player as the source (rather than nothing). It is still classed as magic damage (for * the record, all this does in vanilla is make witches 85% resistant to it - but that seems kinda right anyway). * isRetaliatory defaults to false. - *

    + *

    * Now that this is its own class, this static method is largely redundant, but it's not worth refactoring the * entire mod just to get rid of this method and use the constructor instead. * @@ -186,7 +165,7 @@ public class MagicDamage extends EntityDamageSource implements IElementalDamage * @param type The type that this damage belongs to; used for resistances and wand perks. Use * {@link DamageType#MAGIC} for regular, non-elemental magic damage (sometimes you might not want an element * even though the spell has one - for example, not all necromancy spells are 'withery', so some of them - * might reasonably affect creatures that are ususally immune to wither effects). + * might reasonably affect creatures that are usually immune to wither effects). * @return A damagesource object of type EntityDamageSource */ public static DamageSource causeDirectMagicDamage(Entity caster, DamageType type){ @@ -198,7 +177,7 @@ public class MagicDamage extends EntityDamageSource implements IElementalDamage * types to allow things to distinguish between magic and regular melee/swords. Unlike DamageSource.MAGIC, it does * not bypass armour and has a player as the source (rather than nothing). It is still classed as magic damage (for * the record, all this does in vanilla is make witches 85% resistant to it - but that seems kinda right anyway). - *

    + *

    * Now that this is its own class, this static method is largely redundant, but it's not worth refactoring the * entire mod just to get rid of this method and use the constructor instead. * @@ -206,7 +185,7 @@ public class MagicDamage extends EntityDamageSource implements IElementalDamage * @param type The type that this damage belongs to; used for resistances and wand perks. Use * {@link DamageType#MAGIC} for regular, non-elemental magic damage (sometimes you might not want an element * even though the spell has one - for example, not all necromancy spells are 'withery', so some of them - * might reasonably affect creatures that are ususally immune to wither effects). + * might reasonably affect creatures that are usually immune to wither effects). * @param isRetaliatory whether this damage source came from a retaliatory attack; prevents infinite loops occurring * when two entities damage each other with retaliatory effects. * @return A damagesource object of type EntityDamageSource @@ -221,7 +200,7 @@ public class MagicDamage extends EntityDamageSource implements IElementalDamage * DamageSource.causeIndirectMagicDamage, it does not bypass armour. It is still classed as magic damage (for the * record, all this does in vanilla is make witches 85% resistant to it - but that seems kinda right anyway). * isRetaliatory defaults to false. - *

    + *

    * Now that this is its own class, this static method is largely redundant, but it's not worth refactoring the * entire mod just to get rid of this method and use the constructor instead. * @@ -230,7 +209,7 @@ public class MagicDamage extends EntityDamageSource implements IElementalDamage * @param type The type that this damage belongs to; used for resistances and wand perks. Use * {@link DamageType#MAGIC} for regular, non-elemental magic damage (sometimes you might not want an element * even though the spell has one - for example, not all necromancy spells are 'withery', so some of them - * might reasonably affect creatures that are ususally immune to wither effects). + * might reasonably affect creatures that are usually immune to wither effects). * @return A damagesource object of type EntityDamageSourceIndirect */ public static DamageSource causeIndirectMagicDamage(Entity magic, Entity caster, DamageType type){ @@ -242,7 +221,7 @@ public class MagicDamage extends EntityDamageSource implements IElementalDamage * types to allow things to distinguish between magic and regular arrows/throwables. Unlike * DamageSource.causeIndirectMagicDamage, it does not bypass armour. It is still classed as magic damage (for the * record, all this does in vanilla is make witches 85% resistant to it - but that seems kinda right anyway). - *

    + *

    * Now that this is its own class, this static method is largely redundant, but it's not worth refactoring the * entire mod just to get rid of this method and use the constructor instead. * @@ -251,7 +230,7 @@ public class MagicDamage extends EntityDamageSource implements IElementalDamage * @param type The type that this damage belongs to; used for resistances and wand perks. Use * {@link DamageType#MAGIC} for regular, non-elemental magic damage (sometimes you might not want an element * even though the spell has one - for example, not all necromancy spells are 'withery', so some of them - * might reasonably affect creatures that are ususally immune to wither effects). + * might reasonably affect creatures that are usually immune to wither effects). * @param isRetaliatory whether this damage source came from a retaliatory attack; prevents infinite loops occurring * when two entities damage each other with retaliatory effects. * @return A damagesource object of type EntityDamageSourceIndirect diff --git a/src/main/java/electroblob/wizardry/util/NBTExtras.java b/src/main/java/electroblob/wizardry/util/NBTExtras.java new file mode 100644 index 00000000..309fa217 --- /dev/null +++ b/src/main/java/electroblob/wizardry/util/NBTExtras.java @@ -0,0 +1,231 @@ +package electroblob.wizardry.util; + +import electroblob.wizardry.Wizardry; +import net.minecraft.nbt.NBTBase; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.nbt.NBTTagList; + +import java.util.*; +import java.util.function.Function; + +/** + * Contains a number of useful static methods for interacting with NBT data, particularly involving collections. + * This was split off from {@link WizardryUtilities} as of wizardry 4.2 in an effort to make the code easier to navigate. + * + * @author Electroblob + * @since Wizardry 4.2 + */ +public final class NBTExtras { + + private NBTExtras(){} // No instances! + + /** + * Generic method that stores any Map to an NBTTagList, given two functions that convert the key and value types in + * that map to subclasses of NBTBase. For what it's worth, there is very little point in using this unless you can + * use something more concise than an anonymous class to do the conversion. A lambda expression, or better, a method + * reference, would fit nicely. For example, take ExtendedPlayer's use of this to store conjured item durations: + *

    + * properties.setTag("conjuredItems", WizardryUtilities.mapToNBT(this.conjuredItemDurations, + * item -> new NBTTagInt(Item.getIdFromItem((Item)item)), NBTTagInt::new)); + *

    + * This is a lot nicer than simply iterating through the map, because for that you need to use the entry list, which + * introduces local variables that aren't really necessary. Notice that, since the values V in the map are simply + * Integer objects, a simple constructor reference to NBTTagInt::new can be used instead of a lambda expression (the + * Integer is auto-unboxed to int). + * + * @param The type of key stored in the given Map. + * @param The type of value stored in the given Map. + * @param The subtype of NBTBase that the keys (of type K) will be converted to. + * @param The subtype of NBTBase that the values (of type V) will be converted to. + * @param map The Map to be stored. + * @param keyFunction A Function that converts the keys in the map to NBT objects that can be stored. + * @param valueFunction A Function that converts the values in the map to NBT objects that can be stored. + * @param keyTagName The tag name to use for the key tags. + * @param valueTagName The tag name to use for the value tags. + * @return An NBTTagList that represents the given Map. + */ + public static NBTTagList mapToNBT(Map map, + Function keyFunction, Function valueFunction, String keyTagName, String valueTagName){ + + NBTTagList tagList = new NBTTagList(); + + for(Map.Entry entry : map.entrySet()){ + NBTTagCompound mapping = new NBTTagCompound(); + mapping.setTag(keyTagName, keyFunction.apply(entry.getKey())); + mapping.setTag(valueTagName, valueFunction.apply(entry.getValue())); + tagList.appendTag(mapping); + } + + return tagList; + } + + /** + * See {@link NBTExtras#mapToNBT(Map, Function, Function, String, String)}; this version is for when the + * names of the individual key/value tags are unimportant (they default to "key" and "value" respectively). + */ + public static NBTTagList mapToNBT(Map map, + Function keyFunction, Function valueFunction){ + return mapToNBT(map, keyFunction, valueFunction, "key", "value"); + } + + /** + * Generic method that reads a Map from an NBTTagList, given two functions that convert the key and value tag types + * into the key and value types in the returned map. The given NBTTagList remains unchanged after calling this + * method. + * + * @param The type of key stored in the returned Map. + * @param The type of value stored in the returned Map. + * @param The subtype of NBTBase that the keys are stored as. + * @param The subtype of NBTBase that the values are stored as. + * @param tagList The NBTTagList to be converted. This must be a list of compound tags. + * @param keyFunction A Function that converts the generic NBTBase tags in the list to keys of type K for the map. + * @param valueFunction A Function that converts the generic NBTBase tags in the list to values of type V for the + * map. + * @param keyTagName The tag name used for the key tags. + * @param valueTagName The tag name used for the value tags. + * @return A Map containing the keys and values stored in the given NBTTagList. Can be empty, but not null. + * @throws ClassCastException If the tags are not of the expected type. + * @see NBTExtras#mapToNBT(Map, Function, Function, String, String) + */ + @SuppressWarnings("unchecked") // Intentional, because throwing an exception is appropriate here. + public static Map NBTToMap(NBTTagList tagList, + Function keyFunction, Function valueFunction, String keyTagName, String valueTagName){ + + Map map = new HashMap<>(); + + for(int i = 0; i < tagList.tagCount(); i++){ + NBTTagCompound mapping = tagList.getCompoundTagAt(i); + NBTBase keyTag = mapping.getTag(keyTagName); + NBTBase valueTag = mapping.getTag(valueTagName); + K key = null; + try{ + key = keyFunction.apply((L)keyTag); + }catch (ClassCastException e){ + Wizardry.logger.error( + "Error when reading map from NBT: unexpected tag type " + NBTBase.NBT_TYPES[keyTag.getId()], e); + } + V value = null; + try{ + value = valueFunction.apply((W)valueTag); + }catch (ClassCastException e){ + Wizardry.logger.error( + "Error when reading map from NBT: unexpected tag type " + NBTBase.NBT_TYPES[valueTag.getId()], + e); + } + map.put(key, value); + } + + return map; + } + + /** + * See {@link NBTExtras#NBTToMap(NBTTagList, Function, Function, String, String)}; this version is for when + * the names of the individual key/value tags are unimportant (they default to "key" and "value" respectively). + */ + public static Map NBTToMap(NBTTagList tagList, + Function keyFunction, Function valueFunction){ + return NBTToMap(tagList, keyFunction, valueFunction, "key", "value"); + } + + /** + * Stores the given {@link Collection} to an {@link NBTTagList} and returns it, converting the elements in the + * collection to NBT tags (subclasses of {@link NBTBase}) according to the supplied mapper function. + * + * @param The type of element stored in the given collection. + * @param The NBT tag type that the elements will be converted to. + * @param list The collection to be stored. + * @param mapper A function that converts the elements in the collection to NBT objects that can be stored. + * @return An {@code NBTTagList} that represents the given collection. + */ + public static NBTTagList listToNBT(Collection list, Function mapper){ + + NBTTagList tagList = new NBTTagList(); + // If the collection is ordered, it will preserve the order, even though we don't know what type it is yet. + for(E element : list){ + tagList.appendTag(mapper.apply(element)); + } + + return tagList; + } + + /** + * Reads a {@link Collection} from the given {@link NBTTagList}, given a function that converts the element tag + * types to the element types in the returned collection. The given {@code NBTTagList} remains unchanged after + * calling this method. Unless the target variable for this method is of type {@code Collection}, you will need to + * create a new collection containing the elements in the returned collection via that collection's constructor (e.g. + * {@code new HashSet(collection)}). + *

    + * Although this method returns a Collection rather than any of its subtypes, it uses + * an ArrayList internally to guarantee the order of the elements in the returned collection is the same as the + * order in which they were stored. + * + * @param The type of element stored in the returned Collection. + * @param The subtype of NBTBase that the elements are stored as. + * @param tagList The NBTTagList to be converted. + * @param function A Function that converts the generic NBTBase tags in the list to elements for the collection. + * Chances are you will need to cast the NBTBase tag to whichever NBT tag type you are expecting in order to + * access the appropriate getter method. + * @return A Collection containing the elements stored in the given NBTTagList. Can be empty, but not null. + * @throws ClassCastException If the tags are not of the expected type. + */ + @SuppressWarnings("unchecked") // Intentional, because throwing an exception is appropriate here. + public static Collection NBTToList(NBTTagList tagList, Function function){ + // Uses an ArrayList to guarantee iteration order, and also to permit duplicate elements (which are + // perfectly reasonable in this context). + Collection list = new ArrayList<>(); + // The original tag list should remain unchanged, hence the copy. + NBTTagList tagList2 = tagList.copy(); + + while(!tagList2.isEmpty()){ + NBTBase tag = tagList2.removeTag(0); + // Why oh why is NBTTagList not parametrised? It even has a tagType field, so it must know! + try{ + list.add(function.apply((T)tag)); + }catch (ClassCastException e){ + Wizardry.logger.error( + "Error when reading list from NBT: unexpected tag type " + NBTBase.NBT_TYPES[tag.getId()], e); + } + } + + return list; + + } + + /** + * Removes the UUID with the given key from the given NBT tag, if any. Why this doesn't exist in vanilla I have + * no idea. + *

    + * Usage note: this method complements {@link NBTTagCompound#setUniqueId(String, UUID)} and + * {@link NBTTagCompound#getUniqueId(String)}, which store UUIDs by appending "Most" and "Least" to the given + * key to store the most and least significant UUID bits respectively. It will not work for the UUID methods in + * {@link net.minecraft.nbt.NBTUtil}, which store the long values under "M" and "L" in their own compound tag. + */ + public static void removeUniqueId(NBTTagCompound tag, String key){ + tag.removeTag(key + "Most"); + tag.removeTag(key + "Least"); + } + + /** + * Returns an NBTTagCompound which contains only the given UUID, stored using + * {@link NBTTagCompound#setUniqueId(String, UUID)}. Allows for neater storage to NBTTagLists. + * @deprecated Use {@link net.minecraft.nbt.NBTUtil#createUUIDTag(UUID)}. Note that this will break backwards + * compatibility because it uses "M" and "L" instead of "uuidMost" and "uuidLeast". + */ + @Deprecated + public static NBTTagCompound UUIDtoTagCompound(UUID id){ + NBTTagCompound tag = new NBTTagCompound(); + tag.setUniqueId("uuid", id); + return tag; + } + + /** + * Wrapper for {@link NBTTagCompound#getUniqueId(String)} which converts an NBTTagCompound directly to a UUID. + * Intended to be used as the inverse of {@link NBTExtras#UUIDtoTagCompound(UUID)}. + * @deprecated Use {@link net.minecraft.nbt.NBTUtil#getUUIDFromTag(NBTTagCompound)}. Note that this will break + * backwards compatibility because it uses "M" and "L" instead of "uuidMost" and "uuidLeast". + */ + @Deprecated + public static UUID tagCompoundToUUID(NBTTagCompound tag){ + return tag.getUniqueId("uuid"); + } +} diff --git a/src/main/java/electroblob/wizardry/util/ParticleBuilder.java b/src/main/java/electroblob/wizardry/util/ParticleBuilder.java index eb78c50b..273875b2 100644 --- a/src/main/java/electroblob/wizardry/util/ParticleBuilder.java +++ b/src/main/java/electroblob/wizardry/util/ParticleBuilder.java @@ -1,45 +1,51 @@ package electroblob.wizardry.util; -import java.util.Random; - import electroblob.wizardry.Wizardry; import net.minecraft.entity.Entity; +import net.minecraft.entity.EntityLivingBase; import net.minecraft.util.EnumFacing; import net.minecraft.util.EnumParticleTypes; +import net.minecraft.util.ResourceLocation; import net.minecraft.util.math.MathHelper; import net.minecraft.util.math.Vec3d; import net.minecraft.world.World; +import java.util.Random; + /** * "Don't waste time spawning particles manually - let {@code ParticleBuilder} do the work for you!" - *

    - * Singleton class that builds wizardry particles. This is an alternative (and neater, I think) solution to using varargs. - * All building methods are chainable, so particles can be created using only one line of code, similar to the - * {@code BufferBuilder} system. The number of different combinations of parameters now required for the various particle - * types in wizardry made the method overloads in the proxies very cumbersome and inevitably resulted in redundant - * parameters, which made the code messy and hard to read. Those methods have now been removed. - *

    + *

    + * Singleton class that builds wizardry particles. This is an alternative (and neater, I think) solution to vanilla's + * varargs-based system. All building methods are chainable, so particles can be created using only one line of code, + * similar to how {@code BufferBuilder} is used for drawing vertices. This class replaces the particle spawning methods + * in wizardry's proxies. + *

    * {@link ParticleBuilder#instance} retrieves the static instance of the particle builder. Use - * {@link ParticleBuilder#particle(Type)} to start building a particle, or alternatively use the static - * convenience version {@link ParticleBuilder#create(Type)}. Use {@link ParticleBuilder#spawn(World)} + * {@link ParticleBuilder#particle(ResourceLocation)} to start building a particle, or alternatively use the static + * convenience version {@link ParticleBuilder#create(ResourceLocation)}. Use {@link ParticleBuilder#spawn(World)} * to finish building and spawn the particle. Between these two, a variety of parameters can be set using the various * setter methods (see individual method descriptions for more details). These, along with {@code ParticleBuilder.particle(...)}, * return the particle builder instance, allowing them to be chained together to spawn particles using a single line of code. * If any parameters are unspecified these will default to certain values, which may or may not depend on the particle type. * Not all parameters affect all particles. Again, see individual method descriptions for more details. - *

    + *

    * For example, a typical call to the particle builder might look something like this: - *

    + *

    * ParticleBuilder.create(Type.SPARKLE).pos(x, y, z).vel(vx, vy, vz).clr(r, g, b).spawn(world); - *

    + *

    * It also goes without saying that this class should only ever be used client-side. Attempting to spawn particles * on the server side will not work and will print a warning to the console. * @author Electroblob * @since Wizardry 4.2 */ -/* This isn't strictly a builder class in the traditional sense, because rather than returning the built object at the - * end, it sends it to be processed instead and returns nothing. It's also lazy, see the comment about builder variables - * below. */ +// The number of different combinations of parameters now required for the various particle +// types in wizardry made the method overloads in the proxies very cumbersome and inevitably resulted in redundant +// parameters, which made the code messy and hard to read. Those methods have now been removed. + +// Strictly speaking, this isn't a builder class in the traditional sense, because rather than returning the built +// object at the end, it sends it to be processed instead and returns nothing. Additionally, unlike most builders +// it's a singleton, because it's likely to be called very frequently and there's no point making a new instance +// every time and clogging the heap with objects. It's also lazy, see the comment about builder variables below. public final class ParticleBuilder { /** The static instance of the particle builder. */ @@ -51,7 +57,7 @@ public final class ParticleBuilder { // Builder variables // We can't just store a particle and set its parameters in the builder methods, because the server won't like having // a field of a client-only type - private Type type; + private ResourceLocation type; private double x, y, z; private double vx, vy, vz; private float r, g, b; @@ -66,36 +72,66 @@ public final class ParticleBuilder { private Entity entity; private float yaw, pitch; private double tx, ty, tz; + private double tvx, tvy, tvz; private Entity target; + private long seed; + private double length; - /** Enum constants representing the different types of particle added by wizardry. As of 4.2.0, this has been moved - * from its own file {@code WizardryParticleType} to inside {@link ParticleBuilder}. This allowed its name to be - * shortened to simply {@code Type}, making most references more concise. References in classes where another - * {@code Type} is also used can simply refer to the full name, {@code ParticleBuilder.Type}, which is no more verbose - * than before. - *

    + /** + * {@link ResourceLocation} constants representing the different types of particle added by wizardry. These + * effectively replace the enum {@code WizardryParticleType} from previous versions. + *

    * Individual constants have comments detailing their corresponding default parameters. A range of values indicates - * randomness. */ - public enum Type { - /** 3D-rendered light-beam particle.

    Defaults:

    Lifetime: 1 tick
    Colour: white */ BEAM, - /** Helical animated 'buffing' particle.

    Defaults:

    Lifetime: 15 ticks - *
    Velocity: (0, 0.27, 0)
    Colour: white */ BUFF, - /** Spiral particle, like potions.

    Defaults:

    Lifetime: 8-40 ticks
    Colour: white */ DARK_MAGIC, - /** Single pixel particle.

    Defaults:

    Lifetime: 16-80 ticks
    Colour: white */ DUST, - /** Rapid flash, like fireworks.

    Defaults:

    Lifetime: 6 ticks
    Colour: white */ FLASH, - /** Small shard of ice.

    Defaults:

    Lifetime: 8-40 ticks
    Gravity: true */ ICE, - /** Single leaf.

    Defaults:

    Lifetime: 10-15 ticks
    Velocity: (0, -0.03, 0) - *
    Colour: green/brown */ LEAF, - /** 3D-rendered lightning particle.

    Defaults:

    Lifetime: 3 ticks
    Colour: blue */ LIGHTNING, - /** 2D lightning effect, normally on the ground.

    Defaults:

    Lifetime: 7 ticks - *
    Facing: up */ LIGHTNING_PULSE, - /** Bubble that doesn't burst in air.

    Defaults:

    Lifetime: 8-40 ticks */ MAGIC_BUBBLE, - /** Scaleable, moving flame.

    Defaults:

    Lifetime: 8-40 ticks
    */ MAGIC_FIRE, - /** Soft-edged round particle.

    Defaults:

    Lifetime: 8-40 ticks
    Colour: white */ PATH, - /** Scorch mark.

    Defaults:

    Lifetime: 100-140 ticks
    Colour: black
    Fade: black */ SCORCH, - /** Snowflake particle.

    Defaults:

    Lifetime: 40-50 ticks
    Velocity: (0, -0.02, 0) */ SNOW, - /** Animated lightning particle.

    Defaults:

    Lifetime: 3 ticks */ SPARK, - /** Animated sparkle particle.

    Defaults:

    Lifetime: 48-60 ticks
    Colour: white */ SPARKLE + * randomness. + *

    + * To register your own particle types, use {@link electroblob.wizardry.client.particle.ParticleWizardry#registerParticle( + * ResourceLocation, electroblob.wizardry.client.particle.ParticleWizardry.IWizardryParticleFactory) + * ParticleWizardry.registerParticle(ResourceLocation, IWizardryParticleFactory)}. + */ + // This was originally an enum, but I think having 'Type' explicitly declared is quite nice so I've left it as a + // nested class. + public static class Type { + /** 3D-rendered light-beam particle.

    Defaults:
    Lifetime: 1 tick
    Colour: white */ + public static final ResourceLocation BEAM = new ResourceLocation(Wizardry.MODID,"beam"); + /** Helical animated 'buffing' particle.

    Defaults:
    Lifetime: 15 ticks + *
    Velocity: (0, 0.27, 0)
    Colour: white */ + public static final ResourceLocation BUFF = new ResourceLocation(Wizardry.MODID,"buff"); + /** Spiral particle, like potions.

    Defaults:
    Lifetime: 8-40 ticks
    Colour: white */ + public static final ResourceLocation DARK_MAGIC = new ResourceLocation(Wizardry.MODID,"dark_magic"); + /** Single pixel particle.

    Defaults:
    Lifetime: 16-80 ticks
    Colour: white */ + public static final ResourceLocation DUST = new ResourceLocation(Wizardry.MODID,"dust"); + /** Rapid flash, like fireworks.

    Defaults:
    Lifetime: 6 ticks
    Colour: white */ + public static final ResourceLocation FLASH = new ResourceLocation(Wizardry.MODID,"flash"); + /** Small shard of ice.

    Defaults:
    Lifetime: 8-40 ticks
    Gravity: true */ + public static final ResourceLocation ICE = new ResourceLocation(Wizardry.MODID,"ice"); + /** Single leaf.

    Defaults:
    Lifetime: 10-15 ticks
    Velocity: (0, -0.03, 0) + *
    Colour: green/brown */ + public static final ResourceLocation LEAF = new ResourceLocation(Wizardry.MODID,"leaf"); + /** 3D-rendered lightning particle.

    Defaults:
    Lifetime: 3 ticks
    Colour: blue */ + public static final ResourceLocation LIGHTNING = new ResourceLocation(Wizardry.MODID,"lightning"); + /** 2D lightning effect, normally on the ground.

    Defaults:
    Lifetime: 7 ticks + *
    Facing: up */ + public static final ResourceLocation LIGHTNING_PULSE = new ResourceLocation(Wizardry.MODID,"lightning_pulse"); + /** Bubble that doesn't burst in air.

    Defaults:
    Lifetime: 8-40 ticks */ + public static final ResourceLocation MAGIC_BUBBLE = new ResourceLocation(Wizardry.MODID,"magic_bubble"); + /** Animated flame.

    Defaults:
    Lifetime: 12-16 ticks
    */ + public static final ResourceLocation MAGIC_FIRE = new ResourceLocation(Wizardry.MODID,"magic_fire"); + /** Soft-edged round particle.

    Defaults:
    Lifetime: 8-40 ticks
    Colour: white */ + public static final ResourceLocation PATH = new ResourceLocation(Wizardry.MODID,"path"); + /** Scorch mark.

    Defaults:
    Lifetime: 100-140 ticks
    Colour: black
    Fade: black */ + public static final ResourceLocation SCORCH = new ResourceLocation(Wizardry.MODID,"scorch"); + /** Snowflake particle.

    Defaults:
    Lifetime: 40-50 ticks
    Velocity: (0, -0.02, 0) */ + public static final ResourceLocation SNOW = new ResourceLocation(Wizardry.MODID,"snow"); + /** Animated lightning particle.

    Defaults:
    Lifetime: 3 ticks */ + public static final ResourceLocation SPARK = new ResourceLocation(Wizardry.MODID,"spark"); + /** Animated sparkle particle.

    Defaults:<
    Lifetime: 48-60 ticks
    Colour: white */ + public static final ResourceLocation SPARKLE = new ResourceLocation(Wizardry.MODID,"sparkle"); + /** 3D-rendered expanding sphere.

    Defaults:<
    Lifetime: 6 ticks
    Colour: white */ + public static final ResourceLocation SPHERE = new ResourceLocation(Wizardry.MODID,"sphere"); + /** Wrapped animated 'summoning' particle.

    Defaults:<
    Lifetime: 15 ticks */ + public static final ResourceLocation SUMMON = new ResourceLocation(Wizardry.MODID,"summon"); + /** 3D-rendered vine particle.

    Defaults:
    Lifetime: 1 tick
    Colour: green */ + public static final ResourceLocation VINE = new ResourceLocation(Wizardry.MODID,"vine"); } private ParticleBuilder(){ @@ -106,12 +142,12 @@ public final class ParticleBuilder { /** * Starts building a particle of the given type. Static convenience version of - * {@link ParticleBuilder#particle(Type)}; makes code more concise. + * {@link ParticleBuilder#particle(ResourceLocation)}; makes code more concise. * @param type The type of particle to build * @return The particle builder instance, allowing other methods to be chained onto this one * @throws IllegalStateException if the particle builder is already building. */ - public static ParticleBuilder create(Type type){ + public static ParticleBuilder create(ResourceLocation type){ return ParticleBuilder.instance.particle(type); } @@ -121,8 +157,8 @@ public final class ParticleBuilder { * @return The particle builder instance, allowing other methods to be chained onto this one * @throws IllegalStateException if the particle builder is already building. */ - public ParticleBuilder particle(Type type){ - if(building) throw new IllegalStateException("Already Building! Particle being built: " + getCurrentParticleString()); + public ParticleBuilder particle(ResourceLocation type){ + if(building) throw new IllegalStateException("Already building! Particle being built: " + getCurrentParticleString()); this.type = type; this.building = true; return this; @@ -131,7 +167,7 @@ public final class ParticleBuilder { /** Gets a readable string representation of the current builder parameters; used in error messages. */ private String getCurrentParticleString(){ return String.format("[ Type: %s, Position: (%s, %s, %s), Velocity: (%s, %s, %s), Colour: (%s, %s, %s), " - + "Fade Colour: (%s, %s, %s), Radius: %s, Revs/tick: %s, Lifetime: %s, Gravity: %s, Shaded: %s," + + "Fade Colour: (%s, %s, %s), Radius: %s, Revs/tick: %s, Lifetime: %s, Gravity: %s, Shaded: %s, " + "Scale: %s, Entity: %s ]", type, x, y, z, vx, vy, vz, r, g, b, fr, fg, fb, radius, rpt, lifetime, gravity, shaded, scale, entity); } @@ -139,7 +175,7 @@ public final class ParticleBuilder { /** * Sets the position of the particle being built. If unspecified, this defaults to the origin (0, 0, 0). If an entity * is specified using {@link ParticleBuilder#entity(Entity)}, this will be relative to that entity's position. - *

    + *

    * Affects: All particle types * @param x The x coordinate to set * @param y The y coordinate to set @@ -158,7 +194,7 @@ public final class ParticleBuilder { /** * Sets the position of the particle being built. This is a vector-based alternative to {@link ParticleBuilder#pos( * double, double, double)}, allowing for even more concise code when a vector is available. - *

    + *

    * Affects: All particle types * @param pos A vector representing the coordinates of the particle to be built. * @return The particle builder instance, allowing other methods to be chained onto this one @@ -171,8 +207,8 @@ public final class ParticleBuilder { /** * Sets the velocity of the particle being built. If unspecified, this defaults to the particle's default velocity, * specified within its constructor. - *

    - * Affects: All particle types except {@link Type#DUST DUST} + *

    + * Affects: All particle types * @param vx The x velocity to set * @param vy The y velocity to set * @param vz The z velocity to set @@ -190,8 +226,8 @@ public final class ParticleBuilder { /** * Sets the velocity of the particle being built. This is a vector-based alternative to {@link ParticleBuilder#vel( * double, double, double)}, allowing for even more concise code when a vector is available. - *

    - * Affects: All particle types + *

    + * Affects: All particle types except * @param vel A vector representing the velocity of the particle to be built. * @return The particle builder instance, allowing other methods to be chained onto this one * @throws IllegalStateException if the particle builder is not yet building. @@ -202,10 +238,11 @@ public final class ParticleBuilder { /** * Sets the colour of the particle being built. If unspecified, this defaults to the particle's default colour, - * specified within its constructor. - *

    - * Affects: {@link Type#DARK_MAGIC DARK_MAGIC}, {@link Type#DUST DUST}, {@link Type#FLASH FLASH}, - * {@link Type#LEAF LEAF}, {@link Type#PATH PATH}, {@link Type#SPARKLE SPARKLE} + * specified within its constructor. If all colour components are 0 or 1, at least one must have the float suffix + * ({@code f} or {@code F}) or the integer overload will be used instead, causing the particle to appear black! + *

    + * Affects: All particle types except {@link Type#ICE ICE}, {@link Type#MAGIC_BUBBLE MAGIC_BUBBLE} + * and {@link Type#MAGIC_FIRE MAGIC_FIRE} * @param r The red colour component to set; will be clamped to between 0 and 1 * @param g The green colour component to set; will be clamped to between 0 and 1 * @param b The blue colour component to set; will be clamped to between 0 and 1 @@ -219,13 +256,47 @@ public final class ParticleBuilder { this.b = MathHelper.clamp(b, 0, 1); return this; } + + /** + * Sets the colour of the particle being built. This is an 8-bit (0-255) integer version of + * {@link ParticleBuilder#clr(float, float, float)}. + *

    + * Affects: All particle types except {@link Type#ICE ICE}, {@link Type#MAGIC_BUBBLE MAGIC_BUBBLE} + * and {@link Type#MAGIC_FIRE MAGIC_FIRE} + * @param r The red colour component to set; will be clamped to between 0 and 255 + * @param g The green colour component to set; will be clamped to between 0 and 255 + * @param b The blue colour component to set; will be clamped to between 0 and 255 + * @return The particle builder instance, allowing other methods to be chained onto this one + * @throws IllegalStateException if the particle builder is not yet building. + */ + public ParticleBuilder clr(int r, int g, int b){ + return this.clr(r/255f, g/255f, b/255f); // Yes, 255 is correct and not 256, or else we can't have pure white + } + + /** + * Sets the colour of the particle being built. This is a 6-digit hex colour version of + * {@link ParticleBuilder#clr(float, float, float)}. + *

    + * Affects: All particle types except {@link Type#ICE ICE}, {@link Type#MAGIC_BUBBLE MAGIC_BUBBLE} + * and {@link Type#MAGIC_FIRE MAGIC_FIRE} + * @param hex The colour to be set, as a packed 6-digit hex integer (e.g. 0xff0000). + * @return The particle builder instance, allowing other methods to be chained onto this one + * @throws IllegalStateException if the particle builder is not yet building. + */ + public ParticleBuilder clr(int hex){ + int r = (hex & 0xFF0000) >> 16; + int g = (hex & 0xFF00) >> 8; + int b = (hex & 0xFF); + return this.clr(r, g, b); + } /** * Sets the fade colour of the particle being built. If unspecified, this defaults to the whatever the particle's base - * colour is. - *

    - * Affects: {@link Type#DARK_MAGIC DARK_MAGIC}, {@link Type#DUST DUST}, {@link Type#FLASH FLASH}, - * {@link Type#LEAF LEAF}, {@link Type#PATH PATH}, {@link Type#SPARKLE SPARKLE} + * colour is. If all colour components are 0 or 1, at least one must have the float suffix + * ({@code f} or {@code F}) or the integer overload will be used instead, causing the particle to appear black! + *

    + * Affects: All particle types except {@link Type#ICE ICE}, {@link Type#MAGIC_BUBBLE MAGIC_BUBBLE} + * and {@link Type#MAGIC_FIRE MAGIC_FIRE} * @param r The red colour component to set; will be clamped to between 0 and 1 * @param g The green colour component to set; will be clamped to between 0 and 1 * @param b The blue colour component to set; will be clamped to between 0 and 1 @@ -239,10 +310,43 @@ public final class ParticleBuilder { this.fb = MathHelper.clamp(b, 0, 1); return this; } + + /** + * Sets the fade colour of the particle being built. This is an 8-bit (0-255) integer version of + * {@link ParticleBuilder#fade(float, float, float)}. + *

    + * Affects: All particle types except {@link Type#ICE ICE}, {@link Type#MAGIC_BUBBLE MAGIC_BUBBLE} + * and {@link Type#MAGIC_FIRE MAGIC_FIRE} + * @param r The red colour component to set; will be clamped to between 0 and 255 + * @param g The green colour component to set; will be clamped to between 0 and 255 + * @param b The blue colour component to set; will be clamped to between 0 and 255 + * @return The particle builder instance, allowing other methods to be chained onto this one + * @throws IllegalStateException if the particle builder is not yet building. + */ + public ParticleBuilder fade(int r, int g, int b){ + return this.clr(r/255f, g/255f, b/255f); // Yes, 255 is correct and not 256, or else we can't have pure white + } + + /** + * Sets the fade colour of the particle being built. This is a 6-digit hex colour version of + * {@link ParticleBuilder#fade(float, float, float)}. + *

    + * Affects: All particle types except {@link Type#ICE ICE}, {@link Type#MAGIC_BUBBLE MAGIC_BUBBLE} + * and {@link Type#MAGIC_FIRE MAGIC_FIRE} + * @param hex The colour to be set, as a packed 6-digit hex integer (e.g. 0xff0000). + * @return The particle builder instance, allowing other methods to be chained onto this one + * @throws IllegalStateException if the particle builder is not yet building. + */ + public ParticleBuilder fade(int hex){ + int r = (hex & 0xFF0000) >> 16; + int g = (hex & 0xFF00) >> 8; + int b = (hex & 0xFF); + return this.clr(r, g, b); + } /** * Sets the scale of the particle being built. If unspecified, this defaults to 1. - *

    + *

    * Affects: All particle types * @param scale The scale to set, as a multiple of the particle's default scale * @return The particle builder instance, allowing other methods to be chained onto this one @@ -257,7 +361,7 @@ public final class ParticleBuilder { /** * Sets the lifetime of the particle being built. If unspecified, this defaults to the particle's default lifetime, * specified within its constructor. - *

    + *

    * Affects: All particle types * @param lifetime The lifetime to set in ticks * @return The particle builder instance, allowing other methods to be chained onto this one @@ -268,10 +372,28 @@ public final class ParticleBuilder { this.lifetime = lifetime; return this; } + + /** + * Sets the seed of the particle being built. If unspecified, this defaults to the particle's default seed, + * specified within its constructor (this is normally chosen at random). + *

    + * Pro tip: to get a particle to stay the same while a continuous spell is in use (but change between casts), + * use {@code .seed(world.getTotalWorldTime() - ticksInUse)}. + *

    + * Affects: All particle types + * @param seed The seed to set + * @return The particle builder instance, allowing other methods to be chained onto this one + * @throws IllegalStateException if the particle builder is not yet building. + */ + public ParticleBuilder seed(long seed){ + if(!building) throw new IllegalStateException("Not building yet!"); + this.seed = seed; + return this; + } /** * Sets the spin parameters of the particle being built. If unspecified, these both default to 0. - *

    + *

    * Affects: All particle types * @param radius The rotation radius to set * @param speed The rotation speed to set, in revolutions per tick @@ -284,11 +406,12 @@ public final class ParticleBuilder { this.rpt = speed; return this; } - + + // Used to say Affects: {@link Type#ICE ICE}, {@link Type#SPARKLE SPARKLE} - not sure that's true any more /** * Sets the gravity of the particle being built. If unspecified, this defaults to false. - *

    - * Affects: {@link Type#ICE ICE}, {@link Type#SPARKLE SPARKLE} + *

    + * Affects: All particle types * @param gravity True to enable gravity for the particle, false to disable * @return The particle builder instance, allowing other methods to be chained onto this one * @throws IllegalStateException if the particle builder is not yet building. @@ -301,7 +424,7 @@ public final class ParticleBuilder { /** * Sets the shading of the particle being built. If unspecified, this defaults to false. - *

    + *

    * Affects: All particle types * @param shaded True to enable shading for the particle, false for full brightness * @return The particle builder instance, allowing other methods to be chained onto this one @@ -315,7 +438,7 @@ public final class ParticleBuilder { /** * Sets the collisions of the particle being built. If unspecified, this defaults to false. - *

    + *

    * Affects: All particle types * @param collide True to enable block collisions for the particle, false to disable * @return The particle builder instance, allowing other methods to be chained onto this one @@ -331,7 +454,7 @@ public final class ParticleBuilder { * Sets the entity of the particle being built. This will cause the particle to move with the given entity, and will * make the position specified using {@link ParticleBuilder#pos(double, double, double)} relative to that * entity's position. - *

    + *

    * Affects: All particle types * @param entity The entity to set (passing in null will do nothing but will not cause any problems, so for the sake * of conciseness it is not necessary to perform a null check on the passed-in argument) @@ -347,7 +470,7 @@ public final class ParticleBuilder { /** * Sets the rotation of the particle being built. If unspecified, the particle will use the default behaviour and * rotate to face the viewer. - *

    + *

    * Affects: All particle types * @param yaw The yaw angle to set in degrees, where 0 is south. * @param pitch The pitch angle to set in degrees, where 0 is horizontal. @@ -365,7 +488,8 @@ public final class ParticleBuilder { * Sets the rotation of the particle being built. This is an {@code EnumFacing}-based alternative to {@link * ParticleBuilder#face(float, float)} which sets the yaw and pitch to the appropriate angles for the given facing. * For example, if the given facing is {@code NORTH}, the particle will render parallel to the north face of blocks. - *

    + * If unspecified, the particle will use the default behaviour and rotate to face the viewer. + *

    * Affects: All particle types * @param direction The {@code EnumFacing} direction to set. * @return The particle builder instance, allowing other methods to be chained onto this one @@ -374,11 +498,13 @@ public final class ParticleBuilder { public ParticleBuilder face(EnumFacing direction){ return face(direction.getHorizontalAngle(), direction.getAxis().isVertical() ? direction.getAxisDirection().getOffset() * 90 : 0); } + + // ============================================= Targeted-only methods ============================================= /** * Sets the target of the particle being built. This will cause the particle to stretch to touch the given position. - *

    - * Affects: + *

    + * Affects: Targeted particles, namely {@link Type#BEAM BEAM}, {@link Type#LIGHTNING LIGHTNING} and {@link Type#VINE VINE} * @param x The target x-coordinate to set * @param y The target y-coordinate to set * @param z The target z-coordinate to set @@ -394,10 +520,11 @@ public final class ParticleBuilder { } /** - * Sets the target of the particle being built. This is a vector-based alternative to {@link ParticleBuilder# - * target(double, double, double)}, allowing for even more concise code when a vector is available. - *

    - * Affects: All particle types + * Sets the target of the particle being built. This is a vector-based alternative to + * {@link ParticleBuilder#target(double, double, double)}, allowing for even more concise code when a vector is + * available. + *

    + * Affects: Targeted particles, namely {@link Type#BEAM BEAM}, {@link Type#LIGHTNING LIGHTNING} and {@link Type#VINE VINE} * @param pos A vector representing the target position of the particle to be built. * @return The particle builder instance, allowing other methods to be chained onto this one * @throws IllegalStateException if the particle builder is not yet building. @@ -405,11 +532,59 @@ public final class ParticleBuilder { public ParticleBuilder target(Vec3d pos){ return target(pos.x, pos.y, pos.z); } + + /** + * Sets the target point velocity of the particle being built. This will cause the position it stretches to touch to move + * at the given velocity. Has no effect unless {@link ParticleBuilder#target(double, double, double)} or one of its + * overloads is also set.

    + * Affects: Targeted particles, namely {@link Type#BEAM BEAM}, {@link Type#LIGHTNING LIGHTNING} and {@link Type#VINE VINE} + * @param vx The target point x velocity to set + * @param vy The target point y velocity to set + * @param vz The target point z velocity to set + * @return The particle builder instance, allowing other methods to be chained onto this one + * @throws IllegalStateException if the particle builder is not yet building. + */ + public ParticleBuilder tvel(double vx, double vy, double vz){ + if(!building) throw new IllegalStateException("Not building yet!"); + this.tvx = vx; + this.tvy = vy; + this.tvz = vz; + return this; + } + + /** + * Sets the target point velocity of the particle being built. This is a vector-based alternative to + * {@link ParticleBuilder#tvel(double, double, double)}, allowing for even more concise code when a vector is + * available. + *

    + * Affects: Targeted particles, namely {@link Type#BEAM BEAM}, {@link Type#LIGHTNING LIGHTNING} and {@link Type#VINE VINE} + * @param vel A vector representing the target point velocity of the particle to be built. + * @return The particle builder instance, allowing other methods to be chained onto this one + * @throws IllegalStateException if the particle builder is not yet building. + */ + public ParticleBuilder tvel(Vec3d vel){ + return tvel(vel.x, vel.y, vel.z); + } + + /** + * Sets the target and target velocity of the particle being built. This method takes an origin entity and a + * position and estimates the position of the target point based on the given entity's rotational velocities and its + * distance from the given position. + *

    + * Affects: Targeted particles, namely {@link Type#BEAM BEAM}, {@link Type#LIGHTNING LIGHTNING} and {@link Type#VINE VINE} + * @param length The length of the particle being built. + * @return The particle builder instance, allowing other methods to be chained onto this one + * @throws IllegalStateException if the particle builder is not yet building. + */ + public ParticleBuilder length(double length){ + this.length = length; + return this; + } /** * Sets the target of the particle being built. This will cause the particle to stretch to touch the given entity. - *

    - * Affects: + *

    + * Affects: Targeted particles, namely {@link Type#BEAM BEAM}, {@link Type#LIGHTNING LIGHTNING} and {@link Type#VINE VINE} * @param target The entity to set * @return The particle builder instance, allowing other methods to be chained onto this one * @throws IllegalStateException if the particle builder is not yet building. @@ -429,7 +604,7 @@ public final class ParticleBuilder { if(!building) throw new IllegalStateException("Not building yet!"); - if(y < 0 && entity == null) Wizardry.logger.warn("Spawning particle below y = 0 - are you sure the position/entity" + if(y < 0 && entity == null) Wizardry.logger.warn("Spawning particle below y = 0 - are you sure the position/entity " + "has been set correctly?"); if(!world.isRemote){ @@ -443,22 +618,27 @@ public final class ParticleBuilder { electroblob.wizardry.client.particle.ParticleWizardry particle = Wizardry.proxy.createParticle(type, world, x, y, z); if(particle == null){ + // No need to display a warning here, we already did it in the client proxy reset(); return; } // Anything with an if statement here allows default values to be set in particle constructors + if(!Double.isNaN(vx) && !Double.isNaN(vy) && !Double.isNaN(vz)) particle.setVelocity(vx, vy, vz); + if(r >= 0 && g >= 0 && b >= 0) particle.setRBGColorF(r, g, b); + if(fr >= 0 && fg >= 0 && fb >= 0) particle.setFadeColour(fr, fg, fb); + if(lifetime >= 0) particle.setMaxAge(lifetime); + if(radius > 0) particle.setSpin(radius, rpt); + if(!Float.isNaN(yaw) && !Float.isNaN(pitch)) particle.setFacing(yaw, pitch); + if(seed != 0) particle.setSeed(seed); + if(!Double.isNaN(tvx) && !Double.isNaN(tvy) && !Double.isNaN(tvz)) particle.setTargetVelocity(tvx, tvy, tvz); + if(length > 0) particle.setLength(length); + particle.multipleParticleScaleBy(scale); - if(!Double.isNaN(vx) && !Double.isNaN(vy) && !Double.isNaN(vz)) particle.setVelocity(vx, vy, vz); - if(r >= 0 && g >= 0 && b >= 0) particle.setRBGColorF(r, g, b); - if(fr >= 0 && fg >= 0 && fb >= 0)particle.setFadeColour(fr, fg, fb); - if(lifetime >= 0) particle.setMaxAge(lifetime); particle.setGravity(gravity); particle.setShaded(shaded); particle.setCollisions(collide); - if(radius > 0) particle.setSpin(radius, rpt); particle.setEntity(entity); - if(!Float.isNaN(yaw) && !Float.isNaN(pitch)) particle.setFacing(yaw, pitch); particle.setTargetPosition(tx, ty, tz); particle.setTargetEntity(target); @@ -498,7 +678,12 @@ public final class ParticleBuilder { tx = Double.NaN; ty = Double.NaN; tz = Double.NaN; + tvx = Double.NaN; + tvy = Double.NaN; + tvz = Double.NaN; target = null; + seed = 0; + length = -1; } // ============================================== Convenience methods ============================================== @@ -513,14 +698,14 @@ public final class ParticleBuilder { * Equivalent to calling {@code ParticleBuilder.create(type).pos(...)}; users should chain any additional builder * methods onto this one and finish with {@code .spawn(world)} as normal. * Used extensively with summoned creatures; makes code much neater and more concise. - *

    + *

    * N.B. this does not cause the particle to move with the given entity. * @param type The type of particle to build * @param entity The entity to position the particle at * @return The particle builder instance, allowing other methods to be chained onto this one * @throws IllegalStateException if the particle builder is already building. */ - public static ParticleBuilder create(Type type, Entity entity){ + public static ParticleBuilder create(ResourceLocation type, Entity entity){ double x = entity.posX + (entity.world.rand.nextDouble() - 0.5D) * (double)entity.width; double y = entity.posY + entity.world.rand.nextDouble() * (double)entity.height; @@ -545,7 +730,7 @@ public final class ParticleBuilder { * @return The particle builder instance, allowing other methods to be chained onto this one * @throws IllegalStateException if the particle builder is already building. */ - public static ParticleBuilder create(Type type, Random random, double x, double y, double z, double radius, boolean move){ + public static ParticleBuilder create(ResourceLocation type, Random random, double x, double y, double z, double radius, boolean move){ double px = x + (random.nextDouble()*2 - 1) * radius; double py = y + (random.nextDouble()*2 - 1) * radius; @@ -560,7 +745,9 @@ public final class ParticleBuilder { /** Spawns spark and large smoke particles (8 of each) within a 1x1x1 volume centred on the given position. */ public static void spawnShockParticles(World world, double x, double y, double z) { + double px, py, pz; + for(int i=0; i<8; i++){ px = x + world.rand.nextDouble() - 0.5; py = y + world.rand.nextDouble() - 0.5; @@ -572,5 +759,19 @@ public final class ParticleBuilder { world.spawnParticle(EnumParticleTypes.SMOKE_LARGE, px, py, pz, 0, 0, 0); } } + + /** Spawns golden-yellow sparkle particles around the given entity's head and a golden-yellow buff particle around + * its entire body. */ + public static void spawnHealParticles(World world, EntityLivingBase entity){ + + for(int i = 0; i < 10; i++){ + double x = entity.posX + world.rand.nextDouble() * 2 - 1; + double y = entity.getEntityBoundingBox().minY + entity.getEyeHeight() - 0.5 + world.rand.nextDouble(); + double z = entity.posZ + world.rand.nextDouble() * 2 - 1; + ParticleBuilder.create(Type.SPARKLE).pos(x, y, z).vel(0, 0.1, 0).clr(1, 1, 0.3f).spawn(world); + } + + ParticleBuilder.create(Type.BUFF).entity(entity).clr(1, 1, 0.3f).spawn(world); + } } diff --git a/src/main/java/electroblob/wizardry/util/RayTracer.java b/src/main/java/electroblob/wizardry/util/RayTracer.java new file mode 100644 index 00000000..6079251d --- /dev/null +++ b/src/main/java/electroblob/wizardry/util/RayTracer.java @@ -0,0 +1,207 @@ +package electroblob.wizardry.util; + +import electroblob.wizardry.entity.ICustomHitbox; +import net.minecraft.entity.Entity; +import net.minecraft.entity.EntityLivingBase; +import net.minecraft.util.math.AxisAlignedBB; +import net.minecraft.util.math.RayTraceResult; +import net.minecraft.util.math.Vec3d; +import net.minecraft.world.World; + +import javax.annotation.Nullable; +import java.util.List; +import java.util.function.Predicate; + +/** + * Contains a number of static methods that perform raytracing and related functions. This was split off from + * {@link WizardryUtilities} as of wizardry 4.2 in an effort to make the code easier to navigate. + * + * @author Electroblob + * @since Wizardry 4.2 + */ +public final class RayTracer { + + private RayTracer(){} // No instances! + + /** + * Helper method which performs a ray trace for blocks only from an entity's eye position in the direction + * they are looking, over a specified range, using {@link World#rayTraceBlocks(Vec3d, Vec3d, boolean, boolean, boolean)}. + * + * @param world The world in which to perform the ray trace. + * @param entity The entity from which to perform the ray trace. The ray trace will start from this entity's eye + * position and proceed in the direction the entity is looking. + * @param range The distance over which the ray trace will be performed. + * @param hitLiquids True to return hits on the surfaces of liquids, false to ignore liquid blocks as if they were + * not there. + * @return A {@link RayTraceResult} representing the object that was hit, which may be either a block or nothing. + * Returns {@code null} only if the origin and endpoint are within the same block. + */ + @Nullable + public static RayTraceResult standardBlockRayTrace(World world, EntityLivingBase entity, double range, boolean hitLiquids, + boolean ignoreUncollidables, boolean returnLastUncollidable){ + // This method does not apply an offset like ray spells do, since it is not desirable in most other use cases. + Vec3d origin = new Vec3d(entity.posX, entity.getEntityBoundingBox().minY + entity.getEyeHeight(), entity.posZ); + Vec3d endpoint = origin.add(entity.getLookVec().scale(range)); + return world.rayTraceBlocks(origin, endpoint, hitLiquids, ignoreUncollidables, returnLastUncollidable); + } + + /** + * Helper method which performs a ray trace for blocks only from an entity's eye position in the direction + * they are looking, over a specified range. This is a shorthand for + * {@link #standardBlockRayTrace(World, EntityLivingBase, double, boolean, boolean, boolean)}; ignoreUncollidables + * and returnLastUncollidable default to false. + */ + @Nullable + public static RayTraceResult standardBlockRayTrace(World world, EntityLivingBase entity, double range, boolean hitLiquids){ + return standardBlockRayTrace(world, entity, range, hitLiquids, false, false); + } + + /** + * Helper method which performs a ray trace for blocks and entities from an entity's eye position in the direction + * they are looking, over a specified range, using {@link RayTracer#rayTrace(World, Vec3d, Vec3d, float, boolean, boolean, boolean, Class, Predicate)}. Aim assist is zero, the entity type is simply {@code Entity} (all entities), and the + * filter removes the given entity and any dying entities and allows all others. + * + * @param world The world in which to perform the ray trace. + * @param entity The entity from which to perform the ray trace. The ray trace will start from this entity's eye + * position and proceed in the direction the entity is looking. This entity will be ignored when ray tracing. + * @param range The distance over which the ray trace will be performed. + * @param hitLiquids True to return hits on the surfaces of liquids, false to ignore liquid blocks as if they were + * not there. + * @return A {@link RayTraceResult} representing the object that was hit, which may be an entity, a block or + * nothing. Returns {@code null} only if the origin and endpoint are within the same block and no entity was hit. + */ + @Nullable + public static RayTraceResult standardEntityRayTrace(World world, Entity entity, double range, boolean hitLiquids){ + // This method does not apply an offset like ray spells do, since it is not desirable in most other use cases. + Vec3d origin = new Vec3d(entity.posX, entity.getEntityBoundingBox().minY + entity.getEyeHeight(), entity.posZ); + Vec3d endpoint = origin.add(entity.getLookVec().scale(range)); + return rayTrace(world, origin, endpoint, 0, hitLiquids, false, false, Entity.class, ignoreEntityFilter(entity)); + } + + /** + * Helper method for use with {@link RayTracer#rayTrace(World, Vec3d, Vec3d, float, boolean, boolean, boolean, Class, Predicate)} + * which returns a {@link Predicate} that returns true for the given entity, plus any entities that have zero health + * or less (i.e. are in the process of dying). This is a commonly used filter in spells. + * + * @param entity The entity that the returned predicate should return true for. + * @return A {@link Predicate} that returns true for the given entity and any entities that are in the process of + * dying, false for all other entities. + */ + public static Predicate ignoreEntityFilter(Entity entity){ + return e -> e == entity || (e instanceof EntityLivingBase && ((EntityLivingBase)e).getHealth() <= 0); + } + + /** + * Performs a ray trace for blocks and entities, starting at the given origin and finishing at the given endpoint. + * As of wizardry 4.2, the ray tracing methods have been rewritten to be more user-friendly and implement proper + * aim assist. + *

    + * N.B. It is possible to ignore entities entirely by passing in a {@code Predicate} that is always false; + * however, in this specific case it is more efficient to use + * {@link World#rayTraceBlocks(Vec3d, Vec3d, boolean, boolean, boolean)} or one of its overloads. + * + * @param world The world in which to perform the ray trace. + * @param origin A vector representing the coordinates of the start point of the ray trace. + * @param endpoint A vector representing the coordinates of the finish point of the ray trace. + * @param aimAssist In addition to direct hits, the ray trace will also hit entities that are up to this distance + * from its path. For a normal ray trace, this should be 0. Values greater than 0 will give an 'aim assist' effect. + * @param hitLiquids Whether liquids should be ignored when ray tracing blocks + * @param ignoreUncollidables Whether blocks with no collisions should be ignored + * @param returnLastUncollidable If blocks with no collisions are ignored, whether to return the last one (useful if, + * for example, you want to replace snow layers or tall grass) + * @param entityType The class of entities to include; all other entities will be ignored. + * @param filter A {@link Predicate} which filters out entities that can be ignored; often used to exclude the + * player that is performing the ray trace. + * + * @return A {@link RayTraceResult} representing the object that was hit, which may be an entity, a block or + * nothing. Returns {@code null} only if the origin and endpoint are within the same block and no entity was hit. + * + * @see RayTracer#standardEntityRayTrace(World, Entity, double, boolean) + * @see RayTracer#standardBlockRayTrace(World, EntityLivingBase, double, boolean) + */ + // Interestingly enough, aimAssist can be negative, which means hits have to be in the middle of entities! + @Nullable + public static RayTraceResult rayTrace(World world, Vec3d origin, Vec3d endpoint, float aimAssist, + boolean hitLiquids, boolean ignoreUncollidables, boolean returnLastUncollidable, Class entityType, Predicate filter){ + + // 1 is the standard amount of extra search volume, and aim assist needs to increase this further as well as + // expanding the entities' bounding boxes. + float borderSize = 1 + aimAssist; + + // The AxisAlignedBB constructor accepts min/max coords in either order. + AxisAlignedBB searchVolume = new AxisAlignedBB(origin.x, origin.y, origin.z, endpoint.x, endpoint.y, endpoint.z) + .grow(borderSize, borderSize, borderSize); + + // Gets all of the entities in the bounding box that could be collided with. + List entities = world.getEntitiesWithinAABB(entityType, searchVolume); + // Applies the given filter to remove entities that should be ignored. + entities.removeIf(filter); + + // Finds the first block hit by the ray trace, if any. + RayTraceResult result = world.rayTraceBlocks(origin, endpoint, hitLiquids, ignoreUncollidables, returnLastUncollidable); + + // Clips the entity search range to the part of the ray trace before the block hit, if it hit a block. + if(result != null){ + endpoint = result.hitVec; + } + + // Search variables + Entity closestHitEntity = null; + Vec3d closestHitPosition = endpoint; + AxisAlignedBB entityBounds; + Vec3d intercept = null; + + // Iterates through all the entities + for(Entity entity : entities){ + + // I'd like to add the following line so we can, for example, use greater telekinesis through a + // ring of fire, but doing so will stop forcefields blocking particles + //if(!entity.canBeCollidedWith()) continue; + + float fuzziness = WizardryUtilities.isLiving(entity) ? aimAssist : 0; // Only living entities have aim assist + + if(entity instanceof ICustomHitbox){ // Custom hitboxes + intercept = ((ICustomHitbox)entity).calculateIntercept(origin, endpoint, fuzziness); + + }else{ // Normal hit detection + + entityBounds = entity.getEntityBoundingBox(); + + if(entityBounds != null){ + + // This is zero for everything except fireballs... + float entityBorderSize = entity.getCollisionBorderSize(); + // ... meaning the following line does nothing in all other cases. + // -> Added the non-zero check to prevent unnecessary AABB object creation. + if(entityBorderSize != 0) + entityBounds = entityBounds.grow(entityBorderSize, entityBorderSize, entityBorderSize); + + // Aim assist expands the bounding box to hit entities within the specified distance of the ray trace. + if(fuzziness != 0) entityBounds = entityBounds.grow(fuzziness, fuzziness, fuzziness); + + // Finds the first point at which the ray trace intercepts the entity's bounding box, if any. + RayTraceResult hit = entityBounds.calculateIntercept(origin, endpoint); + if(hit != null) intercept = hit.hitVec; + } + } + + // If the ray trace hit the entity... + if(intercept != null){ + // Decides whether the entity that was hit is the closest so far, and if so, overwrites the old one. + float currentHitDistance = (float)intercept.distanceTo(origin); + float closestHitDistance = (float)closestHitPosition.distanceTo(origin); + if(currentHitDistance < closestHitDistance){ + closestHitEntity = entity; + closestHitPosition = intercept; + } + } + } + + // If the ray trace hit an entity, return that entity; otherwise return the result of the block ray trace. + if(closestHitEntity != null){ + result = new RayTraceResult(closestHitEntity, closestHitPosition); + } + + return result; + } +} diff --git a/src/main/java/electroblob/wizardry/util/RelativeFacing.java b/src/main/java/electroblob/wizardry/util/RelativeFacing.java new file mode 100644 index 00000000..f5988df9 --- /dev/null +++ b/src/main/java/electroblob/wizardry/util/RelativeFacing.java @@ -0,0 +1,42 @@ +package electroblob.wizardry.util; + +import net.minecraft.entity.Entity; +import net.minecraft.util.EnumFacing; + +/** + * Like {@link EnumFacing}, but relative! + */ +public enum RelativeFacing { + + DOWN("down", -1), + UP("up", -1), + FRONT("front", 0), + BACK("back", 2), + LEFT("left", 3), + RIGHT("right", 1); + + public final String name; + private final int horizontalIndex; + + private static final RelativeFacing[] HORIZONTALS = new RelativeFacing[4]; + + RelativeFacing(String name, int horizontalIndex){ + this.name = name; + this.horizontalIndex = horizontalIndex; + } + + static { + for(RelativeFacing facing : values()){ + if(facing.horizontalIndex > -1) HORIZONTALS[facing.horizontalIndex] = facing; + } + } + + public static RelativeFacing relativise(EnumFacing absolute, Entity relativeTo){ + if(absolute == EnumFacing.DOWN) return DOWN; + if(absolute == EnumFacing.UP) return UP; + EnumFacing look = relativeTo.getAdjustedHorizontalFacing(); + int relativeIndex = absolute.getHorizontalIndex() - look.getHorizontalIndex(); + if(relativeIndex < 0) relativeIndex += 4; + return HORIZONTALS[relativeIndex]; + } +} diff --git a/src/main/java/electroblob/wizardry/util/SpellModifiers.java b/src/main/java/electroblob/wizardry/util/SpellModifiers.java index a8ee1e91..93ea7e96 100644 --- a/src/main/java/electroblob/wizardry/util/SpellModifiers.java +++ b/src/main/java/electroblob/wizardry/util/SpellModifiers.java @@ -1,31 +1,28 @@ package electroblob.wizardry.util; -import java.util.Collections; -import java.util.HashMap; -import java.util.Map; -import java.util.Map.Entry; - import electroblob.wizardry.event.SpellCastEvent; import io.netty.buffer.ByteBuf; import net.minecraft.item.Item; import net.minecraft.nbt.NBTTagCompound; import net.minecraftforge.fml.common.network.ByteBufUtils; +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; +import java.util.Map.Entry; + /** * "{@code SpellModifiers} - modify all the things!" - *

    + *

    * Object that wraps any number of spell modifiers into one, allowing for expandability within the Spell#cast methods. - * This class is essentially a glorified {@link Map} which can be written to and read from a {@link ByteBuf}. It is - * possible to calculate spell modifiers from wand NBT within the cast methods, but this is cumbersome and does not - * allow the modifiers to be sent to the client, which is sometimes necessary (for example, detonate needs to know about - * range modifiers on the client side or the particles wouldn't show outside of the base range). - *

    + * This class is essentially a glorified {@link Map} which can be written to and read from a {@link ByteBuf}. + *

    * Most external interaction with SpellModifiers objects will be in {@link SpellCastEvent.Pre}, where you can add * additional modifiers to them if desired for use with your own spells, or modify the existing ones. If you have added * a wand upgrade, this is not done automatically for you; you will have to do it yourself (for the simple reason * that not all wand upgrades affect spells). SpellModifiers objects are mutable, so you can simply change the * values they contain to modify the spell. - *

    + *

    * To use a SpellModifiers object within the Spell.cast methods, simply retrieve the desired modifier * using {@link SpellModifiers#get(Item)} for wand upgrades, or {@link SpellModifiers#get(String)} if the modifier is * not from a wand upgrade. @@ -40,21 +37,40 @@ import net.minecraftforge.fml.common.network.ByteBufUtils; // fly. public final class SpellModifiers { - /** Constant string identifier for the potency modifier. All the other modifiers in Wizardry have items. */ + /** Constant string identifier for the potency modifier. */ public static final String POTENCY = "potency"; + /** Constant string identifier for the mana cost modifier. */ + public static final String COST = "cost"; + /** Constant string identifier for the wand progression modifier. */ + public static final String PROGRESSION = "progression"; - private Map multiplierMap; - private Map syncedMultiplierMap; + private final Map multiplierMap; + private final Map syncedMultiplierMap; /** * Creates an empty SpellModifiers object. All calls to get(...) on an empty SpellModifiers object will * return a value of 1. */ public SpellModifiers(){ - multiplierMap = new HashMap(); - syncedMultiplierMap = new HashMap(); + multiplierMap = new HashMap<>(); + syncedMultiplierMap = new HashMap<>(); } +// /** Returns a deep copy of this {@code SpellModifiers} object. */ +// @Override +// public SpellModifiers clone(){ +// SpellModifiers clone; +// try { +// clone = (SpellModifiers)super.clone(); +// }catch(CloneNotSupportedException e){ +// Wizardry.logger.error("Whaaaaat?!", e); +// return null; +// } +// clone.multiplierMap = new HashMap<>(this.multiplierMap); +// clone.syncedMultiplierMap = new HashMap<>(this.syncedMultiplierMap); +// return clone; +// } + /** * Adds the given multiplier to this SpellModifiers object, using the string identifier that the given wand upgrade * item was registered with. @@ -109,6 +125,31 @@ public final class SpellModifiers { return value == null ? 1 : value; } + // Not sure this really makes sense with the current system, it may just be better to keep it how it is +// /** +// * Returns the level of upgrade (i.e. number of upgrades or wand tier) that would be required to +// * generate a modifier with the given key. This does not necessarily mean that was how this modifier was +// * applied; and the returned value may not be a whole number if commands were involved. +// */ +// public float level(String key){ +// return 0; +// } + + /** + * Returns an amplified version of the multiplier corresponding to the given string key. An amplified + * modifier is the original modifier scaled about 1 - for example, amplifying by 2 would produce the + * following results:
    + * 1.3 -> 1.6
    + * 2 -> 3
    + * 0.7 -> 0.4
    + * 1 -> 1
    + * (In other words, the modifier is decreased by 1, multiplied by the scalar and then increased by 1 again.)
    + * N.B. This does not change the stored modifier. + */ + public float amplified(String key, float scalar){ + return (get(key) - 1) * scalar + 1; + } + /** * Returns an unmodifiable map of the modifiers stored in this SpellModifiers object. Useful for iterating through * the modifiers. @@ -146,10 +187,10 @@ public final class SpellModifiers { /** * Creates a new SpellModifiers object from the given NBTTagCompound. The NBTTagCompound should have 1 or more float * tags, which will be stored as modifiers under the same name as the tag. For example, the following NBT tag (in - * command syntax) will create a SpellModifiers object with a damage modifier of 1.5 and a range modifier of 2: - *

    + * command syntax) represents a SpellModifiers object with a damage modifier of 1.5 and a range modifier of 2: + *

    * {damage:1.5, range:2} - *

    + *

    * Note that needsSyncing is set to true for all returned modifiers. */ public static SpellModifiers fromNBT(NBTTagCompound nbt){ @@ -159,5 +200,22 @@ public final class SpellModifiers { } return modifiers; } + + /** + * Creates a new NBTTagCompound for this SpellModifiers object. The NBTTagCompound will have a float tags for each + * modifier, which will be stored using the modifier names as keys. For example, the following NBT tag (in + * command syntax) represents a SpellModifiers object with a damage modifier of 1.5 and a range modifier of 2: + *

    + * {damage:1.5, range:2} + *

    + * Note that information about syncing of modifiers is discarded. + */ + public NBTTagCompound toNBT(){ + NBTTagCompound nbt = new NBTTagCompound(); + for(Entry entry : multiplierMap.entrySet()){ + nbt.setFloat(entry.getKey(), entry.getValue()); + } + return nbt; + } } diff --git a/src/main/java/electroblob/wizardry/util/SpellProperties.java b/src/main/java/electroblob/wizardry/util/SpellProperties.java new file mode 100644 index 00000000..55e7d00b --- /dev/null +++ b/src/main/java/electroblob/wizardry/util/SpellProperties.java @@ -0,0 +1,361 @@ +package electroblob.wizardry.util; + +import com.google.gson.Gson; +import com.google.gson.JsonObject; +import com.google.gson.JsonParseException; +import com.google.gson.JsonSyntaxException; +import electroblob.wizardry.Wizardry; +import electroblob.wizardry.constants.Element; +import electroblob.wizardry.constants.SpellType; +import electroblob.wizardry.constants.Tier; +import electroblob.wizardry.registry.Spells; +import electroblob.wizardry.spell.Spell; +import io.netty.buffer.ByteBuf; +import net.minecraft.util.JsonUtils; +import net.minecraft.util.ResourceLocation; +import net.minecraftforge.common.crafting.CraftingHelper; +import net.minecraftforge.fml.common.Loader; +import net.minecraftforge.fml.common.ModContainer; +import org.apache.commons.io.FilenameUtils; +import org.apache.commons.io.IOUtils; + +import java.io.BufferedReader; +import java.io.IOException; +import java.nio.file.Files; +import java.util.*; +import java.util.stream.Collectors; + +/** + * Object that stores base properties associated with spells. Each spell has a single instance of this class which + * stores its base properties and other data. This class also handles loading of the properties from JSON. + *

    + * All the fields in this class are final and are assigned during object creation. This is because the intent is that a + * new SpellProperties object is created on load and synced with each client on player login. Having final fields + * therefore guarantees that the properties are always synced whenever necessary, but cannot otherwise be fiddled + * with programmatically. + *

    + * Generally, users need not worry about this class; it is intended that the various property getters in Spell be used + * rather than querying this class directly (in fact, you can't do that without reflection anyway). + *

    + * @author Electroblob + * @since Wizardry 4.2 + */ +// There is not a particular semantic reason to separate this from the Spell class itself. However, doing so means that +// everything related to the JSON spell system is kept in one place and doesn't clutter the (already long) Spell class. +// Additionally, it allows SpellProperties objects to be passed around during loading and syncing. +public final class SpellProperties { + + private static final Gson gson = new Gson(); + + /** Set of enum constants representing contexts in which a spell can be enabled/disabled. */ + public enum Context { + + /** Disabling this context will make a spell's book unobtainable and unusable. */ BOOK("book"), + /** Disabling this context will make a spell's scroll unobtainable and unusable. */ SCROLL("scroll"), + /** Disabling this context will prevent a spell from being cast using a wand. */ WANDS("wands"), + /** Disabling this context will prevent NPCs from casting or dropping a spell. */ NPCS("npcs"), + /** Disabling this context will prevent dispensers from casting a spell. */ DISPENSERS("dispensers"), + /** Disabling this context will prevent a spell from being cast using commands. */ COMMANDS("commands"), + /** Disabling this context will prevent a spell's book or scroll generating in chests. */ TREASURE("treasure"), + /** Disabling this context will prevent a spell's book or scroll from being sold by NPCs.*/ TRADES("trades"), + /** Disabling this context will prevent a spell's book or scroll being dropped by mobs. */ LOOTING("looting"); + + /** The JSON identifier for this context. */ + public final String name; + + Context(String name){ + this.name = name; + } + } + + /** A map storing whether each context is enabled for this spell. */ + private final Map enabledContexts; + /** A map storing the base values for this spell. These values are defined by the spell class and cannot be + * changed. */ + // We're using Number here because it makes implementors think about what they convert it to. + // If we did what attributes do and just use doubles, people (myself included!) might plug them into calculations + // without thinking. However, with Number you can't just do that, you have to convert and therefore you have to + // decide how to do the conversion. Internally they're handled as floats though. + private final Map baseValues; + + /** The tier this spell belongs to. */ + public final Tier tier; + /** The element this spell belongs to. */ + public final Element element; + /** The type of spell this is classified as. */ + public final SpellType type; + /** Mana cost of the spell. If it is a continuous spell the cost is per second. */ + public final int cost; + /** The charge-up time of the spell, in ticks. */ + public final int chargeup; + /** The cooldown time of the spell, in ticks. */ + public final int cooldown; + + // Sometimes it just makes more sense to do the JSON parsing in the constructor + // It's the only way we're gonna keep the fields final! + /** + * Parses the given JSON object and constructs a new {@code SpellProperties} from it, setting all the relevant + * fields and references. + * + * @param json A JSON object representing the spell properties to be constructed. + * @param spell The spell that this {@code SpellProperties} object is for. + * @throws JsonSyntaxException if at any point the JSON object is found to be invalid. + */ + private SpellProperties(JsonObject json, Spell spell){ + + String[] baseValueNames = spell.getPropertyKeys(); + + enabledContexts = new EnumMap<>(Context.class); + baseValues = new HashMap<>(); + + JsonObject enabled = JsonUtils.getJsonObject(json, "enabled"); + + // This time we know the exact set of properties so we can iterate over them instead of the json object + // In fact, we actually want to throw an exception if any of them are missing + for(Context context : Context.values()){ + enabledContexts.put(context, JsonUtils.getBoolean(enabled, context.name)); + } + + try { + tier = Tier.fromName(JsonUtils.getString(json, "tier")); + element = Element.fromName(JsonUtils.getString(json, "element")); + type = SpellType.fromName(JsonUtils.getString(json, "type")); + }catch(IllegalArgumentException e){ + throw new JsonSyntaxException("Incorrect spell property value", e); + } + + cost = JsonUtils.getInt(json, "cost"); + chargeup = JsonUtils.getInt(json, "chargeup"); + cooldown = JsonUtils.getInt(json, "cooldown"); + + // There's not much point specifying the classes of the numbers here because the json getter methods just + // perform conversion to the requested type anyway. It therefore makes very little difference whether the + // conversion is done during JSON parsing or when we actually use the value - and at least in the latter case, + // individual subclasses have control over how it is converted. + + // My case in point: summoning 2.5 spiders is obviously nonsense, but what happens when we cast that with a + // modifier of 2? Should we round the base value down to 2 and then apply the x2 modifier to get 4 spiders? + // Should we round it up instead? Or should we apply the modifier first and then do the rounding, so with no + // modifier we still get 2 spiders but with the x2 modifier we get 5? + // The most pragmatic solution is to let the spell class decide for itself. + // (Of course, we can only hope that the users aren't jerks and don't try to summon 2 and a half spiders...) + + JsonObject baseValueObject = JsonUtils.getJsonObject(json, "base_properties"); + + // If the code requests more values than the JSON file contains, that will cause a JsonSyntaxException here anyway. + // If there are redundant values in the JSON file, chances are that a user has misunderstood the system and tried + // to add properties that aren't implemented. However, redundant values will also be found if a programmer has + // forgotten to call addProperties in their spell constructor (I know I have!), potentially causing a crash at + // some random point in the future. Since redundant values aren't a problem by themselves, we shouldn't throw an + // exception, but a warning is appropriate. + + int redundantKeys = baseValueObject.size() - baseValueNames.length; + if(redundantKeys > 0) Wizardry.logger.warn("Spell " + spell.getRegistryName() + " has " + redundantKeys + + " redundant spell property key(s) defined in its JSON file. Extra values will have no effect! (Modders:" + + " make sure you have called addProperties(...) during spell construction)"); + + if(baseValueNames.length > 0){ + + for(String baseValueName : baseValueNames){ + baseValues.put(baseValueName, JsonUtils.getFloat(baseValueObject, baseValueName)); + } + } + + } + + /** Constructs a new SpellProperties object for the given spell, reading its values from the given ByteBuf. */ + public SpellProperties(Spell spell, ByteBuf buf){ + + enabledContexts = new EnumMap<>(Context.class); + baseValues = new HashMap<>(); + + for(Context context : Context.values()){ + // Enum maps have a guaranteed iteration order so this works fine + enabledContexts.put(context, buf.readBoolean()); + } + + tier = Tier.values()[buf.readShort()]; + element = Element.values()[buf.readShort()]; + type = SpellType.values()[buf.readShort()]; + + cost = buf.readInt(); + chargeup = buf.readInt(); + cooldown = buf.readInt(); + + List keys = Arrays.asList(spell.getPropertyKeys()); + Collections.sort(keys); // Should be the same list of keys in the same order they were written to the ByteBuf + + for(String key : keys){ + baseValues.put(key, buf.readFloat()); + } + } + + /** Writes this SpellProperties object to the given ByteBuf so it can be sent via packets. */ + public void write(ByteBuf buf){ + + for(Context context : Context.values()){ + // Enum maps have a guaranteed iteration order so this works fine + buf.writeBoolean(enabledContexts.get(context)); + } + + buf.writeShort(tier.ordinal()); + buf.writeShort(element.ordinal()); + buf.writeShort(type.ordinal()); + + buf.writeInt(cost); + buf.writeInt(chargeup); + buf.writeInt(cooldown); + + List keys = new ArrayList<>(baseValues.keySet()); + Collections.sort(keys); // Sort alphabetically (as long as the order is consistent it doesn't matter) + + for(String key : keys){ + buf.writeFloat(baseValues.get(key).floatValue()); + } + } + + /** + * Returns whether the spell is enabled in any of the given contexts. + * @param contexts The context in which to check if the spell is enabled. + * @return True if the spell is enabled in any of the given contexts, false if not. + */ + public boolean isEnabled(Context... contexts){ + return enabledContexts.entrySet().stream().anyMatch(e -> e.getValue() && Arrays.asList(contexts).contains(e.getKey())); + } + + /** + * Returns the base value for this spell that corresponds to the given identifier. + * @param identifier The string identifier to fetch the base value for. + * @return The base value, as a {@code Number}. + * @throws IllegalArgumentException if no base value was defined with the given identifier. + */ + public Number getBaseValue(String identifier){ + if(!baseValues.containsKey(identifier)){ + throw new IllegalArgumentException("Base value with identifier '" + identifier + "' is not defined."); + } + return baseValues.get(identifier); + } + + /** + * Called from preInit() in the main mod class to initialise the spell property system. + */ + // For some reason I had this called from a method in CommonProxy which was overridden to do nothing in + // ClientProxy, but that method was never called and instead this one was called directly from the main mod class. + // I *think* I decided against the proxy thing and just forgot to delete the methods (they're gone now), but if + // things don't work as expected then that may be why - pretty sure it's fine though since the properties get + // wiped client-side on each login anyway. + public static void init(){ + // Collecting to a set should give us one of each mod ID + Set modIDs = Spell.getSpells(Spell.allSpells).stream().map(s -> s.getRegistryName().getNamespace()).collect(Collectors.toSet()); + + boolean flag = true; + + for(String modID : modIDs){ + flag &= loadSpellProperties(modID); // Don't short-circuit, or mods later on won't get loaded! + } + + if(!flag) Wizardry.logger.warn("Some spell property files did not load correctly; this will likely cause problems later!"); + } + + // Sooooooo I just realised that resource packs - you know, that famously client-side thing - can now define + // stuff that should be specified by the server. No wonder it all got moved to data packs in 1.13... + // Anyway, for the time being we're in 1.12 so we're gonna have to do this instead. + + // For crafting recipes, Forge does some stuff behind the scenes to load recipe JSON files from mods' namespaces. + // This leverages the same methods. + + private static boolean loadSpellProperties(String modID){ + + // Yes, I know you're not supposed to do orElse(null). But... meh. + ModContainer mod = Loader.instance().getModList().stream().filter(m -> m.getModId().equals(modID)).findFirst().orElse(null); + + if(mod == null){ + Wizardry.logger.warn("Tried to load spell properties for mod with ID '" + modID + "', but no such mod was loaded"); + return false; // Failed! + } + + // Spells will be removed from this list as their properties are set + // If everything works properly, it should be empty by the end + List spells = Spell.getSpells(s -> s.getRegistryName().getNamespace().equals(modID)); + if(modID.equals(Wizardry.MODID)) spells.add(Spells.none); // In this particular case we do need the none spell + + Wizardry.logger.info("Loading spell properties for " + spells.size() + " spells in mod " + modID); + + // This method is used by Forge to load mod recipes and advancements, so it's a fair bet it's the right one + // In the absence of Javadoc, here's what the non-obvious parameters do: + // - preprocessor is called once with just the root directory, allowing any global index files to be processed + // - processor is called once for each file in the directory so processing can be done + // - defaultUnfoundRoot is the default value to return if the root specified isn't found + // - visitAllFiles determines whether the method short-circuits; in other words, if the processor returns false + // at any point and visitAllFiles is false, the method returns immediately. + boolean success = CraftingHelper.findFiles(mod, "assets/" + modID + "/spells", null, + + (root, file) -> { + + String relative = root.relativize(file).toString(); + if(!"json".equals(FilenameUtils.getExtension(file.toString())) || relative.startsWith("_")) + return true; // True or it'll look like it failed just because it found a non-JSON file + + String name = FilenameUtils.removeExtension(relative).replaceAll("\\\\", "/"); + ResourceLocation key = new ResourceLocation(modID, name); + + Spell spell = Spell.registry.getValue(key); + + // If no spell matches a particular file, log it and just ignore the file + if(spell == null){ + Wizardry.logger.info("Spell properties file " + name + ".json does not match any registered spells; ensure the filename is spelled correctly."); + return true; + } + + BufferedReader reader = null; + + // We want to do this regardless of whether the JSON file got read properly, because that prints its + // own separate warning + if(!spells.remove(spell)) Wizardry.logger.warn("What's going on?!"); + + try{ + + reader = Files.newBufferedReader(file); + + JsonObject json = JsonUtils.fromJson(gson, reader, JsonObject.class); + SpellProperties properties = new SpellProperties(json, spell); + spell.setProperties(properties); + + }catch(JsonParseException jsonparseexception){ + Wizardry.logger.error("Parsing error loading spell property file for " + key, jsonparseexception); + return false; + }catch(IOException ioexception){ + Wizardry.logger.error("Couldn't read spell property file for " + key, ioexception); + return false; + }finally{ + IOUtils.closeQuietly(reader); + } + + return true; + + }, + true, true); + + // If a spell is missing its file, log an error + if(!spells.isEmpty()){ + if(spells.size() <= 15){ + spells.forEach(s -> Wizardry.logger.error("Spell " + s.getRegistryName() + " is missing a properties file!")); + }else{ + // If there are more than 15 don't bother logging them all, chances are they're all missing + Wizardry.logger.error("Mod " + modID + " has " + spells.size() + " spells that are missing properties files!"); + } + } + + return success; + } +} + +// We probably could have used the attribute system for all of this, but I am reluctant to do so for a number of +// reasons: +// - It's a mess. +// - Unlike entities and itemstacks, spells don't have a separate instance for each time they are cast, which might +// prove problematic. +// - I'm loading my base properties once and not touching them again, so they're more like block materials than anything +// else. +// - Some of the properties aren't numerical, and some of them can't have modifiers applied. In fact, most of them can't! +// So even if we were to use attributes, we'd still need this class. \ No newline at end of file diff --git a/src/main/java/electroblob/wizardry/util/WandHelper.java b/src/main/java/electroblob/wizardry/util/WandHelper.java index 332f8cc3..449a807c 100644 --- a/src/main/java/electroblob/wizardry/util/WandHelper.java +++ b/src/main/java/electroblob/wizardry/util/WandHelper.java @@ -1,9 +1,5 @@ package electroblob.wizardry.util; -import java.util.Collections; -import java.util.HashMap; -import java.util.Set; - import electroblob.wizardry.item.ItemWand; import electroblob.wizardry.registry.Spells; import electroblob.wizardry.registry.WizardryItems; @@ -12,25 +8,29 @@ import net.minecraft.item.Item; import net.minecraft.item.ItemStack; import net.minecraft.nbt.NBTTagCompound; +import java.util.Collections; +import java.util.HashMap; +import java.util.Set; + /** * "Never fear, {@code WandHelper} is here!" - *

    + *

    * Much like {@link net.minecraft.enchantment.EnchantmentHelper EnchantmentHelper}, this class has some static methods * which allow cleaner and more concise interaction with the wand NBT data, which is quite a complex structure. Such * interaction previously resulted in rather verbose and repetitive code which was hard to read and even harder to * debug! For example, this class allowed {@link electroblob.wizardry.item.ItemWand ItemWand} to be shortened by about * 80 lines. In addition, by having all the various null checks and array size checks in one place, the chance of * accidental errors due to forgetting to check these things is greatly reduced. - *

    + *

    * Note that these methods contain no game logic at all; they are purely for interacting with the NBT data. Conversely, * you should never need to access the wand's NBT data directly when using this class, but the keys are public in the * unlikely case that this is necessary. - *

    + *

    * Also note that none of the methods in this class actually check that the given ItemStack contains an ItemWand; you * can, for example, pass in a stack of snowballs without causing problems, but that is of course pointless! However, if * you have your own spell casting item (which doesn't extend ItemWand), this setup means you can still use this class * to manage its NBT structure. - *

    + *

    * All get methods in this class return some kind of default if the passed-in wand stack has no nbt data. See * individual method descriptions for more details.
    * All set methods in this class create a new nbt data for the passed-in wand if it has none, before doing @@ -46,11 +46,13 @@ public final class WandHelper { public static final String SPELL_ARRAY_KEY = "spells"; public static final String SELECTED_SPELL_KEY = "selectedSpell"; public static final String COOLDOWN_ARRAY_KEY = "cooldown"; + public static final String MAX_COOLDOWN_ARRAY_KEY = "maxCooldown"; public static final String UPGRADES_KEY = "upgrades"; + public static final String PROGRESSION_KEY = "progression"; private static final HashMap upgradeMap = new HashMap(); - static{ + static { upgradeMap.put(WizardryItems.condenser_upgrade, "condenser"); upgradeMap.put(WizardryItems.storage_upgrade, "storage"); upgradeMap.put(WizardryItems.siphon_upgrade, "siphon"); @@ -59,8 +61,11 @@ public final class WandHelper { upgradeMap.put(WizardryItems.cooldown_upgrade, "cooldown"); upgradeMap.put(WizardryItems.blast_upgrade, "blast"); upgradeMap.put(WizardryItems.attunement_upgrade, "attunement"); + upgradeMap.put(WizardryItems.melee_upgrade, "melee"); } + // =================================================== Spells =================================================== + /** * Returns an array containing the spells currently bound to the given wand. As of Wizardry 1.1, this array is not * always the same size; it can be anywhere between 5 and 8 (inclusive) in length. If the wand has no spell data, @@ -77,7 +82,7 @@ public final class WandHelper { spells = new Spell[spellIDs.length]; for(int i = 0; i < spellIDs.length; i++){ - spells[i] = Spell.get(spellIDs[i]); + spells[i] = Spell.byMetadata(spellIDs[i]); } } @@ -95,7 +100,7 @@ public final class WandHelper { int[] spellIDs = new int[spells.length]; for(int i = 0; i < spells.length; i++){ - spellIDs[i] = spells[i] != null ? spells[i].id() : Spells.none.id(); + spellIDs[i] = spells[i] != null ? spells[i].metadata() : Spells.none.metadata(); } wand.getTagCompound().setIntArray(SPELL_ARRAY_KEY, spellIDs); @@ -123,9 +128,10 @@ public final class WandHelper { public static Spell getNextSpell(ItemStack wand){ Spell[] spells = getSpells(wand); + int index = getNextSpellIndex(wand); - if(wand.getTagCompound() != null){ - return spells[getNextSpellIndex(wand)]; + if(index >= 0 && index < spells.length){ + return spells[index]; } return Spells.none; @@ -136,9 +142,10 @@ public final class WandHelper { public static Spell getPreviousSpell(ItemStack wand){ Spell[] spells = getSpells(wand); + int index = getPreviousSpellIndex(wand); - if(wand.getTagCompound() != null){ - return spells[getPreviousSpellIndex(wand)]; + if(index >= 0 && index < spells.length){ + return spells[index]; } return Spells.none; @@ -165,6 +172,8 @@ public final class WandHelper { } private static int getNextSpellIndex(ItemStack wand){ + + if(wand.getTagCompound() == null) wand.setTagCompound(new NBTTagCompound()); int numberOfSpells = getSpells(wand).length; int spellIndex = wand.getTagCompound().getInteger(SELECTED_SPELL_KEY); @@ -181,6 +190,8 @@ public final class WandHelper { } private static int getPreviousSpellIndex(ItemStack wand){ + + if(wand.getTagCompound() == null) wand.setTagCompound(new NBTTagCompound()); int numberOfSpells = getSpells(wand).length; int spellIndex = wand.getTagCompound().getInteger(SELECTED_SPELL_KEY); @@ -194,6 +205,8 @@ public final class WandHelper { return spellIndex; } + // ================================================== Cooldowns ================================================== + /** * Returns an array of the cooldowns for each spell bound to the given wand. As of Wizardry 1.1, this array is not * always the same size; it can be anywhere between 5 and 8 (inclusive) in length. If the wand has no cooldown data, @@ -211,7 +224,8 @@ public final class WandHelper { return cooldowns; } - /** Sets the given wand's cooldown array. The array can be anywhere between 5 and 8 (inclusive) in length. */ + /** Sets the given wand's cooldown array. The array can be anywhere between 5 and 8 (inclusive) in length. + * Unlike {@link WandHelper#setCurrentCooldown(ItemStack, int)}, this will not set the max cooldowns. */ public static void setCooldowns(ItemStack wand, int[] cooldowns){ if(wand.getTagCompound() == null) wand.setTagCompound((new NBTTagCompound())); @@ -266,7 +280,7 @@ public final class WandHelper { return cooldowns[getPreviousSpellIndex(wand)]; } - /** Sets the given wand's cooldown for the currently selected spell. */ + /** Sets the given wand's cooldown for the currently selected spell. Will also set the maximum cooldown. */ public static void setCurrentCooldown(ItemStack wand, int cooldown){ if(wand.getTagCompound() == null) wand.setTagCompound((new NBTTagCompound())); @@ -280,8 +294,52 @@ public final class WandHelper { cooldowns[wand.getTagCompound().getInteger(SELECTED_SPELL_KEY)] = cooldown; setCooldowns(wand, cooldowns); + + int[] maxCooldowns = getMaxCooldowns(wand); + + if(maxCooldowns.length == 0) maxCooldowns = new int[getSpells(wand).length]; + + maxCooldowns[wand.getTagCompound().getInteger(SELECTED_SPELL_KEY)] = cooldown; + + setMaxCooldowns(wand, maxCooldowns); } + /** + * Returns an array of the max cooldowns for each spell bound to the given wand. If the wand has no cooldown data, + * returns an array of length 0. + */ + public static int[] getMaxCooldowns(ItemStack wand){ + + int[] cooldowns = new int[0]; + + if(wand.getTagCompound() != null){ + + return wand.getTagCompound().getIntArray(MAX_COOLDOWN_ARRAY_KEY); + } + + return cooldowns; + } + + /** Sets the given wand's cooldown array. The array can be anywhere between 5 and 8 (inclusive) in length. */ + public static void setMaxCooldowns(ItemStack wand, int[] cooldowns){ + + if(wand.getTagCompound() == null) wand.setTagCompound((new NBTTagCompound())); + + wand.getTagCompound().setIntArray(MAX_COOLDOWN_ARRAY_KEY, cooldowns); + } + + /** Returns the given wand's max cooldown for the currently selected spell, or 0 if the wand has no cooldown data. */ + public static int getCurrentMaxCooldown(ItemStack wand){ + + int[] cooldowns = getMaxCooldowns(wand); + + if(cooldowns.length == 0) return 0; + // Don't need to check if the tag compound is null since the above check is equivalent. + return cooldowns[wand.getTagCompound().getInteger(SELECTED_SPELL_KEY)]; + } + + // ================================================== Upgrades ================================================== + /** * Returns the number of upgrades of the given type that have been applied to the given wand, or 0 if the wand has * no upgrade data or the given item is not a valid wand upgrade. @@ -371,4 +429,28 @@ public final class WandHelper { throw new IllegalArgumentException("Duplicate wand upgrade identifier: " + identifier); upgradeMap.put(upgrade, identifier); } + + // ================================================= Progression ================================================= + + /** Sets the given wand's progression to the given value. */ + public static void setProgression(ItemStack wand, int progression){ + + if(wand.getTagCompound() == null) wand.setTagCompound((new NBTTagCompound())); + + wand.getTagCompound().setInteger(PROGRESSION_KEY, progression); + } + + /** Returns the progression value for the given wand, or 0 if the wand has no data. */ + public static int getProgression(ItemStack wand){ + + if(wand.getTagCompound() == null) return 0; + + return wand.getTagCompound().getInteger(PROGRESSION_KEY); + } + + /** Adds the given amount of progression to this wand's progression value. */ + public static void addProgression(ItemStack wand, int progression){ + setProgression(wand, getProgression(wand) + progression); + } + } diff --git a/src/main/java/electroblob/wizardry/util/WizardryUtilities.java b/src/main/java/electroblob/wizardry/util/WizardryUtilities.java index 592a3bc3..8cbdcb58 100644 --- a/src/main/java/electroblob/wizardry/util/WizardryUtilities.java +++ b/src/main/java/electroblob/wizardry/util/WizardryUtilities.java @@ -1,70 +1,49 @@ package electroblob.wizardry.util; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collection; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Map.Entry; -import java.util.Random; -import java.util.UUID; -import java.util.function.Function; -import java.util.function.Predicate; - -import javax.annotation.Nullable; - -import org.apache.commons.lang3.tuple.ImmutablePair; - import electroblob.wizardry.CommonProxy; -import electroblob.wizardry.WizardData; import electroblob.wizardry.Wizardry; -import electroblob.wizardry.constants.Element; -import electroblob.wizardry.constants.Tier; -import electroblob.wizardry.entity.living.ISummonedCreature; -import electroblob.wizardry.registry.WizardryItems; -import electroblob.wizardry.registry.WizardryPotions; -import electroblob.wizardry.spell.MindControl; +import electroblob.wizardry.data.WizardData; +import electroblob.wizardry.entity.living.ISpellCaster; +import electroblob.wizardry.item.ISpellCastingItem; import electroblob.wizardry.spell.Spell; +import net.minecraft.block.Block; +import net.minecraft.block.BlockLog; +import net.minecraft.block.properties.IProperty; import net.minecraft.block.state.IBlockState; import net.minecraft.entity.Entity; -import net.minecraft.entity.EntityLiving; import net.minecraft.entity.EntityLivingBase; +import net.minecraft.entity.effect.EntityLightningBolt; import net.minecraft.entity.item.EntityArmorStand; import net.minecraft.entity.monster.EntityCreeper; import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.entity.projectile.EntityArrow; +import net.minecraft.entity.projectile.EntityThrowable; import net.minecraft.inventory.EntityEquipmentSlot; import net.minecraft.inventory.EntityEquipmentSlot.Type; import net.minecraft.item.Item; import net.minecraft.item.ItemStack; -import net.minecraft.nbt.NBTBase; -import net.minecraft.nbt.NBTTagCompound; -import net.minecraft.nbt.NBTTagList; import net.minecraft.network.datasync.DataParameter; import net.minecraft.server.MinecraftServer; -import net.minecraft.util.DamageSource; -import net.minecraft.util.EnumFacing; -import net.minecraft.util.NonNullList; -import net.minecraft.util.SoundCategory; -import net.minecraft.util.SoundEvent; -import net.minecraft.util.math.AxisAlignedBB; -import net.minecraft.util.math.BlockPos; -import net.minecraft.util.math.MathHelper; -import net.minecraft.util.math.RayTraceResult; -import net.minecraft.util.math.Vec3d; +import net.minecraft.util.*; +import net.minecraft.util.EnumFacing.Axis; +import net.minecraft.util.math.*; import net.minecraft.world.EnumDifficulty; import net.minecraft.world.World; -import net.minecraftforge.fml.relauncher.ReflectionHelper; -import net.minecraftforge.fml.relauncher.Side; -import net.minecraftforge.fml.relauncher.SideOnly; +import net.minecraftforge.event.ForgeEventFactory; +import net.minecraftforge.fml.common.ObfuscationReflectionHelper; + +import javax.annotation.Nullable; +import java.util.*; +import java.util.function.BiPredicate; +import java.util.function.Predicate; /** * "Where do you put random but useful bits and pieces? {@code WizardryUtilities} of course - the 'stuff that doesn't * fit anywhere else' class!" - *

    + *

    * This class contains some useful static methods for use anywhere - items, entities, spells, events, blocks, etc. * Broadly speaking, these fall into the following categories: - *

    + *

    * - In-world utilities (position calculating, retrieving entities, etc.)
    * - Raytracing
    * - NBT and data storage utilities
    @@ -83,6 +62,8 @@ public final class WizardryUtilities { public static final EntityEquipmentSlot[] ARMOUR_SLOTS; /** Changed to a constant in wizardry 2.1, since this is a lot more efficient. */ private static final DataParameter POWERED; +// /** Pointing item action used in various spells. */ +// public static final EnumAction POINT; static { // The list of slots needs to be mutable. @@ -92,10 +73,32 @@ public final class WizardryUtilities { ARMOUR_SLOTS = slots.toArray(new EntityEquipmentSlot[0]); // Null is passed in deliberately since POWERED is a static field. - POWERED = ReflectionHelper.getPrivateValue(EntityCreeper.class, null, "POWERED", "field_184714_b"); + POWERED = ObfuscationReflectionHelper.getPrivateValue(EntityCreeper.class, null, "field_184714_b"); + + //POINT = EnumHelper.addAction("POINT"); + } + + /** A global offset used for placing/rendering flat things so that they appear to sit flush with the face of blocks + * but do not cause z-fighting at a distance where it is noticeable. */ + // This value is a compromise between flushness and minimum view distance for z-fighting to occur. 0.005 seems to + // be immune to z-fighting until over a hundred blocks away, which is pretty good, and the distance from flat + // surfaces is still indistinguishable. + public static final double ANTI_Z_FIGHTING_OFFSET = 0.005; + + // I'm fed up with remembering these... + /** Stores constant values for attribute modifier operations (and javadoc for what they actually do!) */ + public static final class Operations { + /** Adds the attribute modifier amount to the base value. */ + public static final int ADD = 0; + /** Multiplies the base value by 1 plus the attribute modifier amount. Multiple modifiers are processed in + * parallel, i.e. the calculation is based on the base value and does not depend on previous modifiers. */ + public static final int MULTIPLY_FLAT = 1; + /** Multiplies the base value by 1 plus the attribute modifier amount. Multiple modifiers are processed in + * series, i.e. the calculation is based on the value after previous modifiers are applied, in the order added. */ + public static final int MULTIPLY_CUMULATIVE = 2; } - // SECTION Block/Entity/World Utilities + // World, Blocks and Coordinates // =============================================================================================================== /** @@ -117,64 +120,208 @@ public final class WizardryUtilities { return i; } - + /** - * Returns whether the block at the given coordinates can be replaced by another one (works as if a block is being - * placed by a player). True for air, liquids, vines, tall grass and snow layers but not for flowers, signs etc. + * Returns whether the block at the given position can be replaced by another one (works as if a block is being + * placed by a player). True for air, vines, tall grass and snow layers but not for flowers, signs etc. * This is a shortcut for world.getBlockState(pos).getMaterial().isReplaceable(). - * - * @see WizardryUtilities#canBlockBeReplacedB(World, BlockPos) + * + * @param world The world the block is in. + * @param pos The position of the block. + * @param excludeLiquids True to treat liquids as non-replaceable, false to treat liquids as replaceable. + * + * @see WizardryUtilities#canBlockBeReplaced(World, BlockPos) */ - public static boolean canBlockBeReplaced(World world, BlockPos pos){ - return world.isAirBlock(new BlockPos(pos)) || world.getBlockState(pos).getMaterial().isReplaceable(); + public static boolean canBlockBeReplaced(World world, BlockPos pos, boolean excludeLiquids){ + return (world.isAirBlock(new BlockPos(pos)) || world.getBlockState(pos).getMaterial().isReplaceable()) + && (!excludeLiquids || !world.getBlockState(pos).getMaterial().isLiquid()); } /** - * Returns whether the block at the given coordinates can be replaced by another one (works as if a block is being - * placed by a player) and is not a liquid. True for air, vines, tall grass and snow layers but not for flowers, - * signs etc. or any liquids. - * - * @see WizardryUtilities#canBlockBeReplaced(World, BlockPos) + * Returns whether the block at the given position can be replaced by another one (works as if a block is being + * placed by a player). True for air, liquids, vines, tall grass and snow layers but not for flowers, signs etc. + * This is a shorthand version of {@link WizardryUtilities#canBlockBeReplaced(World, BlockPos, boolean)}; + * excludeLiquids defaults to false. + * + * @param world The world the block is in. + * @param pos The position of the block. */ - public static boolean canBlockBeReplacedB(World world, BlockPos pos){ - return canBlockBeReplaced(world, pos) && !world.getBlockState(pos).getMaterial().isLiquid(); + public static boolean canBlockBeReplaced(World world, BlockPos pos){ + return canBlockBeReplaced(world, pos, false); } /** * Returns whether the block at the given coordinates is unbreakable in survival mode. In vanilla this is true for - * bedrock and end portal frame, for example. This is a shortcut for:

    + * bedrock and end portal frame, for example. This is a shortcut for:

    * {@code world.getBlockState(pos).getBlockHardness(world, pos) == -1.0f} */ public static boolean isBlockUnbreakable(World world, BlockPos pos){ return !world.isAirBlock(new BlockPos(pos)) && world.getBlockState(pos).getBlockHardness(world, pos) == -1.0f; } + /** + * Returns a block state for the given block, with all properties set to the values from the given source state. + * The source block state must have exactly the same properties as the destination block will allow or an + * {@link IllegalArgumentException} will be thrown. + *

    + * This method allows, for example, an oak door block to be replaced with a spruce one whilst keeping the same + * orientation, door half, open/closed state, etc. + * @param block The new block type + * @param source The block state to copy property values from + * @return The resulting block state + */ + @SuppressWarnings("unchecked") // Don't complain to me about Mojang's code design... + public static IBlockState copyState(Block block, IBlockState source){ + + IBlockState state = block.getDefaultState(); + + for(IProperty property : source.getPropertyKeys()){ + // It ain't pretty but it works + state = state.withProperty(property, (Comparable)source.getProperties().get(property)); + } + + return state; + } + + /** + * Finds the nearest surface (according to the given criteria) in the given direction from the given position, + * within the range specified. This is a generalised replacement for the old {@code getNearestFloorLevel} methods; + * overloads and predefined surface criteria that replicate the old behaviours are available. + * + * @param world The world to search in + * @param pos The position to search from + * @param direction The direction to search in; also defines the direction the surface must face. + * @param range The maximum distance from the given y coordinate to search. + * @param doubleSided True to also search in the opposite direction, false to only search in the given direction. + * @param criteria A {@link SurfaceCriteria} representing the criteria defining a surface. See that class for + * available predefined criteria. + * @return The x, y, or z coordinate of the closest surface, or null if no surface was found. This represents the + * exact position of the block boundary that forms the surface (and therefore it may correspond to the coordinate + * of the inside or outside block of the surface depending on the direction). + */ + @Nullable + public static Integer getNearestSurface(World world, BlockPos pos, EnumFacing direction, int range, + boolean doubleSided, SurfaceCriteria criteria){ + + // This is a neat trick that allows a default 'not found' return value for integers where all possible integer + // values could, in theory, be returned. The alternative is to use a double and have NaN as the default, but + // that would introduce extra casting, and since NaN can be calculated with, it could produce strange results + // when unaccounted for. Using an Integer means it'll immediately throw an NPE instead. + Integer surface = null; + int currentBest = Integer.MAX_VALUE; + + for(int i = doubleSided ? -range : 0; i <= range && i < currentBest; i++){ // Now short-circuits for efficiency + + BlockPos testPos = pos.offset(direction, i); + + if(criteria.test(world, testPos, direction)){ + // Because the loop now short-circuits, this must be closer than the previous surface found + surface = (int)component(getFaceCentre(testPos, direction), direction.getAxis()); + currentBest = Math.abs(i); + } + } + + return surface; + } + + /** + * A {@code SurfaceCriteria} object is used to define a 'surface', a boundary between two blocks which differ in + * some way, for use in {@link WizardryUtilities#getNearestSurface(World, BlockPos, EnumFacing, int, boolean, SurfaceCriteria)}. + * This provides a more flexible replacement for the (now deprecated) {@code getNearestFloorLevel} methods.
    + *
    + * In the context of this class, 'outside' refers to the side of the surface that is in the supplied direction, + * and 'inside' refers to the side which is in the opposite direction. For example, if the direction is {@code UP}, + * the inside of the surface is defined as below it, and the outside is defined as above it. + */ + @FunctionalInterface + public interface SurfaceCriteria { + + /** + * Tests whether the inputs define a valid surface according to this set of criteria. + * @param world The world in which the surface is to be tested. + * @param pos The block coordinates of the inside ('solid' part) of the surface. + * @param side The direction in which the surface must face. + * @return True if the side {@code side} of the block at {@code pos} in {@code world} is a valid surface + * according to this set of criteria, false otherwise. + */ + boolean test(World world, BlockPos pos, EnumFacing side); + + /** Returns a {@code SurfaceCriteria} with the opposite arrangement to this one. */ + default SurfaceCriteria flip(){ + return (world, pos, side) -> this.test(world, pos.offset(side), side.getOpposite()); + } + + /** Returns a {@code SurfaceCriteria} based on the given condition, where the inside of the surface satisfies + * the condition and the outside does not. */ + static SurfaceCriteria basedOn(BiPredicate condition){ + return (world, pos, side) -> condition.test(world, pos) && !condition.test(world, pos.offset(side)); + } + + /** Returns a {@code SurfaceCriteria} based on the given condition, where the inside of the surface satisfies + * the condition and the outside does not. */ + static SurfaceCriteria basedOn(Predicate condition){ + return (world, pos, side) -> condition.test(world.getBlockState(pos)) && !condition.test(world.getBlockState(pos.offset(side))); + } + + /** Surface criterion which defines a surface as the boundary between a block that cannot be moved through and + * a block that can be moved through. This means the surface can be stood on. */ + SurfaceCriteria COLLIDABLE = basedOn(b -> b.getMaterial().blocksMovement()); + + /** Surface criterion which defines a surface as the boundary between a block that is solid on the required side and + * a block that is replaceable. This means the surface can be built on. */ + SurfaceCriteria BUILDABLE = (world, pos, side) -> world.isSideSolid(pos, side) && world.getBlockState(pos.offset(side)).getBlock().isReplaceable(world, pos); + + /** Surface criterion which defines a surface as the boundary between a block that is solid on the required side + * or a liquid, and an air block. Used for freezing water and placing snow. */ + // Was getNearestFloorLevelB + SurfaceCriteria SOLID_LIQUID_TO_AIR = (world, pos, side) -> (world.getBlockState(pos).getMaterial().isLiquid() + || world.isSideSolid(pos, side) && world.isAirBlock(pos.offset(side))); + + /** Surface criterion which defines a surface as the boundary between any non-air block and an air block. + * Used for particles. */ + // Was getNearestFloorLevelC + SurfaceCriteria NOT_AIR_TO_AIR = basedOn(World::isAirBlock).flip(); + + /** Surface criterion which defines a surface as the boundary between a block that cannot be moved through, and + * a block that can be moved through or a tree block (log or leaves). Used for structure generation. */ + SurfaceCriteria COLLIDABLE_IGNORING_TREES = basedOn((world, pos) -> + world.getBlockState(pos).getMaterial().blocksMovement() + && !(world.getBlockState(pos).getBlock() instanceof BlockLog) + && !(world.getBlockState(pos).getBlock().isLeaves(world.getBlockState(pos), world, pos) + && !(world.getBlockState(pos).getBlock().isFoliage(world, pos)))); + + } + + /** + * Finds the nearest floor level in the given direction from the given position, + * within the range specified. This is a shorthand for + * {@link WizardryUtilities#getNearestSurface(World, BlockPos, EnumFacing, int, boolean, SurfaceCriteria)}; + * {@code doubleSided} defaults to true, {@code direction} defaults to {@code EnumFacing.UP}, and + * {@code criteria} defaults to {@link SurfaceCriteria#COLLIDABLE}. + */ + @Nullable + public static Integer getNearestFloor(World world, BlockPos pos, int range){ + return getNearestSurface(world, pos, EnumFacing.UP, range, true, SurfaceCriteria.COLLIDABLE); + } + /** * Finds the nearest floor level to the given y coord within the range specified at the given x and z coords. - * Liquids and other blocks that cannot be built on top of do not count, but stuff like signs does. (Technically any - * block is allowed to be the floor according to the code, but seeing as it searches upwards and non-solid blocks - * usually need a supporting block, the floor is likely to always be solid). + * As of Wizardry 4.2, this is now a wrapper for {@link WizardryUtilities#getNearestFloor(World, BlockPos, int)} + * which retains the old functionality (i.e. returning an {@code int}, with -1 as 'not found') for compatibility. * * @param world The world to search in * @param pos The coordinates to search from * @param range The maximum distance from the given y coordinate to search. * @return The y coordinate of the closest floor level, or -1 if there is none. Returns the actual level of the * floor as would be seen in the debug screen when the player is standing on it. - * @see WizardryUtilities#getNearestFloorLevelB(World, BlockPos, int) + * @deprecated Use {@link WizardryUtilities#getNearestFloor(World, BlockPos, int)}; this method may be removed in + * future. */ + // Since this is always a y-coordinate, the 'not found' value can just be any negative number. + @Deprecated public static int getNearestFloorLevel(World world, BlockPos pos, int range){ - - int yCoord = -2; - for(int i = -range; i <= range; i++){ - // The last bit determines whether the block found to be a suitable floor is closer than the previous one - // found. - if(world.isSideSolid(pos.up(i), EnumFacing.UP) - && (world.isAirBlock(pos.up(i + 1)) || !world.isSideSolid(pos.up(i + 1), EnumFacing.UP)) - && (i < yCoord - pos.getY() || yCoord == -2)){ - yCoord = pos.getY() + i; - } - } - return yCoord + 1; + Integer floor = getNearestFloor(world, pos, range); + return floor == null ? -1 : floor; } /** @@ -186,21 +333,13 @@ public final class WizardryUtilities { * @param range The maximum distance from the given y coordinate to search. * @return The y coordinate of the closest floor level, or -1 if there is none. Returns the actual level of the * floor as would be seen in the debug screen when the player is standing on it. - * @see WizardryUtilities#getNearestFloorLevel(World, BlockPos, int) + * @deprecated Use {@link WizardryUtilities#getNearestSurface(World, BlockPos, EnumFacing, int, boolean, SurfaceCriteria)}; + * this method may be removed in future. */ + @Deprecated public static int getNearestFloorLevelB(World world, BlockPos pos, int range){ - int yCoord = -2; - for(int i = -range; i <= range; i++){ - if(world.isAirBlock(new BlockPos(pos.up(i + 1))) - && (world.getBlockState(pos.up(i)).getMaterial().isLiquid() - || world.isSideSolid(pos.up(i), EnumFacing.UP)) - && (i < yCoord - pos.getY() || yCoord == -2)){ - // The last bit determines whether the block found to be a suitable floor is closer than the previous - // one found. - yCoord = pos.getY() + i; - } - } - return yCoord + 1; + Integer floor = getNearestSurface(world, pos, EnumFacing.UP, range, true, SurfaceCriteria.SOLID_LIQUID_TO_AIR); + return floor == null ? -1 : floor; } /** @@ -212,18 +351,13 @@ public final class WizardryUtilities { * @param range The maximum distance from the given y coordinate to search. * @return The y coordinate of the closest floor level, or -1 if there is none. Returns the actual level of the * floor as would be seen in the debug screen when the player is standing on it. - * @see WizardryUtilities#getNearestFloorLevel(World, BlockPos, int) + * @deprecated Use {@link WizardryUtilities#getNearestSurface(World, BlockPos, EnumFacing, int, boolean, SurfaceCriteria)}; + * this method may be removed in future. */ + @Deprecated public static int getNearestFloorLevelC(World world, BlockPos pos, int range){ - int yCoord = -2; - for(int i = -range; i <= range; i++){ - if(world.isAirBlock(new BlockPos(pos.up(i + 1))) && (i < yCoord - pos.getY() || yCoord == -2)){ - // The last bit determines whether the block found to be a suitable floor is closer than the previous - // one found. - yCoord = pos.getY() + i; - } - } - return yCoord + 1; + Integer floor = getNearestSurface(world, pos, EnumFacing.UP, range, true, SurfaceCriteria.NOT_AIR_TO_AIR); + return floor == null ? -1 : floor; } /** @@ -274,8 +408,8 @@ public final class WizardryUtilities { for(int x = -horizontalRange; x <= horizontalRange; x++){ for(int z = -horizontalRange; z <= horizontalRange; z++){ - int y = WizardryUtilities.getNearestFloorLevel(world, origin.add(x, 0, z), verticalRange); - if(y > -1) possibleLocations.add(new BlockPos(origin.getX() + x, y, origin.getZ() + z)); + Integer y = WizardryUtilities.getNearestFloor(world, origin.add(x, 0, z), verticalRange); + if(y != null) possibleLocations.add(new BlockPos(origin.getX() + x, y, origin.getZ() + z)); } } @@ -297,10 +431,43 @@ public final class WizardryUtilities { return entity.world.getBlockState(pos); } + /** + * Generates a sphere of block positions centred on the given position, with the given radius. This is an efficient + * implementation - rather than simply generating a cube and cutting the rest out, it works as follows: + *

    + * 1. Step through all x offsets within the specified radius
    + * 2. For each x offset, check the maximum y offset within the radius using Pythagoras
    + * 3. Step through the resulting valid y offsets
    + * 4. For each y offset, check the maximum z offset within the radius using Pythagoras
    + * 5. Step through the resulting valid z offsets + * @return A list of BlockPos objects in a sphere. This list will be ordered negative to positive, with axes + * nested in order (i.e. blocks in a line on the z axis will be consecutive in the list). + */ + public static List getBlockSphere(BlockPos centre, double radius){ + + // Extra efficiency by assigning enough capacity for a cube of side length r + List sphere = new ArrayList<>((int)Math.pow(radius, 3)); + + for(int i=-(int)radius; i<=radius; i++){ + + float r1 = MathHelper.sqrt(radius*radius - i*i); + + for(int j=-(int)r1; j<=r1; j++){ + + float r2 = MathHelper.sqrt(radius*radius - i*i - j*j); + + for(int k=-(int)r2; k<=r2; k++){ + sphere.add(centre.add(i, j, k)); + } + } + } + + return sphere; + } + /** * Shorthand for {@link WizardryUtilities#getEntitiesWithinRadius(double, double, double, double, World, Class)} - * with EntityLivingBase as the entity type. This is by far the most common use for that method, which is why this - * shorthand exists. + * with EntityLivingBase as the entity type. This is by far the most common use for that method. * * @param radius The search radius * @param x The x coordinate to search around @@ -334,21 +501,121 @@ public final class WizardryUtilities { for(int i = 0; i < entityList.size(); i++){ if(entityList.get(i).getDistance(x, y, z) > radius){ entityList.remove(i); + break; } } return entityList; } + // Why is there a distanceSqToCentre method in Vec3i but not a getCentre method? + /** - * Gets an entity from its UUID. Note that you should check this isn't null. If the UUID is known to belong to an - * EntityPlayer, use the more efficient {@link World#getPlayerEntityByUUID(UUID)} instead. + * Returns a {@link Vec3d} of the coordinates at the centre of the given block position (i.e. the block coordinates + * plus 0.5 in x, y, and z). + */ + public static Vec3d getCentre(BlockPos pos){ + return new Vec3d(pos).add(0.5, 0.5, 0.5); + } + + /** + * Returns a {@link Vec3d} of the coordinates at the centre of the given bounding box (The one in {@code AxisAlignedBB} + * itself is client-side only). + */ + public static Vec3d getCentre(AxisAlignedBB box){ + return new Vec3d(box.minX + (box.maxX - box.minX) * 0.5, box.minY + (box.maxY - box.minY) * 0.5, box.minZ + (box.maxZ - box.minZ) * 0.5); + } + + /** + * Returns a {@link Vec3d} of the coordinates at the centre of the given face of the given block position (i.e. the + * centre of the block plus 0.5 in the given direction). + */ + public static Vec3d getFaceCentre(BlockPos pos, EnumFacing face){ + return getCentre(pos).add(new Vec3d(face.getDirectionVec()).scale(0.5)); + } + + /** + * Returns the component of the given {@link Vec3d} corresponding to the given {@link Axis Axis}. + */ + public static double component(Vec3d vec, Axis axis){ + return new double[]{vec.x, vec.y, vec.z}[axis.ordinal()]; // Damn, that's compact. + } + + /** + * Returns the component of the given {@link Vec3i} corresponding to the given {@link Axis Axis}. + */ + public static int component(Vec3i vec, Axis axis){ + return new int[]{vec.getX(), vec.getY(), vec.getZ()}[axis.ordinal()]; + } + + /** + * Returns a new {@link Vec3d} with the component corresponding to the given {@link Axis Axis} replaced by the + * given value. + */ + public static Vec3d replaceComponent(Vec3d vec, Axis axis, double newValue){ + double[] components = {vec.x, vec.y, vec.z}; + components[axis.ordinal()] = newValue; + return new Vec3d(components[0], components[1], components[2]); + } + + /** + * Returns a new {@link Vec3i} with the component corresponding to the given {@link Axis Axis} replaced by the + * given value. + */ + public static Vec3i replaceComponent(Vec3i vec, Axis axis, int newValue){ + int[] components = {vec.getX(), vec.getY(), vec.getZ()}; + components[axis.ordinal()] = newValue; + return new Vec3i(components[0], components[1], components[2]); + } + + /** + * Returns an array of {@code Vec3d} objects representing the vertices of the given bounding box. + * @param box The bounding box whose vertices are to be returned. + * @return The list of vertices, which will contain 8 elements. Using EnumFacing initials, the order is: + * DNW, DNE, DSE, DSW, UNW, UNE, USE, USW. The returned coordinates are absolute (i.e. measured from the world origin). + */ + public static Vec3d[] getVertices(AxisAlignedBB box){ + return new Vec3d[]{ + new Vec3d(box.minX, box.minY, box.minZ), + new Vec3d(box.maxX, box.minY, box.minZ), + new Vec3d(box.maxX, box.minY, box.maxZ), + new Vec3d(box.minX, box.minY, box.maxZ), + new Vec3d(box.minX, box.maxY, box.minZ), + new Vec3d(box.maxX, box.maxY, box.minZ), + new Vec3d(box.maxX, box.maxY, box.maxZ), + new Vec3d(box.minX, box.maxY, box.maxZ) + }; + } + + /** + * Returns an array of {@code Vec3d} objects representing the vertices of the block at the given position. + * @param pos The position of the block whose vertices are to be returned. + * @return The list of vertices, which will contain 8 elements. Using EnumFacing initials, the order is: + * DNW, DNE, DSE, DSW, UNW, UNE, USE, USW. The returned coordinates are absolute (i.e. measured from the world origin). + */ + public static Vec3d[] getVertices(World world, BlockPos pos){ + return getVertices(world.getBlockState(pos).getBoundingBox(world, pos).offset(pos.getX(), pos.getY(), pos.getZ())); + } + + /** + * Returns the pitch angle in degrees of the given {@link EnumFacing}. For some reason {@code EnumFacing} has a get + * yaw method ({@link EnumFacing#getHorizontalAngle()}) but not a get pitch method. + */ + public static float getPitch(EnumFacing facing){ + return facing == EnumFacing.UP ? 90 : facing == EnumFacing.DOWN ? -90 : 0; + } + + /** + * 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. * * @param world The world the entity is in * @param id The entity's UUID * @return The Entity that has the given UUID, or null if no such entity exists in the specified world. */ @Nullable - public static Entity getEntityByUUID(World world, UUID id){ + public static Entity getEntityByUUID(World world, @Nullable UUID id){ + + if(id == null) return null; // It would return null eventually but there's no point even looking for(Entity entity : world.loadedEntityList){ // This is a perfect example of where you need to use .equals() and not ==. For most applications, @@ -382,6 +649,9 @@ public final class WizardryUtilities { player.world.playSound(null, player.posX, player.posY, player.posZ, sound, SoundCategory.PLAYERS, volume, pitch); } + // Players and Mobs + // =============================================================================================================== + /** * Returns the entity riding the given entity, or null if there is none. Allows for neater code now that entities * have a list of passengers, because it is necessary to check that the list is not empty first. @@ -430,8 +700,25 @@ public final class WizardryUtilities { * 0.01D){ dx = (Math.random() - Math.random()) * 0.01D; } - // The first argument is never used. - target.knockBack(null, 0.4f, dx, dz); + target.knockBack(attacker, 0.4f, dx, dz); + } + + /** + * Undoes 1 tick's worth of velocity change due to gravity for the given entity. If the entity has no gravity, + * this method does nothing. This method is intended to be used in situations where entity gravity needs to be + * turned on and off and it is not practical to use {@link Entity#setNoGravity(boolean)}, usually if there is no + * easy way to get a reference to the entity to turn gravity back on. + * + * @param entity The entity to undo gravity for. + */ + public static void undoGravity(Entity entity){ + if(!entity.hasNoGravity()){ + double gravity = 0.04; + if(entity instanceof EntityThrowable) gravity = 0.03; + else if(entity instanceof EntityArrow) gravity = 0.05; + else if(entity instanceof EntityLivingBase) gravity = 0.08; + entity.motionY += gravity; + } } /** @@ -503,6 +790,13 @@ public final class WizardryUtilities { return server.getPlayerList().getOppedPlayers().getEntry(player.getGameProfile()) != null; } + /** Checks that the given entity is allowed to damage blocks in the given world. If the entity is a player, this + * checks the player block damage config setting, otherwise it posts a mob griefing event and returns the result. */ + public static boolean canDamageBlocks(EntityLivingBase entity, World world){ + if(entity instanceof EntityPlayer) return Wizardry.settings.playerBlockDamage; + return ForgeEventFactory.getMobGriefingEvent(world, entity); + } + /** Returns the default aiming arror used by skeletons for the given difficulty. For reference, these are: Easy - 10, * Normal - 6, Hard - 2, Peaceful - 10 (rarely used). */ public static int getDefaultAimingError(EnumDifficulty difficulty){ @@ -536,159 +830,79 @@ public final class WizardryUtilities { public static void chargeCreeper(EntityCreeper creeper){ creeper.getDataManager().set(POWERED, true); } - - // SECTION Raytracing - // =============================================================================================================== - + /** - * Helper method which performs a ray trace for blocks only from an entity's eye position in the direction - * they are looking, over a specified range, using {@link World#rayTraceBlocks(Vec3d, Vec3d, boolean)}. - * - * @param world The world in which to perform the ray trace. - * @param entity The entity from which to perform the ray trace. The ray trace will start from this entity's eye - * position and proceed in the direction the entity is looking. - * @param range The distance over which the ray trace will be performed. - * @param hitLiquids True to return hits on the surfaces of liquids, false to ignore liquid blocks as if they were - * not there. - * @return A {@link RayTraceResult} representing the object that was hit, which may be either a block or nothing. - * Returns {@code null} only if the origin and endpoint are within the same block. + * Returns true if the given caster is currently casting the given spell by any means. This method is intended to + * eliminate the long and cumbersome wand use checking in event handlers, which often missed out spells cast by + * means other than wands. + * @param caster The potential spell caster, which may be a player or an {@link ISpellCaster}. Any other entity will + * cause this method to always return false. + * @param spell The spell to check for. The spell must be continuous or this method will always return false. + * @return True if the caster is currently casting the given spell through any means, false otherwise. */ - @Nullable - public static RayTraceResult standardBlockRayTrace(World world, EntityLivingBase entity, double range, boolean hitLiquids){ - // This method does not apply an offset like ray spells do, since it is not desirable in most other use cases. - Vec3d origin = new Vec3d(entity.posX, entity.getEntityBoundingBox().minY + entity.getEyeHeight(), entity.posZ); - Vec3d endpoint = origin.add(entity.getLookVec().scale(range)); - return world.rayTraceBlocks(origin, endpoint, hitLiquids); - } - - /** - * Helper method which performs a ray trace for blocks and entities from an entity's eye position in the direction - * they are looking, over a specified range, using {@link WizardryUtilities#rayTrace(World, Vec3d, Vec3d, float, - * boolean, Class, Predicate)}. Aim assist is zero, the entity type is simply {@code Entity} (all entities), and the - * filter removes the given entity and any dying entities and allows all others. - * - * @param world The world in which to perform the ray trace. - * @param entity The entity from which to perform the ray trace. The ray trace will start from this entity's eye - * position and proceed in the direction the entity is looking. This entity will be ignored when ray tracing. - * @param range The distance over which the ray trace will be performed. - * @param hitLiquids True to return hits on the surfaces of liquids, false to ignore liquid blocks as if they were - * not there. - * @return A {@link RayTraceResult} representing the object that was hit, which may be an entity, a block or - * nothing. Returns {@code null} only if the origin and endpoint are within the same block and no entity was hit. - */ - @Nullable - public static RayTraceResult standardEntityRayTrace(World world, Entity entity, double range, boolean hitLiquids){ - // This method does not apply an offset like ray spells do, since it is not desirable in most other use cases. - Vec3d origin = new Vec3d(entity.posX, entity.getEntityBoundingBox().minY + entity.getEyeHeight(), entity.posZ); - Vec3d endpoint = origin.add(entity.getLookVec().scale(range)); - return WizardryUtilities.rayTrace(world, origin, endpoint, 0, hitLiquids, Entity.class, e -> e == entity); - } - - /** - * Performs a ray trace for blocks and entities, starting at the given origin and finishing at the given endpoint. - * As of wizardry 4.2, the ray tracing methods have been rewritten to be more user-friendly and implement proper - * aim assist. - *

    - * N.B. It is possible to ignore entities entirely by passing in a {@code Predicate} that is always false; - * however, in this specific case it is more efficient to use - * {@link World#rayTraceBlocks(Vec3d, Vec3d, boolean, boolean, boolean)} or one of its overloads. - * - * @param The type of entities to include; all other entities will be ignored. - * @param world The world in which to perform the ray trace. - * @param origin A vector representing the coordinates of the start point of the ray trace. - * @param endpoint A vector representing the coordinates of the finish point of the ray trace. - * @param aimAssist In addition to direct hits, the ray trace will also hit entities that are up to this distance - * from its path. For a normal ray trace, this should be 0. Values greater than 0 will give an 'aim assist' effect. - * @param hitLiquids Whether liquids should be ignored when ray tracing blocks - * @param entityType The class of entities to include; all other entities will be ignored. - * @param filter A {@link Predicate} which filters out entities that can be ignored; often used to exclude the - * player that is performing the ray trace. - * - * @return A {@link RayTraceResult} representing the object that was hit, which may be an entity, a block or - * nothing. Returns {@code null} only if the origin and endpoint are within the same block and no entity was hit. - * - * @see WizardryUtilities#standardEntityRayTrace(World, Entity, double, boolean) - * @see WizardryUtilities#standardBlockRayTrace(World, EntityLivingBase, double, boolean) - */ - // Interestingly enough, aimAssist can be negative, which means hits have to be in the middle of entities! - @Nullable - public static RayTraceResult rayTrace(World world, Vec3d origin, Vec3d endpoint, float aimAssist, - boolean hitLiquids, Class entityType, Predicate filter){ + // The reason this is a boolean check is that actually returning a spell presents a problem: players can cast two + // continuous spells at once, one via commands and one via an item, so which do you choose? Since the main point was + // to check for specific spells, it seems more useful to do it this way. + public static boolean isCasting(EntityLivingBase caster, Spell spell){ - // 1 is the standard amount of extra search volume, and aim assist needs to increase this further as well as - // expanding the entities' bounding boxes. - float borderSize = 1 + aimAssist; - - // The AxisAlignedBB constructor accepts min/max coords in either order. - AxisAlignedBB searchVolume = new AxisAlignedBB(origin.x, origin.y, origin.z, endpoint.x, endpoint.y, endpoint.z) - .grow(borderSize, borderSize, borderSize); + if(!spell.isContinuous) return false; - // Gets all of the entities in the bounding box that could be collided with. - List entities = world.getEntitiesWithinAABB(entityType, searchVolume); - // Applies the given filter to remove entities that should be ignored. - entities.removeIf(filter); - - // Finds the first block hit by the ray trace, if any. - RayTraceResult result = world.rayTraceBlocks(origin, endpoint, hitLiquids); - - // Clips the entity search range to the part of the ray trace before the block hit, if it hit a block. - if(result != null){ - endpoint = result.hitVec; - } - - // Search variables - Entity closestHitEntity = null; - Vec3d closestHitPosition = endpoint; - AxisAlignedBB entityBounds; - RayTraceResult intercept; - - // Iterates through all the entities - for(Entity entity : entities){ + if(caster instanceof EntityPlayer){ - entityBounds = entity.getEntityBoundingBox(); + WizardData data = WizardData.get((EntityPlayer)caster); - if(entityBounds != null){ + if(data != null && data.currentlyCasting() == spell) return true; - // This is zero for everything except fireballs... - float entityBorderSize = entity.getCollisionBorderSize(); - // ... meaning the following line does nothing in all other cases. - // -> Added the non-zero check to prevent unnecessary AABB object creation. - if(entityBorderSize != 0) entityBounds = entityBounds.grow(entityBorderSize, entityBorderSize, entityBorderSize); - - // Aim assist expands the bounding box to hit entities within the specified distance of the ray trace. - if(aimAssist != 0) entityBounds = entityBounds.grow(aimAssist, aimAssist, aimAssist); - - // Finds the first point at which the ray trace intercepts the entity's bounding box, if any. - intercept = entityBounds.calculateIntercept(origin, endpoint); - - // If the ray trace hit the entity... - if(intercept != null){ - // Decides whether the entity that was hit is the closest so far, and if so, overwrites the old one. - float currentHitDistance = (float)intercept.hitVec.distanceTo(origin); - float closestHitDistance = (float)closestHitPosition.distanceTo(origin); - if(currentHitDistance < closestHitDistance){ - closestHitEntity = entity; - closestHitPosition = intercept.hitVec; - } + if(caster.isHandActive()){ + + ItemStack stack = caster.getHeldItem(caster.getActiveHand()); + + if(stack.getItem() instanceof ISpellCastingItem && ((ISpellCastingItem)stack.getItem()).getCurrentSpell(stack) == spell + && ((ISpellCastingItem)stack.getItem()).canCast(stack, spell, (EntityPlayer)caster, + EnumHand.MAIN_HAND, 0, new SpellModifiers())){ + return true; } } + + }else if(caster instanceof ISpellCaster){ + if(((ISpellCaster)caster).getContinuousSpell() == spell) return true; } - // If the ray trace hit an entity, return that entity; otherwise return the result of the block ray trace. - if(closestHitEntity != null){ - result = new RayTraceResult(closestHitEntity, closestHitPosition); - } - - return result; + return false; } - // SECTION NBT and Data Storage + /** + * Returns whether the given {@link DamageSource} is melee damage. This method makes a best guess as to whether + * the damage was from a melee attack; there is no way of testing this properly. + * @param source The damage source to be tested. + * @return True if the given damage source is melee damage, false otherwise. + */ + public static boolean isMeleeDamage(DamageSource source){ + + // With the exception of minions, melee damage always has the same entity for immediate/true source + if(!(source instanceof MinionDamage) && source.getImmediateSource() != source.getTrueSource()) return false; + if(source.isProjectile()) return false; // Projectile damage obviously isn't melee damage + if(source.isUnblockable()) return false; // Melee damage should always be blockable + if(!(source instanceof MinionDamage) && source instanceof IElementalDamage) return false; + if(!(source.getTrueSource() instanceof EntityLivingBase)) return false; // Only living things can melee! + + if(source.getTrueSource() instanceof EntityPlayer && source.getDamageLocation() != null + && source.getDamageLocation().distanceTo(source.getTrueSource().getPositionVector()) > ((EntityLivingBase)source + .getTrueSource()).getEntityAttribute(EntityPlayer.REACH_DISTANCE).getAttributeValue()){ + return false; // Out of melee reach for players + } + + // If it got through all that, chances are it's melee damage + return true; + } + + // Miscellaneous // =============================================================================================================== /** * Verifies that the given string is a valid string representation of a UUID. More specifically, returns true if and * only if the given string is not null and matches the regular expression: - *

    + *

    *
    /^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$/

    * which is the regex equivalent of the standard string representation of a UUID as described in * {@link UUID#toString()}. This method is intended to be used as a check to prevent an @@ -705,355 +919,24 @@ public final class WizardryUtilities { } /** - * Generic method that stores any Map to an NBTTagList, given two functions that convert the key and value types in - * that map to subclasses of NBTBase. For what it's worth, there is very little point in using this unless you can - * use something more concise than an anonymous class to do the conversion. A lambda expression, or better, a method - * reference, would fit nicely. For example, take ExtendedPlayer's use of this to store conjured item durations: - *

    - * properties.setTag("conjuredItems", WizardryUtilities.mapToNBT(this.conjuredItemDurations, - * item -> new NBTTagInt(Item.getIdFromItem((Item)item)), NBTTagInt::new)); - *

    - * This is a lot nicer than simply iterating through the map, because for that you need to use the entry list, which - * introduces local variables that aren't really necessary. Notice that, since the values V in the map are simply - * Integer objects, a simple constructor reference to NBTTagInt::new can be used instead of a lambda expression (the - * Integer is auto-unboxed to int). - * - * @param The type of key stored in the given Map. - * @param The type of value stored in the given Map. - * @param The subtype of NBTBase that the keys (of type K) will be converted to. - * @param The subtype of NBTBase that the values (of type V) will be converted to. - * @param map The Map to be stored. - * @param keyFunction A Function that converts the keys in the map to NBT objects that can be stored. - * @param valueFunction A Function that converts the values in the map to NBT objects that can be stored. - * @param keyTagName The tag name to use for the key tags. - * @param valueTagName The tag name to use for the value tags. - * @return An NBTTagList that represents the given Map. + * Flattens the given nested collection. The returned collection is an unmodifiable collection of all the elements + * contained within all of the sub-collections of the given nested collection. + * @param collection A nested collection to flatten + * @param The type of elements in the given nested collection + * @return The resulting flattened collection. */ - public static NBTTagList mapToNBT(Map map, - Function keyFunction, Function valueFunction, String keyTagName, String valueTagName){ - - NBTTagList tagList = new NBTTagList(); - - for(Entry entry : map.entrySet()){ - NBTTagCompound mapping = new NBTTagCompound(); - mapping.setTag(keyTagName, keyFunction.apply(entry.getKey())); - mapping.setTag(valueTagName, valueFunction.apply(entry.getValue())); - tagList.appendTag(mapping); - } - - return tagList; + public static Collection flatten(Collection> collection){ + Collection result = new ArrayList<>(); + collection.forEach(result::addAll); + return Collections.unmodifiableCollection(result); } - /** - * See {@link WizardryUtilities#mapToNBT(Map, Function, Function, String, String)}; this version is for when the - * names of the individual key/value tags are unimportant (they default to "key" and "value" respectively). - */ - public static NBTTagList mapToNBT(Map map, - Function keyFunction, Function valueFunction){ - return mapToNBT(map, keyFunction, valueFunction, "key", "value"); - } - - /** - * Generic method that reads a Map from an NBTTagList, given two functions that convert the key and value tag types - * into the key and value types in the returned map. The given NBTTagList remains unchanged after calling this - * method. - * - * @param The type of key stored in the returned Map. - * @param The type of value stored in the returned Map. - * @param The subtype of NBTBase that the keys are stored as. - * @param The subtype of NBTBase that the values are stored as. - * @param tagList The NBTTagList to be converted. This must be a list of compound tags. - * @param keyFunction A Function that converts the generic NBTBase tags in the list to keys of type K for the map. - * @param valueFunction A Function that converts the generic NBTBase tags in the list to values of type V for the - * map. - * @param keyTagName The tag name used for the key tags. - * @param valueTagName The tag name used for the value tags. - * @return A Map containing the keys and values stored in the given NBTTagList. Can be empty, but not null. - * @throws ClassCastException If the tags are not of the expected type. - * @see WizardryUtilities#mapToNBT(Map, Function, Function, String, String) - */ - @SuppressWarnings("unchecked") // Intentional, because throwing an exception is appropriate here. - public static Map NBTToMap(NBTTagList tagList, - Function keyFunction, Function valueFunction, String keyTagName, String valueTagName){ - - Map map = new HashMap(); - - for(int i = 0; i < tagList.tagCount(); i++){ - NBTTagCompound mapping = tagList.getCompoundTagAt(i); - NBTBase keyTag = mapping.getTag(keyTagName); - NBTBase valueTag = mapping.getTag(valueTagName); - K key = null; - try{ - key = keyFunction.apply((L)keyTag); - }catch (ClassCastException e){ - Wizardry.logger.error( - "Error when reading map from NBT: unexpected tag type " + NBTBase.NBT_TYPES[keyTag.getId()], e); - } - V value = null; - try{ - value = valueFunction.apply((W)valueTag); - }catch (ClassCastException e){ - Wizardry.logger.error( - "Error when reading map from NBT: unexpected tag type " + NBTBase.NBT_TYPES[valueTag.getId()], - e); - } - map.put(key, value); - } - - return map; - } - - /** - * See {@link WizardryUtilities#NBTToMap(NBTTagList, Function, Function, String, String)}; this version is for when - * the names of the individual key/value tags are unimportant (they default to "key" and "value" respectively). - */ - public static Map NBTToMap(NBTTagList tagList, - Function keyFunction, Function valueFunction){ - return NBTToMap(tagList, keyFunction, valueFunction, "key", "value"); - } - - /** - * Generic method that stores any Collection to an NBTTagList, given a function that converts the elements in that - * collection to subclasses of NBTBase. For what it's worth, there is very little point in using this unless you can - * use something more concise than an anonymous class to do the conversion. A lambda expression, or better, a method - * reference, would fit nicely. - * - * @param The type of element stored in the given Collection. - * @param The NBT tag type that the elements will be converted to. - * @param list The Collection to be stored. - * @param function A Function that converts the elements in the collection to NBT objects that can be stored. - * @return An NBTTagList that represents the given Collection. - */ - public static NBTTagList listToNBT(Collection list, Function function){ - - NBTTagList tagList = new NBTTagList(); - // If the collection is ordered, it will preserve the order, even though we don't know what type it is yet. - for(E element : list){ - tagList.appendTag(function.apply(element)); - } - - return tagList; - } - - /** - * Generic method that reads a Collection from an NBTTagList, given a function that converts the element tag types - * to the element types in the returned collection. The given NBTTagList remains unchanged after calling this - * method. Unless the target variable for this method is of type Collection, you will need to create a new - * collection containing the elements in the returned collection via that collection's constructor (e.g. {@code new - * HashSet(collection)}). Although this method returns a Collection rather than any of its subtypes, it uses - * an ArrayList internally to guarantee the order of the elements in the returned collection is the same as the - * order in which they were stored. As such, you may safely cast to List should you wish. - * - * @param The type of element stored in the returned Collection. - * @param The subtype of NBTBase that the elements are stored as. - * @param tagList The NBTTagList to be converted. - * @param function A Function that converts the generic NBTBase tags in the list to elements for the collection. - * Chances are you will need to cast the NBTBase tag to whichever NBT tag type you are expecting in order to - * access the appropriate getter method. - * @return A Collection containing the elements stored in the given NBTTagList. Can be empty, but not null. - * @throws ClassCastException If the tags are not of the expected type. - */ - @SuppressWarnings("unchecked") // Intentional, because throwing an exception is appropriate here. - public static Collection NBTToList(NBTTagList tagList, Function function){ - // Uses an ArrayList to guarantee iteration order, and also to permit duplicate elements (which are - // perfectly reasonable in this context). - Collection list = new ArrayList(); - // The original tag list should remain unchanged, hence the copy. - NBTTagList tagList2 = (NBTTagList)tagList.copy(); - - while(!tagList2.hasNoTags()){ - NBTBase tag = tagList2.removeTag(0); - // Why oh why is NBTTagList not parametrised? It even has a tagType field, so it must know! - try{ - list.add(function.apply((T)tag)); - }catch (ClassCastException e){ - Wizardry.logger.error( - "Error when reading list from NBT: unexpected tag type " + NBTBase.NBT_TYPES[tag.getId()], e); - } - } - - return list; - - } - - /** Removes the UUID with the given key from the given NBT tag, if any. Why this doesn't exist in vanilla I have - * no idea. */ - public static void removeUniqueId(NBTTagCompound tag, String key){ - tag.removeTag(key + "Most"); - tag.removeTag(key + "Least"); - } - - // TODO: Backport: It has recently become apparent that storing UUIDs as strings is not good practice, so backport - // these two - // methods to 1.7.10 and replace tag.setUniqueId and tag.getUniqueId with their respective contents from 1.10.2. - - /** - * Returns an NBTTagCompound which contains only the given UUID, stored using - * {@link NBTTagCompound#setUniqueId(String, UUID)}. Allows for neater storage to NBTTagLists. - */ - public static NBTTagCompound UUIDtoTagCompound(UUID id){ - NBTTagCompound tag = new NBTTagCompound(); - tag.setUniqueId("uuid", id); - return tag; - } - - /** - * Wrapper for {@link NBTTagCompound#getUniqueId(String)} which converts an NBTTagCompound directly to a UUID. - * Intended to be used as the inverse of {@link WizardryUtilities#UUIDtoTagCompound(UUID)}. - */ - public static UUID tagCompoundToUUID(NBTTagCompound tag){ - return tag.getUniqueId("uuid"); - } - - // SECTION Ally Designation System - // =============================================================================================================== - - /** - * Returns whether the given target can be attacked by the given attacker. It is up to the caller of this method to - * work out what this means; it doesn't necessarily mean the target is completely immune (for example, revenge - * targeting might reasonably bypass this). This method is intended for use where the damage is indirect and/or - * unavoidable; direct attacks should not check this method. Currently this means the following situations check - * this method: - *

    - * - AI targeting for summoned creatures
    - * - AI targeting for mind-controlled creatures
    - * - Constructs with an area of effect
    - * - Instantaneous spells with an area of effect around the caster (e.g. forest's curse, thunderstorm)
    - * - Any lightning chaining effects
    - * - Any projectiles which seek targets - *

    - * Also note that the friendly fire option is dealt with in the event handler. This method acts as a sort of wrapper - * for all the ADS stuff in {@link WizardData}; more details about the ally designation system can be found there. - * - * @param attacker The entity that cast the spell originally - * @param target The entity being attacked - * - * @return False under any of the following circumstances, true otherwise: - *

    - * - The target is null - *

    - * - The target is the attacker (this isn't as stupid as it sounds - anything with an AoE might cause this - * to be true, as can summoned creatures) - *

    - * - The target and the attacker are both players and the target is an ally of the attacker (but the - * attacker need not be an ally of the target) - *

    - * - The target is a creature that was summoned/controlled by the attacker or by an ally of the attacker. - *

    - * As of wizardry 4.1.2, this method now returns true instead of false if the attacker is null. This - * is because in the vast majority of cases, it makes more sense this way: if a construct has no caster, it - * should affect all entities; if a minion has no caster it should target all entities; etc. - */ - public static boolean isValidTarget(Entity attacker, Entity target){ - - // Always return true if the attacker is null - if(attacker == null) return true; - - // Always return false if the target is null - if(target == null) return false; - - // Tests whether the target is the attacker - if(target == attacker) return false; - - // Tests whether the target is a creature that was summoned by the attacker - if(target instanceof ISummonedCreature && ((ISummonedCreature)target).getCaster() == attacker){ - return false; - } - - // Tests whether the target is a creature that was mind controlled by the attacker - if(target instanceof EntityLiving && ((EntityLivingBase)target).isPotionActive(WizardryPotions.mind_control)){ - - NBTTagCompound entityNBT = target.getEntityData(); - - if(entityNBT != null && entityNBT.hasUniqueId(MindControl.NBT_KEY)){ - if(attacker == WizardryUtilities.getEntityByUUID(target.world, - entityNBT.getUniqueId(MindControl.NBT_KEY))){ - return false; - } - } - } - - // Ally section - if(attacker instanceof EntityPlayer && WizardData.get((EntityPlayer)attacker) != null){ - - if(target instanceof EntityPlayer){ - // Tests whether the target is an ally of the attacker - if(WizardData.get((EntityPlayer)attacker).isPlayerAlly((EntityPlayer)target)){ - return false; - } - - }else if(target instanceof ISummonedCreature){ - // Tests whether the target is a creature that was summoned by an ally of the attacker - if(((ISummonedCreature)target).getCaster() instanceof EntityPlayer && WizardData.get((EntityPlayer)attacker) - .isPlayerAlly((EntityPlayer)((ISummonedCreature)target).getCaster())){ - return false; - } - - }else if(target instanceof EntityLiving && ((EntityLivingBase)target).isPotionActive(WizardryPotions.mind_control)){ - // Tests whether the target is a creature that was mind controlled by an ally of the attacker - NBTTagCompound entityNBT = target.getEntityData(); - - if(entityNBT != null && entityNBT.hasKey(MindControl.NBT_KEY)){ - - Entity controller = WizardryUtilities.getEntityByUUID(target.world, entityNBT.getUniqueId(MindControl.NBT_KEY)); - - if(controller instanceof EntityPlayer && WizardData.get((EntityPlayer)attacker).isPlayerAlly((EntityPlayer)controller)){ - return false; - } - } - } - } - - return true; - } - - /** Helper method for testing if the second player is an ally of the first player. Makes the code neater. */ - public static boolean isPlayerAlly(EntityPlayer allyOf, EntityPlayer possibleAlly){ - - WizardData properties = WizardData.get(allyOf); - - if(properties != null && properties.isPlayerAlly(possibleAlly)) return true; - - return false; - } - - // SECTION Loot and Weighting - // =============================================================================================================== - - /** - * See {@link WizardryUtilities#getStandardWeightedRandomSpellId(Random, boolean)}. nonContinuous defaults to false. - */ - public static int getStandardWeightedRandomSpellId(Random random){ - return getStandardWeightedRandomSpellId(random, false); - } - - /** - * Helper method which gets a spell id according to the standard weighting. The tier is a weighted random value; the - * actual spell within that tier is completely random. Will not return the id of a spell which has been disabled in - * the config. This is for simple stuff like chests and drops; more complex generators like wizard trades don't use - * this method. - *

    - * For reference, the standard weighting is as follows: Basic: 60%, Apprentice: 25%, Advanced: 10%, Master: 5% - * - * @param random An instance of {@link Random} to use for RNG - * @param nonContinuous Whether the spells must be non-continuous (used for scrolls) - * @return A random spell id number - */ - public static int getStandardWeightedRandomSpellId(Random random, boolean nonContinuous){ - - Tier tier = Tier.getWeightedRandomTier(random); - - List spells = Spell.getSpells(new Spell.TierElementFilter(tier, null)); - if(nonContinuous) spells.retainAll(Spell.getSpells(Spell.nonContinuousSpells)); - - // Ensures the tier chosen actually has spells in it, and if not uses BASIC instead. - if(spells.isEmpty()){ - spells = Spell.getSpells(new Spell.TierElementFilter(Tier.BASIC, null)); - if(nonContinuous) spells.retainAll(Spell.getSpells(Spell.nonContinuousSpells)); - } - - // Finds a random spell in the list and returns its id. - return spells.get(random.nextInt(spells.size())).id(); - } + // Neat way of getting a random element from a set, wasn't needed in the end but kept here for future reference +// public static E randomElement(Collection collection, Random random){ +// if(collection.isEmpty()) throw new IndexOutOfBoundsException("The given collection must not be empty"); +// Iterator iterator = collection.iterator(); +// for(int n = random.nextInt(collection.size()); n > 0; n--) iterator.next(); +// return iterator.next(); +// } } diff --git a/src/main/java/electroblob/wizardry/worldgen/MossifierTemplateProcessor.java b/src/main/java/electroblob/wizardry/worldgen/MossifierTemplateProcessor.java new file mode 100644 index 00000000..fab35b0d --- /dev/null +++ b/src/main/java/electroblob/wizardry/worldgen/MossifierTemplateProcessor.java @@ -0,0 +1,51 @@ +package electroblob.wizardry.worldgen; + +import net.minecraft.block.BlockStoneBrick; +import net.minecraft.init.Blocks; +import net.minecraft.util.math.BlockPos; +import net.minecraft.world.World; +import net.minecraft.world.gen.structure.template.ITemplateProcessor; +import net.minecraft.world.gen.structure.template.Template; + +import javax.annotation.Nullable; + +/** Structure template processor that randomly 'mossifies' cobblestone and stone bricks in the structure. This is done + * using weighting so there is more moss at the bottom, making it look more natural. */ +// Behold, the ACME Mossifier 3000! (Patent pending) +public class MossifierTemplateProcessor implements ITemplateProcessor { + + private final float mossiness; + private final float heightWeight; + private final int groundLevel; + + /** + * Creates a new {@code MossifierTemplateProcessor} with the given parameters. + * @param mossiness The chance for each block in a given layer to be mossified. + * @param heightWeight The amount by which mossiness reduces for each subsequent level upwards. + * @param groundLevel The ground level for the structure, at which height is taken to be zero for the purposes of + * calculating mossiness. + */ + public MossifierTemplateProcessor(float mossiness, float heightWeight, int groundLevel){ + this.mossiness = mossiness; + this.heightWeight = heightWeight; + this.groundLevel = groundLevel; + } + + @Nullable + @Override + public Template.BlockInfo processBlock(World world, BlockPos pos, Template.BlockInfo info){ + + float chance = mossiness - heightWeight * (pos.getY() - groundLevel); + + if(world.rand.nextFloat() < chance){ + if(info.blockState.getBlock() == Blocks.COBBLESTONE){ + return new Template.BlockInfo(info.pos, Blocks.MOSSY_COBBLESTONE.getDefaultState(), info.tileentityData); + }else if(info.blockState.getBlock() == Blocks.STONEBRICK){ + return new Template.BlockInfo(info.pos, Blocks.STONEBRICK.getDefaultState() + .withProperty(BlockStoneBrick.VARIANT, BlockStoneBrick.EnumType.MOSSY), info.tileentityData); + } + } + + return info; + } +} diff --git a/src/main/java/electroblob/wizardry/worldgen/MultiTemplateProcessor.java b/src/main/java/electroblob/wizardry/worldgen/MultiTemplateProcessor.java new file mode 100644 index 00000000..791ba318 --- /dev/null +++ b/src/main/java/electroblob/wizardry/worldgen/MultiTemplateProcessor.java @@ -0,0 +1,39 @@ +package electroblob.wizardry.worldgen; + +import net.minecraft.util.math.BlockPos; +import net.minecraft.world.World; +import net.minecraft.world.gen.structure.template.ITemplateProcessor; +import net.minecraft.world.gen.structure.template.Template; + +import javax.annotation.Nullable; + +/** Structure template processor that allows multiple processors to be run in order. */ +public class MultiTemplateProcessor implements ITemplateProcessor { + + private final ITemplateProcessor[] processors; + private final boolean stopWhenNull; + + /** + * Creates a new {@code MultiTemplateProcessor} which applies the given processors in order. + * @param stopWhenNull True to skip any remaining processors in the sequence if one of them returns null, false to + * process them all regardless. If this is false, you should ensure all the given processors + * accept null {@link net.minecraft.world.gen.structure.template.Template.BlockInfo} arguments. + * @param processors The processors to be run, in order (i.e. the first one given will be applied first). + */ + public MultiTemplateProcessor(boolean stopWhenNull, ITemplateProcessor... processors){ + this.processors = processors; + this.stopWhenNull = stopWhenNull; + } + + @Nullable + @Override + public Template.BlockInfo processBlock(World world, BlockPos pos, Template.BlockInfo info){ + + for(ITemplateProcessor processor : processors){ + info = processor.processBlock(world, pos, info); + if(stopWhenNull && info == null) break; + } + + return info; + } +} \ No newline at end of file diff --git a/src/main/java/electroblob/wizardry/worldgen/WoodTypeTemplateProcessor.java b/src/main/java/electroblob/wizardry/worldgen/WoodTypeTemplateProcessor.java new file mode 100644 index 00000000..a900c929 --- /dev/null +++ b/src/main/java/electroblob/wizardry/worldgen/WoodTypeTemplateProcessor.java @@ -0,0 +1,90 @@ +package electroblob.wizardry.worldgen; + +import electroblob.wizardry.util.WizardryUtilities; +import net.minecraft.block.Block; +import net.minecraft.block.BlockPlanks; +import net.minecraft.block.BlockWoodSlab; +import net.minecraft.init.Blocks; +import net.minecraft.util.math.BlockPos; +import net.minecraft.world.World; +import net.minecraft.world.gen.structure.template.ITemplateProcessor; +import net.minecraft.world.gen.structure.template.Template; + +import javax.annotation.Nullable; +import java.util.EnumMap; + +/** Structure template processor that switches all wood in the structure to a certain given wood type. */ +public class WoodTypeTemplateProcessor implements ITemplateProcessor { + + private final BlockPlanks.EnumType woodType; + + private final EnumMap DOORS; + private final EnumMap STAIRS; + private final EnumMap FENCES; + private final EnumMap FENCE_GATES; + + /** + * Creates a new {@code WoodTypeTemplateProcessor} of the given type. + * @param woodType The wood type to be used. + */ + public WoodTypeTemplateProcessor(BlockPlanks.EnumType woodType){ + + this.woodType = woodType; + + DOORS = new EnumMap<>(BlockPlanks.EnumType.class); + DOORS.put(BlockPlanks.EnumType.OAK, Blocks.OAK_DOOR); + DOORS.put(BlockPlanks.EnumType.SPRUCE, Blocks.SPRUCE_DOOR); + DOORS.put(BlockPlanks.EnumType.BIRCH, Blocks.BIRCH_DOOR); + DOORS.put(BlockPlanks.EnumType.JUNGLE, Blocks.JUNGLE_DOOR); + DOORS.put(BlockPlanks.EnumType.ACACIA, Blocks.ACACIA_DOOR); + DOORS.put(BlockPlanks.EnumType.DARK_OAK, Blocks.DARK_OAK_DOOR); + + STAIRS = new EnumMap<>(BlockPlanks.EnumType.class); + STAIRS.put(BlockPlanks.EnumType.OAK, Blocks.OAK_STAIRS); + STAIRS.put(BlockPlanks.EnumType.SPRUCE, Blocks.SPRUCE_STAIRS); + STAIRS.put(BlockPlanks.EnumType.BIRCH, Blocks.BIRCH_STAIRS); + STAIRS.put(BlockPlanks.EnumType.JUNGLE, Blocks.JUNGLE_STAIRS); + STAIRS.put(BlockPlanks.EnumType.ACACIA, Blocks.ACACIA_STAIRS); + STAIRS.put(BlockPlanks.EnumType.DARK_OAK, Blocks.DARK_OAK_STAIRS); + + FENCES = new EnumMap<>(BlockPlanks.EnumType.class); + FENCES.put(BlockPlanks.EnumType.OAK, Blocks.OAK_FENCE); + FENCES.put(BlockPlanks.EnumType.SPRUCE, Blocks.SPRUCE_FENCE); + FENCES.put(BlockPlanks.EnumType.BIRCH, Blocks.BIRCH_FENCE); + FENCES.put(BlockPlanks.EnumType.JUNGLE, Blocks.JUNGLE_FENCE); + FENCES.put(BlockPlanks.EnumType.ACACIA, Blocks.ACACIA_FENCE); + FENCES.put(BlockPlanks.EnumType.DARK_OAK, Blocks.DARK_OAK_FENCE); + + FENCE_GATES = new EnumMap<>(BlockPlanks.EnumType.class); + FENCE_GATES.put(BlockPlanks.EnumType.OAK, Blocks.OAK_FENCE_GATE); + FENCE_GATES.put(BlockPlanks.EnumType.SPRUCE, Blocks.SPRUCE_FENCE_GATE); + FENCE_GATES.put(BlockPlanks.EnumType.BIRCH, Blocks.BIRCH_FENCE_GATE); + FENCE_GATES.put(BlockPlanks.EnumType.JUNGLE, Blocks.JUNGLE_FENCE_GATE); + FENCE_GATES.put(BlockPlanks.EnumType.ACACIA, Blocks.ACACIA_FENCE_GATE); + FENCE_GATES.put(BlockPlanks.EnumType.DARK_OAK, Blocks.DARK_OAK_FENCE_GATE); + } + + @Nullable + @Override + public Template.BlockInfo processBlock(World world, BlockPos pos, Template.BlockInfo info){ + + // Why do these each have their own property key? + if(info.blockState.getBlock() instanceof BlockPlanks){ + return new Template.BlockInfo(info.pos, info.blockState.withProperty(BlockPlanks.VARIANT, woodType), info.tileentityData); + }else if(info.blockState.getBlock() instanceof BlockWoodSlab){ + return new Template.BlockInfo(info.pos, info.blockState.withProperty(BlockWoodSlab.VARIANT, woodType), info.tileentityData); + // This is a mess, no wonder the flattening happened + }else if(DOORS.containsValue(info.blockState.getBlock())){ + return new Template.BlockInfo(info.pos, WizardryUtilities.copyState(DOORS.get(woodType), info.blockState), info.tileentityData); + }else if(STAIRS.containsValue(info.blockState.getBlock())){ + return new Template.BlockInfo(info.pos, WizardryUtilities.copyState(STAIRS.get(woodType), info.blockState), info.tileentityData); + }else if(FENCES.containsValue(info.blockState.getBlock())){ + return new Template.BlockInfo(info.pos, WizardryUtilities.copyState(FENCES.get(woodType), info.blockState), info.tileentityData); + }else if(FENCE_GATES.containsValue(info.blockState.getBlock())){ + return new Template.BlockInfo(info.pos, WizardryUtilities.copyState(FENCE_GATES.get(woodType), info.blockState), info.tileentityData); + } + + return info; + } + +} diff --git a/src/main/java/electroblob/wizardry/worldgen/WorldGenCrystalFlower.java b/src/main/java/electroblob/wizardry/worldgen/WorldGenCrystalFlower.java new file mode 100644 index 00000000..8de076b8 --- /dev/null +++ b/src/main/java/electroblob/wizardry/worldgen/WorldGenCrystalFlower.java @@ -0,0 +1,61 @@ +package electroblob.wizardry.worldgen; + +import com.google.common.primitives.Ints; +import electroblob.wizardry.Wizardry; +import electroblob.wizardry.registry.WizardryBlocks; +import net.minecraft.block.state.IBlockState; +import net.minecraft.util.EnumFacing; +import net.minecraft.util.math.BlockPos; +import net.minecraft.world.World; +import net.minecraft.world.chunk.IChunkProvider; +import net.minecraft.world.gen.IChunkGenerator; +import net.minecraftforge.fml.common.IWorldGenerator; + +import java.util.Random; + +public class WorldGenCrystalFlower implements IWorldGenerator { + + @Override + public void generate(Random random, int chunkX, int chunkZ, World world, IChunkGenerator chunkGenerator, IChunkProvider chunkProvider){ + + if(Ints.contains(Wizardry.settings.flowerDimensions, world.provider.getDimension())){ + this.generatePlant(WizardryBlocks.crystal_flower.getDefaultState(), world, random, 8 + chunkX * 16, 8 + chunkZ * 16, 2, 20); + } + } + + /** + * Generates the specified plant randomly throughout the world. + * + * @param state The plant block + * @param world The world + * @param random A instance of {@code Random} to use + * @param x The x coordinate of the first block in the chunk + * @param z The y coordinate of the first block in the chunk + * @param chancesToSpawn Number of chances to spawn a flower patch + * @param groupSize The number of times to try generating a flower per flower patch spawn + */ + public void generatePlant(IBlockState state, World world, Random random, int x, int z, int chancesToSpawn, int groupSize){ + + for(int i = 0; i < chancesToSpawn; i++){ + + int randPosX = x + random.nextInt(16); + int randPosY = random.nextInt(256); + int randPosZ = z + random.nextInt(16); + + for(int l = 0; l < groupSize; ++l){ + + int i1 = randPosX + random.nextInt(8) - random.nextInt(8); + int j1 = randPosY + random.nextInt(4) - random.nextInt(4); + int k1 = randPosZ + random.nextInt(8) - random.nextInt(8); + + BlockPos pos = new BlockPos(i1, j1, k1); + + if(world.isBlockLoaded(pos) && world.isAirBlock(pos) && (!world.provider.isNether() || j1 < 127) + && state.getBlock().canPlaceBlockOnSide(world, pos, EnumFacing.UP)){ + + world.setBlockState(pos, state, 2); + } + } + } + } +} diff --git a/src/main/java/electroblob/wizardry/worldgen/WorldGenCrystalOre.java b/src/main/java/electroblob/wizardry/worldgen/WorldGenCrystalOre.java new file mode 100644 index 00000000..151b3776 --- /dev/null +++ b/src/main/java/electroblob/wizardry/worldgen/WorldGenCrystalOre.java @@ -0,0 +1,61 @@ +package electroblob.wizardry.worldgen; + +import com.google.common.primitives.Ints; +import electroblob.wizardry.Wizardry; +import electroblob.wizardry.registry.WizardryBlocks; +import net.minecraft.block.state.IBlockState; +import net.minecraft.util.math.BlockPos; +import net.minecraft.world.World; +import net.minecraft.world.chunk.IChunkProvider; +import net.minecraft.world.gen.IChunkGenerator; +import net.minecraft.world.gen.feature.WorldGenMinable; +import net.minecraftforge.fml.common.IWorldGenerator; + +import java.util.Random; + +public class WorldGenCrystalOre implements IWorldGenerator { + + @Override + public void generate(Random random, int chunkX, int chunkZ, World world, IChunkGenerator chunkGenerator, IChunkProvider chunkProvider){ + + if(Ints.contains(Wizardry.settings.oreDimensions, world.provider.getDimension())){ + this.addOreSpawn(WizardryBlocks.crystal_ore.getDefaultState(), world, random, chunkX * 16, chunkZ * 16, 16, 16, 5, 7, 5, 30); + } + } + + /** + * Adds an Ore Spawn to Minecraft. Simply register all Ores to spawn with this method in your Generation method in + * your IWorldGeneration extending Class + * + * @param state The Block to spawn + * @param world The World to spawn in + * @param random A Random object for retrieving random positions within the world to spawn the Block + * @param blockXPos An int for passing the X-Coordinate for the Generation method + * @param blockZPos An int for passing the Z-Coordinate for the Generation method + * @param maxX An int for setting the maximum X-Coordinate values for spawning on the X-Axis on a Per-Chunk basis + * @param maxZ An int for setting the maximum Z-Coordinate values for spawning on the Z-Axis on a Per-Chunk basis + * @param maxVeinSize An int for setting the maximum size of a vein + * @param chancesToSpawn An int for the Number of chances available for the Block to spawn per-chunk + * @param minY An int for the minimum Y-Coordinate height at which this block may spawn + * @param maxY An int for the maximum Y-Coordinate height at which this block may spawn + **/ + public void addOreSpawn(IBlockState state, World world, Random random, int blockXPos, int blockZPos, int maxX, + int maxZ, int maxVeinSize, int chancesToSpawn, int minY, int maxY){ + // int maxPossY = minY + (maxY - 1); + assert maxY > minY : "The maximum Y must be greater than the Minimum Y"; + assert maxX > 0 && maxX <= 16 : "addOreSpawn: The Maximum X must be greater than 0 and less than 16"; + assert minY > 0 : "addOreSpawn: The Minimum Y must be greater than 0"; + assert maxY < 256 && maxY > 0 : "addOreSpawn: The Maximum Y must be less than 256 but greater than 0"; + assert maxZ > 0 && maxZ <= 16 : "addOreSpawn: The Maximum Z must be greater than 0 and less than 16"; + + int diffBtwnMinMaxY = maxY - minY; + for(int x = 0; x < chancesToSpawn; x++){ + int posX = blockXPos + random.nextInt(maxX); + int posY = minY + random.nextInt(diffBtwnMinMaxY); + int posZ = blockZPos + random.nextInt(maxZ); + // N.B. This method applies the anti-cascading-lag offset itself + (new WorldGenMinable(state, maxVeinSize)).generate(world, random, new BlockPos(posX, posY, posZ)); + } + } + +} diff --git a/src/main/java/electroblob/wizardry/worldgen/WorldGenObelisk.java b/src/main/java/electroblob/wizardry/worldgen/WorldGenObelisk.java new file mode 100644 index 00000000..e8d6d1d2 --- /dev/null +++ b/src/main/java/electroblob/wizardry/worldgen/WorldGenObelisk.java @@ -0,0 +1,101 @@ +package electroblob.wizardry.worldgen; + +import electroblob.wizardry.Wizardry; +import electroblob.wizardry.block.BlockRunestone; +import electroblob.wizardry.constants.Element; +import electroblob.wizardry.integration.antiqueatlas.WizardryAntiqueAtlasIntegration; +import net.minecraft.init.Blocks; +import net.minecraft.tileentity.MobSpawnerBaseLogic; +import net.minecraft.tileentity.TileEntityMobSpawner; +import net.minecraft.util.Mirror; +import net.minecraft.util.ResourceLocation; +import net.minecraft.util.math.BlockPos; +import net.minecraft.world.World; +import net.minecraft.world.gen.structure.template.ITemplateProcessor; +import net.minecraft.world.gen.structure.template.PlacementSettings; +import net.minecraft.world.gen.structure.template.Template; +import org.apache.commons.lang3.ArrayUtils; + +import java.util.EnumMap; +import java.util.Map; +import java.util.Random; + +public class WorldGenObelisk extends WorldGenSurfaceStructure { + + private static final String SPAWNER_DATA_BLOCK_TAG = "spawner"; + + private static final EnumMap MOB_TYPES = new EnumMap<>(Element.class); + + static { + MOB_TYPES.put(Element.FIRE, new ResourceLocation(Wizardry.MODID, "blaze_minion")); + MOB_TYPES.put(Element.ICE, new ResourceLocation(Wizardry.MODID, "ice_wraith")); + MOB_TYPES.put(Element.LIGHTNING, new ResourceLocation(Wizardry.MODID, "lightning_wraith")); + MOB_TYPES.put(Element.NECROMANCY, new ResourceLocation(Wizardry.MODID, "wither_skeleton_minion")); + MOB_TYPES.put(Element.EARTH, new ResourceLocation(Wizardry.MODID, "spider_minion")); + MOB_TYPES.put(Element.SORCERY, new ResourceLocation(Wizardry.MODID, "vex_minion")); + MOB_TYPES.put(Element.HEALING, new ResourceLocation(Wizardry.MODID, "husk_minion")); + } + + @Override + public String getStructureName(){ + return "obelisk"; + } + + @Override + public long getRandomSeedModifier(){ + return 19348242L; + } + + @Override + public Mirror[] getValidMirrors(){ + return new Mirror[]{Mirror.NONE}; // It's symmetrical so there's no point mirroring it + } + + @Override + public boolean canGenerate(Random random, World world, int chunkX, int chunkZ){ + return ArrayUtils.contains(Wizardry.settings.obeliskDimensions, world.provider.getDimension()) + && Wizardry.settings.obeliskRarity > 0 && random.nextInt(Wizardry.settings.obeliskRarity) == 0; + } + + @Override + public ResourceLocation getStructureFile(Random random){ + return Wizardry.settings.obeliskFiles[random.nextInt(Wizardry.settings.obeliskFiles.length)]; + } + + @Override + public void spawnStructure(Random random, World world, BlockPos origin, Template template, PlacementSettings settings, ResourceLocation structureFile){ + + final Element element = Element.values()[1 + random.nextInt(Element.values().length-1)]; + + ITemplateProcessor processor = (w, p, i) -> i.blockState.getBlock() instanceof BlockRunestone ? new Template.BlockInfo( + i.pos, i.blockState.withProperty(BlockRunestone.ELEMENT, element), i.tileentityData) : i; + + template.addBlocksToWorld(world, origin, processor, settings, 2); + + WizardryAntiqueAtlasIntegration.markObelisk(world, origin.getX(), origin.getZ()); + + // Mob spawner + Map dataBlocks = template.getDataBlocks(origin, settings); + + for(Map.Entry entry : dataBlocks.entrySet()){ + + if(entry.getValue().equals(SPAWNER_DATA_BLOCK_TAG)){ + + world.setBlockState(entry.getKey(), Blocks.MOB_SPAWNER.getDefaultState()); + + if(world.getTileEntity(entry.getKey()) instanceof TileEntityMobSpawner){ + + MobSpawnerBaseLogic spawnerLogic = ((TileEntityMobSpawner)world.getTileEntity(entry.getKey())).getSpawnerBaseLogic(); + spawnerLogic.setEntityId(MOB_TYPES.get(element)); + + }else{ + Wizardry.logger.info("Tried to set the mob spawned by an obelisk, but the expected TileEntityMobSpawner was not present"); + } + + }else{ + // This probably shouldn't happen... + Wizardry.logger.info("Unrecognised data block value {} in structure {}", entry.getValue(), structureFile); + } + } + } +} diff --git a/src/main/java/electroblob/wizardry/worldgen/WorldGenShrine.java b/src/main/java/electroblob/wizardry/worldgen/WorldGenShrine.java new file mode 100644 index 00000000..076a811d --- /dev/null +++ b/src/main/java/electroblob/wizardry/worldgen/WorldGenShrine.java @@ -0,0 +1,95 @@ +package electroblob.wizardry.worldgen; + +import electroblob.wizardry.Wizardry; +import electroblob.wizardry.block.BlockPedestal; +import electroblob.wizardry.block.BlockRunestone; +import electroblob.wizardry.constants.Element; +import electroblob.wizardry.integration.antiqueatlas.WizardryAntiqueAtlasIntegration; +import electroblob.wizardry.registry.WizardryBlocks; +import electroblob.wizardry.spell.ArcaneLock; +import electroblob.wizardry.tileentity.TileEntityShrineCore; +import net.minecraft.tileentity.TileEntity; +import net.minecraft.util.ResourceLocation; +import net.minecraft.util.math.BlockPos; +import net.minecraft.world.World; +import net.minecraft.world.gen.structure.template.ITemplateProcessor; +import net.minecraft.world.gen.structure.template.PlacementSettings; +import net.minecraft.world.gen.structure.template.Template; +import org.apache.commons.lang3.ArrayUtils; + +import java.util.Map; +import java.util.Random; +import java.util.UUID; + +public class WorldGenShrine extends WorldGenSurfaceStructure { + + private static final String CORE_DATA_BLOCK_TAG = "core"; + + @Override + public String getStructureName(){ + return "shrine"; + } + + @Override + public long getRandomSeedModifier(){ + return 17502749L; + } + + @Override + public boolean canGenerate(Random random, World world, int chunkX, int chunkZ){ + return ArrayUtils.contains(Wizardry.settings.shrineDimensions, world.provider.getDimension()) + && Wizardry.settings.shrineRarity > 0 && random.nextInt(Wizardry.settings.shrineRarity) == 0; + } + + @Override + public ResourceLocation getStructureFile(Random random){ + return Wizardry.settings.shrineFiles[random.nextInt(Wizardry.settings.shrineFiles.length)]; + } + + @Override + public void spawnStructure(Random random, World world, BlockPos origin, Template template, PlacementSettings settings, ResourceLocation structureFile){ + + final Element element = Element.values()[1 + random.nextInt(Element.values().length-1)]; + + ITemplateProcessor processor = (w, p, i) -> i.blockState.getBlock() instanceof BlockRunestone ? new Template.BlockInfo( + i.pos, i.blockState.withProperty(BlockRunestone.ELEMENT, element), i.tileentityData) : i; + + template.addBlocksToWorld(world, origin, processor, settings, 2); + + WizardryAntiqueAtlasIntegration.markShrine(world, origin.getX(), origin.getZ()); + + // Shrine core + Map dataBlocks = template.getDataBlocks(origin, settings); + + for(Map.Entry entry : dataBlocks.entrySet()){ + + if(entry.getValue().equals(CORE_DATA_BLOCK_TAG)){ + // This bit could have been done with a template processor, but we also need to link the chest and lock it + world.setBlockState(entry.getKey(), WizardryBlocks.runestone_pedestal.getDefaultState() + .withProperty(BlockPedestal.ELEMENT, element).withProperty(BlockPedestal.NATURAL, true)); + + TileEntity core = world.getTileEntity(entry.getKey()); + TileEntity container = world.getTileEntity(entry.getKey().up()); + + if(container != null){ + + container.getTileData().setUniqueId(ArcaneLock.NBT_KEY, new UUID(0, 0)); // Nil UUID + + if(core instanceof TileEntityShrineCore){ + ((TileEntityShrineCore)core).linkContainer(container); + }else{ + Wizardry.logger.info("What?!"); + } + + }else{ + Wizardry.logger.info("Expected chest or other container at {} in structure {}, found no tile entity", entry.getKey(), structureFile); + } + + }else{ + // This probably shouldn't happen... + Wizardry.logger.info("Unrecognised data block value {} in structure {}", entry.getValue(), structureFile); + } + } + } + +} diff --git a/src/main/java/electroblob/wizardry/worldgen/WorldGenSurfaceStructure.java b/src/main/java/electroblob/wizardry/worldgen/WorldGenSurfaceStructure.java new file mode 100644 index 00000000..a2b58c31 --- /dev/null +++ b/src/main/java/electroblob/wizardry/worldgen/WorldGenSurfaceStructure.java @@ -0,0 +1,450 @@ +package electroblob.wizardry.worldgen; + +import com.google.common.math.Quantiles; +import electroblob.wizardry.Wizardry; +import electroblob.wizardry.registry.WizardryAdvancementTriggers; +import electroblob.wizardry.util.WizardryUtilities; +import it.unimi.dsi.fastutil.longs.Long2ObjectMap; +import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap; +import net.minecraft.block.Block; +import net.minecraft.block.BlockLeaves; +import net.minecraft.block.BlockLog; +import net.minecraft.entity.Entity; +import net.minecraft.entity.item.EntityItem; +import net.minecraft.entity.player.EntityPlayerMP; +import net.minecraft.init.Blocks; +import net.minecraft.nbt.NBTBase; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.util.EnumFacing; +import net.minecraft.util.Mirror; +import net.minecraft.util.ResourceLocation; +import net.minecraft.util.Rotation; +import net.minecraft.util.math.*; +import net.minecraft.world.World; +import net.minecraft.world.chunk.IChunkProvider; +import net.minecraft.world.gen.IChunkGenerator; +import net.minecraft.world.gen.structure.MapGenStructureData; +import net.minecraft.world.gen.structure.StructureBoundingBox; +import net.minecraft.world.gen.structure.template.PlacementSettings; +import net.minecraft.world.gen.structure.template.Template; +import net.minecraftforge.common.BiomeDictionary; +import net.minecraftforge.common.util.Constants; +import net.minecraftforge.fml.common.IWorldGenerator; +import net.minecraftforge.fml.common.Mod; +import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; +import net.minecraftforge.fml.common.gameevent.TickEvent; + +import javax.annotation.Nullable; +import java.util.*; + +/** Base structure generation class which handles code common to all wizardry's above-ground structures, such as + * calculating the median ground level. */ +@Mod.EventBusSubscriber +public abstract class WorldGenSurfaceStructure implements IWorldGenerator { + + /** The maximum fraction of the area where a structure is to be spawned that may be covered by liquid. */ + private static final float MAX_LIQUID_FRACTION = 0.4f; + + /** Static map used to store all structure generators for the purpose of advancements. */ + private static final Map generators = new HashMap<>(); + + /** A random instance used solely for the purpose of emulating the world generation to predict locations. */ + private final Random random; + + private World world; + + private MapGenStructureData structureData; + + /** Stores the bounding boxes of all structures of this type that have been generated so far. */ + protected final Long2ObjectMap structureMap = new Long2ObjectOpenHashMap<>(1024); + + public WorldGenSurfaceStructure(){ + random = new Random(); // Seed will be set later + generators.put(this.getStructureName(), this); + } + + /** Returns a constant (but unique) long value used to change the random seed so that each generator produces a + * different sequence of numbers. Without this, all wizardry's generators attempt to generate in the same chunks + * when set to the same rarity. */ + public abstract long getRandomSeedModifier(); + + /** Pre-check for whether the structure can generate. Usually this is just used for randomisation so that + * calculations are only performed for chunks that will generate a structure; most placement-specific stuff + * can just be done using a check inside {@link WorldGenSurfaceStructure#spawnStructure(Random, World, BlockPos, Template, PlacementSettings, ResourceLocation)} */ + public abstract boolean canGenerate(Random random, World world, int chunkX, int chunkZ); + + /** Called each time the structure is generated to get a structure file to use. */ + public abstract ResourceLocation getStructureFile(Random random); + + /** Returns the name of this structure type, which is used as an identifier in the world save file and for + * advancement JSON files. */ + public abstract String getStructureName(); + + /** + * Spawns the structure at the given origin with the given placement settings. + * @param random A {@code Random} instance to use for any further parameters that need randomising. + * @param world The world to spawn the structure in. + * @param origin The origin coordinates of the structure in the world, pre-adjusted for floor height and rotation + * to avoid floating structures and minimise cascading worldgen lag. + * @param template The template to be generated. + * @param settings The placement settings for the structure. + * @param structureFile The location of the chosen structure file, for logging purposes. + */ + public abstract void spawnStructure(Random random, World world, BlockPos origin, Template template, PlacementSettings settings, ResourceLocation structureFile); + + /** Specifies valid rotation values for the structure. By default this returns all rotations. */ + public Rotation[] getValidRotations(){ + return Rotation.values(); + } + + /** Specifies valid rotation values for the structure. By default this returns an array of {@code Mirror.LEFT_RIGHT} + * and {@code Mirror.NONE}. */ + public Mirror[] getValidMirrors(){ + return new Mirror[]{Mirror.NONE, Mirror.LEFT_RIGHT}; + } + + /** + * Finds a random position within the given chunk at which the given template may be generated. + * In an effort to make structure rarity more uniform, they now get a number of tries to spawn in each + * randomly-selected chunk so they have a better chance of avoiding stuff that might be in the way (cliffs, + * villages, lakes, etc.). + *

    + * This method calculates the median floor height to ensure that sudden changes in level are ignored and the + * structure is always spawned at the same level as the majority of the underlying floor. Trees are also ignored + * when determining floor level, so that forests don't impede structure spawning. + * + * @param template The template to be generated + * @param settings The placement settings for the structure template + * @param random A random instance to use. This should have had its seed set according to the world seed and chunk + * coordinates. + * @param world The world in which to spawn the structure + * @param chunkX The x-coordinate of the chunk being populated + * @param chunkZ The z-coordinate of the chunk being populated + * @return The coordinates of the position found, or null if no suitable position was found. The returned + * {@code BlockPos} is always the northwest corner of the structure, and the y-coordinate is that of the + * uppermost block at those (x, z) coordinates. If the structure is being rotated this needs to be altered using + * {@link Template#getZeroPositionWithTransform(BlockPos, Mirror, Rotation)} before it can be fed into the template + * spawning methods. + */ + @Nullable + protected BlockPos findValidPosition(Template template, PlacementSettings settings, Random random, World world, + int chunkX, int chunkZ){ + + // Offset by (8, 8) to minimise cascading worldgen lag + // See https://www.reddit.com/r/feedthebeast/cowmments/5x0twz/investigating_extreme_worldgen_lag/?ref=share&ref_source=embed&utm_content=title&utm_medium=post_embed&utm_name=c07cbb545f74487793783012794733d8&utm_source=embedly&utm_term=5x0twz + // Multiplying and left-shifting are identical but it's good practice to bitshift here I guess + BlockPos origin = new BlockPos(8 + (chunkX << 4) + random.nextInt(16), 0, 8 + (chunkZ << 4) + random.nextInt(16)); + + BlockPos size = template.transformedSize(settings.getRotation()); + // Estimate a starting height for searching for the floor + BlockPos centre = world.getTopSolidOrLiquidBlock(new BlockPos(origin.add(size.getX()/2, 0, size.getZ()/2))); + Integer startingHeight = WizardryUtilities.getNearestSurface(world, centre, EnumFacing.UP, 32, true, + WizardryUtilities.SurfaceCriteria.COLLIDABLE_IGNORING_TREES); + + if(startingHeight == null) return null; + + if(Wizardry.settings.fastWorldgen){ + BlockPos result = origin.up(startingHeight); + // Fast worldgen doesn't check for water, instead it checks the biome like vanilla, which is crude but fast + return BiomeDictionary.hasType(world.getBiome(result), BiomeDictionary.Type.WATER) ? null : result; + } + + int[] floorHeights = new int[size.getX() * size.getZ()]; + + int liquidCount = 0; + + for(int i = 0; i < floorHeights.length; i++){ + // Despite what its name suggests, this method does not return the position of a liquid. It is in fact + // exactly what is needed here since it is used for placing villages and stuff, and doesn't include leaves + // or other foliage. + BlockPos pos = origin.add(i / size.getZ(), 0, i % size.getZ()); + Integer floor = WizardryUtilities.getNearestSurface(world, pos.up(startingHeight), EnumFacing.UP, 32, true, + WizardryUtilities.SurfaceCriteria.COLLIDABLE_IGNORING_TREES); + floorHeights[i] = floor == null ? 0 : floor; // Very unlikely that floor is null + // ^ That method gets the top solid block. Most non-solid blocks are ok to have around the structure, + // with the exception of liquids, so if there are too many the position is deemed unsuitable. + if(world.getBlockState(pos.up(floorHeights[i])).getMaterial().isLiquid()) liquidCount++; + if(liquidCount > floorHeights.length * MAX_LIQUID_FRACTION) return null; + } + + // Get the median floor height (rather than the mean, that way cliffs should have no effect) + int medianFloorHeight = MathHelper.floor(Quantiles.median().compute(floorHeights)); + + // Now we know the y level of the base of the structure, we can check for stuff in the way + // A structure is deemed to have stuff in the way if the floor level at any of the (x, z) positions it + // occupies differs from the base y level by more than its distance from the centre plus a constant. + // In practical terms, this means structures can't spawn on steep slopes or inside cave mouths or buildings. + + for(int i = 0; i < floorHeights.length; i++){ + int orthogonalDist = Math.max(Math.abs(i / size.getZ() - size.getX()/2), Math.abs(i % size.getZ() - size.getZ()/2)); + if(Math.abs(floorHeights[i] - medianFloorHeight) > Math.max(2, orthogonalDist)) return null; // Something is in the way + } + + return origin.up(medianFloorHeight - 1); + } + + @Override + public void generate(Random random, int chunkX, int chunkZ, World world, IChunkGenerator chunkGenerator, IChunkProvider chunkProvider){ + + if(!world.getWorldInfo().isMapFeaturesEnabled()) return; + + // Don't need to worry about overflows because they'll just wrap around, which is fine for this purpose + random.setSeed(random.nextLong() + getRandomSeedModifier()); + + initializeStructureData(world); // Load the data from the save file if it isn't already loaded + + if(canGenerate(random, world, chunkX, chunkZ)){ + + ResourceLocation structureFile = getStructureFile(random); + + Template template = world.getSaveHandler().getStructureTemplateManager().getTemplate( + world.getMinecraftServer(), structureFile); + + Rotation[] rotations = getValidRotations(); + Mirror[] mirrors = getValidMirrors(); + + PlacementSettings settings = new PlacementSettings() + .setRotation(rotations[random.nextInt(rotations.length)]) + .setMirror(mirrors[random.nextInt(mirrors.length)]); + + int triesLeft = 10; + + BlockPos origin; + + do { + origin = findValidPosition(template, settings, random, world, chunkX, chunkZ); + triesLeft--; + }while(triesLeft > 0 && origin != null); + + if(origin == null) return; + + // Need to subtract 1 from each coordinate since both corners are inclusive + StructureBoundingBox box = new StructureBoundingBox(origin, origin.add(template.transformedSize(settings.getRotation())).add(-1, -1, -1)); + + // DEBUG +// world.setBlockState(new BlockPos(box.minX, box.minY, box.minZ), Blocks.CONCRETE.getDefaultState().withProperty(BlockColored.COLOR, EnumDyeColor.MAGENTA)); +// world.setBlockState(new BlockPos(box.maxX, box.maxY, box.maxZ), Blocks.CONCRETE.getDefaultState().withProperty(BlockColored.COLOR, EnumDyeColor.MAGENTA)); + + if(!Wizardry.settings.fastWorldgen){ + for(WorldGenSurfaceStructure generator : generators.values()){ + StructureBoundingBox otherbox = generator.structureMap.get(ChunkPos.asLong(origin.getX() >> 4, origin.getZ() >> 4)); + if(otherbox != null && otherbox.intersectsWith(box)) return; + } + } + + settings.setBoundingBox(box); + + // PlacementSettings rotates and mirrors the structure around the origin, keeping the origin in the same + // place in the world. This means the structure can be rotated/mirrored into the 8 block border, undoing all + // our hard work to try and prevent cascading worldgen lag! + + // To properly minimise cascading worldgen lag, the method below returns the position where the corner needs + // to be such that the original structure's NW (-X, -Z) corner is at the origin. + origin = template.getZeroPositionWithTransform(origin, settings.getMirror(), settings.getRotation()); + + spawnStructure(random, world, origin, template, settings, structureFile); + + if(!Wizardry.settings.fastWorldgen) removeFloatingTrees(world, box); + + structureMap.put(ChunkPos.asLong(origin.getX() >> 4, origin.getZ() >> 4), settings.getBoundingBox()); + + NBTTagCompound tag = new NBTTagCompound(); + tag.setInteger("ChunkX", chunkX); + tag.setInteger("ChunkZ", chunkZ); + tag.setTag("BB", settings.getBoundingBox().toNBTTagIntArray()); + structureData.writeInstance(tag, chunkX, chunkZ); + structureData.markDirty(); + } + } + + /** Copied from MapGenStructure. Unlike most NBT loading, this is lazy - it only gets read from NBT when requested. */ + protected void initializeStructureData(World world){ + + // If the world that was last generated is not this world, load the data for the new world + // This is a bit of a dirty hack, it would be better if we had separate instances per-world but... effort... + // For now it works, maybe one day I'll improve it + if(world != this.world){ + + this.world = world; + + this.structureData = (MapGenStructureData)world.getPerWorldStorage().getOrLoadData(MapGenStructureData.class, this.getStructureName()); + + // This has to be cleared or worlds will interfere with each other! + // Vanilla doesn't have to do this because each world has a separate ChunkGenerator which stores MapGenBase + // instances + this.structureMap.clear(); + + if(this.structureData == null){ + + this.structureData = new MapGenStructureData(this.getStructureName()); + world.getPerWorldStorage().setData(this.getStructureName(), this.structureData); + + }else{ + + NBTTagCompound nbt = this.structureData.getTagCompound(); + + for(String s : nbt.getKeySet()){ + + NBTBase nbtbase = nbt.getTag(s); + + if(nbtbase.getId() == Constants.NBT.TAG_COMPOUND){ + + NBTTagCompound entry = (NBTTagCompound)nbtbase; + + if(entry.hasKey("ChunkX") && entry.hasKey("ChunkZ") && entry.hasKey("BB")){ + + int i = entry.getInteger("ChunkX"); + int j = entry.getInteger("ChunkZ"); + int[] coords = entry.getIntArray("BB"); + + this.structureMap.put(ChunkPos.asLong(i, j), new StructureBoundingBox(coords)); + } + } + } + } + } + } + + /** Finds and removes any floating bits of tree in and above the given structure bounding box. */ + protected static void removeFloatingTrees(World world, StructureBoundingBox boundingBox){ + + boolean changed = true; + int y = boundingBox.minY; + + // Remove all the logs + + while(changed && y < world.getHeight()){ // I do hope the trees don't reach the world height... + + // Always checks at least the first layer above the bounding box in case the structure cut the rest off + if(y > boundingBox.maxY + 1) changed = false; + + for(int x = boundingBox.minX; x <= boundingBox.maxX; x++){ + for(int z = boundingBox.minZ; z <= boundingBox.maxZ; z++){ + + BlockPos pos = new BlockPos(x, y, z); + + Block block = world.getBlockState(pos).getBlock(); + Block below = world.getBlockState(pos.down()).getBlock(); + + if(block instanceof BlockLog){ + if(below != Blocks.GRASS && below != Blocks.DIRT && !(below instanceof BlockLog) && + !below.isLeaves(world.getBlockState(pos.down()), world, pos.down())){ + world.setBlockToAir(pos); + changed = true; + } + } + } + } + + y++; + } + + // Now update all leaves in the area 16 times to make them decay + + int border = 8; + + List leaves = new ArrayList<>(); + + for(int x = boundingBox.minX - border; x <= boundingBox.maxX + border; x++){ + for(int y1 = boundingBox.minY - border; y1 <= y + border; y1++){ + for(int z = boundingBox.minZ - border; z <= boundingBox.maxZ + border; z++){ + BlockPos pos = new BlockPos(x, y1, z); + if(world.getBlockState(pos).getBlock() instanceof BlockLeaves) leaves.add(pos); + } + } + } + + for(int i=0; i<16; i++){ + leaves.forEach(p -> world.getBlockState(p).getBlock().updateTick(world, p, world.getBlockState(p), null)); + } + + // Finally, remove all the items that were dropped as a result of leaf decay + + AxisAlignedBB box = new AxisAlignedBB(boundingBox.minX, boundingBox.minY, boundingBox.minZ, boundingBox.maxX, y, boundingBox.maxZ).grow(border); + + world.getEntitiesWithinAABB(EntityItem.class, box).forEach(Entity::setDead); + + } + + /** Returns true if the given position is within a structure of this type in the given world, false + * otherwise. This will not work on chunks that are yet to be generated; attempting to do so will print a + * warning to the console. */ + public boolean isInsideStructure(World world, double x, double y, double z){ + + initializeStructureData(world); // Load the data from the save file if it isn't already loaded + + int chunkX = (int)x >> 4; + int chunkZ = (int)z >> 4; + + if(!world.isChunkGeneratedAt(chunkX, chunkZ)){ + Wizardry.logger.warn("Testing whether position ({}, {}, {}) is inside a structure, but that chunk hasn't been generated yet", x, y, z); + return false; + } + + // Vanilla just iterates through the entire structure map, but we can be a little more intelligent + // about it by only testing the chunks near the player (since all the structures are smaller than 32x32) + long[] chunks = {ChunkPos.asLong(chunkX - 1, chunkZ - 1), ChunkPos.asLong(chunkX - 1, chunkZ), ChunkPos.asLong(chunkX - 1, chunkZ + 1), + ChunkPos.asLong(chunkX, chunkZ - 1), ChunkPos.asLong(chunkX, chunkZ), ChunkPos.asLong(chunkX, chunkZ + 1), + ChunkPos.asLong(chunkX + 1, chunkZ - 1), ChunkPos.asLong(chunkX + 1, chunkZ), ChunkPos.asLong(chunkX + 1, chunkZ + 1)}; + + for(long chunkPos : chunks){ + if(structureMap.containsKey(chunkPos) && structureMap.get(chunkPos).isVecInside(new Vec3i(x, y, z))) + return true; + } + + return false; + } + + /** Copied from MapGenMineshaft. The general idea (it seems) is to emulate the world generator's randomisation + * without actually placing any blocks. Presumably mineshafts don't need sub-chunk randomisation? */ + public BlockPos getNearestStructurePos(World world, BlockPos pos, boolean findUnexplored){ + + // TODO: We have a problem here, in that the 'pragmatic' placement algorithm (good as it is) requires + // the chunk to have already been generated, so we can't be sure if a structure actually exists until + // the chunk is actually generated. + + int j = pos.getX() >> 4; + int k = pos.getZ() >> 4; + + for (int l = 0; l <= 1000; ++l) + { + for (int i1 = -l; i1 <= l; ++i1) + { + boolean flag = i1 == -l || i1 == l; + + for (int j1 = -l; j1 <= l; ++j1) + { + boolean flag1 = j1 == -l || j1 == l; + + if (flag || flag1) + { + // TESTME: Is this the same as Forge's per-chunk seeds? (see caller of generate()) + int k1 = j + i1; + int l1 = k + j1; + this.random.setSeed((long)(k1 ^ l1) ^ world.getSeed()); + this.random.nextInt(); + + if(this.canGenerate(this.random, world, k1, l1) && (!findUnexplored || !world.isChunkGeneratedAt(k1, l1))){ + return new BlockPos((k1 << 4) + 8, 64, (l1 << 4) + 8); + } + } + } + } + } + + return null; + } + + /** Returns the world generator with the given name. */ + public static WorldGenSurfaceStructure byName(String name){ + return generators.get(name); + } + + @SubscribeEvent + public static void onPlayerTick(TickEvent.PlayerTickEvent event){ + if(event.player instanceof EntityPlayerMP && event.player.ticksExisted % 20 == 0){ + WizardryAdvancementTriggers.visit_structure.trigger((EntityPlayerMP)event.player); + } + } + +} diff --git a/src/main/java/electroblob/wizardry/worldgen/WorldGenWizardTower.java b/src/main/java/electroblob/wizardry/worldgen/WorldGenWizardTower.java new file mode 100644 index 00000000..64882da9 --- /dev/null +++ b/src/main/java/electroblob/wizardry/worldgen/WorldGenWizardTower.java @@ -0,0 +1,165 @@ +package electroblob.wizardry.worldgen; + +import com.google.common.collect.ImmutableMap; +import electroblob.wizardry.Wizardry; +import electroblob.wizardry.entity.living.EntityEvilWizard; +import electroblob.wizardry.entity.living.EntityWizard; +import electroblob.wizardry.integration.antiqueatlas.WizardryAntiqueAtlasIntegration; +import electroblob.wizardry.util.WizardryUtilities; +import net.minecraft.block.BlockPlanks; +import net.minecraft.block.BlockStainedHardenedClay; +import net.minecraft.block.state.IBlockState; +import net.minecraft.init.Biomes; +import net.minecraft.init.Blocks; +import net.minecraft.item.EnumDyeColor; +import net.minecraft.util.ResourceLocation; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.Vec3d; +import net.minecraft.world.World; +import net.minecraft.world.biome.Biome; +import net.minecraft.world.gen.structure.template.ITemplateProcessor; +import net.minecraft.world.gen.structure.template.PlacementSettings; +import net.minecraft.world.gen.structure.template.Template; +import net.minecraftforge.common.BiomeDictionary; +import org.apache.commons.lang3.ArrayUtils; + +import java.util.HashSet; +import java.util.Map; +import java.util.Random; +import java.util.Set; + +public class WorldGenWizardTower extends WorldGenSurfaceStructure { + + // TODO: Add wizard towers to the /locate command + // This requires some careful manipulation of Random objects to replicate the positions exactly for the current + // world. See the end of ChunkGeneratorOverworld for the relevant methods. + + private static final String WIZARD_DATA_BLOCK_TAG = "wizard"; + private static final String EVIL_WIZARD_DATA_BLOCK_TAG = "evil_wizard"; + + private final Map SPECIAL_WALL_BLOCKS; + + public WorldGenWizardTower(){ + // These are initialised here because it's a convenient point after the blocks are registered + SPECIAL_WALL_BLOCKS = ImmutableMap.of( + BiomeDictionary.Type.MESA, Blocks.RED_SANDSTONE.getDefaultState(), + BiomeDictionary.Type.MOUNTAIN, Blocks.STONEBRICK.getDefaultState(), + BiomeDictionary.Type.NETHER, Blocks.NETHER_BRICK.getDefaultState(), + BiomeDictionary.Type.SANDY, Blocks.SANDSTONE.getDefaultState() + ); + } + + @Override + public String getStructureName(){ + return "wizard_tower"; + } + + @Override + public long getRandomSeedModifier(){ + return 10473957L; // Yep, I literally typed 8 digits at random + } + + @Override + public boolean canGenerate(Random random, World world, int chunkX, int chunkZ){ + return ArrayUtils.contains(Wizardry.settings.towerDimensions, world.provider.getDimension()) + && Wizardry.settings.towerRarity > 0 && random.nextInt(Wizardry.settings.towerRarity) == 0; + } + + @Override + public ResourceLocation getStructureFile(Random random){ + return random.nextDouble() < Wizardry.settings.evilWizardChance ? + Wizardry.settings.towerWithChestFiles[random.nextInt(Wizardry.settings.towerWithChestFiles.length)] : + Wizardry.settings.towerFiles[random.nextInt(Wizardry.settings.towerFiles.length)]; + } + + @Override + public void spawnStructure(Random random, World world, BlockPos origin, Template template, PlacementSettings settings, ResourceLocation structureFile){ + + final EnumDyeColor colour = EnumDyeColor.values()[random.nextInt(EnumDyeColor.values().length)]; + final Biome biome = world.getBiome(origin); + + final IBlockState wallMaterial = SPECIAL_WALL_BLOCKS.keySet().stream().filter(t -> BiomeDictionary.hasType(biome, t)) + .findFirst().map(SPECIAL_WALL_BLOCKS::get).orElse(Blocks.COBBLESTONE.getDefaultState()); + + final float mossiness = getBiomeMossiness(biome); + final BlockPlanks.EnumType woodType = getBiomeWoodVariant(biome); + + final Set blocksPlaced = new HashSet<>(); + + ITemplateProcessor processor = new MultiTemplateProcessor(true, + // Roof colour + (w, p, i) -> i.blockState.getBlock() instanceof BlockStainedHardenedClay ? new Template.BlockInfo( + i.pos, i.blockState.withProperty(BlockStainedHardenedClay.COLOR, colour), i.tileentityData) : i, + // Wall material + (w, p, i) -> i.blockState.getBlock() == Blocks.COBBLESTONE ? new Template.BlockInfo(i.pos, + wallMaterial, i.tileentityData) : i, + // Wood type + new WoodTypeTemplateProcessor(woodType), + // Mossifier + new MossifierTemplateProcessor(mossiness, 0.04f, origin.getY() + 1), + // Block recording (the process() method doesn't get called for structure voids) + (w, p, i) -> {if(i.blockState.getBlock() != Blocks.AIR) blocksPlaced.add(p); return i;} + ); + + template.addBlocksToWorld(world, origin, processor, settings, 2); + + WizardryAntiqueAtlasIntegration.markTower(world, origin.getX(), origin.getZ()); + + // Wizard spawning + Map dataBlocks = template.getDataBlocks(origin, settings); + + for(Map.Entry entry : dataBlocks.entrySet()){ + + Vec3d vec = WizardryUtilities.getCentre(entry.getKey()); + + if(entry.getValue().equals(WIZARD_DATA_BLOCK_TAG)){ + + EntityWizard wizard = new EntityWizard(world); + wizard.setLocationAndAngles(vec.x, vec.y, vec.z, 0, 0); + wizard.onInitialSpawn(world.getDifficultyForLocation(origin), null); + wizard.setTowerBlocks(blocksPlaced); + world.spawnEntity(wizard); + + }else if(entry.getValue().equals(EVIL_WIZARD_DATA_BLOCK_TAG)){ + + EntityEvilWizard wizard = new EntityEvilWizard(world); + wizard.setLocationAndAngles(vec.x, vec.y, vec.z, 0, 0); + wizard.hasStructure = true; // Stops it despawning + wizard.onInitialSpawn(world.getDifficultyForLocation(origin), null); + world.spawnEntity(wizard); + + }else{ + // This probably shouldn't happen... + Wizardry.logger.info("Unrecognised data block value {} in structure {}", entry.getValue(), structureFile); + } + } + } + + private static float getBiomeMossiness(Biome biome){ + if(BiomeDictionary.hasType(biome, BiomeDictionary.Type.DENSE)) return 0.7f; + if(BiomeDictionary.hasType(biome, BiomeDictionary.Type.JUNGLE)) return 0.7f; + if(BiomeDictionary.hasType(biome, BiomeDictionary.Type.WET)) return 0.5f; + if(BiomeDictionary.hasType(biome, BiomeDictionary.Type.SWAMP)) return 0.5f; + if(BiomeDictionary.hasType(biome, BiomeDictionary.Type.FOREST)) return 0.3f; + if(BiomeDictionary.hasType(biome, BiomeDictionary.Type.LUSH)) return 0.3f; + if(BiomeDictionary.hasType(biome, BiomeDictionary.Type.DRY)) return 0; + if(BiomeDictionary.hasType(biome, BiomeDictionary.Type.COLD)) return 0; + if(BiomeDictionary.hasType(biome, BiomeDictionary.Type.DEAD)) return 0; + if(BiomeDictionary.hasType(biome, BiomeDictionary.Type.WASTELAND)) return 0; + if(BiomeDictionary.hasType(biome, BiomeDictionary.Type.NETHER)) return 0; + return 0.1f; // Everything else (plains, etc.) has a small amount of moss + } + + private static BlockPlanks.EnumType getBiomeWoodVariant(Biome biome){ + // Unfortunately, I can't check all the wood types with the biome dictionary + if(BiomeDictionary.hasType(biome, BiomeDictionary.Type.CONIFEROUS)) return BlockPlanks.EnumType.SPRUCE; + if(biome == Biomes.BIRCH_FOREST || biome == Biomes.BIRCH_FOREST_HILLS) return BlockPlanks.EnumType.BIRCH; + if(BiomeDictionary.hasType(biome, BiomeDictionary.Type.JUNGLE)) return BlockPlanks.EnumType.JUNGLE; + if(BiomeDictionary.hasType(biome, BiomeDictionary.Type.SAVANNA)) return BlockPlanks.EnumType.ACACIA; + // Not technically a tree type, but I think it fits quite well anyway + if(BiomeDictionary.hasType(biome, BiomeDictionary.Type.SPOOKY)) return BlockPlanks.EnumType.DARK_OAK; + // Everything else is oak + return BlockPlanks.EnumType.OAK; + } + +} diff --git a/src/main/resources/assets/ebwizardry/advancements/advanced.json b/src/main/resources/assets/ebwizardry/advancements/advanced.json new file mode 100644 index 00000000..7bc58eb8 --- /dev/null +++ b/src/main/resources/assets/ebwizardry/advancements/advanced.json @@ -0,0 +1,108 @@ +{ + "display": { + "icon": { + "item": "ebwizardry:advanced_wand" + }, + "title": { + "translate": "advancement.ebwizardry:advanced" + }, + "description": { + "translate": "advancement.ebwizardry:advanced.desc" + } + }, + "parent": "ebwizardry:apprentice", + "criteria": { + "magic": { + "trigger": "minecraft:inventory_changed", + "conditions": { + "items": [ + { + "item": "ebwizardry:advanced_wand" + } + ] + } + }, + "fire": { + "trigger": "minecraft:inventory_changed", + "conditions": { + "items": [ + { + "item": "ebwizardry:advanced_fire_wand" + } + ] + } + }, + "ice": { + "trigger": "minecraft:inventory_changed", + "conditions": { + "items": [ + { + "item": "ebwizardry:advanced_ice_wand" + } + ] + } + }, + "lightning": { + "trigger": "minecraft:inventory_changed", + "conditions": { + "items": [ + { + "item": "ebwizardry:advanced_lightning_wand" + } + ] + } + }, + "necromancy": { + "trigger": "minecraft:inventory_changed", + "conditions": { + "items": [ + { + "item": "ebwizardry:advanced_necromancy_wand" + } + ] + } + }, + "earth": { + "trigger": "minecraft:inventory_changed", + "conditions": { + "items": [ + { + "item": "ebwizardry:advanced_earth_wand" + } + ] + } + }, + "sorcery": { + "trigger": "minecraft:inventory_changed", + "conditions": { + "items": [ + { + "item": "ebwizardry:advanced_sorcery_wand" + } + ] + } + }, + "healing": { + "trigger": "minecraft:inventory_changed", + "conditions": { + "items": [ + { + "item": "ebwizardry:advanced_healing_wand" + } + ] + } + } + }, + "requirements": [ + [ + "magic", + "fire", + "ice", + "lightning", + "necromancy", + "earth", + "sorcery", + "healing" + ] + ] +} \ No newline at end of file diff --git a/src/main/resources/assets/ebwizardry/advancements/all_artefacts.json b/src/main/resources/assets/ebwizardry/advancements/all_artefacts.json new file mode 100644 index 00000000..1ad658b9 --- /dev/null +++ b/src/main/resources/assets/ebwizardry/advancements/all_artefacts.json @@ -0,0 +1,647 @@ +{ + "display": { + "title": { + "translate": "advancement.ebwizardry:all_artefacts" + }, + "description": { + "translate": "advancement.ebwizardry:all_artefacts.desc" + }, + "icon": { + "item": "ebwizardry:amulet_resurrection" + }, + "frame": "challenge" + }, + "parent": "ebwizardry:artefact", + "criteria": { + "ring_condensing": { + "trigger": "minecraft:inventory_changed", + "conditions": { + "items": [ + { + "item": "ebwizardry:ring_condensing" + } + ] + } + }, + "ring_siphoning": { + "trigger": "minecraft:inventory_changed", + "conditions": { + "items": [ + { + "item": "ebwizardry:ring_siphoning" + } + ] + } + }, + "ring_battlemage": { + "trigger": "minecraft:inventory_changed", + "conditions": { + "items": [ + { + "item": "ebwizardry:ring_battlemage" + } + ] + } + }, + "ring_combustion": { + "trigger": "minecraft:inventory_changed", + "conditions": { + "items": [ + { + "item": "ebwizardry:ring_combustion" + } + ] + } + }, + "ring_fire_melee": { + "trigger": "minecraft:inventory_changed", + "conditions": { + "items": [ + { + "item": "ebwizardry:ring_fire_melee" + } + ] + } + }, + "ring_fire_biome": { + "trigger": "minecraft:inventory_changed", + "conditions": { + "items": [ + { + "item": "ebwizardry:ring_fire_biome" + } + ] + } + }, + "ring_disintegration": { + "trigger": "minecraft:inventory_changed", + "conditions": { + "items": [ + { + "item": "ebwizardry:ring_disintegration" + } + ] + } + }, + "ring_ice_melee": { + "trigger": "minecraft:inventory_changed", + "conditions": { + "items": [ + { + "item": "ebwizardry:ring_ice_melee" + } + ] + } + }, + "ring_ice_biome": { + "trigger": "minecraft:inventory_changed", + "conditions": { + "items": [ + { + "item": "ebwizardry:ring_ice_biome" + } + ] + } + }, + "ring_arcane_frost": { + "trigger": "minecraft:inventory_changed", + "conditions": { + "items": [ + { + "item": "ebwizardry:ring_arcane_frost" + } + ] + } + }, + "ring_shattering": { + "trigger": "minecraft:inventory_changed", + "conditions": { + "items": [ + { + "item": "ebwizardry:ring_shattering" + } + ] + } + }, + "ring_lightning_melee": { + "trigger": "minecraft:inventory_changed", + "conditions": { + "items": [ + { + "item": "ebwizardry:ring_lightning_melee" + } + ] + } + }, + "ring_storm": { + "trigger": "minecraft:inventory_changed", + "conditions": { + "items": [ + { + "item": "ebwizardry:ring_storm" + } + ] + } + }, + "ring_seeking": { + "trigger": "minecraft:inventory_changed", + "conditions": { + "items": [ + { + "item": "ebwizardry:ring_seeking" + } + ] + } + }, + "ring_hammer": { + "trigger": "minecraft:inventory_changed", + "conditions": { + "items": [ + { + "item": "ebwizardry:ring_hammer" + } + ] + } + }, + "ring_soulbinding": { + "trigger": "minecraft:inventory_changed", + "conditions": { + "items": [ + { + "item": "ebwizardry:ring_soulbinding" + } + ] + } + }, + "ring_leeching": { + "trigger": "minecraft:inventory_changed", + "conditions": { + "items": [ + { + "item": "ebwizardry:ring_leeching" + } + ] + } + }, + "ring_necromancy_melee": { + "trigger": "minecraft:inventory_changed", + "conditions": { + "items": [ + { + "item": "ebwizardry:ring_necromancy_melee" + } + ] + } + }, + "ring_mind_control": { + "trigger": "minecraft:inventory_changed", + "conditions": { + "items": [ + { + "item": "ebwizardry:ring_mind_control" + } + ] + } + }, + "ring_poison": { + "trigger": "minecraft:inventory_changed", + "conditions": { + "items": [ + { + "item": "ebwizardry:ring_poison" + } + ] + } + }, + "ring_earth_melee": { + "trigger": "minecraft:inventory_changed", + "conditions": { + "items": [ + { + "item": "ebwizardry:ring_earth_melee" + } + ] + } + }, + "ring_earth_biome": { + "trigger": "minecraft:inventory_changed", + "conditions": { + "items": [ + { + "item": "ebwizardry:ring_earth_biome" + } + ] + } + }, + "ring_full_moon": { + "trigger": "minecraft:inventory_changed", + "conditions": { + "items": [ + { + "item": "ebwizardry:ring_full_moon" + } + ] + } + }, + "ring_extraction": { + "trigger": "minecraft:inventory_changed", + "conditions": { + "items": [ + { + "item": "ebwizardry:ring_extraction" + } + ] + } + }, + "ring_mana_return": { + "trigger": "minecraft:inventory_changed", + "conditions": { + "items": [ + { + "item": "ebwizardry:ring_mana_return" + } + ] + } + }, + "ring_blockwrangler": { + "trigger": "minecraft:inventory_changed", + "conditions": { + "items": [ + { + "item": "ebwizardry:ring_blockwrangler" + } + ] + } + }, + "ring_conjurer": { + "trigger": "minecraft:inventory_changed", + "conditions": { + "items": [ + { + "item": "ebwizardry:ring_conjurer" + } + ] + } + }, + "ring_defender": { + "trigger": "minecraft:inventory_changed", + "conditions": { + "items": [ + { + "item": "ebwizardry:ring_defender" + } + ] + } + }, + "ring_paladin": { + "trigger": "minecraft:inventory_changed", + "conditions": { + "items": [ + { + "item": "ebwizardry:ring_paladin" + } + ] + } + }, + "ring_interdiction": { + "trigger": "minecraft:inventory_changed", + "conditions": { + "items": [ + { + "item": "ebwizardry:ring_interdiction" + } + ] + } + }, + "amulet_arcane_defence": { + "trigger": "minecraft:inventory_changed", + "conditions": { + "items": [ + { + "item": "ebwizardry:amulet_arcane_defence" + } + ] + } + }, + "amulet_warding": { + "trigger": "minecraft:inventory_changed", + "conditions": { + "items": [ + { + "item": "ebwizardry:amulet_warding" + } + ] + } + }, + "amulet_wisdom": { + "trigger": "minecraft:inventory_changed", + "conditions": { + "items": [ + { + "item": "ebwizardry:amulet_wisdom" + } + ] + } + }, + "amulet_fire_protection": { + "trigger": "minecraft:inventory_changed", + "conditions": { + "items": [ + { + "item": "ebwizardry:amulet_fire_protection" + } + ] + } + }, + "amulet_fire_cloaking": { + "trigger": "minecraft:inventory_changed", + "conditions": { + "items": [ + { + "item": "ebwizardry:amulet_fire_cloaking" + } + ] + } + }, + "amulet_ice_immunity": { + "trigger": "minecraft:inventory_changed", + "conditions": { + "items": [ + { + "item": "ebwizardry:amulet_ice_immunity" + } + ] + } + }, + "amulet_ice_protection": { + "trigger": "minecraft:inventory_changed", + "conditions": { + "items": [ + { + "item": "ebwizardry:amulet_ice_protection" + } + ] + } + }, + "amulet_potential": { + "trigger": "minecraft:inventory_changed", + "conditions": { + "items": [ + { + "item": "ebwizardry:amulet_potential" + } + ] + } + }, + "amulet_channeling": { + "trigger": "minecraft:inventory_changed", + "conditions": { + "items": [ + { + "item": "ebwizardry:amulet_channeling" + } + ] + } + }, + "amulet_lich": { + "trigger": "minecraft:inventory_changed", + "conditions": { + "items": [ + { + "item": "ebwizardry:amulet_lich" + } + ] + } + }, + "amulet_wither_immunity": { + "trigger": "minecraft:inventory_changed", + "conditions": { + "items": [ + { + "item": "ebwizardry:amulet_wither_immunity" + } + ] + } + }, + "amulet_glide": { + "trigger": "minecraft:inventory_changed", + "conditions": { + "items": [ + { + "item": "ebwizardry:amulet_glide" + } + ] + } + }, + "amulet_banishing": { + "trigger": "minecraft:inventory_changed", + "conditions": { + "items": [ + { + "item": "ebwizardry:amulet_banishing" + } + ] + } + }, + "amulet_anchoring": { + "trigger": "minecraft:inventory_changed", + "conditions": { + "items": [ + { + "item": "ebwizardry:amulet_anchoring" + } + ] + } + }, + "amulet_recovery": { + "trigger": "minecraft:inventory_changed", + "conditions": { + "items": [ + { + "item": "ebwizardry:amulet_recovery" + } + ] + } + }, + "amulet_transience": { + "trigger": "minecraft:inventory_changed", + "conditions": { + "items": [ + { + "item": "ebwizardry:amulet_transience" + } + ] + } + }, + "amulet_resurrection": { + "trigger": "minecraft:inventory_changed", + "conditions": { + "items": [ + { + "item": "ebwizardry:amulet_resurrection" + } + ] + } + }, + "amulet_auto_shield": { + "trigger": "minecraft:inventory_changed", + "conditions": { + "items": [ + { + "item": "ebwizardry:amulet_auto_shield" + } + ] + } + }, + "charm_haggler": { + "trigger": "minecraft:inventory_changed", + "conditions": { + "items": [ + { + "item": "ebwizardry:charm_haggler" + } + ] + } + }, + "charm_experience_tome": { + "trigger": "minecraft:inventory_changed", + "conditions": { + "items": [ + { + "item": "ebwizardry:charm_experience_tome" + } + ] + } + }, + "charm_auto_smelt": { + "trigger": "minecraft:inventory_changed", + "conditions": { + "items": [ + { + "item": "ebwizardry:charm_auto_smelt" + } + ] + } + }, + "charm_lava_walking": { + "trigger": "minecraft:inventory_changed", + "conditions": { + "items": [ + { + "item": "ebwizardry:charm_lava_walking" + } + ] + } + }, + "charm_storm": { + "trigger": "minecraft:inventory_changed", + "conditions": { + "items": [ + { + "item": "ebwizardry:charm_storm" + } + ] + } + }, + "charm_minion_health": { + "trigger": "minecraft:inventory_changed", + "conditions": { + "items": [ + { + "item": "ebwizardry:charm_minion_health" + } + ] + } + }, + "charm_minion_variants": { + "trigger": "minecraft:inventory_changed", + "conditions": { + "items": [ + { + "item": "ebwizardry:charm_minion_variants" + } + ] + } + }, + "charm_flight": { + "trigger": "minecraft:inventory_changed", + "conditions": { + "items": [ + { + "item": "ebwizardry:charm_flight" + } + ] + } + }, + "charm_growth": { + "trigger": "minecraft:inventory_changed", + "conditions": { + "items": [ + { + "item": "ebwizardry:charm_growth" + } + ] + } + }, + "charm_abseiling": { + "trigger": "minecraft:inventory_changed", + "conditions": { + "items": [ + { + "item": "ebwizardry:charm_abseiling" + } + ] + } + }, + "charm_silk_touch": { + "trigger": "minecraft:inventory_changed", + "conditions": { + "items": [ + { + "item": "ebwizardry:charm_silk_touch" + } + ] + } + }, + "charm_stop_time": { + "trigger": "minecraft:inventory_changed", + "conditions": { + "items": [ + { + "item": "ebwizardry:charm_stop_time" + } + ] + } + }, + "charm_light": { + "trigger": "minecraft:inventory_changed", + "conditions": { + "items": [ + { + "item": "ebwizardry:charm_light" + } + ] + } + }, + "charm_transportation": { + "trigger": "minecraft:inventory_changed", + "conditions": { + "items": [ + { + "item": "ebwizardry:charm_transportation" + } + ] + } + }, + "charm_feeding": { + "trigger": "minecraft:inventory_changed", + "conditions": { + "items": [ + { + "item": "ebwizardry:charm_feeding" + } + ] + } + } + } +} \ No newline at end of file diff --git a/src/main/resources/assets/ebwizardry/advancements/all_spells.json b/src/main/resources/assets/ebwizardry/advancements/all_spells.json index ce7c75c1..16a35949 100644 --- a/src/main/resources/assets/ebwizardry/advancements/all_spells.json +++ b/src/main/resources/assets/ebwizardry/advancements/all_spells.json @@ -1,20 +1,1393 @@ { "display": { "icon": { - "item": "ebwizardry:wizard_handbook" + "item": "ebwizardry:spell_book" }, "title": { - "translate": "advancement.wizardry:all_spells" + "translate": "advancement.ebwizardry:all_spells" }, "description": { - "translate": "advancement.wizardry:all_spells.desc" + "translate": "advancement.ebwizardry:all_spells.desc" }, - "frame": "challenge" + "frame": "challenge" }, "parent": "ebwizardry:master", "criteria": { - "criteria_0": { - "trigger": "ebwizardry:trigger_all_spells" + "agility": { + "trigger": "ebwizardry:cast_spell", + "conditions": { + "spell": { + "spell": "agility" + } + } + }, + "arc": { + "trigger": "ebwizardry:cast_spell", + "conditions": { + "spell": { + "spell": "arc" + } + } + }, + "arcane_jammer": { + "trigger": "ebwizardry:cast_spell", + "conditions": { + "spell": { + "spell": "arcane_jammer" + } + } + }, + "arcane_lock": { + "trigger": "ebwizardry:cast_spell", + "conditions": { + "spell": { + "spell": "arcane_lock" + } + } + }, + "arrow_rain": { + "trigger": "ebwizardry:cast_spell", + "conditions": { + "spell": { + "spell": "arrow_rain" + } + } + }, + "banish": { + "trigger": "ebwizardry:cast_spell", + "conditions": { + "spell": { + "spell": "banish" + } + } + }, + "black_hole": { + "trigger": "ebwizardry:cast_spell", + "conditions": { + "spell": { + "spell": "black_hole" + } + } + }, + "blink": { + "trigger": "ebwizardry:cast_spell", + "conditions": { + "spell": { + "spell": "blink" + } + } + }, + "blizzard": { + "trigger": "ebwizardry:cast_spell", + "conditions": { + "spell": { + "spell": "blizzard" + } + } + }, + "bubble": { + "trigger": "ebwizardry:cast_spell", + "conditions": { + "spell": { + "spell": "bubble" + } + } + }, + "chain_lightning": { + "trigger": "ebwizardry:cast_spell", + "conditions": { + "spell": { + "spell": "chain_lightning" + } + } + }, + "charge": { + "trigger": "ebwizardry:cast_spell", + "conditions": { + "spell": { + "spell": "charge" + } + } + }, + "clairvoyance": { + "trigger": "ebwizardry:cast_spell", + "conditions": { + "spell": { + "spell": "clairvoyance" + } + } + }, + "cobwebs": { + "trigger": "ebwizardry:cast_spell", + "conditions": { + "spell": { + "spell": "cobwebs" + } + } + }, + "combustion_rune": { + "trigger": "ebwizardry:cast_spell", + "conditions": { + "spell": { + "spell": "combustion_rune" + } + } + }, + "conjure_armour": { + "trigger": "ebwizardry:cast_spell", + "conditions": { + "spell": { + "spell": "conjure_armour" + } + } + }, + "conjure_block": { + "trigger": "ebwizardry:cast_spell", + "conditions": { + "spell": { + "spell": "conjure_block" + } + } + }, + "conjure_bow": { + "trigger": "ebwizardry:cast_spell", + "conditions": { + "spell": { + "spell": "conjure_bow" + } + } + }, + "conjure_pickaxe": { + "trigger": "ebwizardry:cast_spell", + "conditions": { + "spell": { + "spell": "conjure_pickaxe" + } + } + }, + "conjure_sword": { + "trigger": "ebwizardry:cast_spell", + "conditions": { + "spell": { + "spell": "conjure_sword" + } + } + }, + "containment": { + "trigger": "ebwizardry:cast_spell", + "conditions": { + "spell": { + "spell": "containment" + } + } + }, + "cure_effects": { + "trigger": "ebwizardry:cast_spell", + "conditions": { + "spell": { + "spell": "cure_effects" + } + } + }, + "curse_of_enfeeblement": { + "trigger": "ebwizardry:cast_spell", + "conditions": { + "spell": { + "spell": "curse_of_enfeeblement" + } + } + }, + "curse_of_soulbinding": { + "trigger": "ebwizardry:cast_spell", + "conditions": { + "spell": { + "spell": "curse_of_soulbinding" + } + } + }, + "curse_of_undeath": { + "trigger": "ebwizardry:cast_spell", + "conditions": { + "spell": { + "spell": "curse_of_undeath" + } + } + }, + "darkness_orb": { + "trigger": "ebwizardry:cast_spell", + "conditions": { + "spell": { + "spell": "darkness_orb" + } + } + }, + "darkvision": { + "trigger": "ebwizardry:cast_spell", + "conditions": { + "spell": { + "spell": "darkvision" + } + } + }, + "dart": { + "trigger": "ebwizardry:cast_spell", + "conditions": { + "spell": { + "spell": "dart" + } + } + }, + "decay": { + "trigger": "ebwizardry:cast_spell", + "conditions": { + "spell": { + "spell": "decay" + } + } + }, + "decoy": { + "trigger": "ebwizardry:cast_spell", + "conditions": { + "spell": { + "spell": "decoy" + } + } + }, + "detonate": { + "trigger": "ebwizardry:cast_spell", + "conditions": { + "spell": { + "spell": "detonate" + } + } + }, + "diamondflesh": { + "trigger": "ebwizardry:cast_spell", + "conditions": { + "spell": { + "spell": "diamondflesh" + } + } + }, + "disintegration": { + "trigger": "ebwizardry:cast_spell", + "conditions": { + "spell": { + "spell": "disintegration" + } + } + }, + "divination": { + "trigger": "ebwizardry:cast_spell", + "conditions": { + "spell": { + "spell": "divination" + } + } + }, + "dragon_fireball": { + "trigger": "ebwizardry:cast_spell", + "conditions": { + "spell": { + "spell": "dragon_fireball" + } + } + }, + "earthquake": { + "trigger": "ebwizardry:cast_spell", + "conditions": { + "spell": { + "spell": "earthquake" + } + } + }, + "empowering_presence": { + "trigger": "ebwizardry:cast_spell", + "conditions": { + "spell": { + "spell": "empowering_presence" + } + } + }, + "entrapment": { + "trigger": "ebwizardry:cast_spell", + "conditions": { + "spell": { + "spell": "entrapment" + } + } + }, + "evade": { + "trigger": "ebwizardry:cast_spell", + "conditions": { + "spell": { + "spell": "evade" + } + } + }, + "fireball": { + "trigger": "ebwizardry:cast_spell", + "conditions": { + "spell": { + "spell": "fireball" + } + } + }, + "firebolt": { + "trigger": "ebwizardry:cast_spell", + "conditions": { + "spell": { + "spell": "firebolt" + } + } + }, + "firebomb": { + "trigger": "ebwizardry:cast_spell", + "conditions": { + "spell": { + "spell": "firebomb" + } + } + }, + "fire_resistance": { + "trigger": "ebwizardry:cast_spell", + "conditions": { + "spell": { + "spell": "fire_resistance" + } + } + }, + "fire_sigil": { + "trigger": "ebwizardry:cast_spell", + "conditions": { + "spell": { + "spell": "fire_sigil" + } + } + }, + "fireskin": { + "trigger": "ebwizardry:cast_spell", + "conditions": { + "spell": { + "spell": "fireskin" + } + } + }, + "fire_breath": { + "trigger": "ebwizardry:cast_spell", + "conditions": { + "spell": { + "spell": "fire_breath" + } + } + }, + "flame_ray": { + "trigger": "ebwizardry:cast_spell", + "conditions": { + "spell": { + "spell": "flame_ray" + } + } + }, + "flaming_axe": { + "trigger": "ebwizardry:cast_spell", + "conditions": { + "spell": { + "spell": "flaming_axe" + } + } + }, + "flaming_weapon": { + "trigger": "ebwizardry:cast_spell", + "conditions": { + "spell": { + "spell": "flaming_weapon" + } + } + }, + "flight": { + "trigger": "ebwizardry:cast_spell", + "conditions": { + "spell": { + "spell": "flight" + } + } + }, + "font_of_mana": { + "trigger": "ebwizardry:cast_spell", + "conditions": { + "spell": { + "spell": "font_of_mana" + } + } + }, + "font_of_vitality": { + "trigger": "ebwizardry:cast_spell", + "conditions": { + "spell": { + "spell": "font_of_vitality" + } + } + }, + "force_arrow": { + "trigger": "ebwizardry:cast_spell", + "conditions": { + "spell": { + "spell": "force_arrow" + } + } + }, + "forcefield": { + "trigger": "ebwizardry:cast_spell", + "conditions": { + "spell": { + "spell": "forcefield" + } + } + }, + "force_orb": { + "trigger": "ebwizardry:cast_spell", + "conditions": { + "spell": { + "spell": "force_orb" + } + } + }, + "forests_curse": { + "trigger": "ebwizardry:cast_spell", + "conditions": { + "spell": { + "spell": "forests_curse" + } + } + }, + "forest_of_thorns": { + "trigger": "ebwizardry:cast_spell", + "conditions": { + "spell": { + "spell": "forest_of_thorns" + } + } + }, + "freeze": { + "trigger": "ebwizardry:cast_spell", + "conditions": { + "spell": { + "spell": "freeze" + } + } + }, + "freezing_weapon": { + "trigger": "ebwizardry:cast_spell", + "conditions": { + "spell": { + "spell": "freezing_weapon" + } + } + }, + "frost_axe": { + "trigger": "ebwizardry:cast_spell", + "conditions": { + "spell": { + "spell": "frost_axe" + } + } + }, + "frost_ray": { + "trigger": "ebwizardry:cast_spell", + "conditions": { + "spell": { + "spell": "frost_ray" + } + } + }, + "frost_sigil": { + "trigger": "ebwizardry:cast_spell", + "conditions": { + "spell": { + "spell": "frost_sigil" + } + } + }, + "frost_step": { + "trigger": "ebwizardry:cast_spell", + "conditions": { + "spell": { + "spell": "frost_step" + } + } + }, + "glide": { + "trigger": "ebwizardry:cast_spell", + "conditions": { + "spell": { + "spell": "glide" + } + } + }, + "grapple": { + "trigger": "ebwizardry:cast_spell", + "conditions": { + "spell": { + "spell": "grapple" + } + } + }, + "greater_fireball": { + "trigger": "ebwizardry:cast_spell", + "conditions": { + "spell": { + "spell": "greater_fireball" + } + } + }, + "greater_heal": { + "trigger": "ebwizardry:cast_spell", + "conditions": { + "spell": { + "spell": "greater_heal" + } + } + }, + "greater_telekinesis": { + "trigger": "ebwizardry:cast_spell", + "conditions": { + "spell": { + "spell": "greater_telekinesis" + } + } + }, + "greater_ward": { + "trigger": "ebwizardry:cast_spell", + "conditions": { + "spell": { + "spell": "greater_ward" + } + } + }, + "group_heal": { + "trigger": "ebwizardry:cast_spell", + "conditions": { + "spell": { + "spell": "group_heal" + } + } + }, + "growth_aura": { + "trigger": "ebwizardry:cast_spell", + "conditions": { + "spell": { + "spell": "growth_aura" + } + } + }, + "hailstorm": { + "trigger": "ebwizardry:cast_spell", + "conditions": { + "spell": { + "spell": "hailstorm" + } + } + }, + "heal": { + "trigger": "ebwizardry:cast_spell", + "conditions": { + "spell": { + "spell": "heal" + } + } + }, + "heal_ally": { + "trigger": "ebwizardry:cast_spell", + "conditions": { + "spell": { + "spell": "heal_ally" + } + } + }, + "healing_aura": { + "trigger": "ebwizardry:cast_spell", + "conditions": { + "spell": { + "spell": "healing_aura" + } + } + }, + "homing_spark": { + "trigger": "ebwizardry:cast_spell", + "conditions": { + "spell": { + "spell": "homing_spark" + } + } + }, + "iceball": { + "trigger": "ebwizardry:cast_spell", + "conditions": { + "spell": { + "spell": "iceball" + } + } + }, + "ice_age": { + "trigger": "ebwizardry:cast_spell", + "conditions": { + "spell": { + "spell": "ice_age" + } + } + }, + "ice_charge": { + "trigger": "ebwizardry:cast_spell", + "conditions": { + "spell": { + "spell": "ice_charge" + } + } + }, + "ice_lance": { + "trigger": "ebwizardry:cast_spell", + "conditions": { + "spell": { + "spell": "ice_lance" + } + } + }, + "ice_shard": { + "trigger": "ebwizardry:cast_spell", + "conditions": { + "spell": { + "spell": "ice_shard" + } + } + }, + "ice_shroud": { + "trigger": "ebwizardry:cast_spell", + "conditions": { + "spell": { + "spell": "ice_shroud" + } + } + }, + "ice_spikes": { + "trigger": "ebwizardry:cast_spell", + "conditions": { + "spell": { + "spell": "ice_spikes" + } + } + }, + "ice_statue": { + "trigger": "ebwizardry:cast_spell", + "conditions": { + "spell": { + "spell": "ice_statue" + } + } + }, + "ignite": { + "trigger": "ebwizardry:cast_spell", + "conditions": { + "spell": { + "spell": "ignite" + } + } + }, + "imbue_weapon": { + "trigger": "ebwizardry:cast_spell", + "conditions": { + "spell": { + "spell": "imbue_weapon" + } + } + }, + "intimidate": { + "trigger": "ebwizardry:cast_spell", + "conditions": { + "spell": { + "spell": "intimidate" + } + } + }, + "invigorating_presence": { + "trigger": "ebwizardry:cast_spell", + "conditions": { + "spell": { + "spell": "invigorating_presence" + } + } + }, + "invisibility": { + "trigger": "ebwizardry:cast_spell", + "conditions": { + "spell": { + "spell": "invisibility" + } + } + }, + "invoke_weather": { + "trigger": "ebwizardry:cast_spell", + "conditions": { + "spell": { + "spell": "invoke_weather" + } + } + }, + "ironflesh": { + "trigger": "ebwizardry:cast_spell", + "conditions": { + "spell": { + "spell": "ironflesh" + } + } + }, + "leap": { + "trigger": "ebwizardry:cast_spell", + "conditions": { + "spell": { + "spell": "leap" + } + } + }, + "levitation": { + "trigger": "ebwizardry:cast_spell", + "conditions": { + "spell": { + "spell": "levitation" + } + } + }, + "life_drain": { + "trigger": "ebwizardry:cast_spell", + "conditions": { + "spell": { + "spell": "life_drain" + } + } + }, + "light": { + "trigger": "ebwizardry:cast_spell", + "conditions": { + "spell": { + "spell": "light" + } + } + }, + "lightning_arrow": { + "trigger": "ebwizardry:cast_spell", + "conditions": { + "spell": { + "spell": "lightning_arrow" + } + } + }, + "lightning_bolt": { + "trigger": "ebwizardry:cast_spell", + "conditions": { + "spell": { + "spell": "lightning_bolt" + } + } + }, + "lightning_disc": { + "trigger": "ebwizardry:cast_spell", + "conditions": { + "spell": { + "spell": "lightning_disc" + } + } + }, + "lightning_hammer": { + "trigger": "ebwizardry:cast_spell", + "conditions": { + "spell": { + "spell": "lightning_hammer" + } + } + }, + "lightning_pulse": { + "trigger": "ebwizardry:cast_spell", + "conditions": { + "spell": { + "spell": "lightning_pulse" + } + } + }, + "lightning_ray": { + "trigger": "ebwizardry:cast_spell", + "conditions": { + "spell": { + "spell": "lightning_ray" + } + } + }, + "lightning_sigil": { + "trigger": "ebwizardry:cast_spell", + "conditions": { + "spell": { + "spell": "lightning_sigil" + } + } + }, + "lightning_web": { + "trigger": "ebwizardry:cast_spell", + "conditions": { + "spell": { + "spell": "lightning_web" + } + } + }, + "magic_missile": { + "trigger": "ebwizardry:cast_spell", + "conditions": { + "spell": { + "spell": "magic_missile" + } + } + }, + "metamorphosis": { + "trigger": "ebwizardry:cast_spell", + "conditions": { + "spell": { + "spell": "metamorphosis" + } + } + }, + "meteor": { + "trigger": "ebwizardry:cast_spell", + "conditions": { + "spell": { + "spell": "meteor" + } + } + }, + "mind_control": { + "trigger": "ebwizardry:cast_spell", + "conditions": { + "spell": { + "spell": "mind_control" + } + } + }, + "mind_trick": { + "trigger": "ebwizardry:cast_spell", + "conditions": { + "spell": { + "spell": "mind_trick" + } + } + }, + "mine": { + "trigger": "ebwizardry:cast_spell", + "conditions": { + "spell": { + "spell": "mine" + } + } + }, + "muffle": { + "trigger": "ebwizardry:cast_spell", + "conditions": { + "spell": { + "spell": "muffle" + } + } + }, + "oakflesh": { + "trigger": "ebwizardry:cast_spell", + "conditions": { + "spell": { + "spell": "oakflesh" + } + } + }, + "paralysis": { + "trigger": "ebwizardry:cast_spell", + "conditions": { + "spell": { + "spell": "paralysis" + } + } + }, + "petrify": { + "trigger": "ebwizardry:cast_spell", + "conditions": { + "spell": { + "spell": "petrify" + } + } + }, + "phase_step": { + "trigger": "ebwizardry:cast_spell", + "conditions": { + "spell": { + "spell": "phase_step" + } + } + }, + "plague_of_darkness": { + "trigger": "ebwizardry:cast_spell", + "conditions": { + "spell": { + "spell": "plague_of_darkness" + } + } + }, + "pocket_furnace": { + "trigger": "ebwizardry:cast_spell", + "conditions": { + "spell": { + "spell": "pocket_furnace" + } + } + }, + "pocket_workbench": { + "trigger": "ebwizardry:cast_spell", + "conditions": { + "spell": { + "spell": "pocket_workbench" + } + } + }, + "poison": { + "trigger": "ebwizardry:cast_spell", + "conditions": { + "spell": { + "spell": "poison" + } + } + }, + "poison_bomb": { + "trigger": "ebwizardry:cast_spell", + "conditions": { + "spell": { + "spell": "poison_bomb" + } + } + }, + "possession": { + "trigger": "ebwizardry:cast_spell", + "conditions": { + "spell": { + "spell": "possession" + } + } + }, + "ray_of_purification": { + "trigger": "ebwizardry:cast_spell", + "conditions": { + "spell": { + "spell": "ray_of_purification" + } + } + }, + "remove_curse": { + "trigger": "ebwizardry:cast_spell", + "conditions": { + "spell": { + "spell": "remove_curse" + } + } + }, + "replenish_hunger": { + "trigger": "ebwizardry:cast_spell", + "conditions": { + "spell": { + "spell": "replenish_hunger" + } + } + }, + "resurrection": { + "trigger": "ebwizardry:cast_spell", + "conditions": { + "spell": { + "spell": "resurrection" + } + } + }, + "reversal": { + "trigger": "ebwizardry:cast_spell", + "conditions": { + "spell": { + "spell": "reversal" + } + } + }, + "ring_of_fire": { + "trigger": "ebwizardry:cast_spell", + "conditions": { + "spell": { + "spell": "ring_of_fire" + } + } + }, + "satiety": { + "trigger": "ebwizardry:cast_spell", + "conditions": { + "spell": { + "spell": "satiety" + } + } + }, + "shadow_ward": { + "trigger": "ebwizardry:cast_spell", + "conditions": { + "spell": { + "spell": "shadow_ward" + } + } + }, + "shield": { + "trigger": "ebwizardry:cast_spell", + "conditions": { + "spell": { + "spell": "shield" + } + } + }, + "shockwave": { + "trigger": "ebwizardry:cast_spell", + "conditions": { + "spell": { + "spell": "shockwave" + } + } + }, + "shulker_bullet": { + "trigger": "ebwizardry:cast_spell", + "conditions": { + "spell": { + "spell": "shulker_bullet" + } + } + }, + "silverfish_swarm": { + "trigger": "ebwizardry:cast_spell", + "conditions": { + "spell": { + "spell": "silverfish_swarm" + } + } + }, + "sixth_sense": { + "trigger": "ebwizardry:cast_spell", + "conditions": { + "spell": { + "spell": "sixth_sense" + } + } + }, + "slime": { + "trigger": "ebwizardry:cast_spell", + "conditions": { + "spell": { + "spell": "slime" + } + } + }, + "slow_time": { + "trigger": "ebwizardry:cast_spell", + "conditions": { + "spell": { + "spell": "slow_time" + } + } + }, + "smoke_bomb": { + "trigger": "ebwizardry:cast_spell", + "conditions": { + "spell": { + "spell": "smoke_bomb" + } + } + }, + "snare": { + "trigger": "ebwizardry:cast_spell", + "conditions": { + "spell": { + "spell": "snare" + } + } + }, + "snowball": { + "trigger": "ebwizardry:cast_spell", + "conditions": { + "spell": { + "spell": "snowball" + } + } + }, + "spark_bomb": { + "trigger": "ebwizardry:cast_spell", + "conditions": { + "spell": { + "spell": "spark_bomb" + } + } + }, + "spectral_pathway": { + "trigger": "ebwizardry:cast_spell", + "conditions": { + "spell": { + "spell": "spectral_pathway" + } + } + }, + "speed_time": { + "trigger": "ebwizardry:cast_spell", + "conditions": { + "spell": { + "spell": "speed_time" + } + } + }, + "spider_swarm": { + "trigger": "ebwizardry:cast_spell", + "conditions": { + "spell": { + "spell": "spider_swarm" + } + } + }, + "static_aura": { + "trigger": "ebwizardry:cast_spell", + "conditions": { + "spell": { + "spell": "static_aura" + } + } + }, + "summon_blaze": { + "trigger": "ebwizardry:cast_spell", + "conditions": { + "spell": { + "spell": "summon_blaze" + } + } + }, + "summon_ice_giant": { + "trigger": "ebwizardry:cast_spell", + "conditions": { + "spell": { + "spell": "summon_ice_giant" + } + } + }, + "summon_ice_wraith": { + "trigger": "ebwizardry:cast_spell", + "conditions": { + "spell": { + "spell": "summon_ice_wraith" + } + } + }, + "summon_iron_golem": { + "trigger": "ebwizardry:cast_spell", + "conditions": { + "spell": { + "spell": "summon_iron_golem" + } + } + }, + "summon_lightning_wraith": { + "trigger": "ebwizardry:cast_spell", + "conditions": { + "spell": { + "spell": "summon_lightning_wraith" + } + } + }, + "summon_phoenix": { + "trigger": "ebwizardry:cast_spell", + "conditions": { + "spell": { + "spell": "summon_phoenix" + } + } + }, + "summon_shadow_wraith": { + "trigger": "ebwizardry:cast_spell", + "conditions": { + "spell": { + "spell": "summon_shadow_wraith" + } + } + }, + "summon_skeleton": { + "trigger": "ebwizardry:cast_spell", + "conditions": { + "spell": { + "spell": "summon_skeleton" + } + } + }, + "summon_skeleton_legion": { + "trigger": "ebwizardry:cast_spell", + "conditions": { + "spell": { + "spell": "summon_skeleton_legion" + } + } + }, + "summon_snow_golem": { + "trigger": "ebwizardry:cast_spell", + "conditions": { + "spell": { + "spell": "summon_snow_golem" + } + } + }, + "summon_spirit_horse": { + "trigger": "ebwizardry:cast_spell", + "conditions": { + "spell": { + "spell": "summon_spirit_horse" + } + } + }, + "summon_spirit_wolf": { + "trigger": "ebwizardry:cast_spell", + "conditions": { + "spell": { + "spell": "summon_spirit_wolf" + } + } + }, + "summon_storm_elemental": { + "trigger": "ebwizardry:cast_spell", + "conditions": { + "spell": { + "spell": "summon_storm_elemental" + } + } + }, + "summon_wither_skeleton": { + "trigger": "ebwizardry:cast_spell", + "conditions": { + "spell": { + "spell": "summon_wither_skeleton" + } + } + }, + "summon_zombie": { + "trigger": "ebwizardry:cast_spell", + "conditions": { + "spell": { + "spell": "summon_zombie" + } + } + }, + "telekinesis": { + "trigger": "ebwizardry:cast_spell", + "conditions": { + "spell": { + "spell": "telekinesis" + } + } + }, + "thunderbolt": { + "trigger": "ebwizardry:cast_spell", + "conditions": { + "spell": { + "spell": "thunderbolt" + } + } + }, + "thunderstorm": { + "trigger": "ebwizardry:cast_spell", + "conditions": { + "spell": { + "spell": "thunderstorm" + } + } + }, + "tornado": { + "trigger": "ebwizardry:cast_spell", + "conditions": { + "spell": { + "spell": "tornado" + } + } + }, + "transience": { + "trigger": "ebwizardry:cast_spell", + "conditions": { + "spell": { + "spell": "transience" + } + } + }, + "transportation": { + "trigger": "ebwizardry:cast_spell", + "conditions": { + "spell": { + "spell": "transportation" + } + } + }, + "vanishing_box": { + "trigger": "ebwizardry:cast_spell", + "conditions": { + "spell": { + "spell": "vanishing_box" + } + } + }, + "vex_swarm": { + "trigger": "ebwizardry:cast_spell", + "conditions": { + "spell": { + "spell": "vex_swarm" + } + } + }, + "wall_of_frost": { + "trigger": "ebwizardry:cast_spell", + "conditions": { + "spell": { + "spell": "wall_of_frost" + } + } + }, + "ward": { + "trigger": "ebwizardry:cast_spell", + "conditions": { + "spell": { + "spell": "ward" + } + } + }, + "water_breathing": { + "trigger": "ebwizardry:cast_spell", + "conditions": { + "spell": { + "spell": "water_breathing" + } + } + }, + "whirlwind": { + "trigger": "ebwizardry:cast_spell", + "conditions": { + "spell": { + "spell": "whirlwind" + } + } + }, + "wither": { + "trigger": "ebwizardry:cast_spell", + "conditions": { + "spell": { + "spell": "wither" + } + } + }, + "wither_skull": { + "trigger": "ebwizardry:cast_spell", + "conditions": { + "spell": { + "spell": "wither_skull" + } + } } } } \ No newline at end of file diff --git a/src/main/resources/assets/ebwizardry/advancements/anger_wizard.json b/src/main/resources/assets/ebwizardry/advancements/anger_wizard.json index ea1b5070..b9d5dee3 100644 --- a/src/main/resources/assets/ebwizardry/advancements/anger_wizard.json +++ b/src/main/resources/assets/ebwizardry/advancements/anger_wizard.json @@ -4,10 +4,10 @@ "item": "minecraft:iron_sword" }, "title": { - "translate": "advancement.wizardry:anger_wizard" + "translate": "advancement.ebwizardry:anger_wizard" }, "description": { - "translate": "advancement.wizardry:anger_wizard.desc" + "translate": "advancement.ebwizardry:anger_wizard.desc" } }, "parent": "ebwizardry:wizard_trade", diff --git a/src/main/resources/assets/ebwizardry/advancements/apprentice.json b/src/main/resources/assets/ebwizardry/advancements/apprentice.json index 493f7963..12596e68 100644 --- a/src/main/resources/assets/ebwizardry/advancements/apprentice.json +++ b/src/main/resources/assets/ebwizardry/advancements/apprentice.json @@ -4,16 +4,105 @@ "item": "ebwizardry:apprentice_wand" }, "title": { - "translate": "advancement.wizardry:apprentice" + "translate": "advancement.ebwizardry:apprentice" }, "description": { - "translate": "advancement.wizardry:apprentice.desc" + "translate": "advancement.ebwizardry:apprentice.desc" } }, "parent": "ebwizardry:arcane_initiate", "criteria": { - "criteria_0": { - "trigger": "ebwizardry:trigger_apprentice" + "magic": { + "trigger": "minecraft:inventory_changed", + "conditions": { + "items": [ + { + "item": "ebwizardry:apprentice_wand" + } + ] + } + }, + "fire": { + "trigger": "minecraft:inventory_changed", + "conditions": { + "items": [ + { + "item": "ebwizardry:apprentice_fire_wand" + } + ] + } + }, + "ice": { + "trigger": "minecraft:inventory_changed", + "conditions": { + "items": [ + { + "item": "ebwizardry:apprentice_ice_wand" + } + ] + } + }, + "lightning": { + "trigger": "minecraft:inventory_changed", + "conditions": { + "items": [ + { + "item": "ebwizardry:apprentice_lightning_wand" + } + ] + } + }, + "necromancy": { + "trigger": "minecraft:inventory_changed", + "conditions": { + "items": [ + { + "item": "ebwizardry:apprentice_necromancy_wand" + } + ] + } + }, + "earth": { + "trigger": "minecraft:inventory_changed", + "conditions": { + "items": [ + { + "item": "ebwizardry:apprentice_earth_wand" + } + ] + } + }, + "sorcery": { + "trigger": "minecraft:inventory_changed", + "conditions": { + "items": [ + { + "item": "ebwizardry:apprentice_sorcery_wand" + } + ] + } + }, + "healing": { + "trigger": "minecraft:inventory_changed", + "conditions": { + "items": [ + { + "item": "ebwizardry:apprentice_healing_wand" + } + ] + } } - } + }, + "requirements": [ + [ + "magic", + "fire", + "ice", + "lightning", + "necromancy", + "earth", + "sorcery", + "healing" + ] + ] } \ No newline at end of file diff --git a/src/main/resources/assets/ebwizardry/advancements/arcane_initiate.json b/src/main/resources/assets/ebwizardry/advancements/arcane_initiate.json index 927f6fe4..6d4bcc33 100644 --- a/src/main/resources/assets/ebwizardry/advancements/arcane_initiate.json +++ b/src/main/resources/assets/ebwizardry/advancements/arcane_initiate.json @@ -1,10 +1,10 @@ { "display": { "title": { - "translate": "advancement.wizardry:arcane_initiate" + "translate": "advancement.ebwizardry:arcane_initiate" }, "description": { - "translate": "advancement.wizardry:arcane_initiate.desc" + "translate": "advancement.ebwizardry:arcane_initiate.desc" }, "icon": { "item": "ebwizardry:magic_wand" diff --git a/src/main/resources/assets/ebwizardry/advancements/armour_set.json b/src/main/resources/assets/ebwizardry/advancements/armour_set.json index 7e36d47c..c69d5c65 100644 --- a/src/main/resources/assets/ebwizardry/advancements/armour_set.json +++ b/src/main/resources/assets/ebwizardry/advancements/armour_set.json @@ -1,10 +1,10 @@ { "display": { "title": { - "translate": "advancement.wizardry:armour_set" + "translate": "advancement.ebwizardry:armour_set" }, "description": { - "translate": "advancement.wizardry:armour_set.desc" + "translate": "advancement.ebwizardry:armour_set.desc" }, "icon": { "item": "ebwizardry:wizard_hat" @@ -12,8 +12,24 @@ }, "parent": "ebwizardry:arcane_initiate", "criteria": { - "criteria_0": { - "trigger": "ebwizardry:trigger_armour_set" + "wizard_hat": { + "trigger": "minecraft:inventory_changed", + "conditions": { + "items": [ + { + "item": "ebwizardry:wizard_hat" + }, + { + "item": "ebwizardry:wizard_robe" + }, + { + "item": "ebwizardry:wizard_leggings" + }, + { + "item": "ebwizardry:wizard_boots" + } + ] + } } } } \ No newline at end of file diff --git a/src/main/resources/assets/ebwizardry/advancements/artefact.json b/src/main/resources/assets/ebwizardry/advancements/artefact.json new file mode 100644 index 00000000..a5287409 --- /dev/null +++ b/src/main/resources/assets/ebwizardry/advancements/artefact.json @@ -0,0 +1,713 @@ +{ + "display": { + "title": { + "translate": "advancement.ebwizardry:artefact" + }, + "description": { + "translate": "advancement.ebwizardry:artefact.desc" + }, + "icon": { + "item": "ebwizardry:ring_condensing" + } + }, + "parent": "ebwizardry:visit_shrine", + "criteria": { + "ring_condensing": { + "trigger": "minecraft:inventory_changed", + "conditions": { + "items": [ + { + "item": "ebwizardry:ring_condensing" + } + ] + } + }, + "ring_siphoning": { + "trigger": "minecraft:inventory_changed", + "conditions": { + "items": [ + { + "item": "ebwizardry:ring_siphoning" + } + ] + } + }, + "ring_battlemage": { + "trigger": "minecraft:inventory_changed", + "conditions": { + "items": [ + { + "item": "ebwizardry:ring_battlemage" + } + ] + } + }, + "ring_combustion": { + "trigger": "minecraft:inventory_changed", + "conditions": { + "items": [ + { + "item": "ebwizardry:ring_combustion" + } + ] + } + }, + "ring_fire_melee": { + "trigger": "minecraft:inventory_changed", + "conditions": { + "items": [ + { + "item": "ebwizardry:ring_fire_melee" + } + ] + } + }, + "ring_fire_biome": { + "trigger": "minecraft:inventory_changed", + "conditions": { + "items": [ + { + "item": "ebwizardry:ring_fire_biome" + } + ] + } + }, + "ring_disintegration": { + "trigger": "minecraft:inventory_changed", + "conditions": { + "items": [ + { + "item": "ebwizardry:ring_disintegration" + } + ] + } + }, + "ring_ice_melee": { + "trigger": "minecraft:inventory_changed", + "conditions": { + "items": [ + { + "item": "ebwizardry:ring_ice_melee" + } + ] + } + }, + "ring_ice_biome": { + "trigger": "minecraft:inventory_changed", + "conditions": { + "items": [ + { + "item": "ebwizardry:ring_ice_biome" + } + ] + } + }, + "ring_arcane_frost": { + "trigger": "minecraft:inventory_changed", + "conditions": { + "items": [ + { + "item": "ebwizardry:ring_arcane_frost" + } + ] + } + }, + "ring_shattering": { + "trigger": "minecraft:inventory_changed", + "conditions": { + "items": [ + { + "item": "ebwizardry:ring_shattering" + } + ] + } + }, + "ring_lightning_melee": { + "trigger": "minecraft:inventory_changed", + "conditions": { + "items": [ + { + "item": "ebwizardry:ring_lightning_melee" + } + ] + } + }, + "ring_storm": { + "trigger": "minecraft:inventory_changed", + "conditions": { + "items": [ + { + "item": "ebwizardry:ring_storm" + } + ] + } + }, + "ring_seeking": { + "trigger": "minecraft:inventory_changed", + "conditions": { + "items": [ + { + "item": "ebwizardry:ring_seeking" + } + ] + } + }, + "ring_hammer": { + "trigger": "minecraft:inventory_changed", + "conditions": { + "items": [ + { + "item": "ebwizardry:ring_hammer" + } + ] + } + }, + "ring_soulbinding": { + "trigger": "minecraft:inventory_changed", + "conditions": { + "items": [ + { + "item": "ebwizardry:ring_soulbinding" + } + ] + } + }, + "ring_leeching": { + "trigger": "minecraft:inventory_changed", + "conditions": { + "items": [ + { + "item": "ebwizardry:ring_leeching" + } + ] + } + }, + "ring_necromancy_melee": { + "trigger": "minecraft:inventory_changed", + "conditions": { + "items": [ + { + "item": "ebwizardry:ring_necromancy_melee" + } + ] + } + }, + "ring_mind_control": { + "trigger": "minecraft:inventory_changed", + "conditions": { + "items": [ + { + "item": "ebwizardry:ring_mind_control" + } + ] + } + }, + "ring_poison": { + "trigger": "minecraft:inventory_changed", + "conditions": { + "items": [ + { + "item": "ebwizardry:ring_poison" + } + ] + } + }, + "ring_earth_melee": { + "trigger": "minecraft:inventory_changed", + "conditions": { + "items": [ + { + "item": "ebwizardry:ring_earth_melee" + } + ] + } + }, + "ring_earth_biome": { + "trigger": "minecraft:inventory_changed", + "conditions": { + "items": [ + { + "item": "ebwizardry:ring_earth_biome" + } + ] + } + }, + "ring_full_moon": { + "trigger": "minecraft:inventory_changed", + "conditions": { + "items": [ + { + "item": "ebwizardry:ring_full_moon" + } + ] + } + }, + "ring_extraction": { + "trigger": "minecraft:inventory_changed", + "conditions": { + "items": [ + { + "item": "ebwizardry:ring_extraction" + } + ] + } + }, + "ring_mana_return": { + "trigger": "minecraft:inventory_changed", + "conditions": { + "items": [ + { + "item": "ebwizardry:ring_mana_return" + } + ] + } + }, + "ring_blockwrangler": { + "trigger": "minecraft:inventory_changed", + "conditions": { + "items": [ + { + "item": "ebwizardry:ring_blockwrangler" + } + ] + } + }, + "ring_conjurer": { + "trigger": "minecraft:inventory_changed", + "conditions": { + "items": [ + { + "item": "ebwizardry:ring_conjurer" + } + ] + } + }, + "ring_defender": { + "trigger": "minecraft:inventory_changed", + "conditions": { + "items": [ + { + "item": "ebwizardry:ring_defender" + } + ] + } + }, + "ring_paladin": { + "trigger": "minecraft:inventory_changed", + "conditions": { + "items": [ + { + "item": "ebwizardry:ring_paladin" + } + ] + } + }, + "ring_interdiction": { + "trigger": "minecraft:inventory_changed", + "conditions": { + "items": [ + { + "item": "ebwizardry:ring_interdiction" + } + ] + } + }, + "amulet_arcane_defence": { + "trigger": "minecraft:inventory_changed", + "conditions": { + "items": [ + { + "item": "ebwizardry:amulet_arcane_defence" + } + ] + } + }, + "amulet_warding": { + "trigger": "minecraft:inventory_changed", + "conditions": { + "items": [ + { + "item": "ebwizardry:amulet_warding" + } + ] + } + }, + "amulet_wisdom": { + "trigger": "minecraft:inventory_changed", + "conditions": { + "items": [ + { + "item": "ebwizardry:amulet_wisdom" + } + ] + } + }, + "amulet_fire_protection": { + "trigger": "minecraft:inventory_changed", + "conditions": { + "items": [ + { + "item": "ebwizardry:amulet_fire_protection" + } + ] + } + }, + "amulet_fire_cloaking": { + "trigger": "minecraft:inventory_changed", + "conditions": { + "items": [ + { + "item": "ebwizardry:amulet_fire_cloaking" + } + ] + } + }, + "amulet_ice_immunity": { + "trigger": "minecraft:inventory_changed", + "conditions": { + "items": [ + { + "item": "ebwizardry:amulet_ice_immunity" + } + ] + } + }, + "amulet_ice_protection": { + "trigger": "minecraft:inventory_changed", + "conditions": { + "items": [ + { + "item": "ebwizardry:amulet_ice_protection" + } + ] + } + }, + "amulet_potential": { + "trigger": "minecraft:inventory_changed", + "conditions": { + "items": [ + { + "item": "ebwizardry:amulet_potential" + } + ] + } + }, + "amulet_channeling": { + "trigger": "minecraft:inventory_changed", + "conditions": { + "items": [ + { + "item": "ebwizardry:amulet_channeling" + } + ] + } + }, + "amulet_lich": { + "trigger": "minecraft:inventory_changed", + "conditions": { + "items": [ + { + "item": "ebwizardry:amulet_lich" + } + ] + } + }, + "amulet_wither_immunity": { + "trigger": "minecraft:inventory_changed", + "conditions": { + "items": [ + { + "item": "ebwizardry:amulet_wither_immunity" + } + ] + } + }, + "amulet_glide": { + "trigger": "minecraft:inventory_changed", + "conditions": { + "items": [ + { + "item": "ebwizardry:amulet_glide" + } + ] + } + }, + "amulet_banishing": { + "trigger": "minecraft:inventory_changed", + "conditions": { + "items": [ + { + "item": "ebwizardry:amulet_banishing" + } + ] + } + }, + "amulet_anchoring": { + "trigger": "minecraft:inventory_changed", + "conditions": { + "items": [ + { + "item": "ebwizardry:amulet_anchoring" + } + ] + } + }, + "amulet_recovery": { + "trigger": "minecraft:inventory_changed", + "conditions": { + "items": [ + { + "item": "ebwizardry:amulet_recovery" + } + ] + } + }, + "amulet_transience": { + "trigger": "minecraft:inventory_changed", + "conditions": { + "items": [ + { + "item": "ebwizardry:amulet_transience" + } + ] + } + }, + "amulet_resurrection": { + "trigger": "minecraft:inventory_changed", + "conditions": { + "items": [ + { + "item": "ebwizardry:amulet_resurrection" + } + ] + } + }, + "amulet_auto_shield": { + "trigger": "minecraft:inventory_changed", + "conditions": { + "items": [ + { + "item": "ebwizardry:amulet_auto_shield" + } + ] + } + }, + "charm_haggler": { + "trigger": "minecraft:inventory_changed", + "conditions": { + "items": [ + { + "item": "ebwizardry:charm_haggler" + } + ] + } + }, + "charm_experience_tome": { + "trigger": "minecraft:inventory_changed", + "conditions": { + "items": [ + { + "item": "ebwizardry:charm_experience_tome" + } + ] + } + }, + "charm_auto_smelt": { + "trigger": "minecraft:inventory_changed", + "conditions": { + "items": [ + { + "item": "ebwizardry:charm_auto_smelt" + } + ] + } + }, + "charm_lava_walking": { + "trigger": "minecraft:inventory_changed", + "conditions": { + "items": [ + { + "item": "ebwizardry:charm_lava_walking" + } + ] + } + }, + "charm_storm": { + "trigger": "minecraft:inventory_changed", + "conditions": { + "items": [ + { + "item": "ebwizardry:charm_storm" + } + ] + } + }, + "charm_minion_health": { + "trigger": "minecraft:inventory_changed", + "conditions": { + "items": [ + { + "item": "ebwizardry:charm_minion_health" + } + ] + } + }, + "charm_minion_variants": { + "trigger": "minecraft:inventory_changed", + "conditions": { + "items": [ + { + "item": "ebwizardry:charm_minion_variants" + } + ] + } + }, + "charm_flight": { + "trigger": "minecraft:inventory_changed", + "conditions": { + "items": [ + { + "item": "ebwizardry:charm_flight" + } + ] + } + }, + "charm_growth": { + "trigger": "minecraft:inventory_changed", + "conditions": { + "items": [ + { + "item": "ebwizardry:charm_growth" + } + ] + } + }, + "charm_abseiling": { + "trigger": "minecraft:inventory_changed", + "conditions": { + "items": [ + { + "item": "ebwizardry:charm_abseiling" + } + ] + } + }, + "charm_silk_touch": { + "trigger": "minecraft:inventory_changed", + "conditions": { + "items": [ + { + "item": "ebwizardry:charm_silk_touch" + } + ] + } + }, + "charm_stop_time": { + "trigger": "minecraft:inventory_changed", + "conditions": { + "items": [ + { + "item": "ebwizardry:charm_stop_time" + } + ] + } + }, + "charm_light": { + "trigger": "minecraft:inventory_changed", + "conditions": { + "items": [ + { + "item": "ebwizardry:charm_light" + } + ] + } + }, + "charm_transportation": { + "trigger": "minecraft:inventory_changed", + "conditions": { + "items": [ + { + "item": "ebwizardry:charm_transportation" + } + ] + } + }, + "charm_feeding": { + "trigger": "minecraft:inventory_changed", + "conditions": { + "items": [ + { + "item": "ebwizardry:charm_feeding" + } + ] + } + } + }, + "requirements": [ + [ + "ring_condensing", + "ring_siphoning", + "ring_battlemage", + "ring_combustion", + "ring_fire_melee", + "ring_fire_biome", + "ring_disintegration", + "ring_ice_melee", + "ring_ice_biome", + "ring_arcane_frost", + "ring_shattering", + "ring_lightning_melee", + "ring_storm", + "ring_seeking", + "ring_hammer", + "ring_soulbinding", + "ring_leeching", + "ring_necromancy_melee", + "ring_mind_control", + "ring_poison", + "ring_earth_melee", + "ring_earth_biome", + "ring_full_moon", + "ring_extraction", + "ring_mana_return", + "ring_blockwrangler", + "ring_conjurer", + "ring_defender", + "ring_paladin", + "ring_interdiction", + "amulet_arcane_defence", + "amulet_warding", + "amulet_wisdom", + "amulet_fire_protection", + "amulet_fire_cloaking", + "amulet_ice_immunity", + "amulet_ice_protection", + "amulet_potential", + "amulet_channeling", + "amulet_lich", + "amulet_wither_immunity", + "amulet_glide", + "amulet_banishing", + "amulet_anchoring", + "amulet_recovery", + "amulet_transience", + "amulet_resurrection", + "amulet_auto_shield", + "charm_haggler", + "charm_experience_tome", + "charm_auto_smelt", + "charm_lava_walking", + "charm_storm", + "charm_minion_health", + "charm_minion_variants", + "charm_flight", + "charm_growth", + "charm_abseiling", + "charm_silk_touch", + "charm_stop_time", + "charm_light", + "charm_transportation", + "charm_feeding" + ] + ] +} \ No newline at end of file diff --git a/src/main/resources/assets/ebwizardry/advancements/buy_master_spell.json b/src/main/resources/assets/ebwizardry/advancements/buy_master_spell.json index 1f00f8b4..3cf455d4 100644 --- a/src/main/resources/assets/ebwizardry/advancements/buy_master_spell.json +++ b/src/main/resources/assets/ebwizardry/advancements/buy_master_spell.json @@ -1,13 +1,13 @@ { "display": { "title": { - "translate": "advancement.wizardry:buy_master_spell" + "translate": "advancement.ebwizardry:buy_master_spell" }, "description": { - "translate": "advancement.wizardry:buy_master_spell.desc" + "translate": "advancement.ebwizardry:buy_master_spell.desc" }, "icon": { - "item": "ebwizardry:spell_book" + "item": "ebwizardry:astral_diamond" }, "frame": "goal" }, diff --git a/src/main/resources/assets/ebwizardry/advancements/charge_creeper.json b/src/main/resources/assets/ebwizardry/advancements/charge_creeper.json deleted file mode 100644 index 8fad22e1..00000000 --- a/src/main/resources/assets/ebwizardry/advancements/charge_creeper.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "display": { - "title": { - "translate": "advancement.wizardry:charge_creeper" - }, - "description": { - "translate": "advancement.wizardry:charge_creeper.desc" - }, - "icon": { - "item": "minecraft:gunpowder" - } - }, - "parent": "ebwizardry:arcane_initiate", - "criteria": { - "criteria_0": { - "trigger": "ebwizardry:trigger_charge_creeper" - } - } -} \ No newline at end of file diff --git a/src/main/resources/assets/ebwizardry/advancements/craft_flask.json b/src/main/resources/assets/ebwizardry/advancements/craft_flask.json deleted file mode 100644 index 7ae4cba2..00000000 --- a/src/main/resources/assets/ebwizardry/advancements/craft_flask.json +++ /dev/null @@ -1,26 +0,0 @@ -{ - "display": { - "title": { - "translate": "advancement.wizardry:craft_flask" - }, - "description": { - "translate": "advancement.wizardry:craft_flask.desc" - }, - "icon": { - "item": "ebwizardry:mana_flask" - } - }, - "parent": "ebwizardry:arcane_initiate", - "criteria": { - "criteria_0": { - "trigger": "minecraft:inventory_changed", - "conditions": { - "items": [ - { - "item": "ebwizardry:mana_flask" - } - ] - } - } - } -} \ No newline at end of file diff --git a/src/main/resources/assets/ebwizardry/advancements/crystal.json b/src/main/resources/assets/ebwizardry/advancements/crystal.json index ddbbf5f4..9dcc0773 100644 --- a/src/main/resources/assets/ebwizardry/advancements/crystal.json +++ b/src/main/resources/assets/ebwizardry/advancements/crystal.json @@ -1,13 +1,14 @@ { "display": { "title": { - "translate": "advancement.wizardry:crystal" + "translate": "advancement.ebwizardry:crystal" }, "description": { - "translate": "advancement.wizardry:crystal.desc" + "translate": "advancement.ebwizardry:crystal.desc" }, "icon": { - "item": "ebwizardry:magic_crystal" + "item": "ebwizardry:magic_crystal", + "data": 0 } }, "parent": "ebwizardry:root", @@ -17,7 +18,8 @@ "conditions": { "items": [ { - "item": "ebwizardry:magic_crystal" + "item": "ebwizardry:magic_crystal", + "data": 0 } ] } diff --git a/src/main/resources/assets/ebwizardry/advancements/defeat_evil_wizard.json b/src/main/resources/assets/ebwizardry/advancements/defeat_evil_wizard.json index 7faa2467..810f1074 100644 --- a/src/main/resources/assets/ebwizardry/advancements/defeat_evil_wizard.json +++ b/src/main/resources/assets/ebwizardry/advancements/defeat_evil_wizard.json @@ -1,16 +1,16 @@ { "display": { "title": { - "translate": "advancement.wizardry:defeat_evil_wizard" + "translate": "advancement.ebwizardry:defeat_evil_wizard" }, "description": { - "translate": "advancement.wizardry:defeat_evil_wizard.desc" + "translate": "advancement.ebwizardry:defeat_evil_wizard.desc" }, "icon": { "item": "ebwizardry:wizard_boots_necromancy" } }, - "parent": "ebwizardry:wizard_trade", + "parent": "ebwizardry:arcane_initiate", "criteria": { "criteria_0": { "trigger": "minecraft:player_killed_entity", diff --git a/src/main/resources/assets/ebwizardry/advancements/discover_master_spell.json b/src/main/resources/assets/ebwizardry/advancements/discover_master_spell.json new file mode 100644 index 00000000..35b38fd0 --- /dev/null +++ b/src/main/resources/assets/ebwizardry/advancements/discover_master_spell.json @@ -0,0 +1,28 @@ +{ + "display": { + "title": { + "translate": "advancement.ebwizardry:discover_master_spell" + }, + "description": { + "translate": "advancement.ebwizardry:discover_master_spell.desc" + }, + "icon": { + "item": "minecraft:blaze_powder" + }, + "frame": "challenge" + }, + "parent": "ebwizardry:spell_failure", + "criteria": { + "criteria_0": { + "trigger": "ebwizardry:discover_spell", + "conditions": { + "spell": { + "tiers": [ + "master" + ] + }, + "source": "casting" + } + } + } +} \ No newline at end of file diff --git a/src/main/resources/assets/ebwizardry/advancements/discover_spell.json b/src/main/resources/assets/ebwizardry/advancements/discover_spell.json new file mode 100644 index 00000000..ba0b2d72 --- /dev/null +++ b/src/main/resources/assets/ebwizardry/advancements/discover_spell.json @@ -0,0 +1,22 @@ +{ + "display": { + "title": { + "translate": "advancement.ebwizardry:discover_spell" + }, + "description": { + "translate": "advancement.ebwizardry:discover_spell.desc" + }, + "icon": { + "item": "minecraft:paper" + } + }, + "parent": "ebwizardry:arcane_initiate", + "criteria": { + "criteria_0": { + "trigger": "ebwizardry:discover_spell", + "conditions": { + "source": "casting" + } + } + } +} \ No newline at end of file diff --git a/src/main/resources/assets/ebwizardry/advancements/element_master.json b/src/main/resources/assets/ebwizardry/advancements/element_master.json deleted file mode 100644 index bf8d38f4..00000000 --- a/src/main/resources/assets/ebwizardry/advancements/element_master.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "display": { - "title": { - "translate": "advancement.wizardry:element_master" - }, - "description": { - "translate": "advancement.wizardry:element_master.desc" - }, - "icon": { - "item": "ebwizardry:master_ice_wand" - }, - "frame": "challenge" - }, - "parent": "ebwizardry:elemental", - "criteria": { - "criteria_0": { - "trigger": "ebwizardry:trigger_element_master" - } - } -} \ No newline at end of file diff --git a/src/main/resources/assets/ebwizardry/advancements/elemental.json b/src/main/resources/assets/ebwizardry/advancements/elemental.json deleted file mode 100644 index 43eb4c16..00000000 --- a/src/main/resources/assets/ebwizardry/advancements/elemental.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "display": { - "title": { - "translate": "advancement.wizardry:elemental" - }, - "description": { - "translate": "advancement.wizardry:elemental.desc" - }, - "icon": { - "item": "ebwizardry:basic_fire_wand" - } - }, - "parent": "ebwizardry:arcane_initiate", - "criteria": { - "criteria_0": { - "trigger": "ebwizardry:trigger_elemental" - } - } -} \ No newline at end of file diff --git a/src/main/resources/assets/ebwizardry/advancements/enchant_scroll.json b/src/main/resources/assets/ebwizardry/advancements/enchant_scroll.json new file mode 100644 index 00000000..abf5782b --- /dev/null +++ b/src/main/resources/assets/ebwizardry/advancements/enchant_scroll.json @@ -0,0 +1,24 @@ +{ + "display": { + "icon": { + "item": "ebwizardry:scroll" + }, + "title": { + "translate": "advancement.ebwizardry:enchant_scroll" + }, + "description": { + "translate": "advancement.ebwizardry:enchant_scroll.desc" + } + }, + "parent": "ebwizardry:arcane_initiate", + "criteria": { + "criteria_0": { + "trigger": "ebwizardry:arcane_workbench", + "conditions": { + "item": { + "item": "ebwizardry:scroll" + } + } + } + } +} \ No newline at end of file diff --git a/src/main/resources/assets/ebwizardry/advancements/frankenstein.json b/src/main/resources/assets/ebwizardry/advancements/frankenstein.json deleted file mode 100644 index d197636c..00000000 --- a/src/main/resources/assets/ebwizardry/advancements/frankenstein.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "display": { - "title": { - "translate": "advancement.wizardry:frankenstein" - }, - "description": { - "translate": "advancement.wizardry:frankenstein.desc" - }, - "icon": { - "item": "ebwizardry:advanced_lightning_wand" - }, - "frame": "challenge" - }, - "parent": "ebwizardry:charge_creeper", - "criteria": { - "criteria_0": { - "trigger": "ebwizardry:trigger_frankenstein" - } - } -} \ No newline at end of file diff --git a/src/main/resources/assets/ebwizardry/advancements/freeze_blaze.json b/src/main/resources/assets/ebwizardry/advancements/freeze_blaze.json deleted file mode 100644 index 595fdabe..00000000 --- a/src/main/resources/assets/ebwizardry/advancements/freeze_blaze.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "display": { - "title": { - "translate": "advancement.wizardry:freeze_blaze" - }, - "description": { - "translate": "advancement.wizardry:freeze_blaze.desc" - }, - "icon": { - "item": "minecraft:ice" - } - }, - "parent": "ebwizardry:apprentice", - "criteria": { - "criteria_0": { - "trigger": "ebwizardry:trigger_freeze_blaze" - } - } -} \ No newline at end of file diff --git a/src/main/resources/assets/ebwizardry/advancements/handbook/arcane_workbench.json b/src/main/resources/assets/ebwizardry/advancements/handbook/arcane_workbench.json new file mode 100644 index 00000000..0822d951 --- /dev/null +++ b/src/main/resources/assets/ebwizardry/advancements/handbook/arcane_workbench.json @@ -0,0 +1,14 @@ +{ + "criteria": { + "criteria_0": { + "trigger": "minecraft:inventory_changed", + "conditions": { + "items": [ + { + "item": "ebwizardry:arcane_workbench" + } + ] + } + } + } +} \ No newline at end of file diff --git a/src/main/resources/assets/ebwizardry/advancements/handbook/crystal_flowers.json b/src/main/resources/assets/ebwizardry/advancements/handbook/crystal_flowers.json new file mode 100644 index 00000000..b336c1d3 --- /dev/null +++ b/src/main/resources/assets/ebwizardry/advancements/handbook/crystal_flowers.json @@ -0,0 +1,14 @@ +{ + "criteria": { + "criteria_0": { + "trigger": "minecraft:inventory_changed", + "conditions": { + "items": [ + { + "item": "ebwizardry:crystal_flower" + } + ] + } + } + } +} \ No newline at end of file diff --git a/src/main/resources/assets/ebwizardry/advancements/handbook/elements.json b/src/main/resources/assets/ebwizardry/advancements/handbook/elements.json new file mode 100644 index 00000000..de48f0b3 --- /dev/null +++ b/src/main/resources/assets/ebwizardry/advancements/handbook/elements.json @@ -0,0 +1,92 @@ +{ + "criteria": { + "fire": { + "trigger": "minecraft:inventory_changed", + "conditions": { + "items": [ + { + "item": "ebwizardry:magic_crystal", + "data": 1 + } + ] + } + }, + "ice": { + "trigger": "minecraft:inventory_changed", + "conditions": { + "items": [ + { + "item": "ebwizardry:magic_crystal", + "data": 2 + } + ] + } + }, + "lightning": { + "trigger": "minecraft:inventory_changed", + "conditions": { + "items": [ + { + "item": "ebwizardry:magic_crystal", + "data": 3 + } + ] + } + }, + "necromancy": { + "trigger": "minecraft:inventory_changed", + "conditions": { + "items": [ + { + "item": "ebwizardry:magic_crystal", + "data": 4 + } + ] + } + }, + "earth": { + "trigger": "minecraft:inventory_changed", + "conditions": { + "items": [ + { + "item": "ebwizardry:magic_crystal", + "data": 5 + } + ] + } + }, + "sorcery": { + "trigger": "minecraft:inventory_changed", + "conditions": { + "items": [ + { + "item": "ebwizardry:magic_crystal", + "data": 6 + } + ] + } + }, + "healing": { + "trigger": "minecraft:inventory_changed", + "conditions": { + "items": [ + { + "item": "ebwizardry:magic_crystal", + "data": 7 + } + ] + } + } + }, + "requirements": [ + [ + "fire", + "ice", + "lightning", + "necromancy", + "earth", + "sorcery", + "healing" + ] + ] +} \ No newline at end of file diff --git a/src/main/resources/assets/ebwizardry/advancements/handbook/magical_creatures.json b/src/main/resources/assets/ebwizardry/advancements/handbook/magical_creatures.json new file mode 100644 index 00000000..4bcdae10 --- /dev/null +++ b/src/main/resources/assets/ebwizardry/advancements/handbook/magical_creatures.json @@ -0,0 +1,242 @@ +{ + "criteria": { + "ice_wraith": { + "trigger": "minecraft:player_killed_entity", + "conditions": { + "entity": { + "type": "ebwizardry:ice_wraith" + } + } + }, + "lightning_wraith": { + "trigger": "minecraft:player_killed_entity", + "conditions": { + "entity": { + "type": "ebwizardry:lightning_wraith" + } + } + }, + "spirit_wolf": { + "trigger": "minecraft:player_killed_entity", + "conditions": { + "entity": { + "type": "ebwizardry:spirit_wolf" + } + } + }, + "spirit_horse": { + "trigger": "minecraft:player_killed_entity", + "conditions": { + "entity": { + "type": "ebwizardry:spirit_horse" + } + } + }, + "phoenix": { + "trigger": "minecraft:player_killed_entity", + "conditions": { + "entity": { + "type": "ebwizardry:phoenix" + } + } + }, + "ice_giant": { + "trigger": "minecraft:player_killed_entity", + "conditions": { + "entity": { + "type": "ebwizardry:ice_giant" + } + } + }, + "shadow_wraith": { + "trigger": "minecraft:player_killed_entity", + "conditions": { + "entity": { + "type": "ebwizardry:shadow_wraith" + } + } + }, + "storm_elemental": { + "trigger": "minecraft:player_killed_entity", + "conditions": { + "entity": { + "type": "ebwizardry:storm_elemental" + } + } + }, + "silverfish_swarm": { + "trigger": "ebwizardry:cast_spell", + "conditions": { + "spell": { + "spell": "silverfish_swarm" + } + } + }, + "spider_swarm": { + "trigger": "ebwizardry:cast_spell", + "conditions": { + "spell": { + "spell": "spider_swarm" + } + } + }, + "vex_swarm": { + "trigger": "ebwizardry:cast_spell", + "conditions": { + "spell": { + "spell": "vex_swarm" + } + } + }, + "summon_blaze": { + "trigger": "ebwizardry:cast_spell", + "conditions": { + "spell": { + "spell": "summon_blaze" + } + } + }, + "summon_ice_giant": { + "trigger": "ebwizardry:cast_spell", + "conditions": { + "spell": { + "spell": "summon_ice_giant" + } + } + }, + "summon_ice_wraith": { + "trigger": "ebwizardry:cast_spell", + "conditions": { + "spell": { + "spell": "summon_ice_wraith" + } + } + }, + "summon_iron_golem": { + "trigger": "ebwizardry:cast_spell", + "conditions": { + "spell": { + "spell": "summon_iron_golem" + } + } + }, + "summon_lightning_wraith": { + "trigger": "ebwizardry:cast_spell", + "conditions": { + "spell": { + "spell": "summon_lightning_wraith" + } + } + }, + "summon_phoenix": { + "trigger": "ebwizardry:cast_spell", + "conditions": { + "spell": { + "spell": "summon_phoenix" + } + } + }, + "summon_shadow_wraith": { + "trigger": "ebwizardry:cast_spell", + "conditions": { + "spell": { + "spell": "summon_shadow_wraith" + } + } + }, + "summon_skeleton": { + "trigger": "ebwizardry:cast_spell", + "conditions": { + "spell": { + "spell": "summon_skeleton" + } + } + }, + "summon_skeleton_legion": { + "trigger": "ebwizardry:cast_spell", + "conditions": { + "spell": { + "spell": "summon_skeleton_legion" + } + } + }, + "summon_snow_golem": { + "trigger": "ebwizardry:cast_spell", + "conditions": { + "spell": { + "spell": "summon_snow_golem" + } + } + }, + "summon_spirit_horse": { + "trigger": "ebwizardry:cast_spell", + "conditions": { + "spell": { + "spell": "summon_spirit_horse" + } + } + }, + "summon_spirit_wolf": { + "trigger": "ebwizardry:cast_spell", + "conditions": { + "spell": { + "spell": "summon_spirit_wolf" + } + } + }, + "summon_storm_elemental": { + "trigger": "ebwizardry:cast_spell", + "conditions": { + "spell": { + "spell": "summon_storm_elemental" + } + } + }, + "summon_wither_skeleton": { + "trigger": "ebwizardry:cast_spell", + "conditions": { + "spell": { + "spell": "summon_wither_skeleton" + } + } + }, + "summon_zombie": { + "trigger": "ebwizardry:cast_spell", + "conditions": { + "spell": { + "spell": "summon_zombie" + } + } + } + }, + "requirements": [ + [ + "ice_wraith", + "lightning_wraith", + "spirit_wolf", + "spirit_horse", + "phoenix", + "ice_giant", + "shadow_wraith", + "storm_elemental", + "silverfish_swarm", + "spider_swarm", + "vex_swarm", + "summon_blaze", + "summon_ice_giant", + "summon_ice_wraith", + "summon_iron_golem", + "summon_lightning_wraith", + "summon_phoenix", + "summon_shadow_wraith", + "summon_skeleton", + "summon_skeleton_legion", + "summon_snow_golem", + "summon_spirit_horse", + "summon_spirit_wolf", + "summon_storm_elemental", + "summon_wither_skeleton", + "summon_zombie" + ] + ] +} \ No newline at end of file diff --git a/src/main/resources/assets/ebwizardry/advancements/handbook/mana_flasks.json b/src/main/resources/assets/ebwizardry/advancements/handbook/mana_flasks.json new file mode 100644 index 00000000..05c91520 --- /dev/null +++ b/src/main/resources/assets/ebwizardry/advancements/handbook/mana_flasks.json @@ -0,0 +1,10 @@ +{ + "criteria": { + "criteria_0": { + "trigger": "minecraft:recipe_unlocked", + "conditions": { + "recipe": "ebwizardry:medium_mana_flask" + } + } + } +} \ No newline at end of file diff --git a/src/main/resources/assets/ebwizardry/advancements/handbook/obelisks.json b/src/main/resources/assets/ebwizardry/advancements/handbook/obelisks.json new file mode 100644 index 00000000..07f802c8 --- /dev/null +++ b/src/main/resources/assets/ebwizardry/advancements/handbook/obelisks.json @@ -0,0 +1,10 @@ +{ + "criteria": { + "criteria_0": { + "trigger": "ebwizardry:visit_structure", + "conditions": { + "structure_type": "obelisk" + } + } + } +} \ No newline at end of file diff --git a/src/main/resources/assets/ebwizardry/advancements/handbook/on_subsection_unlock.json b/src/main/resources/assets/ebwizardry/advancements/handbook/on_subsection_unlock.json new file mode 100644 index 00000000..52e2393c --- /dev/null +++ b/src/main/resources/assets/ebwizardry/advancements/handbook/on_subsection_unlock.json @@ -0,0 +1,7 @@ +{ + "criteria": { + "criteria_0": { + "trigger": "minecraft:impossible" + } + } +} \ No newline at end of file diff --git a/src/main/resources/assets/ebwizardry/advancements/handbook/scrolls.json b/src/main/resources/assets/ebwizardry/advancements/handbook/scrolls.json new file mode 100644 index 00000000..22dfe99a --- /dev/null +++ b/src/main/resources/assets/ebwizardry/advancements/handbook/scrolls.json @@ -0,0 +1,14 @@ +{ + "criteria": { + "criteria_0": { + "trigger": "minecraft:inventory_changed", + "conditions": { + "items": [ + { + "item": "ebwizardry:scroll" + } + ] + } + } + } +} \ No newline at end of file diff --git a/src/main/resources/assets/ebwizardry/advancements/handbook/spells.json b/src/main/resources/assets/ebwizardry/advancements/handbook/spells.json new file mode 100644 index 00000000..1bc8d817 --- /dev/null +++ b/src/main/resources/assets/ebwizardry/advancements/handbook/spells.json @@ -0,0 +1,14 @@ +{ + "criteria": { + "criteria_0": { + "trigger": "minecraft:inventory_changed", + "conditions": { + "items": [ + { + "item": "ebwizardry:spell_book" + } + ] + } + } + } +} \ No newline at end of file diff --git a/src/main/resources/assets/ebwizardry/advancements/handbook/throwables.json b/src/main/resources/assets/ebwizardry/advancements/handbook/throwables.json new file mode 100644 index 00000000..43b8e1e9 --- /dev/null +++ b/src/main/resources/assets/ebwizardry/advancements/handbook/throwables.json @@ -0,0 +1,14 @@ +{ + "criteria": { + "criteria_0": { + "trigger": "minecraft:inventory_changed", + "conditions": { + "items": [ + { + "item": "ebwizardry:firebomb" + } + ] + } + } + } +} \ No newline at end of file diff --git a/src/main/resources/assets/ebwizardry/advancements/handbook/tome_of_arcana.json b/src/main/resources/assets/ebwizardry/advancements/handbook/tome_of_arcana.json new file mode 100644 index 00000000..40ee0c46 --- /dev/null +++ b/src/main/resources/assets/ebwizardry/advancements/handbook/tome_of_arcana.json @@ -0,0 +1,14 @@ +{ + "criteria": { + "criteria_0": { + "trigger": "minecraft:inventory_changed", + "conditions": { + "items": [ + { + "item": "ebwizardry:arcane_tome" + } + ] + } + } + } +} \ No newline at end of file diff --git a/src/main/resources/assets/ebwizardry/advancements/identify_spell.json b/src/main/resources/assets/ebwizardry/advancements/identify_spell.json index 3f58890b..b8c1aaae 100644 --- a/src/main/resources/assets/ebwizardry/advancements/identify_spell.json +++ b/src/main/resources/assets/ebwizardry/advancements/identify_spell.json @@ -1,19 +1,22 @@ { "display": { "title": { - "translate": "advancement.wizardry:identify_spell" + "translate": "advancement.ebwizardry:identify_spell" }, "description": { - "translate": "advancement.wizardry:identify_spell.desc" + "translate": "advancement.ebwizardry:identify_spell.desc" }, "icon": { "item": "ebwizardry:identification_scroll" } }, - "parent": "ebwizardry:arcane_initiate", + "parent": "ebwizardry:discover_spell", "criteria": { "criteria_0": { - "trigger": "ebwizardry:trigger_identify_spell" + "trigger": "ebwizardry:discover_spell", + "conditions": { + "source": "identification_scroll" + } } } } \ No newline at end of file diff --git a/src/main/resources/assets/ebwizardry/advancements/jam_wizard.json b/src/main/resources/assets/ebwizardry/advancements/jam_wizard.json deleted file mode 100644 index f860835e..00000000 --- a/src/main/resources/assets/ebwizardry/advancements/jam_wizard.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "display": { - "title": { - "translate": "advancement.wizardry:jam_wizard" - }, - "description": { - "translate": "advancement.wizardry:jam_wizard.desc" - }, - "icon": { - "item": "minecraft:web" - } - }, - "parent": "ebwizardry:apprentice", - "criteria": { - "criteria_0": { - "trigger": "ebwizardry:trigger_jam_wizard" - } - } -} \ No newline at end of file diff --git a/src/main/resources/assets/ebwizardry/advancements/legendary.json b/src/main/resources/assets/ebwizardry/advancements/legendary.json index f1473e47..691e7a2b 100644 --- a/src/main/resources/assets/ebwizardry/advancements/legendary.json +++ b/src/main/resources/assets/ebwizardry/advancements/legendary.json @@ -1,10 +1,10 @@ { "display": { "title": { - "translate": "advancement.wizardry:legendary" + "translate": "advancement.ebwizardry:legendary" }, "description": { - "translate": "advancement.wizardry:legendary.desc" + "translate": "advancement.ebwizardry:legendary.desc" }, "icon": { "item": "ebwizardry:armour_upgrade" diff --git a/src/main/resources/assets/ebwizardry/advancements/master.json b/src/main/resources/assets/ebwizardry/advancements/master.json index bd6b24fe..12236cbf 100644 --- a/src/main/resources/assets/ebwizardry/advancements/master.json +++ b/src/main/resources/assets/ebwizardry/advancements/master.json @@ -1,19 +1,108 @@ { "display": { "title": { - "translate": "advancement.wizardry:master" + "translate": "advancement.ebwizardry:master" }, "description": { - "translate": "advancement.wizardry:master.desc" + "translate": "advancement.ebwizardry:master.desc" }, "icon": { "item": "ebwizardry:master_wand" } }, - "parent": "ebwizardry:apprentice", + "parent": "ebwizardry:advanced", "criteria": { - "criteria_0": { - "trigger": "ebwizardry:trigger_master" + "magic": { + "trigger": "minecraft:inventory_changed", + "conditions": { + "items": [ + { + "item": "ebwizardry:master_wand" + } + ] + } + }, + "fire": { + "trigger": "minecraft:inventory_changed", + "conditions": { + "items": [ + { + "item": "ebwizardry:master_fire_wand" + } + ] + } + }, + "ice": { + "trigger": "minecraft:inventory_changed", + "conditions": { + "items": [ + { + "item": "ebwizardry:master_ice_wand" + } + ] + } + }, + "lightning": { + "trigger": "minecraft:inventory_changed", + "conditions": { + "items": [ + { + "item": "ebwizardry:master_lightning_wand" + } + ] + } + }, + "necromancy": { + "trigger": "minecraft:inventory_changed", + "conditions": { + "items": [ + { + "item": "ebwizardry:master_necromancy_wand" + } + ] + } + }, + "earth": { + "trigger": "minecraft:inventory_changed", + "conditions": { + "items": [ + { + "item": "ebwizardry:master_earth_wand" + } + ] + } + }, + "sorcery": { + "trigger": "minecraft:inventory_changed", + "conditions": { + "items": [ + { + "item": "ebwizardry:master_sorcery_wand" + } + ] + } + }, + "healing": { + "trigger": "minecraft:inventory_changed", + "conditions": { + "items": [ + { + "item": "ebwizardry:master_healing_wand" + } + ] + } } - } + }, + "requirements": [ + [ + "magic", + "fire", + "ice", + "lightning", + "necromancy", + "earth", + "sorcery", + "healing" + ] + ] } \ No newline at end of file diff --git a/src/main/resources/assets/ebwizardry/advancements/max_out_wand.json b/src/main/resources/assets/ebwizardry/advancements/max_out_wand.json index 2a779459..7a571967 100644 --- a/src/main/resources/assets/ebwizardry/advancements/max_out_wand.json +++ b/src/main/resources/assets/ebwizardry/advancements/max_out_wand.json @@ -1,17 +1,17 @@ { "display": { "title": { - "translate": "advancement.wizardry:max_out_wand" + "translate": "advancement.ebwizardry:max_out_wand" }, "description": { - "translate": "advancement.wizardry:max_out_wand.desc" + "translate": "advancement.ebwizardry:max_out_wand.desc" }, "icon": { "item": "ebwizardry:arcane_tome" }, "frame": "goal" }, - "parent": "ebwizardry:special_upgrade", + "parent": "ebwizardry:master", "criteria": { "criteria_0": { "trigger": "ebwizardry:trigger_max_out_wand" diff --git a/src/main/resources/assets/ebwizardry/advancements/pig_tornado.json b/src/main/resources/assets/ebwizardry/advancements/pig_tornado.json deleted file mode 100644 index 04770269..00000000 --- a/src/main/resources/assets/ebwizardry/advancements/pig_tornado.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "display": { - "title": { - "translate": "advancement.wizardry:pig_tornado" - }, - "description": { - "translate": "advancement.wizardry:pig_tornado.desc" - }, - "icon": { - "item": "minecraft:saddle" - }, - "frame": "challenge" - }, - "parent": "ebwizardry:apprentice", - "criteria": { - "criteria_0": { - "trigger": "ebwizardry:trigger_pig_tornado" - } - } -} \ No newline at end of file diff --git a/src/main/resources/assets/ebwizardry/advancements/root.json b/src/main/resources/assets/ebwizardry/advancements/root.json index 63212c97..6c80c1fb 100644 --- a/src/main/resources/assets/ebwizardry/advancements/root.json +++ b/src/main/resources/assets/ebwizardry/advancements/root.json @@ -1,10 +1,10 @@ { "display": { "title": { - "translate": "advancement.wizardry:root" + "translate": "advancement.ebwizardry:root" }, "description": { - "translate": "advancement.wizardry:root.desc" + "translate": "advancement.ebwizardry:root.desc" }, "show_toast": false, "announce_to_chat": false, diff --git a/src/main/resources/assets/ebwizardry/advancements/self_destruct.json b/src/main/resources/assets/ebwizardry/advancements/self_destruct.json deleted file mode 100644 index d0253a73..00000000 --- a/src/main/resources/assets/ebwizardry/advancements/self_destruct.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "display": { - "title": { - "translate": "advancement.wizardry:self_destruct" - }, - "description": { - "translate": "advancement.wizardry:self_destruct.desc" - }, - "icon": { - "item": "minecraft:pumpkin" - }, - "frame": "challenge" - }, - "parent": "ebwizardry:arcane_initiate", - "criteria": { - "criteria_0": { - "trigger": "ebwizardry:trigger_self_destruct" - } - } -} \ No newline at end of file diff --git a/src/main/resources/assets/ebwizardry/advancements/slime_skeleton.json b/src/main/resources/assets/ebwizardry/advancements/slime_skeleton.json deleted file mode 100644 index 90a982bb..00000000 --- a/src/main/resources/assets/ebwizardry/advancements/slime_skeleton.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "display": { - "title": { - "translate": "advancement.wizardry:slime_skeleton" - }, - "description": { - "translate": "advancement.wizardry:slime_skeleton.desc" - }, - "icon": { - "item": "minecraft:slime_ball" - } - }, - "parent": "ebwizardry:apprentice", - "criteria": { - "criteria_0": { - "trigger": "ebwizardry:trigger_slime_skeleton" - } - } -} \ No newline at end of file diff --git a/src/main/resources/assets/ebwizardry/advancements/special_upgrade.json b/src/main/resources/assets/ebwizardry/advancements/special_upgrade.json index 41b48fd4..324c4973 100644 --- a/src/main/resources/assets/ebwizardry/advancements/special_upgrade.json +++ b/src/main/resources/assets/ebwizardry/advancements/special_upgrade.json @@ -1,16 +1,16 @@ { "display": { "title": { - "translate": "advancement.wizardry:special_upgrade" + "translate": "advancement.ebwizardry:special_upgrade" }, "description": { - "translate": "advancement.wizardry:special_upgrade.desc" + "translate": "advancement.ebwizardry:special_upgrade.desc" }, "icon": { "item": "ebwizardry:condenser_upgrade" } }, - "parent": "ebwizardry:arcane_initiate", + "parent": "ebwizardry:apprentice", "criteria": { "criteria_0": { "trigger": "ebwizardry:trigger_special_upgrade" diff --git a/src/main/resources/assets/ebwizardry/advancements/spell_failure.json b/src/main/resources/assets/ebwizardry/advancements/spell_failure.json new file mode 100644 index 00000000..eed72bdf --- /dev/null +++ b/src/main/resources/assets/ebwizardry/advancements/spell_failure.json @@ -0,0 +1,19 @@ +{ + "display": { + "title": { + "translate": "advancement.ebwizardry:spell_failure" + }, + "description": { + "translate": "advancement.ebwizardry:spell_failure.desc" + }, + "icon": { + "item": "minecraft:pumpkin" + } + }, + "parent": "ebwizardry:discover_spell", + "criteria": { + "criteria_0": { + "trigger": "ebwizardry:trigger_spell_failure" + } + } +} \ No newline at end of file diff --git a/src/main/resources/assets/ebwizardry/advancements/visit_shrine.json b/src/main/resources/assets/ebwizardry/advancements/visit_shrine.json new file mode 100644 index 00000000..01060fb9 --- /dev/null +++ b/src/main/resources/assets/ebwizardry/advancements/visit_shrine.json @@ -0,0 +1,23 @@ +{ + "display": { + "title": { + "translate": "advancement.ebwizardry:visit_shrine" + }, + "description": { + "translate": "advancement.ebwizardry:visit_shrine.desc" + }, + "icon": { + "item": "ebwizardry:runestone", + "data": 5 + } + }, + "parent": "ebwizardry:defeat_evil_wizard", + "criteria": { + "criteria_0": { + "trigger": "ebwizardry:visit_structure", + "conditions": { + "structure_type": "shrine" + } + } + } +} \ No newline at end of file diff --git a/src/main/resources/assets/ebwizardry/advancements/wizard_tower.json b/src/main/resources/assets/ebwizardry/advancements/wizard_tower.json new file mode 100644 index 00000000..2bdd8c0e --- /dev/null +++ b/src/main/resources/assets/ebwizardry/advancements/wizard_tower.json @@ -0,0 +1,22 @@ +{ + "display": { + "title": { + "translate": "advancement.ebwizardry:wizard_tower" + }, + "description": { + "translate": "advancement.ebwizardry:wizard_tower.desc" + }, + "icon": { + "item": "minecraft:bookshelf" + } + }, + "parent": "ebwizardry:arcane_initiate", + "criteria": { + "criteria_0": { + "trigger": "ebwizardry:visit_structure", + "conditions": { + "structure_type": "wizard_tower" + } + } + } +} \ No newline at end of file diff --git a/src/main/resources/assets/ebwizardry/advancements/wizard_trade.json b/src/main/resources/assets/ebwizardry/advancements/wizard_trade.json index b5e6312d..f86668ab 100644 --- a/src/main/resources/assets/ebwizardry/advancements/wizard_trade.json +++ b/src/main/resources/assets/ebwizardry/advancements/wizard_trade.json @@ -1,16 +1,16 @@ { "display": { "title": { - "translate": "advancement.wizardry:wizard_trade" + "translate": "advancement.ebwizardry:wizard_trade" }, "description": { - "translate": "advancement.wizardry:wizard_trade.desc" + "translate": "advancement.ebwizardry:wizard_trade.desc" }, "icon": { "item": "minecraft:emerald" } }, - "parent": "ebwizardry:arcane_initiate", + "parent": "ebwizardry:wizard_tower", "criteria": { "criteria_0": { "trigger": "ebwizardry:trigger_wizard_trade" diff --git a/src/main/resources/assets/ebwizardry/blockstates/crystal_block.json b/src/main/resources/assets/ebwizardry/blockstates/crystal_block.json deleted file mode 100644 index e86e78b6..00000000 --- a/src/main/resources/assets/ebwizardry/blockstates/crystal_block.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "forge_marker": 1, - "variants": { - "normal": { "model": "ebwizardry:crystal_block" } - } -} diff --git a/src/main/resources/assets/ebwizardry/blockstates/dry_frosted_ice.json b/src/main/resources/assets/ebwizardry/blockstates/dry_frosted_ice.json new file mode 100644 index 00000000..6ed17a19 --- /dev/null +++ b/src/main/resources/assets/ebwizardry/blockstates/dry_frosted_ice.json @@ -0,0 +1,8 @@ +{ + "variants": { + "age=0": { "model": "minecraft:frosted_ice_0" }, + "age=1": { "model": "minecraft:frosted_ice_1" }, + "age=2": { "model": "minecraft:frosted_ice_2" }, + "age=3": { "model": "minecraft:frosted_ice_3" } + } +} diff --git a/src/main/resources/assets/ebwizardry/blockstates/earth_crystal_block.json b/src/main/resources/assets/ebwizardry/blockstates/earth_crystal_block.json new file mode 100644 index 00000000..b2e41d3a --- /dev/null +++ b/src/main/resources/assets/ebwizardry/blockstates/earth_crystal_block.json @@ -0,0 +1,6 @@ +{ + "forge_marker": 1, + "variants": { + "normal": { "model": "ebwizardry:earth_crystal_block" } + } +} diff --git a/src/main/resources/assets/ebwizardry/blockstates/earth_runestone.json b/src/main/resources/assets/ebwizardry/blockstates/earth_runestone.json new file mode 100644 index 00000000..235ad22c --- /dev/null +++ b/src/main/resources/assets/ebwizardry/blockstates/earth_runestone.json @@ -0,0 +1,31 @@ +{ + "forge_marker": 1, + "variants": { + "normal": [ + { "model": "ebwizardry:earth_runestone_1", "uvlock": true }, + { "model": "ebwizardry:earth_runestone_1", "uvlock": true, "y": 90 }, + { "model": "ebwizardry:earth_runestone_1", "uvlock": true, "y": 180 }, + { "model": "ebwizardry:earth_runestone_1", "uvlock": true, "y": 270 }, + { "model": "ebwizardry:earth_runestone_1", "uvlock": true, "x": 90 }, + { "model": "ebwizardry:earth_runestone_1", "uvlock": true, "x": 270 }, + { "model": "ebwizardry:earth_runestone_2", "uvlock": true }, + { "model": "ebwizardry:earth_runestone_2", "uvlock": true, "y": 90 }, + { "model": "ebwizardry:earth_runestone_2", "uvlock": true, "y": 180 }, + { "model": "ebwizardry:earth_runestone_2", "uvlock": true, "y": 270 }, + { "model": "ebwizardry:earth_runestone_2", "uvlock": true, "x": 90 }, + { "model": "ebwizardry:earth_runestone_2", "uvlock": true, "x": 270 }, + { "model": "ebwizardry:earth_runestone_3", "uvlock": true }, + { "model": "ebwizardry:earth_runestone_3", "uvlock": true, "y": 90 }, + { "model": "ebwizardry:earth_runestone_3", "uvlock": true, "y": 180 }, + { "model": "ebwizardry:earth_runestone_3", "uvlock": true, "y": 270 }, + { "model": "ebwizardry:earth_runestone_3", "uvlock": true, "x": 90 }, + { "model": "ebwizardry:earth_runestone_3", "uvlock": true, "x": 270 }, + { "model": "ebwizardry:earth_runestone_4", "uvlock": true }, + { "model": "ebwizardry:earth_runestone_4", "uvlock": true, "y": 90 }, + { "model": "ebwizardry:earth_runestone_4", "uvlock": true, "y": 180 }, + { "model": "ebwizardry:earth_runestone_4", "uvlock": true, "y": 270 }, + { "model": "ebwizardry:earth_runestone_4", "uvlock": true, "x": 90 }, + { "model": "ebwizardry:earth_runestone_4", "uvlock": true, "x": 270 } + ] + } +} \ No newline at end of file diff --git a/src/main/resources/assets/ebwizardry/blockstates/earth_runestone_pedestal.json b/src/main/resources/assets/ebwizardry/blockstates/earth_runestone_pedestal.json new file mode 100644 index 00000000..1eda064c --- /dev/null +++ b/src/main/resources/assets/ebwizardry/blockstates/earth_runestone_pedestal.json @@ -0,0 +1,6 @@ +{ + "forge_marker": 1, + "variants": { + "normal": { "model": "ebwizardry:earth_runestone_pedestal" } + } +} \ No newline at end of file diff --git a/src/main/resources/assets/ebwizardry/blockstates/fire_crystal_block.json b/src/main/resources/assets/ebwizardry/blockstates/fire_crystal_block.json new file mode 100644 index 00000000..05979ee4 --- /dev/null +++ b/src/main/resources/assets/ebwizardry/blockstates/fire_crystal_block.json @@ -0,0 +1,6 @@ +{ + "forge_marker": 1, + "variants": { + "normal": { "model": "ebwizardry:fire_crystal_block" } + } +} diff --git a/src/main/resources/assets/ebwizardry/blockstates/fire_runestone.json b/src/main/resources/assets/ebwizardry/blockstates/fire_runestone.json new file mode 100644 index 00000000..8fbbdbc1 --- /dev/null +++ b/src/main/resources/assets/ebwizardry/blockstates/fire_runestone.json @@ -0,0 +1,31 @@ +{ + "forge_marker": 1, + "variants": { + "normal": [ + { "model": "ebwizardry:fire_runestone_1", "uvlock": true }, + { "model": "ebwizardry:fire_runestone_1", "uvlock": true, "y": 90 }, + { "model": "ebwizardry:fire_runestone_1", "uvlock": true, "y": 180 }, + { "model": "ebwizardry:fire_runestone_1", "uvlock": true, "y": 270 }, + { "model": "ebwizardry:fire_runestone_1", "uvlock": true, "x": 90 }, + { "model": "ebwizardry:fire_runestone_1", "uvlock": true, "x": 270 }, + { "model": "ebwizardry:fire_runestone_2", "uvlock": true }, + { "model": "ebwizardry:fire_runestone_2", "uvlock": true, "y": 90 }, + { "model": "ebwizardry:fire_runestone_2", "uvlock": true, "y": 180 }, + { "model": "ebwizardry:fire_runestone_2", "uvlock": true, "y": 270 }, + { "model": "ebwizardry:fire_runestone_2", "uvlock": true, "x": 90 }, + { "model": "ebwizardry:fire_runestone_2", "uvlock": true, "x": 270 }, + { "model": "ebwizardry:fire_runestone_3", "uvlock": true }, + { "model": "ebwizardry:fire_runestone_3", "uvlock": true, "y": 90 }, + { "model": "ebwizardry:fire_runestone_3", "uvlock": true, "y": 180 }, + { "model": "ebwizardry:fire_runestone_3", "uvlock": true, "y": 270 }, + { "model": "ebwizardry:fire_runestone_3", "uvlock": true, "x": 90 }, + { "model": "ebwizardry:fire_runestone_3", "uvlock": true, "x": 270 }, + { "model": "ebwizardry:fire_runestone_4", "uvlock": true }, + { "model": "ebwizardry:fire_runestone_4", "uvlock": true, "y": 90 }, + { "model": "ebwizardry:fire_runestone_4", "uvlock": true, "y": 180 }, + { "model": "ebwizardry:fire_runestone_4", "uvlock": true, "y": 270 }, + { "model": "ebwizardry:fire_runestone_4", "uvlock": true, "x": 90 }, + { "model": "ebwizardry:fire_runestone_4", "uvlock": true, "x": 270 } + ] + } +} \ No newline at end of file diff --git a/src/main/resources/assets/ebwizardry/blockstates/fire_runestone_pedestal.json b/src/main/resources/assets/ebwizardry/blockstates/fire_runestone_pedestal.json new file mode 100644 index 00000000..d7a37acc --- /dev/null +++ b/src/main/resources/assets/ebwizardry/blockstates/fire_runestone_pedestal.json @@ -0,0 +1,6 @@ +{ + "forge_marker": 1, + "variants": { + "normal": { "model": "ebwizardry:fire_runestone_pedestal" } + } +} \ No newline at end of file diff --git a/src/main/resources/assets/ebwizardry/blockstates/healing_crystal_block.json b/src/main/resources/assets/ebwizardry/blockstates/healing_crystal_block.json new file mode 100644 index 00000000..37b3f3a6 --- /dev/null +++ b/src/main/resources/assets/ebwizardry/blockstates/healing_crystal_block.json @@ -0,0 +1,6 @@ +{ + "forge_marker": 1, + "variants": { + "normal": { "model": "ebwizardry:healing_crystal_block" } + } +} diff --git a/src/main/resources/assets/ebwizardry/blockstates/healing_runestone.json b/src/main/resources/assets/ebwizardry/blockstates/healing_runestone.json new file mode 100644 index 00000000..c2af1a54 --- /dev/null +++ b/src/main/resources/assets/ebwizardry/blockstates/healing_runestone.json @@ -0,0 +1,31 @@ +{ + "forge_marker": 1, + "variants": { + "normal": [ + { "model": "ebwizardry:healing_runestone_1", "uvlock": true }, + { "model": "ebwizardry:healing_runestone_1", "uvlock": true, "y": 90 }, + { "model": "ebwizardry:healing_runestone_1", "uvlock": true, "y": 180 }, + { "model": "ebwizardry:healing_runestone_1", "uvlock": true, "y": 270 }, + { "model": "ebwizardry:healing_runestone_1", "uvlock": true, "x": 90 }, + { "model": "ebwizardry:healing_runestone_1", "uvlock": true, "x": 270 }, + { "model": "ebwizardry:healing_runestone_2", "uvlock": true }, + { "model": "ebwizardry:healing_runestone_2", "uvlock": true, "y": 90 }, + { "model": "ebwizardry:healing_runestone_2", "uvlock": true, "y": 180 }, + { "model": "ebwizardry:healing_runestone_2", "uvlock": true, "y": 270 }, + { "model": "ebwizardry:healing_runestone_2", "uvlock": true, "x": 90 }, + { "model": "ebwizardry:healing_runestone_2", "uvlock": true, "x": 270 }, + { "model": "ebwizardry:healing_runestone_3", "uvlock": true }, + { "model": "ebwizardry:healing_runestone_3", "uvlock": true, "y": 90 }, + { "model": "ebwizardry:healing_runestone_3", "uvlock": true, "y": 180 }, + { "model": "ebwizardry:healing_runestone_3", "uvlock": true, "y": 270 }, + { "model": "ebwizardry:healing_runestone_3", "uvlock": true, "x": 90 }, + { "model": "ebwizardry:healing_runestone_3", "uvlock": true, "x": 270 }, + { "model": "ebwizardry:healing_runestone_4", "uvlock": true }, + { "model": "ebwizardry:healing_runestone_4", "uvlock": true, "y": 90 }, + { "model": "ebwizardry:healing_runestone_4", "uvlock": true, "y": 180 }, + { "model": "ebwizardry:healing_runestone_4", "uvlock": true, "y": 270 }, + { "model": "ebwizardry:healing_runestone_4", "uvlock": true, "x": 90 }, + { "model": "ebwizardry:healing_runestone_4", "uvlock": true, "x": 270 } + ] + } +} \ No newline at end of file diff --git a/src/main/resources/assets/ebwizardry/blockstates/healing_runestone_pedestal.json b/src/main/resources/assets/ebwizardry/blockstates/healing_runestone_pedestal.json new file mode 100644 index 00000000..c1017a01 --- /dev/null +++ b/src/main/resources/assets/ebwizardry/blockstates/healing_runestone_pedestal.json @@ -0,0 +1,6 @@ +{ + "forge_marker": 1, + "variants": { + "normal": { "model": "ebwizardry:healing_runestone_pedestal" } + } +} \ No newline at end of file diff --git a/src/main/resources/assets/ebwizardry/blockstates/ice_crystal_block.json b/src/main/resources/assets/ebwizardry/blockstates/ice_crystal_block.json new file mode 100644 index 00000000..711ad5d9 --- /dev/null +++ b/src/main/resources/assets/ebwizardry/blockstates/ice_crystal_block.json @@ -0,0 +1,6 @@ +{ + "forge_marker": 1, + "variants": { + "normal": { "model": "ebwizardry:ice_crystal_block" } + } +} diff --git a/src/main/resources/assets/ebwizardry/blockstates/ice_runestone.json b/src/main/resources/assets/ebwizardry/blockstates/ice_runestone.json new file mode 100644 index 00000000..b50a395f --- /dev/null +++ b/src/main/resources/assets/ebwizardry/blockstates/ice_runestone.json @@ -0,0 +1,31 @@ +{ + "forge_marker": 1, + "variants": { + "normal": [ + { "model": "ebwizardry:ice_runestone_1", "uvlock": true }, + { "model": "ebwizardry:ice_runestone_1", "uvlock": true, "y": 90 }, + { "model": "ebwizardry:ice_runestone_1", "uvlock": true, "y": 180 }, + { "model": "ebwizardry:ice_runestone_1", "uvlock": true, "y": 270 }, + { "model": "ebwizardry:ice_runestone_1", "uvlock": true, "x": 90 }, + { "model": "ebwizardry:ice_runestone_1", "uvlock": true, "x": 270 }, + { "model": "ebwizardry:ice_runestone_2", "uvlock": true }, + { "model": "ebwizardry:ice_runestone_2", "uvlock": true, "y": 90 }, + { "model": "ebwizardry:ice_runestone_2", "uvlock": true, "y": 180 }, + { "model": "ebwizardry:ice_runestone_2", "uvlock": true, "y": 270 }, + { "model": "ebwizardry:ice_runestone_2", "uvlock": true, "x": 90 }, + { "model": "ebwizardry:ice_runestone_2", "uvlock": true, "x": 270 }, + { "model": "ebwizardry:ice_runestone_3", "uvlock": true }, + { "model": "ebwizardry:ice_runestone_3", "uvlock": true, "y": 90 }, + { "model": "ebwizardry:ice_runestone_3", "uvlock": true, "y": 180 }, + { "model": "ebwizardry:ice_runestone_3", "uvlock": true, "y": 270 }, + { "model": "ebwizardry:ice_runestone_3", "uvlock": true, "x": 90 }, + { "model": "ebwizardry:ice_runestone_3", "uvlock": true, "x": 270 }, + { "model": "ebwizardry:ice_runestone_4", "uvlock": true }, + { "model": "ebwizardry:ice_runestone_4", "uvlock": true, "y": 90 }, + { "model": "ebwizardry:ice_runestone_4", "uvlock": true, "y": 180 }, + { "model": "ebwizardry:ice_runestone_4", "uvlock": true, "y": 270 }, + { "model": "ebwizardry:ice_runestone_4", "uvlock": true, "x": 90 }, + { "model": "ebwizardry:ice_runestone_4", "uvlock": true, "x": 270 } + ] + } +} \ No newline at end of file diff --git a/src/main/resources/assets/ebwizardry/blockstates/ice_runestone_pedestal.json b/src/main/resources/assets/ebwizardry/blockstates/ice_runestone_pedestal.json new file mode 100644 index 00000000..d11cb9a1 --- /dev/null +++ b/src/main/resources/assets/ebwizardry/blockstates/ice_runestone_pedestal.json @@ -0,0 +1,6 @@ +{ + "forge_marker": 1, + "variants": { + "normal": { "model": "ebwizardry:ice_runestone_pedestal" } + } +} \ No newline at end of file diff --git a/src/main/resources/assets/ebwizardry/blockstates/lightning_crystal_block.json b/src/main/resources/assets/ebwizardry/blockstates/lightning_crystal_block.json new file mode 100644 index 00000000..5b8deac4 --- /dev/null +++ b/src/main/resources/assets/ebwizardry/blockstates/lightning_crystal_block.json @@ -0,0 +1,6 @@ +{ + "forge_marker": 1, + "variants": { + "normal": { "model": "ebwizardry:lightning_crystal_block" } + } +} diff --git a/src/main/resources/assets/ebwizardry/blockstates/lightning_runestone.json b/src/main/resources/assets/ebwizardry/blockstates/lightning_runestone.json new file mode 100644 index 00000000..9905b6ef --- /dev/null +++ b/src/main/resources/assets/ebwizardry/blockstates/lightning_runestone.json @@ -0,0 +1,31 @@ +{ + "forge_marker": 1, + "variants": { + "normal": [ + { "model": "ebwizardry:lightning_runestone_1", "uvlock": true }, + { "model": "ebwizardry:lightning_runestone_1", "uvlock": true, "y": 90 }, + { "model": "ebwizardry:lightning_runestone_1", "uvlock": true, "y": 180 }, + { "model": "ebwizardry:lightning_runestone_1", "uvlock": true, "y": 270 }, + { "model": "ebwizardry:lightning_runestone_1", "uvlock": true, "x": 90 }, + { "model": "ebwizardry:lightning_runestone_1", "uvlock": true, "x": 270 }, + { "model": "ebwizardry:lightning_runestone_2", "uvlock": true }, + { "model": "ebwizardry:lightning_runestone_2", "uvlock": true, "y": 90 }, + { "model": "ebwizardry:lightning_runestone_2", "uvlock": true, "y": 180 }, + { "model": "ebwizardry:lightning_runestone_2", "uvlock": true, "y": 270 }, + { "model": "ebwizardry:lightning_runestone_2", "uvlock": true, "x": 90 }, + { "model": "ebwizardry:lightning_runestone_2", "uvlock": true, "x": 270 }, + { "model": "ebwizardry:lightning_runestone_3", "uvlock": true }, + { "model": "ebwizardry:lightning_runestone_3", "uvlock": true, "y": 90 }, + { "model": "ebwizardry:lightning_runestone_3", "uvlock": true, "y": 180 }, + { "model": "ebwizardry:lightning_runestone_3", "uvlock": true, "y": 270 }, + { "model": "ebwizardry:lightning_runestone_3", "uvlock": true, "x": 90 }, + { "model": "ebwizardry:lightning_runestone_3", "uvlock": true, "x": 270 }, + { "model": "ebwizardry:lightning_runestone_4", "uvlock": true }, + { "model": "ebwizardry:lightning_runestone_4", "uvlock": true, "y": 90 }, + { "model": "ebwizardry:lightning_runestone_4", "uvlock": true, "y": 180 }, + { "model": "ebwizardry:lightning_runestone_4", "uvlock": true, "y": 270 }, + { "model": "ebwizardry:lightning_runestone_4", "uvlock": true, "x": 90 }, + { "model": "ebwizardry:lightning_runestone_4", "uvlock": true, "x": 270 } + ] + } +} \ No newline at end of file diff --git a/src/main/resources/assets/ebwizardry/blockstates/lightning_runestone_pedestal.json b/src/main/resources/assets/ebwizardry/blockstates/lightning_runestone_pedestal.json new file mode 100644 index 00000000..42616710 --- /dev/null +++ b/src/main/resources/assets/ebwizardry/blockstates/lightning_runestone_pedestal.json @@ -0,0 +1,6 @@ +{ + "forge_marker": 1, + "variants": { + "normal": { "model": "ebwizardry:lightning_runestone_pedestal" } + } +} \ No newline at end of file diff --git a/src/main/resources/assets/ebwizardry/blockstates/magic_crystal_block.json b/src/main/resources/assets/ebwizardry/blockstates/magic_crystal_block.json new file mode 100644 index 00000000..f3f2353c --- /dev/null +++ b/src/main/resources/assets/ebwizardry/blockstates/magic_crystal_block.json @@ -0,0 +1,6 @@ +{ + "forge_marker": 1, + "variants": { + "normal": { "model": "ebwizardry:magic_crystal_block" } + } +} diff --git a/src/main/resources/assets/ebwizardry/blockstates/necromancy_crystal_block.json b/src/main/resources/assets/ebwizardry/blockstates/necromancy_crystal_block.json new file mode 100644 index 00000000..bfe3888a --- /dev/null +++ b/src/main/resources/assets/ebwizardry/blockstates/necromancy_crystal_block.json @@ -0,0 +1,6 @@ +{ + "forge_marker": 1, + "variants": { + "normal": { "model": "ebwizardry:necromancy_crystal_block" } + } +} diff --git a/src/main/resources/assets/ebwizardry/blockstates/necromancy_runestone.json b/src/main/resources/assets/ebwizardry/blockstates/necromancy_runestone.json new file mode 100644 index 00000000..3541a5fd --- /dev/null +++ b/src/main/resources/assets/ebwizardry/blockstates/necromancy_runestone.json @@ -0,0 +1,31 @@ +{ + "forge_marker": 1, + "variants": { + "normal": [ + { "model": "ebwizardry:necromancy_runestone_1", "uvlock": true }, + { "model": "ebwizardry:necromancy_runestone_1", "uvlock": true, "y": 90 }, + { "model": "ebwizardry:necromancy_runestone_1", "uvlock": true, "y": 180 }, + { "model": "ebwizardry:necromancy_runestone_1", "uvlock": true, "y": 270 }, + { "model": "ebwizardry:necromancy_runestone_1", "uvlock": true, "x": 90 }, + { "model": "ebwizardry:necromancy_runestone_1", "uvlock": true, "x": 270 }, + { "model": "ebwizardry:necromancy_runestone_2", "uvlock": true }, + { "model": "ebwizardry:necromancy_runestone_2", "uvlock": true, "y": 90 }, + { "model": "ebwizardry:necromancy_runestone_2", "uvlock": true, "y": 180 }, + { "model": "ebwizardry:necromancy_runestone_2", "uvlock": true, "y": 270 }, + { "model": "ebwizardry:necromancy_runestone_2", "uvlock": true, "x": 90 }, + { "model": "ebwizardry:necromancy_runestone_2", "uvlock": true, "x": 270 }, + { "model": "ebwizardry:necromancy_runestone_3", "uvlock": true }, + { "model": "ebwizardry:necromancy_runestone_3", "uvlock": true, "y": 90 }, + { "model": "ebwizardry:necromancy_runestone_3", "uvlock": true, "y": 180 }, + { "model": "ebwizardry:necromancy_runestone_3", "uvlock": true, "y": 270 }, + { "model": "ebwizardry:necromancy_runestone_3", "uvlock": true, "x": 90 }, + { "model": "ebwizardry:necromancy_runestone_3", "uvlock": true, "x": 270 }, + { "model": "ebwizardry:necromancy_runestone_4", "uvlock": true }, + { "model": "ebwizardry:necromancy_runestone_4", "uvlock": true, "y": 90 }, + { "model": "ebwizardry:necromancy_runestone_4", "uvlock": true, "y": 180 }, + { "model": "ebwizardry:necromancy_runestone_4", "uvlock": true, "y": 270 }, + { "model": "ebwizardry:necromancy_runestone_4", "uvlock": true, "x": 90 }, + { "model": "ebwizardry:necromancy_runestone_4", "uvlock": true, "x": 270 } + ] + } +} \ No newline at end of file diff --git a/src/main/resources/assets/ebwizardry/blockstates/necromancy_runestone_pedestal.json b/src/main/resources/assets/ebwizardry/blockstates/necromancy_runestone_pedestal.json new file mode 100644 index 00000000..50c7ce28 --- /dev/null +++ b/src/main/resources/assets/ebwizardry/blockstates/necromancy_runestone_pedestal.json @@ -0,0 +1,6 @@ +{ + "forge_marker": 1, + "variants": { + "normal": { "model": "ebwizardry:necromancy_runestone_pedestal" } + } +} \ No newline at end of file diff --git a/src/main/resources/assets/ebwizardry/blockstates/obsidian_crust.json b/src/main/resources/assets/ebwizardry/blockstates/obsidian_crust.json new file mode 100644 index 00000000..1d21f4ff --- /dev/null +++ b/src/main/resources/assets/ebwizardry/blockstates/obsidian_crust.json @@ -0,0 +1,8 @@ +{ + "variants": { + "age=0": { "model": "ebwizardry:obsidian_crust_0" }, + "age=1": { "model": "ebwizardry:obsidian_crust_1" }, + "age=2": { "model": "ebwizardry:obsidian_crust_2" }, + "age=3": { "model": "ebwizardry:obsidian_crust_3" } + } +} diff --git a/src/main/resources/assets/ebwizardry/blockstates/sorcery_crystal_block.json b/src/main/resources/assets/ebwizardry/blockstates/sorcery_crystal_block.json new file mode 100644 index 00000000..77fbcb9a --- /dev/null +++ b/src/main/resources/assets/ebwizardry/blockstates/sorcery_crystal_block.json @@ -0,0 +1,6 @@ +{ + "forge_marker": 1, + "variants": { + "normal": { "model": "ebwizardry:sorcery_crystal_block" } + } +} diff --git a/src/main/resources/assets/ebwizardry/blockstates/sorcery_runestone.json b/src/main/resources/assets/ebwizardry/blockstates/sorcery_runestone.json new file mode 100644 index 00000000..4e626b9d --- /dev/null +++ b/src/main/resources/assets/ebwizardry/blockstates/sorcery_runestone.json @@ -0,0 +1,31 @@ +{ + "forge_marker": 1, + "variants": { + "normal": [ + { "model": "ebwizardry:sorcery_runestone_1", "uvlock": true }, + { "model": "ebwizardry:sorcery_runestone_1", "uvlock": true, "y": 90 }, + { "model": "ebwizardry:sorcery_runestone_1", "uvlock": true, "y": 180 }, + { "model": "ebwizardry:sorcery_runestone_1", "uvlock": true, "y": 270 }, + { "model": "ebwizardry:sorcery_runestone_1", "uvlock": true, "x": 90 }, + { "model": "ebwizardry:sorcery_runestone_1", "uvlock": true, "x": 270 }, + { "model": "ebwizardry:sorcery_runestone_2", "uvlock": true }, + { "model": "ebwizardry:sorcery_runestone_2", "uvlock": true, "y": 90 }, + { "model": "ebwizardry:sorcery_runestone_2", "uvlock": true, "y": 180 }, + { "model": "ebwizardry:sorcery_runestone_2", "uvlock": true, "y": 270 }, + { "model": "ebwizardry:sorcery_runestone_2", "uvlock": true, "x": 90 }, + { "model": "ebwizardry:sorcery_runestone_2", "uvlock": true, "x": 270 }, + { "model": "ebwizardry:sorcery_runestone_3", "uvlock": true }, + { "model": "ebwizardry:sorcery_runestone_3", "uvlock": true, "y": 90 }, + { "model": "ebwizardry:sorcery_runestone_3", "uvlock": true, "y": 180 }, + { "model": "ebwizardry:sorcery_runestone_3", "uvlock": true, "y": 270 }, + { "model": "ebwizardry:sorcery_runestone_3", "uvlock": true, "x": 90 }, + { "model": "ebwizardry:sorcery_runestone_3", "uvlock": true, "x": 270 }, + { "model": "ebwizardry:sorcery_runestone_4", "uvlock": true }, + { "model": "ebwizardry:sorcery_runestone_4", "uvlock": true, "y": 90 }, + { "model": "ebwizardry:sorcery_runestone_4", "uvlock": true, "y": 180 }, + { "model": "ebwizardry:sorcery_runestone_4", "uvlock": true, "y": 270 }, + { "model": "ebwizardry:sorcery_runestone_4", "uvlock": true, "x": 90 }, + { "model": "ebwizardry:sorcery_runestone_4", "uvlock": true, "x": 270 } + ] + } +} \ No newline at end of file diff --git a/src/main/resources/assets/ebwizardry/blockstates/sorcery_runestone_pedestal.json b/src/main/resources/assets/ebwizardry/blockstates/sorcery_runestone_pedestal.json new file mode 100644 index 00000000..02e1d413 --- /dev/null +++ b/src/main/resources/assets/ebwizardry/blockstates/sorcery_runestone_pedestal.json @@ -0,0 +1,6 @@ +{ + "forge_marker": 1, + "variants": { + "normal": { "model": "ebwizardry:sorcery_runestone_pedestal" } + } +} \ No newline at end of file diff --git a/src/main/resources/assets/ebwizardry/blockstates/thorns.json b/src/main/resources/assets/ebwizardry/blockstates/thorns.json new file mode 100644 index 00000000..c60cd8cb --- /dev/null +++ b/src/main/resources/assets/ebwizardry/blockstates/thorns.json @@ -0,0 +1,20 @@ +{ + "variants": { + "age=0,half=lower": { "model": "ebwizardry:thorns_lower_0" }, + "age=1,half=lower": { "model": "ebwizardry:thorns_lower_1" }, + "age=2,half=lower": { "model": "ebwizardry:thorns_lower_2" }, + "age=3,half=lower": { "model": "ebwizardry:thorns_lower_3" }, + "age=4,half=lower": { "model": "ebwizardry:thorns_lower_4" }, + "age=5,half=lower": { "model": "ebwizardry:thorns_lower_5" }, + "age=6,half=lower": { "model": "ebwizardry:thorns_lower_6" }, + "age=7,half=lower": { "model": "ebwizardry:thorns_lower_7" }, + "age=0,half=upper": { "model": "ebwizardry:thorns_upper_0" }, + "age=1,half=upper": { "model": "ebwizardry:thorns_upper_1" }, + "age=2,half=upper": { "model": "ebwizardry:thorns_upper_2" }, + "age=3,half=upper": { "model": "ebwizardry:thorns_upper_3" }, + "age=4,half=upper": { "model": "ebwizardry:thorns_upper_4" }, + "age=5,half=upper": { "model": "ebwizardry:thorns_upper_5" }, + "age=6,half=upper": { "model": "ebwizardry:thorns_upper_6" }, + "age=7,half=upper": { "model": "ebwizardry:thorns_upper_7" } + } +} diff --git a/src/main/resources/assets/ebwizardry/lang/en_gb.lang b/src/main/resources/assets/ebwizardry/lang/en_gb.lang index 79604949..7e733c22 100644 --- a/src/main/resources/assets/ebwizardry/lang/en_gb.lang +++ b/src/main/resources/assets/ebwizardry/lang/en_gb.lang @@ -1,285 +1,515 @@ -tile.ebwizardry:arcane_workbench.name=Arcane Workbench -tile.ebwizardry:crystal_ore.name=Crystal Ore -tile.ebwizardry:petrified_stone.name=Petrified Stone -tile.ebwizardry:ice_statue.name=Ice Statue -tile.ebwizardry:crystal_flower.name=Crystal Flower -tile.ebwizardry:snare.name=Snare -tile.ebwizardry:transportation_stone.name=Stone of Transportation -tile.ebwizardry:spectral_block.name=Spectral Block -tile.ebwizardry:crystal_block.name=Block of Crystal +#PARSE_ESCAPES +tile.ebwizardry\:arcane_workbench.name=Arcane Workbench +tile.ebwizardry\:crystal_ore.name=Crystal Ore +tile.ebwizardry\:petrified_stone.name=Petrified Stone +tile.ebwizardry\:ice_statue.name=Ice Statue +tile.ebwizardry\:crystal_flower.name=Crystal Flower +tile.ebwizardry\:snare.name=Snare +tile.ebwizardry\:transportation_stone.name=Stone of Transportation +tile.ebwizardry\:transportation_stone.confirm=You will now be returned here upon casting %1$s +tile.ebwizardry\:transportation_stone.remember=Remembered the location %s, %s, %s in dimension %s +tile.ebwizardry\:transportation_stone.forget=Forgot the location %s, %s, %s in dimension %s +tile.ebwizardry\:transportation_stone.invalid=You must make a circle with 8 stones of transportation first! +tile.ebwizardry\:spectral_block.name=Spectral Block +tile.ebwizardry\:runestone.name=Runestone +tile.ebwizardry\:runestone_pedestal.name=Runestone Pedestal +tile.ebwizardry\:thorns.name=Thorns +tile.ebwizardry\:obsidian_crust.name=Obsidian Crust +tile.ebwizardry\:dry_frosted_ice.name=Dry Frosted Ice -item.ebwizardry:magic_crystal.name=Magic Crystal -item.ebwizardry:magic_wand.name=Magic Wand -item.ebwizardry:apprentice_wand.name=Apprentice Wand -item.ebwizardry:advanced_wand.name=Advanced Wand -item.ebwizardry:master_wand.name=Master Wand -item.ebwizardry:spell_book.name=Spell Book +tile.ebwizardry\:magic_crystal_block.name=Block of Crystal +tile.ebwizardry\:fire_crystal_block.name=Block of Fiery Crystal +tile.ebwizardry\:ice_crystal_block.name=Block of Icy Crystal +tile.ebwizardry\:lightning_crystal_block.name=Block of Stormy Crystal +tile.ebwizardry\:necromancy_crystal_block.name=Block of Dark Crystal +tile.ebwizardry\:earth_crystal_block.name=Block of Verdant Crystal +tile.ebwizardry\:sorcery_crystal_block.name=Block of Mystical Crystal +tile.ebwizardry\:healing_crystal_block.name=Block of Radiant Crystal -item.ebwizardry:spell_book.apply_to_wizard=Replaced %1$s's spell %2$s with %3$s +item.ebwizardry\:crystal_magic.name=Magic Crystal +item.ebwizardry\:crystal_fire.name=Fiery Crystal +item.ebwizardry\:crystal_ice.name=Icy Crystal +item.ebwizardry\:crystal_lightning.name=Stormy Crystal +item.ebwizardry\:crystal_necromancy.name=Dark Crystal +item.ebwizardry\:crystal_earth.name=Verdant Crystal +item.ebwizardry\:crystal_sorcery.name=Mystical Crystal +item.ebwizardry\:crystal_healing.name=Radiant Crystal -item.ebwizardry:arcane_tome.name=Tome of Arcana -item.ebwizardry:arcane_tome.desc1=Upgrades any %1$s -item.ebwizardry:arcane_tome.desc2=wand to %1$s tier +item.ebwizardry\:magic_wand.name=Magic Wand +item.ebwizardry\:apprentice_wand.name=Apprentice Wand +item.ebwizardry\:advanced_wand.name=Advanced Wand +item.ebwizardry\:master_wand.name=Master Wand +item.ebwizardry\:spell_book.name=Spell Book -item.ebwizardry:wizard_handbook.name=The Wizard's Handbook -item.ebwizardry:wizard_handbook.desc=by %1$s +item.ebwizardry\:spell_book.apply_to_wizard=Replaced %1$s's spell %2$s with %3$s -item.ebwizardry:wand.buff=+%1$s %2$s potency -item.ebwizardry:wand.spell=Current Spell: %1$s -item.ebwizardry:wand.mana=Mana: %1$s/%2$s +item.ebwizardry\:arcane_tome.name=Tome of Arcana +item.ebwizardry\:arcane_tome.desc1=Upgrades any %1$s +item.ebwizardry\:arcane_tome.desc2=wand to %1$s tier -item.ebwizardry:wand.addally=%1$s has been added to your list of allies -item.ebwizardry:wand.removeally=%1$s has been removed from your list of allies +item.ebwizardry\:wizard_handbook.name=The Wizard's Handbook +item.ebwizardry\:wizard_handbook.desc=by %1$s -item.ebwizardry:basic_fire_wand.name=Wand of Embers -item.ebwizardry:basic_ice_wand.name=Wand of Frost -item.ebwizardry:basic_lightning_wand.name=Wand of Sparks -item.ebwizardry:basic_necromancy_wand.name=Wand of Shadows -item.ebwizardry:basic_earth_wand.name=Wand of the Forest -item.ebwizardry:basic_sorcery_wand.name=Wand of Mystery -item.ebwizardry:basic_healing_wand.name=Wand of Healing +item.ebwizardry\:wand.generic=wand -item.ebwizardry:apprentice_fire_wand.name=Apprentice Pyromancer Wand -item.ebwizardry:apprentice_ice_wand.name=Apprentice Ice Mage Wand -item.ebwizardry:apprentice_lightning_wand.name=Apprentice Storm Mage Wand -item.ebwizardry:apprentice_necromancy_wand.name=Apprentice Necromancer Wand -item.ebwizardry:apprentice_earth_wand.name=Apprentice Earth Mage Wand -item.ebwizardry:apprentice_sorcery_wand.name=Apprentice Sorcerer Wand -item.ebwizardry:apprentice_healing_wand.name=Apprentice Healer Wand +item.ebwizardry\:wand.buff=+%1$s %2$s potency +item.ebwizardry\:wand.spell=Current Spell\: %1$s +item.ebwizardry\:wand.mana=Mana\: %1$s/%2$s +item.ebwizardry\:wand.progression=Progression\: %1$s/%2$s -item.ebwizardry:advanced_fire_wand.name=Wand of the Pyromancer -item.ebwizardry:advanced_ice_wand.name=Wand of the Ice Mage -item.ebwizardry:advanced_lightning_wand.name=Wand of the Storm Mage -item.ebwizardry:advanced_necromancy_wand.name=Wand of the Necromancer -item.ebwizardry:advanced_earth_wand.name=Wand of the Earth Mage -item.ebwizardry:advanced_sorcery_wand.name=Wand of the Sorcerer -item.ebwizardry:advanced_healing_wand.name=Wand of the Healer +item.ebwizardry\:wand.levelup=%1$s is ready to upgrade to %2$s tier -item.ebwizardry:master_fire_wand.name=Master Pyromancer Wand -item.ebwizardry:master_ice_wand.name=Master Ice Mage Wand -item.ebwizardry:master_lightning_wand.name=Master Storm Mage Wand -item.ebwizardry:master_necromancy_wand.name=Master Necromancer Wand -item.ebwizardry:master_earth_wand.name=Master Earth Mage Wand -item.ebwizardry:master_sorcery_wand.name=Master Sorcerer Wand -item.ebwizardry:master_healing_wand.name=Master Healer Wand +item.ebwizardry\:wand.addally=%1$s has been added to your list of allies +item.ebwizardry\:wand.removeally=%1$s has been removed from your list of allies -item.ebwizardry:spectral_sword.name=Spectral Sword -item.ebwizardry:spectral_pickaxe.name=Spectral Pickaxe -item.ebwizardry:spectral_bow.name=Spectral Bow +item.ebwizardry\:novice_fire_wand.name=Wand of Embers +item.ebwizardry\:novice_ice_wand.name=Wand of Frost +item.ebwizardry\:novice_lightning_wand.name=Wand of Sparks +item.ebwizardry\:novice_necromancy_wand.name=Wand of Shadows +item.ebwizardry\:novice_earth_wand.name=Wand of the Forest +item.ebwizardry\:novice_sorcery_wand.name=Wand of Mystery +item.ebwizardry\:novice_healing_wand.name=Wand of Healing -item.ebwizardry:mana_flask.name=Mana Flask -item.ebwizardry:storage_upgrade.name=Wand Storage Upgrade -item.ebwizardry:siphon_upgrade.name=Wand Siphon Upgrade -item.ebwizardry:condenser_upgrade.name=Wand Condenser Upgrade -item.ebwizardry:range_upgrade.name=Wand Range Upgrade -item.ebwizardry:duration_upgrade.name=Wand Duration Upgrade -item.ebwizardry:cooldown_upgrade.name=Wand Cooldown Upgrade -item.ebwizardry:blast_upgrade.name=Wand Blast Upgrade -item.ebwizardry:attunement_upgrade.name=Wand Attunement Upgrade +item.ebwizardry\:apprentice_fire_wand.name=Apprentice Pyromancer Wand +item.ebwizardry\:apprentice_ice_wand.name=Apprentice Ice Mage Wand +item.ebwizardry\:apprentice_lightning_wand.name=Apprentice Storm Mage Wand +item.ebwizardry\:apprentice_necromancy_wand.name=Apprentice Necromancer Wand +item.ebwizardry\:apprentice_earth_wand.name=Apprentice Earth Mage Wand +item.ebwizardry\:apprentice_sorcery_wand.name=Apprentice Sorcerer Wand +item.ebwizardry\:apprentice_healing_wand.name=Apprentice Healer Wand -item.ebwizardry:flaming_axe.name=Flaming Axe -item.ebwizardry:frost_axe.name=Frost Axe +item.ebwizardry\:advanced_fire_wand.name=Wand of the Pyromancer +item.ebwizardry\:advanced_ice_wand.name=Wand of the Ice Mage +item.ebwizardry\:advanced_lightning_wand.name=Wand of the Storm Mage +item.ebwizardry\:advanced_necromancy_wand.name=Wand of the Necromancer +item.ebwizardry\:advanced_earth_wand.name=Wand of the Earth Mage +item.ebwizardry\:advanced_sorcery_wand.name=Wand of the Sorcerer +item.ebwizardry\:advanced_healing_wand.name=Wand of the Healer -item.ebwizardry:firebomb.name=Firebomb -item.ebwizardry:poison_bomb.name=Poison Bomb -item.ebwizardry:smoke_bomb.name=Smoke Bomb +item.ebwizardry\:master_fire_wand.name=Master Pyromancer Wand +item.ebwizardry\:master_ice_wand.name=Master Ice Mage Wand +item.ebwizardry\:master_lightning_wand.name=Master Storm Mage Wand +item.ebwizardry\:master_necromancy_wand.name=Master Necromancer Wand +item.ebwizardry\:master_earth_wand.name=Master Earth Mage Wand +item.ebwizardry\:master_sorcery_wand.name=Master Sorcerer Wand +item.ebwizardry\:master_healing_wand.name=Master Healer Wand -item.ebwizardry:blank_scroll.name=Blank Scroll -item.ebwizardry:scroll.name=Scroll of %1$s -item.ebwizardry:scroll.undiscovered.name=Scroll "%1$s" -item.ebwizardry:identification_scroll.name=Scroll of Identification -item.ebwizardry:identification_scroll.desc1=%1$sIdentifies an unknown -item.ebwizardry:identification_scroll.desc2=%1$sspell book or scroll -item.ebwizardry:identification_scroll.nothing_to_identify=Nothing to identify! +item.ebwizardry\:spectral_sword.name=Spectral Sword +item.ebwizardry\:spectral_pickaxe.name=Spectral Pickaxe +item.ebwizardry\:spectral_bow.name=Spectral Bow -item.ebwizardry:armour_upgrade.name=Arcane Seal of Protection -item.ebwizardry:armour_upgrade.desc1=%1$sUpgrades any wizard armour -item.ebwizardry:armour_upgrade.desc2=%1$sto make it %2$slegendary +item.ebwizardry\:spectral_sword_upgraded.name=Spectral Sword +item.ebwizardry\:spectral_pickaxe_upgraded.name=Spectral Pickaxe -item.ebwizardry:magic_silk.name=Magical Silk +item.ebwizardry\:small_mana_flask.name=Small Mana Flask +item.ebwizardry\:medium_mana_flask.name=Medium Mana Flask +item.ebwizardry\:large_mana_flask.name=Large Mana Flask -item.ebwizardry:wizard_armour.legendary=Legendary -item.ebwizardry:wizard_armour.buff=-%1$s %2$s cost -item.ebwizardry:wizard_armour.mana=Mana: %1$s/%2$s +item.ebwizardry\:grand_crystal.name=Grand Magic Crystal +item.ebwizardry\:crystal_shard.name=Magic Crystal Shard -item.ebwizardry:wizard_hat.name=Wizard Hat -item.ebwizardry:wizard_robe.name=Wizard Robes -item.ebwizardry:wizard_leggings.name=Wizard Leggings -item.ebwizardry:wizard_boots.name=Wizard Boots +item.ebwizardry\:astral_diamond.name=Astral Diamond -item.ebwizardry:wizard_hat_fire.name=Pyromancer Hat -item.ebwizardry:wizard_robe_fire.name=Pyromancer Robes -item.ebwizardry:wizard_leggings_fire.name=Pyromancer Leggings -item.ebwizardry:wizard_boots_fire.name=Pyromancer Boots +item.ebwizardry\:purifying_elixir.name=Purifying Elixir +item.ebwizardry\:purifying_elixir.desc=Removes curses when consumed -item.ebwizardry:wizard_hat_ice.name=Ice Mage Hat -item.ebwizardry:wizard_robe_ice.name=Ice Mage Robes -item.ebwizardry:wizard_leggings_ice.name=Ice Mage Leggings -item.ebwizardry:wizard_boots_ice.name=Ice Mage Boots +item.ebwizardry\:storage_upgrade.name=Wand Storage Upgrade +item.ebwizardry\:siphon_upgrade.name=Wand Siphon Upgrade +item.ebwizardry\:condenser_upgrade.name=Wand Condenser Upgrade +item.ebwizardry\:range_upgrade.name=Wand Range Upgrade +item.ebwizardry\:duration_upgrade.name=Wand Duration Upgrade +item.ebwizardry\:cooldown_upgrade.name=Wand Cooldown Upgrade +item.ebwizardry\:blast_upgrade.name=Wand Blast Upgrade +item.ebwizardry\:attunement_upgrade.name=Wand Attunement Upgrade +item.ebwizardry\:melee_upgrade.name=Wand Melee Upgrade -item.ebwizardry:wizard_hat_lightning.name=Storm Mage Hat -item.ebwizardry:wizard_robe_lightning.name=Storm Mage Robes -item.ebwizardry:wizard_leggings_lightning.name=Storm Mage Leggings -item.ebwizardry:wizard_boots_lightning.name=Storm Mage Boots +item.ebwizardry\:storage_upgrade.desc=Upgrades the mana capacity of a wand +item.ebwizardry\:siphon_upgrade.desc=Upgrades a wand to extract mana from mobs when killed +item.ebwizardry\:condenser_upgrade.desc=Upgrades a wand to slowly regenerate mana over time +item.ebwizardry\:range_upgrade.desc=Upgrades the effective range of spells cast by a wand +item.ebwizardry\:duration_upgrade.desc=Upgrades the duration of effects cast by a wand +item.ebwizardry\:cooldown_upgrade.desc=Upgrades the spell cooldown speed of a wand +item.ebwizardry\:blast_upgrade.desc=Upgrades the area of effect of spells cast by a wand +item.ebwizardry\:attunement_upgrade.desc=Upgrades the number of spells that can be bound to a wand +item.ebwizardry\:melee_upgrade.desc=Upgrades a wand to use mana to deal more damage to mobs when hit -item.ebwizardry:wizard_hat_necromancy.name=Necromancer Hat -item.ebwizardry:wizard_robe_necromancy.name=Necromancer Robes -item.ebwizardry:wizard_leggings_necromancy.name=Necromancer Leggings -item.ebwizardry:wizard_boots_necromancy.name=Necromancer Boots +item.ebwizardry\:flaming_axe.name=Flaming Axe +item.ebwizardry\:frost_axe.name=Frost Axe -item.ebwizardry:wizard_hat_earth.name=Earth Mage Hat -item.ebwizardry:wizard_robe_earth.name=Earth Mage Robes -item.ebwizardry:wizard_leggings_earth.name=Earth Mage Leggings -item.ebwizardry:wizard_boots_earth.name=Earth Mage Boots +item.ebwizardry\:flaming_axe_upgraded.name=Flaming Axe +item.ebwizardry\:frost_axe_upgraded.name=Frost Axe -item.ebwizardry:wizard_hat_sorcery.name=Sorcerer Hat -item.ebwizardry:wizard_robe_sorcery.name=Sorcerer Robes -item.ebwizardry:wizard_leggings_sorcery.name=Sorcerer Leggings -item.ebwizardry:wizard_boots_sorcery.name=Sorcerer Boots +item.ebwizardry\:firebomb.name=Firebomb +item.ebwizardry\:poison_bomb.name=Poison Bomb +item.ebwizardry\:smoke_bomb.name=Smoke Bomb +item.ebwizardry\:spark_bomb.name=Spark Bomb -item.ebwizardry:wizard_hat_healing.name=Healer Hat -item.ebwizardry:wizard_robe_healing.name=Healer Robes -item.ebwizardry:wizard_leggings_healing.name=Healer Leggings -item.ebwizardry:wizard_boots_healing.name=Healer Boots +item.ebwizardry\:blank_scroll.name=Blank Scroll +item.ebwizardry\:scroll.generic=scroll +item.ebwizardry\:scroll.name=Scroll of %1$s +item.ebwizardry\:scroll.undiscovered.name=Scroll "%1$s" +item.ebwizardry\:identification_scroll.name=Scroll of Identification +item.ebwizardry\:identification_scroll.desc=Identifies an unknown spell book or scroll +item.ebwizardry\:identification_scroll.nothing_to_identify=Nothing to identify! -item.ebwizardry:spawn_wizard.name=Spawn Wizard -item.ebwizardry:spawn_evil_wizard.name=Spawn Evil Wizard +item.ebwizardry\:armour_upgrade.name=Arcane Seal of Protection +item.ebwizardry\:armour_upgrade.desc1=%1$sUpgrades any wizard armour +item.ebwizardry\:armour_upgrade.desc2=%1$sto make it %2$slegendary -item.ebwizardry:spectral_helmet.name=Spectral Helmet -item.ebwizardry:spectral_chestplate.name=Spectral Chestplate -item.ebwizardry:spectral_leggings.name=Spectral Leggings -item.ebwizardry:spectral_boots.name=Spectral Boots +item.ebwizardry\:magic_silk.name=Magical Silk -entity.ebwizardry:summonedcreature.nameplate=%1$s's %2$s -entity.ebwizardry:summonedcreature.nameplate_fallback=Someone's %1$s +item.ebwizardry\:wizard_armour.legendary=Legendary +item.ebwizardry\:wizard_armour.buff=-%1$s %2$s cost +item.ebwizardry\:wizard_armour.mana=Mana\: %1$s/%2$s -entity.ebwizardry:zombie_minion.name=Zombie -entity.ebwizardry:skeleton_minion.name=Skeleton -entity.ebwizardry:spider_minion.name=Spider -entity.ebwizardry:blaze_minion.name=Blaze -entity.ebwizardry:wither_skeleton_minion.name=Wither Skeleton -entity.ebwizardry:ice_wraith.name=Ice Wraith -entity.ebwizardry:lightning_wraith.name=Lightning Wraith -entity.ebwizardry:shadow_wraith.name=Shadow Wraith -entity.ebwizardry:spirit_wolf.name=Spirit Wolf -entity.ebwizardry:spirit_horse.name=Spirit Horse -entity.ebwizardry:ice_giant.name=Ice Giant -entity.ebwizardry:phoenix.name=Phoenix -entity.ebwizardry:wizard.name=Wizard -entity.ebwizardry:magic_slime.name=Magical Slime -entity.ebwizardry:silverfish_minion.name=Silverfish -entity.ebwizardry:storm_elemental.name=Storm Elemental -entity.ebwizardry:evil_wizard.name=Wizard -entity.ebwizardry:decoy.name=Decoy +item.ebwizardry\:wizard_hat.name=Wizard Hat +item.ebwizardry\:wizard_robe.name=Wizard Robes +item.ebwizardry\:wizard_leggings.name=Wizard Leggings +item.ebwizardry\:wizard_boots.name=Wizard Boots -entity.ebwizardry:magic_missile.name=Magic -entity.ebwizardry:arc.name=Magic -entity.ebwizardry:spark_bomb.name=Magic -entity.ebwizardry:ice_shard.name=Magic -entity.ebwizardry:firebomb.name=Magic -entity.ebwizardry:poison_bomb.name=Magic -entity.ebwizardry:force_orb.name=Magic -entity.ebwizardry:spark.name=Magic -entity.ebwizardry:darkness_orb.name=Magic -entity.ebwizardry:fire_sigil.name=Magic -entity.ebwizardry:frost_sigil.name=Magic -entity.ebwizardry:lightning_sigil.name=Magic -entity.ebwizardry:lightning_arrow.name=Magic -entity.ebwizardry:firebolt.name=Magic -entity.ebwizardry:ice_charge.name=Magic -entity.ebwizardry:force_arrow.name=Magic -entity.ebwizardry:dart.name=Magic -entity.ebwizardry:lightning_disc.name=Magic -entity.ebwizardry:thunderbolt.name=Magic -entity.ebwizardry:decay.name=Magic -entity.ebwizardry:ice_lance.name=Magic -entity.ebwizardry:smoke_bomb.name=Magic -entity.ebwizardry:ice_spike.name=Magic +item.ebwizardry\:wizard_hat_fire.name=Pyromancer Hat +item.ebwizardry\:wizard_robe_fire.name=Pyromancer Robes +item.ebwizardry\:wizard_leggings_fire.name=Pyromancer Leggings +item.ebwizardry\:wizard_boots_fire.name=Pyromancer Boots -entity.ebwizardry:black_hole.name=Black Hole -entity.ebwizardry:shield.name=Shield -entity.ebwizardry:meteor.name=Meteor -entity.ebwizardry:blizzard.name=Blizzard -entity.ebwizardry:bubble.name=Bubble -entity.ebwizardry:tornado.name=Tornado -entity.ebwizardry:lightning_hammer.name=Lightning Hammer -entity.ebwizardry:arrow_rain.name=Arrow Rain -entity.ebwizardry:healing_aura.name=Healing Aura -entity.ebwizardry:forcefield.name=Forcefield -entity.ebwizardry:ring_of_fire.name=Ring of Fire -entity.ebwizardry:earthquake.name=Earthquake -entity.ebwizardry:falling_grass.name=Falling Grass -entity.ebwizardry:hailstorm.name=Hailstorm -entity.ebwizardry:lightning_pulse.name=Lightning Pulse +item.ebwizardry\:wizard_hat_ice.name=Ice Mage Hat +item.ebwizardry\:wizard_robe_ice.name=Ice Mage Robes +item.ebwizardry\:wizard_leggings_ice.name=Ice Mage Leggings +item.ebwizardry\:wizard_boots_ice.name=Ice Mage Boots -item_group.ebwizardry=Wizardry -item_group.wizardryspells=Spells +item.ebwizardry\:wizard_hat_lightning.name=Storm Mage Hat +item.ebwizardry\:wizard_robe_lightning.name=Storm Mage Robes +item.ebwizardry\:wizard_leggings_lightning.name=Storm Mage Leggings +item.ebwizardry\:wizard_boots_lightning.name=Storm Mage Boots -advancement.wizardry:root=Wizardry -advancement.wizardry:root.desc=A wizard's journey to mastering the arcane -advancement.wizardry:crystal=A Curious Crystal... -advancement.wizardry:crystal.desc=Mine a magic crystal -advancement.wizardry:arcane_initiate=Arcane Initiate -advancement.wizardry:arcane_initiate.desc=Craft a magic wand with a gold nugget, a stick and a magic crystal -advancement.wizardry:apprentice=Wizard's Apprentice -advancement.wizardry:apprentice.desc=Use a tome of arcana to upgrade your wand -advancement.wizardry:master=Arcane Master -advancement.wizardry:master.desc=Obtain a master wand -advancement.wizardry:all_spells=Mage of All Trades -advancement.wizardry:all_spells.desc=Cast every single spell in the game -advancement.wizardry:wizard_trade=Magic Dealing -advancement.wizardry:wizard_trade.desc=Purchase an item from a wizard -advancement.wizardry:buy_master_spell=Knowledge is Power -advancement.wizardry:buy_master_spell.desc=Purchase a master spell from a wizard -advancement.wizardry:freeze_blaze=Not So Hot Now -advancement.wizardry:freeze_blaze.desc=Freeze a blaze solid -advancement.wizardry:charge_creeper=It's Gonna Blow -advancement.wizardry:charge_creeper.desc='Accidentally' charge a creeper -advancement.wizardry:frankenstein=Frankenstein -advancement.wizardry:frankenstein.desc=Turn a pig into a zombie pigman using the lightning bolt spell -advancement.wizardry:special_upgrade=Arcane Tinkering -advancement.wizardry:special_upgrade.desc=Apply a special upgrade to a wand -advancement.wizardry:craft_flask=It's Magic, Bottled! -advancement.wizardry:craft_flask.desc=Craft a mana flask -advancement.wizardry:elemental=Elemental -advancement.wizardry:elemental.desc=Obtain an elemental wand -advancement.wizardry:armour_set=Now You're a Proper Wizard -advancement.wizardry:armour_set.desc=Craft and equip a full set of wizard armour -advancement.wizardry:legendary=Legendary -advancement.wizardry:legendary.desc=Obtain a piece of legendary wizard armour -advancement.wizardry:self_destruct=That Backfired -advancement.wizardry:self_destruct.desc=Get killed by your own magic -advancement.wizardry:pig_tornado=Not Again... -advancement.wizardry:pig_tornado.desc=Ride a pig into a tornado -advancement.wizardry:jam_wizard=Jamming Session -advancement.wizardry:jam_wizard.desc=Use the arcane jammer spell on a wizard -advancement.wizardry:slime_skeleton=Sticky Situation -advancement.wizardry:slime_skeleton.desc=Engulf a skeleton in slime -advancement.wizardry:anger_wizard=You'll Regret That -advancement.wizardry:anger_wizard.desc=Make a wizard angry -advancement.wizardry:defeat_evil_wizard=Righteousness -advancement.wizardry:defeat_evil_wizard.desc=Defeat an evil wizard -advancement.wizardry:max_out_wand=Fully Equipped -advancement.wizardry:max_out_wand.desc=Apply the maximum number of upgrades to a master wand -advancement.wizardry:element_master=Element Mastery -advancement.wizardry:element_master.desc=Cast all the spells of any element -advancement.wizardry:identify_spell=Arcane Appraisal -advancement.wizardry:identify_spell.desc=Use a scroll of identification to identify a spell book or scroll +item.ebwizardry\:wizard_hat_necromancy.name=Necromancer Hat +item.ebwizardry\:wizard_robe_necromancy.name=Necromancer Robes +item.ebwizardry\:wizard_leggings_necromancy.name=Necromancer Leggings +item.ebwizardry\:wizard_boots_necromancy.name=Necromancer Boots -tile.ebwizardry:transportation_stone.confirm=You will now be returned here upon casting %1$s -tile.ebwizardry:transportation_stone.invalid=You must make a circle with 8 stones of transportation first! +item.ebwizardry\:wizard_hat_earth.name=Earth Mage Hat +item.ebwizardry\:wizard_robe_earth.name=Earth Mage Robes +item.ebwizardry\:wizard_leggings_earth.name=Earth Mage Leggings +item.ebwizardry\:wizard_boots_earth.name=Earth Mage Boots -container.ebwizardry:arcane_workbench=Arcane Workbench -container.ebwizardry:arcane_workbench.apply=Apply -container.ebwizardry:arcane_workbench.mana=Mana: -container.ebwizardry:arcane_workbench.upgrades=Applied Upgrades: +item.ebwizardry\:wizard_hat_sorcery.name=Sorcerer Hat +item.ebwizardry\:wizard_robe_sorcery.name=Sorcerer Robes +item.ebwizardry\:wizard_leggings_sorcery.name=Sorcerer Leggings +item.ebwizardry\:wizard_boots_sorcery.name=Sorcerer Boots -tier.basic=Novice +item.ebwizardry\:wizard_hat_healing.name=Healer Hat +item.ebwizardry\:wizard_robe_healing.name=Healer Robes +item.ebwizardry\:wizard_leggings_healing.name=Healer Leggings +item.ebwizardry\:wizard_boots_healing.name=Healer Boots + +item.ebwizardry\:spawn_wizard.name=Spawn Wizard +item.ebwizardry\:spawn_evil_wizard.name=Spawn Evil Wizard + +item.ebwizardry\:spectral_helmet.name=Spectral Helmet +item.ebwizardry\:spectral_chestplate.name=Spectral Chestplate +item.ebwizardry\:spectral_leggings.name=Spectral Leggings +item.ebwizardry\:spectral_boots.name=Spectral Boots + +item.ebwizardry\:lightning_hammer.name=Lightning Hammer + +item.ebwizardry\:ring_condensing.name=Ring of Condensing +item.ebwizardry\:ring_condensing.desc=Slowly regenerates mana for all wands on your hotbar +item.ebwizardry\:ring_siphoning.name=Ring of Siphoning +item.ebwizardry\:ring_siphoning.desc=Increases siphoned mana by 30%% +item.ebwizardry\:ring_battlemage.name=Ring of the Battlemage +item.ebwizardry\:ring_battlemage.desc=Holding a wand in your offhand and a sword in your main hand grants 10%% extra magic damage +item.ebwizardry\:ring_combustion.name=Ring of Combustion +item.ebwizardry\:ring_combustion.desc=Creatures killed by fire spells explode +item.ebwizardry\:ring_fire_melee.name=Ring of Fiery Touch +item.ebwizardry\:ring_fire_melee.desc=Hitting a creature with a fire wand sets it on fire +item.ebwizardry\:ring_fire_biome.name=Ring of the Desert Sun +item.ebwizardry\:ring_fire_biome.desc=Fire spells are 30%% more potent in hot biomes +item.ebwizardry\:ring_disintegration.name=Ring of Searing Embers +item.ebwizardry\:ring_disintegration.desc=All fire attack spells cause their victims to disintegrate +item.ebwizardry\:ring_ice_melee.name=Ring of Icy Touch +item.ebwizardry\:ring_ice_melee.desc=Hitting a creature with an ice wand gives it the frostbite effect +item.ebwizardry\:ring_ice_biome.name=Ring of Glaciation +item.ebwizardry\:ring_ice_biome.desc=Ice spells are 30%% more potent in snowy biomes +item.ebwizardry\:ring_arcane_frost.name=Ring of Arcane Frost +item.ebwizardry\:ring_arcane_frost.desc=Creatures killed by ice spells release ice shards in all directions +item.ebwizardry\:ring_shattering.name=Ring of Shattering +item.ebwizardry\:ring_shattering.desc=Melee attacks on mobs with the frostbite effect have a chance to shatter them into ice shards +item.ebwizardry\:ring_lightning_melee.name=Ring of Chaining +item.ebwizardry\:ring_lightning_melee.desc=Hitting a creature with a lightning wand shoots lightning at another nearby creature +item.ebwizardry\:ring_storm.name=Ring of the Gathering Storm +item.ebwizardry\:ring_storm.desc=During thunderstorms, lightning spells have dramatically reduced cooldowns +item.ebwizardry\:ring_seeking.name=Ring of Attraction +item.ebwizardry\:ring_seeking.desc=All projectile spells seek their targets +item.ebwizardry\:ring_hammer.name=Ring of Thalek the Almighty +item.ebwizardry\:ring_hammer.desc=Lightning hammers can be picked up and thrown +item.ebwizardry\:ring_soulbinding.name=Soulwalker's Ring +item.ebwizardry\:ring_soulbinding.desc=Creatures damaged by necromancy spells become soulbound to you +item.ebwizardry\:ring_leeching.name=Ring of Leeching +item.ebwizardry\:ring_leeching.desc=All necromancy attacks have a 30%% chance to trigger a life drain effect +item.ebwizardry\:ring_necromancy_melee.name=Ring of Necrotic Touch +item.ebwizardry\:ring_necromancy_melee.desc=Hitting a creature with a necromancy wand gives it the wither effect +item.ebwizardry\:ring_mind_control.name=Ring of the Psychic +item.ebwizardry\:ring_mind_control.desc=Mind-controlled creatures have a chance to mind control other nearby creatures +item.ebwizardry\:ring_poison.name=Serpentine Ring +item.ebwizardry\:ring_poison.desc=All earth spells poison their target +item.ebwizardry\:ring_earth_melee.name=Ring of Venomous Touch +item.ebwizardry\:ring_earth_melee.desc=Hitting a creature with an earth wand poisons it +item.ebwizardry\:ring_earth_biome.name=Dryad's Ring +item.ebwizardry\:ring_earth_biome.desc=Earth spells are 30%% more potent in forests and roofed forests +item.ebwizardry\:ring_full_moon.name=Ring of the Howling Wolf +item.ebwizardry\:ring_full_moon.desc=Earth spells have dramatically reduced cooldowns under a full moon +item.ebwizardry\:ring_extraction.name=Ring of Extraction +item.ebwizardry\:ring_extraction.desc=Kills with sorcery spells grant bonus mana +item.ebwizardry\:ring_mana_return.name=Ring of the Perfectionist +item.ebwizardry\:ring_mana_return.desc=Force arrows that miss their target return the mana they used to your wand +item.ebwizardry\:ring_blockwrangler.name=Blockwrangler's Ring +item.ebwizardry\:ring_blockwrangler.desc=Thrown blocks deal twice their normal damage +item.ebwizardry\:ring_conjurer.name=Conjurer's Ring +item.ebwizardry\:ring_conjurer.desc=Conjured items last twice as long +item.ebwizardry\:ring_defender.name=Ring of the Defender +item.ebwizardry\:ring_defender.desc=Your projectiles pass through forcefields belonging to you or an ally +item.ebwizardry\:ring_paladin.name=Paladin's Ring +item.ebwizardry\:ring_paladin.desc=When you heal yourself or an ally, nearby allies will also gain some health +item.ebwizardry\:ring_interdiction.name=Ring of Interdiction +item.ebwizardry\:ring_interdiction.desc=Your forcefield damages creatures that touch it + +item.ebwizardry\:amulet_arcane_defence.name=Amulet of Arcane Defence +item.ebwizardry\:amulet_arcane_defence.desc=Slowly regenerates mana for all worn wizard armour +item.ebwizardry\:amulet_warding.name=Amulet of Warding +item.ebwizardry\:amulet_warding.desc=Reduces all incoming magic damage by 10%% +item.ebwizardry\:amulet_wisdom.name=Amulet of Wisdom +item.ebwizardry\:amulet_wisdom.desc=Greatly reduces the chance of negative effects when using undiscovered spells +item.ebwizardry\:amulet_fire_protection.name=Flamefast Amulet +item.ebwizardry\:amulet_fire_protection.desc=Reduces fire damage by 30%% +item.ebwizardry\:amulet_fire_cloaking.name=Amulet of Cloaking Flame +item.ebwizardry\:amulet_fire_cloaking.desc=Reduces incoming damage by 75%% whilst standing within a ring of fire belonging to you or an ally +item.ebwizardry\:amulet_ice_immunity.name=Permafrost Amulet +item.ebwizardry\:amulet_ice_immunity.desc=Grants total immunity to frostbite effects +item.ebwizardry\:amulet_ice_protection.name=Frostbound Amulet +item.ebwizardry\:amulet_ice_protection.desc=Reduces frost damage by 30%% +item.ebwizardry\:amulet_potential.name=Amulet of Potential +item.ebwizardry\:amulet_potential.desc=Grants a 15%% chance to shoot lightning at creatures that melee attack you +item.ebwizardry\:amulet_channeling.name=Amulet of Channeling +item.ebwizardry\:amulet_channeling.desc=Grants a 30%% chance to negate incoming shock damage +item.ebwizardry\:amulet_lich.name=Amulet of the Lich +item.ebwizardry\:amulet_lich.desc=Grants a 15%% chance for incoming damage to be dealt to a nearby minion instead +item.ebwizardry\:amulet_wither_immunity.name=Wither Pearl Amulet +item.ebwizardry\:amulet_wither_immunity.desc=Grants total immunity to wither effects +item.ebwizardry\:amulet_glide.name=Windfeather Amulet +item.ebwizardry\:amulet_glide.desc=Falling more than 3 blocks has a 50%% chance to activate the glide effect +item.ebwizardry\:amulet_banishing.name=Enderbound Amulet +item.ebwizardry\:amulet_banishing.desc=Creatures that melee attack you have a 15%% chance to be teleported to a random nearby location +item.ebwizardry\:amulet_anchoring.name=Amulet of Anchoring +item.ebwizardry\:amulet_anchoring.desc=Grants immunity to being moved by magic +item.ebwizardry\:amulet_recovery.name=Amulet of Recovery +item.ebwizardry\:amulet_recovery.desc=When on less than 50%% health, mana from your armour will be used to heal you over time +item.ebwizardry\:amulet_transience.name=Amulet of Transience +item.ebwizardry\:amulet_transience.desc=Grants a 25%% chance to activate a transience effect when critically wounded +item.ebwizardry\:amulet_resurrection.name=Amulet of the Immortal +item.ebwizardry\:amulet_resurrection.desc=The resurrection spell can be used on yourself from beyond the grave +item.ebwizardry\:amulet_auto_shield.name=Hyeleth's Amulet +item.ebwizardry\:amulet_auto_shield.desc=Grants a 25%% chance to trigger the shield spell for a few seconds when bound to a wand on your hotbar + +item.ebwizardry\:charm_haggler.name=Haggler's Sign +item.ebwizardry\:charm_haggler.desc=Wizards are guaranteed to offer a new trade every time you trade with them +item.ebwizardry\:charm_experience_tome.name=Tome of the Diligent +item.ebwizardry\:charm_experience_tome.desc=Increases the rate at which wands gain progression by 40%% +item.ebwizardry\:charm_auto_smelt.name=Metallurgist's Mark +item.ebwizardry\:charm_auto_smelt.desc=Pocket furnace triggers automatically when bound to a wand on your hotbar +item.ebwizardry\:charm_lava_walking.name=Nether Ice Core +item.ebwizardry\:charm_lava_walking.desc=Frost step freezes lava to form an obsidian crust +item.ebwizardry\:charm_storm.name=Bottled Thundercloud +item.ebwizardry\:charm_storm.desc=Invoke weather is guaranteed to summon storms +item.ebwizardry\:charm_minion_health.name=Obsidian Zombie Head +item.ebwizardry\:charm_minion_health.desc=Summoned creatures are 25%% stronger +item.ebwizardry\:charm_minion_variants.name=Talisman of Transformation +item.ebwizardry\:charm_minion_variants.desc=Summoned zombies are husks; summoned skeletons are strays +item.ebwizardry\:charm_flight.name=Emerald Beetle Wing +item.ebwizardry\:charm_flight.desc=Flight and Glide are 50%% faster +item.ebwizardry\:charm_growth.name=Crystal Flower Charm +item.ebwizardry\:charm_growth.desc=Growth aura has a 35%% chance to instantly grow crops to fully-grown +item.ebwizardry\:charm_abseiling.name=Enchanted Twine +item.ebwizardry\:charm_abseiling.desc=Holding sneak whilst grappling slowly pays out the line +item.ebwizardry\:charm_silk_touch.name=Moonstone Orb +item.ebwizardry\:charm_silk_touch.desc=Blocks broken with the mine spell always drop themselves +item.ebwizardry\:charm_stop_time.name=Peculiar Pocketwatch +item.ebwizardry\:charm_stop_time.desc=The slow time spell makes time stand still +item.ebwizardry\:charm_light.name=Elevinia's Everburning Lantern +item.ebwizardry\:charm_light.desc=Conjured light sources last forever and may be dispelled by right-clicking with a wand +item.ebwizardry\:charm_transportation.name=Ancient Compass +item.ebwizardry\:charm_transportation.desc=Up to four stone circles may be remembered and selected from when using transportation +item.ebwizardry\:charm_feeding.name=Bottomless Provisions +item.ebwizardry\:charm_feeding.desc=Replenish hunger triggers automatically when bound to a wand on your hotbar + +item.charge_status.full=Full +item.charge_status.almost_full=Almost full +item.charge_status.mostly_full=Mostly full +item.charge_status.half_full=Half full +item.charge_status.mostly_empty=Mostly empty +item.charge_status.almost_empty=Almost empty +item.charge_status.empty=Empty + +entity.ebwizardry\:summonedcreature.nameplate=%1$s's %2$s +entity.ebwizardry\:summonedcreature.nameplate_fallback=Someone's %1$s + +entity.ebwizardry\:wizard.greeting_0=Good day, fellow wanderer. +entity.ebwizardry\:wizard.greeting_1=Greetings, traveller. What brings you here? +entity.ebwizardry\:wizard.greeting_2=Ah, nice to see another person around here. +entity.ebwizardry\:wizard.speech_0=Might I interest you in any spells, perhaps? +entity.ebwizardry\:wizard.speech_1=Magic is everywhere, if you know where to look. +entity.ebwizardry\:wizard.speech_2=There is still much to be learned about the arcane arts, adventurer. +entity.ebwizardry\:wizard.speech_3=Perhaps you have learned something yourself that you wish to share? +entity.ebwizardry\:wizard.speech_4=Studying the arcane is most fascinating, don't you think? +entity.ebwizardry\:wizard.farewell_0=Good luck in your quest, adventurer. +entity.ebwizardry\:wizard.farewell_1=I trust that we will meet again soon, friend. +entity.ebwizardry\:wizard.farewell_2=Goodbye then, traveller. +entity.ebwizardry\:wizard.combat_0=Be gone, foul creatures! +entity.ebwizardry\:wizard.combat_1=Leave me alone, pests! +entity.ebwizardry\:wizard.combat_2=Undead beings are not welcome here, shoo! +entity.ebwizardry\:wizard.combat_3=Away with you, creatures of darkness! +entity.ebwizardry\:wizard.combat_4=This is all I need! Get out of here, monsters! +entity.ebwizardry\:wizard.combat_5=Return to the caves from whence you came, evil creatures! +entity.ebwizardry\:wizard.player_combat_0=You will regret that decision, traveller! +entity.ebwizardry\:wizard.player_combat_1=What do you think you are doing?! +entity.ebwizardry\:wizard.player_combat_2=Only a fool dares to anger a wizard! +entity.ebwizardry\:wizard.player_combat_3=You will pay for your carelessness, adventurer! +entity.ebwizardry\:wizard.player_combat_4=Be ready to defend yourself, villain! +entity.ebwizardry\:wizard.player_combat_5=Prepare to feel my wrath! + +entity.ebwizardry\:zombie_minion.name=Zombie +entity.ebwizardry\:husk_minion.name=Husk +entity.ebwizardry\:skeleton_minion.name=Skeleton +entity.ebwizardry\:stray_minion.name=Stray +entity.ebwizardry\:spider_minion.name=Spider +entity.ebwizardry\:blaze_minion.name=Blaze +entity.ebwizardry\:wither_skeleton_minion.name=Wither Skeleton +entity.ebwizardry\:ice_wraith.name=Ice Wraith +entity.ebwizardry\:lightning_wraith.name=Lightning Wraith +entity.ebwizardry\:shadow_wraith.name=Shadow Wraith +entity.ebwizardry\:spirit_wolf.name=Spirit Wolf +entity.ebwizardry\:spirit_horse.name=Spirit Horse +entity.ebwizardry\:ice_giant.name=Ice Giant +entity.ebwizardry\:phoenix.name=Phoenix +entity.ebwizardry\:wizard.name=Wizard +entity.ebwizardry\:magic_slime.name=Magical Slime +entity.ebwizardry\:silverfish_minion.name=Silverfish +entity.ebwizardry\:storm_elemental.name=Storm Elemental +entity.ebwizardry\:evil_wizard.name=Wizard +entity.ebwizardry\:decoy.name=Decoy +entity.ebwizardry\:vex_minion.name=Vex + +entity.ebwizardry\:magic_missile.name=Magic +entity.ebwizardry\:arc.name=Magic +entity.ebwizardry\:spark_bomb.name=Magic +entity.ebwizardry\:ice_shard.name=Magic +entity.ebwizardry\:firebomb.name=Magic +entity.ebwizardry\:poison_bomb.name=Magic +entity.ebwizardry\:force_orb.name=Magic +entity.ebwizardry\:spark.name=Magic +entity.ebwizardry\:darkness_orb.name=Magic +entity.ebwizardry\:fire_sigil.name=Magic +entity.ebwizardry\:frost_sigil.name=Magic +entity.ebwizardry\:lightning_sigil.name=Magic +entity.ebwizardry\:lightning_arrow.name=Magic +entity.ebwizardry\:firebolt.name=Magic +entity.ebwizardry\:ice_charge.name=Magic +entity.ebwizardry\:force_arrow.name=Magic +entity.ebwizardry\:dart.name=Magic +entity.ebwizardry\:lightning_disc.name=Magic +entity.ebwizardry\:thunderbolt.name=Magic +entity.ebwizardry\:decay.name=Magic +entity.ebwizardry\:ice_lance.name=Magic +entity.ebwizardry\:smoke_bomb.name=Magic +entity.ebwizardry\:ice_spike.name=Magic +entity.ebwizardry\:combustion_rune.name=Magic + +entity.ebwizardry\:black_hole.name=Black Hole +entity.ebwizardry\:shield.name=Shield +entity.ebwizardry\:meteor.name=Meteor +entity.ebwizardry\:blizzard.name=Blizzard +entity.ebwizardry\:bubble.name=Bubble +entity.ebwizardry\:tornado.name=Tornado +entity.ebwizardry\:lightning_hammer.name=Lightning Hammer +entity.ebwizardry\:arrow_rain.name=Arrow Rain +entity.ebwizardry\:healing_aura.name=Healing Aura +entity.ebwizardry\:forcefield.name=Forcefield +entity.ebwizardry\:ring_of_fire.name=Ring of Fire +entity.ebwizardry\:earthquake.name=Earthquake +entity.ebwizardry\:hailstorm.name=Hailstorm +entity.ebwizardry\:lightning_pulse.name=Lightning Pulse + +itemGroup.ebwizardry=Wizardry +itemGroup.ebwizardryspells=Spells +itemGroup.ebwizardrygear=Wizard Gear + +advancement.ebwizardry\:root=Wizardry +advancement.ebwizardry\:root.desc=A wizard's journey to mastering the arcane +advancement.ebwizardry\:crystal=A Curious Crystal... +advancement.ebwizardry\:crystal.desc=Mine a magic crystal +advancement.ebwizardry\:arcane_initiate=Arcane Initiate +advancement.ebwizardry\:arcane_initiate.desc=Craft a magic wand with a gold nugget, a stick and a magic crystal + +advancement.ebwizardry\:apprentice=Wizard's Apprentice +advancement.ebwizardry\:apprentice.desc=Use a tome of arcana to upgrade your wand +advancement.ebwizardry\:special_upgrade=Arcane Tinkering +advancement.ebwizardry\:special_upgrade.desc=Apply a special upgrade to a wand +advancement.ebwizardry\:advanced=Advancing Rapidly +advancement.ebwizardry\:advanced.desc=Upgrade your wand to advanced tier +advancement.ebwizardry\:master=Arcane Master +advancement.ebwizardry\:master.desc=Obtain a master wand +advancement.ebwizardry\:max_out_wand=Fully Equipped +advancement.ebwizardry\:max_out_wand.desc=Apply the maximum number of upgrades to a master wand +advancement.ebwizardry\:all_spells=Mage of All Trades +advancement.ebwizardry\:all_spells.desc=Cast every single spell in the game + +advancement.ebwizardry\:wizard_tower=Who Lives Here? +advancement.ebwizardry\:wizard_tower.desc=Visit a wizard's tower +advancement.ebwizardry\:wizard_trade=Magic Dealing +advancement.ebwizardry\:wizard_trade.desc=Purchase an item from a wizard +advancement.ebwizardry\:anger_wizard=You'll Regret That +advancement.ebwizardry\:anger_wizard.desc=Make a wizard angry +advancement.ebwizardry\:defeat_evil_wizard=Righteousness +advancement.ebwizardry\:defeat_evil_wizard.desc=Defeat an evil wizard +advancement.ebwizardry\:buy_master_spell=Knowledge is Power +advancement.ebwizardry\:buy_master_spell.desc=Purchase a master spell from a wizard + +advancement.ebwizardry\:discover_spell=Trial And Error +advancement.ebwizardry\:discover_spell.desc=Identify an unknown spell by casting it and seeing what happens +advancement.ebwizardry\:identify_spell=Arcane Appraisal +advancement.ebwizardry\:identify_spell.desc=Find a more reliable way of identifying spells +advancement.ebwizardry\:spell_failure=That Backfired +advancement.ebwizardry\:spell_failure.desc=Find out the hard way how spells can go wrong +advancement.ebwizardry\:discover_master_spell=Dicing With Danger +advancement.ebwizardry\:discover_master_spell.desc=Successfully identify a master spell by trial and error + +advancement.ebwizardry\:visit_shrine=Enshrined +advancement.ebwizardry\:visit_shrine.desc=Enter a shrine and awaken its ancient magic +advancement.ebwizardry\:artefact=A Forgotten Relic +advancement.ebwizardry\:artefact.desc=Lift the protective enchantments from a shrine and claim the treasures within +advancement.ebwizardry\:all_artefacts=A Veritable Museum +advancement.ebwizardry\:all_artefacts.desc=Collect all of the rings, amulets and charms + +advancement.ebwizardry\:armour_set=Now You're a Proper Wizard +advancement.ebwizardry\:armour_set.desc=Craft and equip a full set of wizard armour +advancement.ebwizardry\:legendary=Legendary +advancement.ebwizardry\:legendary.desc=Obtain a piece of legendary wizard armour + +advancement.ebwizardry\:enchant_scroll=Scroll Up! +advancement.ebwizardry\:enchant_scroll.desc=Craft a blank scroll and enchant it with a spell at an arcane workbench + +handbook.toast.title=New Handbook Section Unlocked! + +container.ebwizardry\:arcane_workbench=Arcane Workbench +container.ebwizardry\:arcane_workbench.apply=Apply +container.ebwizardry\:arcane_workbench.mana=Mana\: +container.ebwizardry\:arcane_workbench.upgrades=Applied Upgrades\: + +tier.novice=Novice tier.apprentice=Apprentice tier.advanced=Advanced tier.master=Master -element.simple=None +element.magic=None element.fire=Fire element.ice=Ice element.lightning=Lightning @@ -288,7 +518,7 @@ element.earth=Earth element.sorcery=Sorcery element.healing=Healing -element.simple.wizard=Wizard +element.magic.wizard=Wizard element.fire.wizard=Pyromancer element.ice.wizard=Ice Mage element.lightning.wizard=Storm Mage @@ -301,323 +531,477 @@ spelltype.attack=Attack spelltype.defence=Defence spelltype.utility=Utility spelltype.minion=Minion +spelltype.buff=Buff +spelltype.construct=Construct +spelltype.projectile=Projectile +spelltype.alteration=Alteration spell.disabled=%1$s has been disabled in the config spell.resist=%1$s resisted %2$s spell.discover=Discovered the spell %1$s! -spell.ebwizardry:agility=Agility -spell.ebwizardry:arc=Arc -spell.ebwizardry:arcane_jammer=Arcane Jammer -spell.ebwizardry:arrow_rain=Arrow Rain -spell.ebwizardry:banish=Banish -spell.ebwizardry:black_hole=Black Hole -spell.ebwizardry:blink=Blink -spell.ebwizardry:blizzard=Blizzard -spell.ebwizardry:bubble=Bubble -spell.ebwizardry:chain_lightning=Chain Lightning -spell.ebwizardry:clairvoyance=Clairvoyance -spell.ebwizardry:cobwebs=Cobwebs -spell.ebwizardry:conjure_armour=Conjure Armour -spell.ebwizardry:conjure_bow=Conjure Bow -spell.ebwizardry:conjure_pickaxe=Conjure Pickaxe -spell.ebwizardry:conjure_sword=Conjure Sword -spell.ebwizardry:cure_effects=Cure Effects -spell.ebwizardry:curse_of_soulbinding=Curse of Soulbinding -spell.ebwizardry:darkness_orb=Darkness Orb -spell.ebwizardry:darkvision=Darkvision -spell.ebwizardry:dart=Dart -spell.ebwizardry:decay=Decay -spell.ebwizardry:decoy=Decoy -spell.ebwizardry:detonate=Detonate -spell.ebwizardry:diamondflesh=Diamondflesh -spell.ebwizardry:earthquake=Earthquake -spell.ebwizardry:entrapment=Entrapment -spell.ebwizardry:fireball=Fireball -spell.ebwizardry:firebolt=Firebolt -spell.ebwizardry:firebomb=Firebomb -spell.ebwizardry:fire_resistance=Fire Resistance -spell.ebwizardry:fire_sigil=Fire Sigil -spell.ebwizardry:fireskin=Fireskin -spell.ebwizardry:firestorm=Firestorm -spell.ebwizardry:flame_ray=Flame Ray -spell.ebwizardry:flaming_axe=Flaming Axe -spell.ebwizardry:flaming_weapon=Flaming Weapon -spell.ebwizardry:flight=Flight -spell.ebwizardry:font_of_mana=Font of Mana -spell.ebwizardry:font_of_vitality=Font of Vitality -spell.ebwizardry:force_arrow=Force Arrow -spell.ebwizardry:forcefield=Forcefield -spell.ebwizardry:force_orb=Force Orb -spell.ebwizardry:forests_curse=Forest's Curse -spell.ebwizardry:freeze=Freeze -spell.ebwizardry:freezing_weapon=Freezing Weapon -spell.ebwizardry:frost_axe=Frost Axe -spell.ebwizardry:frost_ray=Frost Ray -spell.ebwizardry:frost_sigil=Frost Sigil -spell.ebwizardry:glide=Glide -spell.ebwizardry:greater_fireball=Greater Fireball -spell.ebwizardry:greater_heal=Greater Heal -spell.ebwizardry:group_heal=Group Heal -spell.ebwizardry:growth_aura=Growth Aura -spell.ebwizardry:hailstorm=Hailstorm -spell.ebwizardry:heal=Heal -spell.ebwizardry:heal_ally=Heal Ally -spell.ebwizardry:healing_aura=Healing Aura -spell.ebwizardry:homing_spark=Homing Spark -spell.ebwizardry:ice_age=Ice Age -spell.ebwizardry:ice_charge=Ice Charge -spell.ebwizardry:ice_lance=Ice Lance -spell.ebwizardry:ice_shard=Ice Shard -spell.ebwizardry:ice_shroud=Ice Shroud -spell.ebwizardry:ice_spikes=Ice Spikes -spell.ebwizardry:ice_statue=Ice Statue -spell.ebwizardry:ignite=Ignite -spell.ebwizardry:imbue_weapon=Imbue Weapon -spell.ebwizardry:intimidate=Intimidate -spell.ebwizardry:invigorating_presence=Invigorating Presence -spell.ebwizardry:invisibility=Invisibility -spell.ebwizardry:invoke_weather=Invoke Weather -spell.ebwizardry:ironflesh=Ironflesh -spell.ebwizardry:leap=Leap -spell.ebwizardry:levitation=Levitation -spell.ebwizardry:life_drain=Life Drain -spell.ebwizardry:light=Light -spell.ebwizardry:lightning_arrow=Lightning Arrow -spell.ebwizardry:lightning_bolt=Lightning Bolt -spell.ebwizardry:lightning_disc=Lightning Disc -spell.ebwizardry:lightning_hammer=Lightning Hammer -spell.ebwizardry:lightning_pulse=Lightning Pulse -spell.ebwizardry:lightning_ray=Lightning Ray -spell.ebwizardry:lightning_sigil=Lightning Sigil -spell.ebwizardry:lightning_web=Lightning Web -spell.ebwizardry:magic_missile=Magic Missile -spell.ebwizardry:metamorphosis=Metamorphosis -spell.ebwizardry:meteor=Meteor -spell.ebwizardry:mind_control=Mind Control -spell.ebwizardry:mind_trick=Mind Trick -spell.ebwizardry:none=[Empty Slot] -spell.ebwizardry:oakflesh=Oakflesh -spell.ebwizardry:petrify=Petrify -spell.ebwizardry:phase_step=Phase Step -spell.ebwizardry:plague_of_darkness=Plague of Darkness -spell.ebwizardry:pocket_furnace=Pocket Furnace -spell.ebwizardry:pocket_workbench=Pocket Workbench -spell.ebwizardry:poison=Poison -spell.ebwizardry:poison_bomb=Poison Bomb -spell.ebwizardry:replenish_hunger=Replenish Hunger -spell.ebwizardry:ring_of_fire=Ring of Fire -spell.ebwizardry:shadow_ward=Shadow Ward -spell.ebwizardry:shield=Shield -spell.ebwizardry:shockwave=Shockwave -spell.ebwizardry:silverfish_swarm=Silverfish Swarm -spell.ebwizardry:sixth_sense=Sixth Sense -spell.ebwizardry:slime=Slime -spell.ebwizardry:smoke_bomb=Smoke Bomb -spell.ebwizardry:snare=Snare -spell.ebwizardry:snowball=Snowball -spell.ebwizardry:spark_bomb=Spark Bomb -spell.ebwizardry:spectral_pathway=Spectral Pathway -spell.ebwizardry:spider_swarm=Spider Swarm -spell.ebwizardry:static_aura=Static Aura -spell.ebwizardry:summon_blaze=Summon Blaze -spell.ebwizardry:summon_ice_giant=Summon Ice Giant -spell.ebwizardry:summon_ice_wraith=Summon Ice Wraith -spell.ebwizardry:summon_iron_golem=Summon Iron Golem -spell.ebwizardry:summon_lightning_wraith=Summon Lightning Wraith -spell.ebwizardry:summon_phoenix=Summon Phoenix -spell.ebwizardry:summon_shadow_wraith=Summon Shadow Wraith -spell.ebwizardry:summon_skeleton=Summon Skeleton -spell.ebwizardry:summon_skeleton_legion=Summon Skeleton Legion -spell.ebwizardry:summon_snow_golem=Summon Snow Golem -spell.ebwizardry:summon_spirit_horse=Summon Spirit Horse -spell.ebwizardry:summon_spirit_wolf=Summon Spirit Wolf -spell.ebwizardry:summon_storm_elemental=Summon Storm Elemental -spell.ebwizardry:summon_wither_skeleton=Summon Wither Skeleton -spell.ebwizardry:summon_zombie=Summon Zombie -spell.ebwizardry:telekinesis=Telekinesis -spell.ebwizardry:thunderbolt=Thunderbolt -spell.ebwizardry:thunderstorm=Thunderstorm -spell.ebwizardry:tornado=Tornado -spell.ebwizardry:transience=Transience -spell.ebwizardry:transportation=Transportation -spell.ebwizardry:vanishing_box=Vanishing Box -spell.ebwizardry:wall_of_frost=Wall of Frost -spell.ebwizardry:water_breathing=Water Breathing -spell.ebwizardry:whirlwind=Whirlwind -spell.ebwizardry:wither=Wither -spell.ebwizardry:wither_skull=Wither Skull +spell.ebwizardry\:agility=Agility +spell.ebwizardry\:arc=Arc +spell.ebwizardry\:arcane_jammer=Arcane Jammer +spell.ebwizardry\:arcane_lock=Arcane Lock +spell.ebwizardry\:arrow_rain=Arrow Rain +spell.ebwizardry\:banish=Banish +spell.ebwizardry\:black_hole=Black Hole +spell.ebwizardry\:blink=Blink +spell.ebwizardry\:blizzard=Blizzard +spell.ebwizardry\:bubble=Bubble +spell.ebwizardry\:chain_lightning=Chain Lightning +spell.ebwizardry\:charge=Charge +spell.ebwizardry\:clairvoyance=Clairvoyance +spell.ebwizardry\:cobwebs=Cobwebs +spell.ebwizardry\:combustion_rune=Combustion Rune +spell.ebwizardry\:conjure_armour=Conjure Armour +spell.ebwizardry\:conjure_block=Conjure Block +spell.ebwizardry\:conjure_bow=Conjure Bow +spell.ebwizardry\:conjure_pickaxe=Conjure Pickaxe +spell.ebwizardry\:conjure_sword=Conjure Sword +spell.ebwizardry\:containment=Containment +spell.ebwizardry\:cure_effects=Cure Effects +spell.ebwizardry\:curse_of_enfeeblement=Curse of Enfeeblement +spell.ebwizardry\:curse_of_soulbinding=Curse of Soulbinding +spell.ebwizardry\:curse_of_undeath=Curse of Undeath +spell.ebwizardry\:darkness_orb=Darkness Orb +spell.ebwizardry\:darkvision=Darkvision +spell.ebwizardry\:dart=Dart +spell.ebwizardry\:decay=Decay +spell.ebwizardry\:decoy=Decoy +spell.ebwizardry\:detonate=Detonate +spell.ebwizardry\:diamondflesh=Diamondflesh +spell.ebwizardry\:disintegration=Disintegration +spell.ebwizardry\:divination=Divination +spell.ebwizardry\:dragon_fireball=Dragon Fireball +spell.ebwizardry\:earthquake=Earthquake +spell.ebwizardry\:empowering_presence=Empowering Presence +spell.ebwizardry\:entrapment=Entrapment +spell.ebwizardry\:evade=Evade +spell.ebwizardry\:fireball=Fireball +spell.ebwizardry\:firebolt=Firebolt +spell.ebwizardry\:firebomb=Firebomb +spell.ebwizardry\:fire_resistance=Fire Resistance +spell.ebwizardry\:fire_sigil=Fire Sigil +spell.ebwizardry\:fireskin=Fireskin +spell.ebwizardry\:fire_breath=Fire Breath +spell.ebwizardry\:flame_ray=Flame Ray +spell.ebwizardry\:flaming_axe=Flaming Axe +spell.ebwizardry\:flaming_weapon=Flaming Weapon +spell.ebwizardry\:flight=Flight +spell.ebwizardry\:font_of_mana=Font of Mana +spell.ebwizardry\:font_of_vitality=Font of Vitality +spell.ebwizardry\:force_arrow=Force Arrow +spell.ebwizardry\:forcefield=Forcefield +spell.ebwizardry\:force_orb=Force Orb +spell.ebwizardry\:forests_curse=Forest's Curse +spell.ebwizardry\:forest_of_thorns=Forest of Thorns +spell.ebwizardry\:freeze=Freeze +spell.ebwizardry\:freezing_weapon=Freezing Weapon +spell.ebwizardry\:frost_axe=Frost Axe +spell.ebwizardry\:frost_ray=Frost Ray +spell.ebwizardry\:frost_sigil=Frost Sigil +spell.ebwizardry\:frost_step=Frost Step +spell.ebwizardry\:glide=Glide +spell.ebwizardry\:grapple=Grapple +spell.ebwizardry\:greater_fireball=Greater Fireball +spell.ebwizardry\:greater_heal=Greater Heal +spell.ebwizardry\:greater_telekinesis=Greater Telekinesis +spell.ebwizardry\:greater_ward=Greater Ward +spell.ebwizardry\:group_heal=Group Heal +spell.ebwizardry\:growth_aura=Growth Aura +spell.ebwizardry\:hailstorm=Hailstorm +spell.ebwizardry\:heal=Heal +spell.ebwizardry\:heal_ally=Heal Ally +spell.ebwizardry\:healing_aura=Healing Aura +spell.ebwizardry\:homing_spark=Homing Spark +spell.ebwizardry\:iceball=Iceball +spell.ebwizardry\:ice_age=Ice Age +spell.ebwizardry\:ice_charge=Ice Charge +spell.ebwizardry\:ice_lance=Ice Lance +spell.ebwizardry\:ice_shard=Ice Shard +spell.ebwizardry\:ice_shroud=Ice Shroud +spell.ebwizardry\:ice_spikes=Ice Spikes +spell.ebwizardry\:ice_statue=Ice Statue +spell.ebwizardry\:ignite=Ignite +spell.ebwizardry\:imbue_weapon=Imbue Weapon +spell.ebwizardry\:intimidate=Intimidate +spell.ebwizardry\:invigorating_presence=Invigorating Presence +spell.ebwizardry\:invisibility=Invisibility +spell.ebwizardry\:invoke_weather=Invoke Weather +spell.ebwizardry\:ironflesh=Ironflesh +spell.ebwizardry\:leap=Leap +spell.ebwizardry\:levitation=Levitation +spell.ebwizardry\:life_drain=Life Drain +spell.ebwizardry\:light=Light +spell.ebwizardry\:lightning_arrow=Lightning Arrow +spell.ebwizardry\:lightning_bolt=Lightning Bolt +spell.ebwizardry\:lightning_disc=Lightning Disc +spell.ebwizardry\:lightning_hammer=Lightning Hammer +spell.ebwizardry\:lightning_pulse=Lightning Pulse +spell.ebwizardry\:lightning_ray=Lightning Ray +spell.ebwizardry\:lightning_sigil=Lightning Sigil +spell.ebwizardry\:lightning_web=Lightning Web +spell.ebwizardry\:magic_missile=Magic Missile +spell.ebwizardry\:metamorphosis=Metamorphosis +spell.ebwizardry\:meteor=Meteor +spell.ebwizardry\:mind_control=Mind Control +spell.ebwizardry\:mind_trick=Mind Trick +spell.ebwizardry\:mine=Mine +spell.ebwizardry\:muffle=Muffle +spell.ebwizardry\:none=[Empty Slot] +spell.ebwizardry\:oakflesh=Oakflesh +spell.ebwizardry\:paralysis=Paralysis +spell.ebwizardry\:petrify=Petrify +spell.ebwizardry\:phase_step=Phase Step +spell.ebwizardry\:plague_of_darkness=Plague of Darkness +spell.ebwizardry\:pocket_furnace=Pocket Furnace +spell.ebwizardry\:pocket_workbench=Pocket Workbench +spell.ebwizardry\:poison=Poison +spell.ebwizardry\:poison_bomb=Poison Bomb +spell.ebwizardry\:possession=Possession +spell.ebwizardry\:ray_of_purification=Ray of Purification +spell.ebwizardry\:remove_curse=Remove Curse +spell.ebwizardry\:replenish_hunger=Replenish Hunger +spell.ebwizardry\:resurrection=Resurrection +spell.ebwizardry\:reversal=Reversal +spell.ebwizardry\:ring_of_fire=Ring of Fire +spell.ebwizardry\:satiety=Satiety +spell.ebwizardry\:shadow_ward=Shadow Ward +spell.ebwizardry\:shield=Shield +spell.ebwizardry\:shockwave=Shockwave +spell.ebwizardry\:shulker_bullet=Shulker Bullet +spell.ebwizardry\:silverfish_swarm=Silverfish Swarm +spell.ebwizardry\:sixth_sense=Sixth Sense +spell.ebwizardry\:slime=Slime +spell.ebwizardry\:slow_time=Slow Time +spell.ebwizardry\:smoke_bomb=Smoke Bomb +spell.ebwizardry\:snare=Snare +spell.ebwizardry\:snowball=Snowball +spell.ebwizardry\:spark_bomb=Spark Bomb +spell.ebwizardry\:spectral_pathway=Spectral Pathway +spell.ebwizardry\:speed_time=Speed Time +spell.ebwizardry\:spider_swarm=Spider Swarm +spell.ebwizardry\:static_aura=Static Aura +spell.ebwizardry\:summon_blaze=Summon Blaze +spell.ebwizardry\:summon_ice_giant=Summon Ice Giant +spell.ebwizardry\:summon_ice_wraith=Summon Ice Wraith +spell.ebwizardry\:summon_iron_golem=Summon Iron Golem +spell.ebwizardry\:summon_lightning_wraith=Summon Lightning Wraith +spell.ebwizardry\:summon_phoenix=Summon Phoenix +spell.ebwizardry\:summon_shadow_wraith=Summon Shadow Wraith +spell.ebwizardry\:summon_skeleton=Summon Skeleton +spell.ebwizardry\:summon_skeleton_legion=Summon Skeleton Legion +spell.ebwizardry\:summon_snow_golem=Summon Snow Golem +spell.ebwizardry\:summon_spirit_horse=Summon Spirit Horse +spell.ebwizardry\:summon_spirit_wolf=Summon Spirit Wolf +spell.ebwizardry\:summon_storm_elemental=Summon Storm Elemental +spell.ebwizardry\:summon_wither_skeleton=Summon Wither Skeleton +spell.ebwizardry\:summon_zombie=Summon Zombie +spell.ebwizardry\:telekinesis=Telekinesis +spell.ebwizardry\:thunderbolt=Thunderbolt +spell.ebwizardry\:thunderstorm=Thunderstorm +spell.ebwizardry\:tornado=Tornado +spell.ebwizardry\:transience=Transience +spell.ebwizardry\:transportation=Transportation +spell.ebwizardry\:vanishing_box=Vanishing Box +spell.ebwizardry\:vex_swarm=Vex Swarm +spell.ebwizardry\:wall_of_frost=Wall of Frost +spell.ebwizardry\:ward=Ward +spell.ebwizardry\:water_breathing=Water Breathing +spell.ebwizardry\:whirlwind=Whirlwind +spell.ebwizardry\:wither=Wither +spell.ebwizardry\:wither_skull=Wither Skull -spell.ebwizardry:agility.desc=Grants the caster faster movement speed and greater jump height for 30 seconds. -spell.ebwizardry:arc.desc=Fires a spark of lightning at the target. -spell.ebwizardry:arcane_jammer.desc=Prevents the target from using magic for 15 seconds. -spell.ebwizardry:arrow_rain.desc="Archers, fire!" -spell.ebwizardry:banish.desc=Teleports the target against its will to a random location within a certain range. -spell.ebwizardry:black_hole.desc=Tear reality asunder. -spell.ebwizardry:blink.desc=Teleports the caster over a short distance to where they are pointing. -spell.ebwizardry:blizzard.desc=Creates a zone of swirling icy wind which slows and continually damages anything trapped inside. The caster is immune to the damage but is still slowed. -spell.ebwizardry:bubble.desc=Fires a jet of bubbles which causes anything it hits to float upwards helplessly. The target will fall after a certain time or if it is damaged. -spell.ebwizardry:chain_lightning.desc=Fires a spark of lightning at the target, which then chains to additional targets up to twice. -spell.ebwizardry:clairvoyance.desc=Reveals the path to a remembered location. With this spell selected, sneak-right-click on a block to set the location. Cast this spell normally to reveal the path. The path will fade after 90 seconds. -spell.ebwizardry:cobwebs.desc=Creates cobwebs where you are pointing, which greatly hamper the movement of any creatures caught amongst them. The cobwebs will vanish after 20 seconds or if broken. -spell.ebwizardry:conjure_armour.desc=Creates spectral armour around the caster which offers protection equal to that of iron armour. The armour lasts for 60 seconds. The caster must have an empty armour slot. -spell.ebwizardry:conjure_bow.desc=Creates a spectral bow with unlimited arrows that lasts for 30 seconds. -spell.ebwizardry:conjure_pickaxe.desc=Creates a spectral pickaxe of equal strength to an iron pickaxe that lasts for 30 seconds. -spell.ebwizardry:conjure_sword.desc=Creates a spectral sword of equal strength to an iron sword that lasts for 30 seconds. -spell.ebwizardry:cure_effects.desc=Removes all potion effects currently affecting the caster, good or bad. -spell.ebwizardry:curse_of_soulbinding.desc=Causes the target's soul to be inextricably bound to that of the caster, meaning all damage dealt to the caster is also dealt to the victim. Lasts until either the victim or the caster dies. -spell.ebwizardry:darkness_orb.desc=Fires a slow moving bolt of dark energy in the direction you are pointing, which withers whatever it hits. -spell.ebwizardry:darkvision.desc=Grants the caster night vision for 45 seconds. -spell.ebwizardry:dart.desc=Fires a dart in the direction you are pointing which damages and weakens its target. -spell.ebwizardry:decay.desc=Creates a patch of decay on the ground which infects any creature that touches it, causing lingering damage over time and spreading more decay wherever it walks. -spell.ebwizardry:decoy.desc=Creates an illusory clone of the caster which tricks mobs into attacking it instead. The decoy will vanish after 30 seconds. -spell.ebwizardry:detonate.desc=Causes an explosion where you are pointing, damaging all nearby creatures - including the caster, if they are too close. -spell.ebwizardry:diamondflesh.desc="Your arrows are no match for me!" -spell.ebwizardry:earthquake.desc=A true master of earth magic can move mountains. -spell.ebwizardry:entrapment.desc=Traps the target in a sphere of darkness which pulls it helplessly upwards and continually damages it. -spell.ebwizardry:fireball.desc=Launches a fireball in the direction you are pointing. -spell.ebwizardry:firebolt.desc=Shoots a jet of fire a short distance in front of you. -spell.ebwizardry:firebomb.desc=Lanches a firebomb in the direction you are pointing which explodes on impact, setting targets on fire. -spell.ebwizardry:fire_resistance.desc=Grants the caster fire resistance for 30 seconds. -spell.ebwizardry:fire_sigil.desc=Places a magical fire trap on the ground which damages and sets on fire the creature that triggers it. -spell.ebwizardry:fireskin.desc=Cloaks the caster in flames for 30 seconds, causing anything that attacks them to catch fire. -spell.ebwizardry:firestorm.desc="I am the dragon." -spell.ebwizardry:flame_ray.desc=Creates a stream of flames in the direction you are pointing which sets on fire and continually damages targets. -spell.ebwizardry:flaming_axe.desc=Creates a flaming axe which sets enemies on fire when hit. Lasts for 30 seconds. -spell.ebwizardry:flaming_weapon.desc=Temporarily imbues the first weapon on the caster's hotbar with the power of flame, causing it to set fire to its victims. The magic wears off after 45 seconds. -spell.ebwizardry:flight.desc=Soar like an eagle. -spell.ebwizardry:font_of_mana.desc="We were filled with an intense magical energy appearing to emanate from the centre of the..." - Extract from the journal of a forgotten mage; the rest of the page has been burnt away. -spell.ebwizardry:font_of_vitality.desc=It feels amazing. -spell.ebwizardry:force_arrow.desc=Shoots an arrow of force in the direction you are pointing. -spell.ebwizardry:forcefield.desc=Creates a forcefield around the caster which repels creatures and deflects projectiles. -spell.ebwizardry:force_orb.desc=Launches a sphere of force which damages and repels nearby creatures on impact. -spell.ebwizardry:forests_curse.desc="How dare you enter my forest!" -spell.ebwizardry:freeze.desc=Freezes the target for 10 seconds. Will also freeze water and create snow on the ground. -spell.ebwizardry:freezing_weapon.desc=Temporarily imbues the first weapon on the caster's hotbar with the power of frost, causing it to freeze its victims. The magic wears off after 45 seconds. -spell.ebwizardry:frost_axe.desc=Creates a frozen axe which freezes enemies when hit. Lasts for 30 seconds. -spell.ebwizardry:frost_ray.desc=Creates a stream of frost in the direction you are pointing which slows and continually damages targets. -spell.ebwizardry:frost_sigil.desc=Places a magical ice trap on the ground which damages and freezes the creature that triggers it. -spell.ebwizardry:glide.desc=Allows the caster to glide downwards while in the air and holding the use item button. -spell.ebwizardry:greater_fireball.desc=Launches a large fireball in the direction you are pointing which explodes on impact. -spell.ebwizardry:greater_heal.desc=Heals the caster by 4 hearts. -spell.ebwizardry:group_heal.desc=Heals the caster and all nearby allies and summoned creatures by 3 hearts. -spell.ebwizardry:growth_aura.desc=Grows all crops near the caster. Also grows tall grass and flowers on grass. -spell.ebwizardry:hailstorm.desc=It was during the great winter of the third age that the ice mages discovered their true power. -spell.ebwizardry:heal.desc=Heals the caster by 2 hearts. -spell.ebwizardry:heal_ally.desc=Heals the target by 2 and a half hearts. -spell.ebwizardry:healing_aura.desc=Creates a zone of healing energy which regenerates the health of any ally inside it. Any undead inside the healing aura will slowly take damage. -spell.ebwizardry:homing_spark.desc=Creates a floating spark which moves towards enemies. -spell.ebwizardry:ice_age.desc="You shall be frozen for an eternity!" -spell.ebwizardry:ice_charge.desc=Launches an ice charge which explodes on impact, freezing nearby creatures and releasing shards in all directions. -spell.ebwizardry:ice_lance.desc=Fires a great spear of ice in the direction you are pointing which overpenetrates targets, damaging and freezing them in the process. -spell.ebwizardry:ice_shard.desc=Fires a shard of ice in the direction you are pointing which damages and slows targets when hit. -spell.ebwizardry:ice_shroud.desc=Creates a shroud of cold around the caster for 30 seconds, causing anything that attacks them to be frozen. -spell.ebwizardry:ice_spikes.desc=Causes razor-sharp ice spikes to rise from the ground where you are pointing, skewering any creatures caught amongst them. -spell.ebwizardry:ice_statue.desc=Freezes the target solid for 20 seconds or until broken out. The target cannot move or do anything while frozen but is also impervious to all damage. -spell.ebwizardry:ignite.desc=Sets the target on fire for 10 seconds. Also works like a flint and steel. -spell.ebwizardry:imbue_weapon.desc=Temporarily imbues the first weapon on the caster's hotbar with magic, rendering it more effective. The magic wears off after 45 seconds. -spell.ebwizardry:intimidate.desc=Emits an intimidating growl which causes nearby creatures to run away in fear. Fear stricken creatures will recover after 30 seconds. -spell.ebwizardry:invigorating_presence.desc=Grants the caster and all nearby allies increased strength for 45 seconds. -spell.ebwizardry:invisibility.desc=Makes the caster invisible for 30 seconds. -spell.ebwizardry:invoke_weather.desc=Changes the weather in the world. -spell.ebwizardry:ironflesh.desc=Greatly improves the caster's damage resistance for 30 seconds. -spell.ebwizardry:leap.desc=Causes the caster to jump upwards several blocks and slightly forward. -spell.ebwizardry:levitation.desc=Raises the caster upwards while the use item button is held. Will also negate fall damage if used before hitting the ground. -spell.ebwizardry:life_drain.desc=Creates a stream of withering energy in the direction you are pointing which drains the life of the target and uses it to gradually regenerate your health. -spell.ebwizardry:light.desc=Creates a magical point of light which illuminates the surrounding area. Lasts for 30 seconds. -spell.ebwizardry:lightning_arrow.desc=Shoots an arrow of lightning in the direction you are pointing. -spell.ebwizardry:lightning_bolt.desc=Causes lightning to strike where you are pointing. -spell.ebwizardry:lightning_disc.desc=Sends a disc of lightning flying off in the direction you are pointing, which seeks targets. -spell.ebwizardry:lightning_hammer.desc="I smite you by the wrath of the heavens!" -spell.ebwizardry:lightning_pulse.desc=Charges the ground around the caster with lightning, damaging and repelling nearby creatures. -spell.ebwizardry:lightning_ray.desc=Creates a stream of lightning in the direction you are pointing which continually damages targets. -spell.ebwizardry:lightning_sigil.desc=Places a magical lightning trap on the ground which damages the creature that triggers it and chains lightning to other nearby creatures. -spell.ebwizardry:lightning_web.desc="Focus. Channel the storm in your mind through your wand and unleash its fury." -spell.ebwizardry:magic_missile.desc=Fires a bolt of magical energy in the direction you are pointing. -spell.ebwizardry:metamorphosis.desc=Changes the target into another form. Only works on some creatures. -spell.ebwizardry:meteor.desc=Some wizards just want to see the world burn... -spell.ebwizardry:mind_control.desc=Takes control of the target's mind for 30 seconds, causing it switch sides and fight for the caster instead. Will not work on creatures that are too strong-willed. -spell.ebwizardry:mind_trick.desc=Confuses and disorients the target for 15 seconds, rendering it unable to attack effectively. The effect will be dispelled if the target takes damage. -spell.ebwizardry:none.desc=To get a spell book with the /give command, use metadata: /give [player] ebwizardry:spell_book 1 [spell id] (if you found this book in a chest, some other mod has messed things up). -spell.ebwizardry:oakflesh.desc=Improves the caster's damage resistance for 30 seconds. -spell.ebwizardry:petrify.desc=Turns the target to stone until broken out, with a chance for it to break out when it is dark. The target cannot move or do anything while petrified but is also impervious to all damage. -spell.ebwizardry:phase_step.desc=Teleports the caster through a 1 block thick wall in front of them. Range upgrades will increase the thickness you can teleport through. -spell.ebwizardry:plague_of_darkness.desc=The darkness will consume them all... -spell.ebwizardry:pocket_furnace.desc=Smelts up to 5 smeltable items in the caster's inventory. Items on the hotbar will be smelted first. -spell.ebwizardry:pocket_workbench.desc=Allows the caster to craft items as if they were at a crafting table. -spell.ebwizardry:poison.desc=Fires poison in the direction you are pointing. -spell.ebwizardry:poison_bomb.desc=Lanches a poison bomb in the direction you are pointing which explodes on impact, poisoning nearby creatures. -spell.ebwizardry:replenish_hunger.desc=Replenishes the caster's food level by 6 hunger points. -spell.ebwizardry:ring_of_fire.desc=Creates a ring of fire around the caster, damaging all nearby enemies and setting them on fire. -spell.ebwizardry:shadow_ward.desc=Creates a wall of darkness in front of the caster which causes half of all incoming damage to be inflicted upon the attacker instead. -spell.ebwizardry:shield.desc=Creates a protective barrier of force that blocks projectiles and magic. Also grants the caster a weak resistance effect. -spell.ebwizardry:shockwave.desc=Boom. -spell.ebwizardry:silverfish_swarm.desc="Ahhhh! They're MULTIPLYING!" -spell.ebwizardry:sixth_sense.desc=Allows the caster to sense the locations of nearby creatures, even through walls, for 20 seconds. -spell.ebwizardry:slime.desc=Engulfs the target in slime which slows and continually damages it. The slime bursts after 10 seconds. -spell.ebwizardry:smoke_bomb.desc=Launches a smoke bomb in the direction you are pointing which explodes on impact, releasing smoke and blinding nearby creatures for a short time. -spell.ebwizardry:snare.desc=Sets a trap on the ground which damages and briefly slows the creature that triggers it. -spell.ebwizardry:snowball.desc=Launches a snowball in the direction you are pointing. -spell.ebwizardry:spark_bomb.desc=Launches a shock charge in the direction you are pointing which releases sparks at nearby enemies on impact. -spell.ebwizardry:spectral_pathway.desc=Creates an indestructible magical bridge in front of you which extends for 15 blocks. The bridge vanishes after 60 seconds. -spell.ebwizardry:spider_swarm.desc=Summons a swarm of venomous spiders to fight for you. The spiders will disappear after 30 seconds or if they are killed. -spell.ebwizardry:static_aura.desc=Surrounds the caster with lightning for 30 seconds, firing a spark of lightning at anything that hits them. -spell.ebwizardry:summon_blaze.desc=Summons a blaze to fight for you. The blaze will disappear after 30 seconds or if it is killed. -spell.ebwizardry:summon_ice_giant.desc="Smash them!" -spell.ebwizardry:summon_ice_wraith.desc=Summons an ice wraith to fight for you. The ice wraith will disappear after 30 seconds or if it is killed. -spell.ebwizardry:summon_iron_golem.desc=Automatic automated autonomous automaton. -spell.ebwizardry:summon_lightning_wraith.desc=Summons a lightning wraith to fight for you. The lightning wraith will disappear after 30 seconds or if it is killed. -spell.ebwizardry:summon_phoenix.desc=From the ashes... -spell.ebwizardry:summon_shadow_wraith.desc=Summons a shadow wraith to fight for you. -spell.ebwizardry:summon_skeleton.desc=Summons a skeleton to fight for you. The skeleton will disappear after 30 seconds or if it is killed. -spell.ebwizardry:summon_skeleton_legion.desc="Rise, undead army!" -spell.ebwizardry:summon_snow_golem.desc=Creates a snow golem to fight for you. Lasts until the snow golem dies. -spell.ebwizardry:summon_spirit_horse.desc=Summons a spirit horse for you to ride. The spirit horse will vanish a short while after it is dismounted, or you can dismiss it by shift-right-clicking on it with any wand. -spell.ebwizardry:summon_spirit_wolf.desc=Summons a spirit wolf companion to fight for you. The spirit wolf will only disappear if it is killed, or you can dismiss it by shift-right-clicking on it with any wand. -spell.ebwizardry:summon_storm_elemental.desc="Storm Elemental: An ancient manifestation of the elements, it can hardly contain the raw power churning within it." - The Wizard's Guide to Arcane Beings, Volume I_i -spell.ebwizardry:summon_wither_skeleton.desc=Summons a wither skeleton to fight for you. The wither skeleton will disappear after 30 seconds or if it is killed. -spell.ebwizardry:summon_zombie.desc=Summons a zombie to fight for you. The zombie will disappear after 30 seconds or if it is killed. -spell.ebwizardry:telekinesis.desc=Moves an item or other small object towards you, or right-clicks the block you are looking at. Can also be used to disarm players. -spell.ebwizardry:thunderbolt.desc=Shoots a bolt of thunder which knocks back targets. -spell.ebwizardry:thunderstorm.desc="Mwahahahahahaha!" -spell.ebwizardry:tornado.desc=Unleashes a tornado in the direction you are pointing which hurls anything in its path skywards. -spell.ebwizardry:transience.desc=Makes the caster transient for 20 seconds. The caster is immune to all damage while transient but cannot break or place blocks or cause any damage. -spell.ebwizardry:transportation.desc=Transports the caster to their remembered stone circle. To use this spell, make a circle of stones of transportation, then right click it with a wand. -spell.ebwizardry:vanishing_box.desc=Grants the caster access to their ender chest storage. -spell.ebwizardry:wall_of_frost.desc=Winter at your fingertips. -spell.ebwizardry:water_breathing.desc=Allows the caster to breathe underwater for 60 seconds. -spell.ebwizardry:whirlwind.desc=Causes the target to be blown upwards and away from you at speed. -spell.ebwizardry:wither.desc=Fires a ray of darkness which withers anything it touches. -spell.ebwizardry:wither_skull.desc=Launches a wither skull in the direction you are pointing. +spell.ebwizardry\:agility.desc=Grants the caster faster movement speed and greater jump height for 30 seconds. +spell.ebwizardry\:arc.desc=Fires a spark of lightning at the target. +spell.ebwizardry\:arcane_jammer.desc=Prevents the target from using magic for 15 seconds. +spell.ebwizardry\:arcane_lock.desc=Creates an impenetrable barrier of force around a container, protecting it from being opened or destroyed. The caster and their allies may still open it, however. +spell.ebwizardry\:arrow_rain.desc="Archers, fire!" +spell.ebwizardry\:banish.desc=Teleports the target against its will to a random locations within a certain range. +spell.ebwizardry\:black_hole.desc=Tear reality asunder. +spell.ebwizardry\:blink.desc=Teleports the caster over a short distance to where they are pointing. +spell.ebwizardry\:blizzard.desc=Creates a zone of swirling icy wind which slows and continually damages anything trapped inside. The caster is immune to the damage but is still slowed. +spell.ebwizardry\:bubble.desc=Fires a jet of bubbles which causes anything it hits to float upwards helplessly. The target will fall after a certain time or if it is damaged. +spell.ebwizardry\:chain_lightning.desc=Fires a spark of lightning at the target, which then chains to additional targets up to twice. +spell.ebwizardry\:charge.desc=Causes the caster to charge rapidly in the direction they are looking, damaging and knocking back anything in their path. +spell.ebwizardry\:clairvoyance.desc=Reveals the path to a remembered locations. With this spell selected, sneak-right-click on a block to set the locations. Cast this spell normally to reveal the path. The path will fade after 90 seconds. +spell.ebwizardry\:cobwebs.desc=Creates cobwebs where you are pointing, which greatly hamper the movement of any creatures caught amongst them. The cobwebs will vanish after 20 seconds or if broken. +spell.ebwizardry\:combustion_rune.desc=Places a magical landmine on the ground where you are pointing, which explodes when stepped upon. +spell.ebwizardry\:conjure_armour.desc=Creates spectral armour around the caster which offers protection equal to that of iron armour. The armour lasts for 60 seconds. The caster must have an empty armour slot. +spell.ebwizardry\:conjure_block.desc=Conjures a spectral block where you are pointing. The spectral block disappears after 45 seconds, or you can dispel it by casting this spell at it again. +spell.ebwizardry\:conjure_bow.desc=Creates a spectral bow with unlimited arrows that lasts for 30 seconds. +spell.ebwizardry\:conjure_pickaxe.desc=Creates a spectral pickaxe of equal strength to an iron pickaxe that lasts for 30 seconds. +spell.ebwizardry\:conjure_sword.desc=Creates a spectral sword of equal strength to an iron sword that lasts for 30 seconds. +spell.ebwizardry\:containment.desc=Contains the target to within a short distance of its current position for 20 seconds. +spell.ebwizardry\:cure_effects.desc=Removes all potion effects currently affecting the caster, good or bad. +spell.ebwizardry\:curse_of_enfeeblement.desc="He was suddenly weakened, as if the life had been wrenched from within him." - Testimony of the only person known to have encountered a member of the soulwalker cult and survived. +spell.ebwizardry\:curse_of_soulbinding.desc=Causes the target's soul to be inextricably bound to that of the caster, meaning all damage dealt to the caster is also dealt to the victim. Lasts until either the victim or the caster dies. +spell.ebwizardry\:curse_of_undeath.desc=Curses the target with undeath, causing it to burn in sunlight, like zombies and skeletons. Lasts until the victim dies. Has no effect on undead creatures. +spell.ebwizardry\:darkness_orb.desc=Fires a slow moving bolt of dark energy in the direction you are pointing, which withers whatever it hits. +spell.ebwizardry\:darkvision.desc=Grants the caster night vision for 45 seconds. +spell.ebwizardry\:dart.desc=Fires a dart in the direction you are pointing which damages and weakens its target. +spell.ebwizardry\:decay.desc=Creates a patch of decay on the ground which infects any creature that touches it, causing lingering damage over time and spreading more decay wherever it walks. +spell.ebwizardry\:decoy.desc=Creates an illusory clone of the caster which tricks mobs into attacking it instead. The decoy will vanish after 30 seconds. +spell.ebwizardry\:detonate.desc=Causes an explosion where you are pointing, damaging all nearby creatures - including the caster, if they are too close. +spell.ebwizardry\:diamondflesh.desc="Your arrows are no match for me!" +spell.ebwizardry\:disintegration.desc=Shoots a powerful bolt of flame a short distance in front of you which causes targets to explode into burning embers when killed. Creatures that step on the embers will be set on fire. +spell.ebwizardry\:divination.desc=Guides the caster to nearby ores and resources. Potency will increase the chance of finding more valuable ores. +spell.ebwizardry\:dragon_fireball.desc=Launches an enderdragon fireball in the direction you are pointing, which releases lingering poisonous clouds on impact. +spell.ebwizardry\:earthquake.desc=A true master of earth magic can move mountains. +spell.ebwizardry\:empowering_presence.desc=Grants the caster and nearby allies increased magic damage for 30 seconds. +spell.ebwizardry\:entrapment.desc=Traps the target in a sphere of darkness which pulls it helplessly upwards and continually damages it. +spell.ebwizardry\:evade.desc=Causes the caster to quickly jump sideways to dodge incoming attacks. +spell.ebwizardry\:fireball.desc=Launches a fireball in the direction you are pointing. +spell.ebwizardry\:firebolt.desc=Shoots a jet of fire a short distance in front of you. +spell.ebwizardry\:firebomb.desc=Lanches a firebomb in the direction you are pointing which explodes on impact, setting targets on fire. +spell.ebwizardry\:fire_resistance.desc=Grants the caster fire resistance for 30 seconds. +spell.ebwizardry\:fire_sigil.desc=Places a magical fire trap on the ground which damages and sets on fire the creature that triggers it. +spell.ebwizardry\:fireskin.desc=Cloaks the caster in flames for 30 seconds, causing anything that attacks them to catch fire. +spell.ebwizardry\:fire_breath.desc="I am the dragon." +spell.ebwizardry\:flame_ray.desc=Creates a stream of flames in the direction you are pointing which sets on fire and continually damages targets. +spell.ebwizardry\:flaming_axe.desc=Creates a flaming axe which sets enemies on fire when hit. Lasts for 30 seconds. +spell.ebwizardry\:flaming_weapon.desc=Temporarily imbues the first weapon on the caster's hotbar with the power of flame, causing it to set fire to its victims. The magic wears off after 45 seconds. +spell.ebwizardry\:flight.desc=Soar like an eagle. +spell.ebwizardry\:font_of_mana.desc="We were filled with an intense magical energy appearing to emanate from the centre of the..." - Extract from the journal of a forgotten mage; the rest of the page has been burnt away. +spell.ebwizardry\:font_of_vitality.desc=It feels amazing. +spell.ebwizardry\:force_arrow.desc=Shoots an arrow of force in the direction you are pointing. +spell.ebwizardry\:forcefield.desc=Creates a forcefield around the caster which repels creatures and deflects projectiles. +spell.ebwizardry\:force_orb.desc=Launches a sphere of force which damages and repels nearby creatures on impact. +spell.ebwizardry\:forests_curse.desc="How dare you enter my forest!" +spell.ebwizardry\:forest_of_thorns.desc=Amidst the wood lies a hidden glade,\nIn the glade a wizard performs,\nMagical arts of an order untold,\nDeep within the forest of thorns. +spell.ebwizardry\:freeze.desc=Freezes the target for 10 seconds. Will also freeze water and create snow on the ground. +spell.ebwizardry\:freezing_weapon.desc=Temporarily imbues the first weapon on the caster's hotbar with the power of frost, causing it to freeze its victims. The magic wears off after 45 seconds. +spell.ebwizardry\:frost_axe.desc=Creates a frozen axe which freezes enemies when hit. Lasts for 30 seconds. +spell.ebwizardry\:frost_ray.desc=Creates a stream of frost in the direction you are pointing which slows and continually damages targets. +spell.ebwizardry\:frost_sigil.desc=Places a magical ice trap on the ground which damages and freezes the creature that triggers it. +spell.ebwizardry\:frost_step.desc=Allows the caster to freeze water as they walk for 30 seconds. +spell.ebwizardry\:grapple.desc=Shoots a magical vine which allows the caster to grapple towards blocks or reel in entities. Release the use item button to let go of the block or entity. +spell.ebwizardry\:glide.desc=Allows the caster to glide downwards while in the air and holding the use item button. +spell.ebwizardry\:greater_fireball.desc=Launches a large fireball in the direction you are pointing which explodes on impact. +spell.ebwizardry\:greater_heal.desc=Heals the caster by 4 hearts. +spell.ebwizardry\:greater_telekinesis.desc=Allows the caster to pick up a block or creature and hold it in the air for as long as the use item button is pressed. Sneaking whilst holding a block or creature will throw it a short distance. +spell.ebwizardry\:greater_ward.desc=Grants the caster a strong shielding effect that greatly reduces incoming magic damage for 30 seconds. +spell.ebwizardry\:group_heal.desc=Heals the caster and all nearby allies and summoned creatures by 3 hearts. +spell.ebwizardry\:growth_aura.desc=Grows all crops near the caster. Also grows tall grass and flowers on grass. +spell.ebwizardry\:hailstorm.desc=It was during the great winter of the third age that the ice mages discovered their true power. +spell.ebwizardry\:heal.desc=Heals the caster by 2 hearts. +spell.ebwizardry\:heal_ally.desc=Heals the target by 2 and a half hearts. +spell.ebwizardry\:healing_aura.desc=Creates a zone of healing energy which regenerates the health of any ally inside it. Any undead inside the healing aura will slowly take damage. +spell.ebwizardry\:homing_spark.desc=Creates a floating spark which moves towards enemies. +spell.ebwizardry\:iceball.desc=Launches an iceball in the direction you are pointing. +spell.ebwizardry\:ice_age.desc="You shall be frozen for an eternity!" +spell.ebwizardry\:ice_charge.desc=Launches an ice charge which explodes on impact, freezing nearby creatures and releasing shards in all directions. +spell.ebwizardry\:ice_lance.desc=Fires a great spear of ice in the direction you are pointing which overpenetrates targets, damaging and freezing them in the process. +spell.ebwizardry\:ice_shard.desc=Fires a shard of ice in the direction you are pointing which damages and slows targets when hit. +spell.ebwizardry\:ice_shroud.desc=Creates a shroud of cold around the caster for 30 seconds, causing anything that attacks them to be frozen. +spell.ebwizardry\:ice_spikes.desc=Causes razor-sharp ice spikes to rise from the ground where you are pointing, skewering any creatures caught amongst them. +spell.ebwizardry\:ice_statue.desc=Freezes the target solid for 20 seconds or until broken out. The target cannot move or do anything while frozen but is also impervious to all damage. +spell.ebwizardry\:ignite.desc=Sets the target on fire for 10 seconds. Also works like a flint and steel. +spell.ebwizardry\:imbue_weapon.desc=Temporarily imbues the first weapon on the caster's hotbar with magic, rendering it more effective. The magic wears off after 45 seconds. +spell.ebwizardry\:intimidate.desc=Emits an intimidating growl which causes nearby creatures to run away in fear. Fear stricken creatures will recover after 30 seconds. +spell.ebwizardry\:invigorating_presence.desc=Grants the caster and all nearby allies increased strength for 45 seconds. +spell.ebwizardry\:invisibility.desc=Makes the caster invisible for 30 seconds. +spell.ebwizardry\:invoke_weather.desc=Changes the weather in the world. +spell.ebwizardry\:ironflesh.desc=Greatly improves the caster's damage resistance for 30 seconds. +spell.ebwizardry\:leap.desc=Causes the caster to jump upwards several blocks and slightly forward. +spell.ebwizardry\:levitation.desc=Raises the caster upwards while the use item button is held. Will also negate fall damage if used before hitting the ground. +spell.ebwizardry\:life_drain.desc=Creates a stream of withering energy in the direction you are pointing which drains the life of the target and uses it to gradually regenerate your health. +spell.ebwizardry\:light.desc=Creates a magical point of light which illuminates the surrounding area. Lasts for 30 seconds. +spell.ebwizardry\:lightning_arrow.desc=Shoots an arrow of lightning in the direction you are pointing. +spell.ebwizardry\:lightning_bolt.desc=Causes lightning to strike where you are pointing. +spell.ebwizardry\:lightning_disc.desc=Sends a disc of lightning flying off in the direction you are pointing, which seeks targets. +spell.ebwizardry\:lightning_hammer.desc="I smite you by the wrath of the heavens!" +spell.ebwizardry\:lightning_pulse.desc=Charges the ground around the caster with lightning, damaging and repelling nearby creatures. +spell.ebwizardry\:lightning_ray.desc=Creates a stream of lightning in the direction you are pointing which continually damages targets. +spell.ebwizardry\:lightning_sigil.desc=Places a magical lightning trap on the ground which damages the creature that triggers it and chains lightning to other nearby creatures. +spell.ebwizardry\:lightning_web.desc="Focus. Channel the storm in your mind through your wand and unleash its fury." +spell.ebwizardry\:magic_missile.desc=Fires a bolt of magical energy in the direction you are pointing. +spell.ebwizardry\:metamorphosis.desc=Changes the target into another form. Only works on some creatures. +spell.ebwizardry\:meteor.desc=Some wizards just want to see the world burn... +spell.ebwizardry\:mind_control.desc=Takes control of the target's mind for 30 seconds, causing it switch sides and fight for the caster instead. Will not work on creatures that are too strong-willed. +spell.ebwizardry\:mind_trick.desc=Confuses and disorients the target for 15 seconds, rendering it unable to attack effectively. The effect will be dispelled if the target takes damage. +spell.ebwizardry\:mine.desc=Breaks the block the caster is looking at. Potency will allow harder blocks to be broken. +spell.ebwizardry\:muffle.desc=Silences any sounds made by the caster for 30 seconds. When muffled, mobs can only detect you when looking towards you. +spell.ebwizardry\:none.desc=To get a spell book with the /give command, use id\: /give [player] ebwizardry\:spell_book 1 [spell id] (if you found this book in a chest, some other mod has messed things up). +spell.ebwizardry\:oakflesh.desc=Improves the caster's damage resistance for 30 seconds. +spell.ebwizardry\:paralysis.desc=Delivers a powerful lightning bolt that paralyses targets for 5 seconds. Paralysed creatures cannot move and will still take damage - but too much will snap the creature out of paralysis. +spell.ebwizardry\:petrify.desc=Turns the target to stone until broken out, with a chance for it to break out when it is dark. The target cannot move or do anything while petrified but is also impervious to all damage. +spell.ebwizardry\:phase_step.desc=Teleports the caster a short distance in front of them, including through walls. Range upgrades will increase the wall thickness you can teleport through. +spell.ebwizardry\:plague_of_darkness.desc=The darkness will consume them all... +spell.ebwizardry\:pocket_furnace.desc=Smelts up to 5 smeltable items in the caster's inventory. Items on the hotbar will be smelted first. +spell.ebwizardry\:pocket_workbench.desc=Allows the caster to craft items as if they were at a crafting table. +spell.ebwizardry\:poison.desc=Fires poison in the direction you are pointing. +spell.ebwizardry\:poison_bomb.desc=Lanches a poison bomb in the direction you are pointing which explodes on impact, poisoning nearby creatures. +spell.ebwizardry\:possession.desc="Become thy enemy." +spell.ebwizardry\:ray_of_purification.desc=Emits a ray of blinding light that damages and blinds its targets. Undead creatures take double damage and are set on fire. +spell.ebwizardry\:remove_curse.desc=Removes any curse currently affecting the caster. +spell.ebwizardry\:replenish_hunger.desc=Replenishes the caster's food level by 4 hunger points. +spell.ebwizardry\:resurrection.desc=With a master healer by your side, being dead is... optional. +spell.ebwizardry\:reversal.desc=Removes a random negative potion effect and inflicts it upon the target, which will suffer that effect for the remaining duration. Potency increases the number of effects that are reversed. +spell.ebwizardry\:ring_of_fire.desc=Creates a ring of fire around the caster, damaging all nearby enemies and setting them on fire. +spell.ebwizardry\:satiety.desc=Replenishes the caster's food level by 8 hunger points. +spell.ebwizardry\:shadow_ward.desc=Creates a wall of darkness in front of the caster which causes half of all incoming damage to be inflicted upon the attacker instead. +spell.ebwizardry\:shield.desc=Creates a protective barrier of force that blocks projectiles and magic. Also grants the caster a weak resistance effect. +spell.ebwizardry\:shockwave.desc=Boom. +spell.ebwizardry\:shulker_bullet.desc=Shoots a shulker bullet which seeks targets and causes them to levitate when hit. +spell.ebwizardry\:silverfish_swarm.desc="Ahhhh! They're MULTIPLYING!" +spell.ebwizardry\:sixth_sense.desc=Allows the caster to sense the locations of nearby creatures, even through walls, for 20 seconds. +spell.ebwizardry\:slime.desc=Engulfs the target in slime which slows and continually damages it. The slime bursts after 10 seconds. +spell.ebwizardry\:slow_time.desc=Chronomancy is the art of manipulating time itself to fit one's needs. It was widely believed to be lost in the past... until now. +spell.ebwizardry\:smoke_bomb.desc=Launches a smoke bomb in the direction you are pointing which explodes on impact, releasing smoke and blinding nearby creatures for a short time. +spell.ebwizardry\:snare.desc=Sets a trap on the ground which damages and briefly slows the creature that triggers it. +spell.ebwizardry\:snowball.desc=Launches a snowball in the direction you are pointing. +spell.ebwizardry\:spark_bomb.desc=Launches a shock charge in the direction you are pointing which releases sparks at nearby enemies on impact. +spell.ebwizardry\:spectral_pathway.desc=Creates an indestructible magical bridge in front of you which extends for 15 blocks. The bridge vanishes after 60 seconds. +spell.ebwizardry\:speed_time.desc=...day, night, dawn, dusk, sunrise and sunset\: thus is the passage of time, which traps us in an endless cycle of... +spell.ebwizardry\:spider_swarm.desc=Summons a swarm of venomous spiders to fight for you. The spiders will disappear after 30 seconds or if they are killed. +spell.ebwizardry\:static_aura.desc=Surrounds the caster with lightning for 30 seconds, firing a spark of lightning at anything that hits them. +spell.ebwizardry\:summon_blaze.desc=Summons a blaze to fight for you. The blaze will disappear after 30 seconds or if it is killed. +spell.ebwizardry\:summon_ice_giant.desc="Smash them!" +spell.ebwizardry\:summon_ice_wraith.desc=Summons an ice wraith to fight for you. The ice wraith will disappear after 30 seconds or if it is killed. +spell.ebwizardry\:summon_iron_golem.desc=Automatic automated autonomous automaton. +spell.ebwizardry\:summon_lightning_wraith.desc=Summons a lightning wraith to fight for you. The lightning wraith will disappear after 30 seconds or if it is killed. +spell.ebwizardry\:summon_phoenix.desc=From the ashes... +spell.ebwizardry\:summon_shadow_wraith.desc=Summons a shadow wraith to fight for you. +spell.ebwizardry\:summon_skeleton.desc=Summons a skeleton to fight for you. The skeleton will disappear after 30 seconds or if it is killed. +spell.ebwizardry\:summon_skeleton_legion.desc="Rise, undead army!" +spell.ebwizardry\:summon_snow_golem.desc=Creates a snow golem to fight for you. Lasts until the snow golem dies. +spell.ebwizardry\:summon_spirit_horse.desc=Summons a spirit horse for you to ride. The spirit horse will vanish a short while after it is dismounted, or you can dismiss it by shift-right-clicking on it with any wand. +spell.ebwizardry\:summon_spirit_wolf.desc=Summons a spirit wolf companion to fight for you. The spirit wolf will only disappear if it is killed, or you can dismiss it by shift-right-clicking on it with any wand. +spell.ebwizardry\:summon_storm_elemental.desc="Storm Elemental\: An ancient manifestation of the elements, it can hardly contain the raw power churning within it." - The Wizard's Guide to Arcane Beings, Volume II +spell.ebwizardry\:summon_wither_skeleton.desc=Summons a wither skeleton to fight for you. The wither skeleton will disappear after 30 seconds or if it is killed. +spell.ebwizardry\:summon_zombie.desc=Summons a zombie to fight for you. The zombie will disappear after 30 seconds or if it is killed. +spell.ebwizardry\:telekinesis.desc=Moves an item or other small object towards you, or right-clicks the block you are looking at. Can also be used to disarm players. +spell.ebwizardry\:thunderbolt.desc=Shoots a bolt of thunder which knocks back targets. +spell.ebwizardry\:thunderstorm.desc="Mwahahahahahaha!" +spell.ebwizardry\:tornado.desc=Unleashes a tornado in the direction you are pointing which hurls anything in its path skywards. +spell.ebwizardry\:transience.desc=Makes the caster transient for 20 seconds. The caster is immune to all damage while transient but cannot break or place blocks or cause any damage. +spell.ebwizardry\:transportation.desc=Transports the caster to their remembered stone circle. To use this spell, make a circle of stones of transportation, then right click it with a wand. +spell.ebwizardry\:vanishing_box.desc=Grants the caster access to their ender chest storage. +spell.ebwizardry\:vex_swarm.desc=Summons a swarm of flying vexes to fight for you. The vexes will disappear after 30 seconds or if they are killed. +spell.ebwizardry\:wall_of_frost.desc=Winter at your fingertips. +spell.ebwizardry\:ward.desc=Grants the caster a shielding effect that reduces incoming magic damage for 30 seconds. +spell.ebwizardry\:water_breathing.desc=Allows the caster to breathe underwater for 60 seconds. +spell.ebwizardry\:whirlwind.desc=Causes the target to be blown upwards and away from you at speed. +spell.ebwizardry\:wither.desc=Fires a ray of darkness which withers anything it touches. +spell.ebwizardry\:wither_skull.desc=Launches a wither skull in the direction you are pointing. -spell.ebwizardry:invoke_weather.sun=The rain begins to stop... -spell.ebwizardry:invoke_weather.rain=The heavens open... -spell.ebwizardry:transportation.missing=Your remembered stone circle is missing or obstructed... -spell.ebwizardry:transportation.undefined=You must remember the location of a stone circle first! -spell.ebwizardry:transportation.wrongdimension=Your remembered stone circle is in another dimension... -spell.ebwizardry:clairvoyance.searching=Searching... -spell.ebwizardry:clairvoyance.confirm=The path revealed upon casting %1$s will now lead back to this point -spell.ebwizardry:clairvoyance.outofrange=Your remembered location is too far away or inaccessible... -spell.ebwizardry:clairvoyance.undefined=You must remember a location first! -spell.ebwizardry:clairvoyance.wrongdimension=Your remembered location is in another dimension... +spell.ebwizardry\:invoke_weather.sun=The rain begins to stop... +spell.ebwizardry\:invoke_weather.rain=The heavens open... +spell.ebwizardry\:transportation.missing=The stone circle is missing or obstructed... +spell.ebwizardry\:transportation.undefined=You must remember the location of a stone circle first! +spell.ebwizardry\:transportation.wrongdimension=No remembered stone circle in this dimension... +spell.ebwizardry\:clairvoyance.searching=Searching... +spell.ebwizardry\:clairvoyance.confirm=The path revealed upon casting %1$s will now lead back to this point +spell.ebwizardry\:clairvoyance.outofrange=Your remembered locations is too far away or inaccessible... +spell.ebwizardry\:clairvoyance.undefined=You must remember a locations first! +spell.ebwizardry\:clairvoyance.wrongdimension=Your remembered locations is in another dimension... +spell.ebwizardry\:possession.insufficienthealth=You don't have enough health to possess %1$s! +spell.ebwizardry\:possession.success=Press %s to stop possessing +spell.ebwizardry\:divination.nothing=Nothing happened. +spell.ebwizardry\:divination.weak=You can just feel your wand twitching %s. +spell.ebwizardry\:divination.moderate=You feel your wand being tugged %s. +spell.ebwizardry\:divination.strong=Your wand pulls %s strongly. +spell.ebwizardry\:divination.very_strong=Your wand lurches %s sharply. +spell.ebwizardry\:divination.down=downwards +spell.ebwizardry\:divination.up=upwards +spell.ebwizardry\:divination.front=forwards +spell.ebwizardry\:divination.back=backwards +spell.ebwizardry\:divination.left=to the left +spell.ebwizardry\:divination.right=to the right +spell.ebwizardry\:resurrection.resurrect_ally=%s was resurrected by %s +spell.ebwizardry\:resurrection.resurrect_self=%s came back to life +spell.ebwizardry\:resurrection.button_wait=Resurrect (%ss) +spell.ebwizardry\:resurrection.button_ready=Resurrect -potion.ebwizardry:frost=Frostbite -potion.ebwizardry:fireskin=Fireskin -potion.ebwizardry:ice_shroud=Ice Shroud -potion.ebwizardry:static_aura=Static Aura -potion.ebwizardry:transience=Transience -potion.ebwizardry:decay=Decay -potion.ebwizardry:sixth_sense=Sixth Sense -potion.ebwizardry:arcane_jammer=Arcane Jammer -potion.ebwizardry:mind_trick=Mind Trick -potion.ebwizardry:mind_control=Mind Control -potion.ebwizardry:font_of_mana=Font of Mana -potion.ebwizardry:fear=Fear +forfeit.ebwizardry\:do_nothing=Nothing happened. -enchantment.ebwizardry:magic_sword=Imbuement -enchantment.ebwizardry:magic_bow=Imbuement -enchantment.ebwizardry:flaming_weapon=Fire Imbuement -enchantment.ebwizardry:freezing_weapon=Frost Imbuement +forfeit.ebwizardry\:burn_self=The %s bursts into flames in your hand! +forfeit.ebwizardry\:fireball=A fireball materialises in front of you! +forfeit.ebwizardry\:firebomb=A firebomb appears right above you! +forfeit.ebwizardry\:explode=A sudden explosion knocks you to the ground! +forfeit.ebwizardry\:blazes=Suddenly, hostile blazes materialise around you! +forfeit.ebwizardry\:burn_surroundings=The area around you is set ablaze! +forfeit.ebwizardry\:meteors=Fiery armageddon rains from the sky! + +forfeit.ebwizardry\:freeze_self=You feel an icy chill rush through you! +forfeit.ebwizardry\:freeze_self_2=From the %s emanates a cold so intense that it roots you to the spot! +forfeit.ebwizardry\:ice_spikes=Ice spikes rise from the ground beneath your feet! +forfeit.ebwizardry\:blizzard=You are suddenly surrounded by a raging blizzard! +forfeit.ebwizardry\:ice_wraiths=Suddenly, hostile ice wraiths materialise around you! +forfeit.ebwizardry\:hailstorm=Razor-sharp ice starts raining down upon you! +forfeit.ebwizardry\:ice_giant=A hostile ice giant materialises in front of you! + +forfeit.ebwizardry\:thunder=The scroll emits a deafening noise, knocking you to the ground! +forfeit.ebwizardry\:storm=Looks like a storm is brewing! +forfeit.ebwizardry\:lightning_sigils=Watch your step! +forfeit.ebwizardry\:lightning=You are struck by lightning! +forfeit.ebwizardry\:paralyse_self=You are paralysed! +forfeit.ebwizardry\:lightning_wraiths=Suddenly, hostile lightning wraiths materialise around you! +forfeit.ebwizardry\:storm_elementals=Hostile storm elementals materialise on all sides! + +forfeit.ebwizardry\:nausea=...huh? What just happened? Where am I? +forfeit.ebwizardry\:zombie_horde=A horde of zombies rises from the ground around you! +forfeit.ebwizardry\:wither_self=Darkness withers your soul! +forfeit.ebwizardry\:cripple_self=The %s emits a deathly howl, and you are crippled to within an inch of your life! +forfeit.ebwizardry\:shadow_wraiths=Hostile shadow wraiths materialise on all sides! + +forfeit.ebwizardry\:snares=It's a trap! +forfeit.ebwizardry\:squid=Squid! +forfeit.ebwizardry\:uproot_plants=All nearby plants are suddenly uprooted! +forfeit.ebwizardry\:poison_self=You are poisoned! +forfeit.ebwizardry\:flood=Water materialises around you! +forfeit.ebwizardry\:bury_self=The ground collapses beneath you! + +forfeit.ebwizardry\:spill_inventory=Your items spill themselves everywhere! +forfeit.ebwizardry\:teleport_self=You are instantly teleported somewhere! +forfeit.ebwizardry\:levitate_self=You begin to float upwards helplessly! +forfeit.ebwizardry\:vex_horde=A horde of vexes materialises around you! +forfeit.ebwizardry\:black_hole=A swirling vortex appears in front of you! +forfeit.ebwizardry\:arrow_rain=A barrage of arrows starts raining down upon you! + +forfeit.ebwizardry\:damage_self=Ouch! +forfeit.ebwizardry\:spill_armour=All your armour falls off! +forfeit.ebwizardry\:hunger=You suddenly feel very hungry! +forfeit.ebwizardry\:blind_self=You are blinded! +forfeit.ebwizardry\:weaken_self=You are severely weakened! +forfeit.ebwizardry\:jam_self=Your magic is rendered useless! +forfeit.ebwizardry\:curse_self=You are cursed with undeath! + +potion.ebwizardry\:frost=Frostbite +potion.ebwizardry\:fireskin=Fireskin +potion.ebwizardry\:ice_shroud=Ice Shroud +potion.ebwizardry\:static_aura=Static Aura +potion.ebwizardry\:transience=Transience +potion.ebwizardry\:decay=Decay +potion.ebwizardry\:sixth_sense=Sixth Sense +potion.ebwizardry\:arcane_jammer=Arcane Jammer +potion.ebwizardry\:mind_trick=Mind Trick +potion.ebwizardry\:mind_control=Mind Control +potion.ebwizardry\:font_of_mana=Font of Mana +potion.ebwizardry\:fear=Fear +potion.ebwizardry\:curse_of_soulbinding=Curse of Soulbinding +potion.ebwizardry\:paralysis=Paralysis +potion.ebwizardry\:muffle=Muffle +potion.ebwizardry\:ward=Ward +potion.ebwizardry\:slow_time=Slow Time +potion.ebwizardry\:empowerment=Empowerment +potion.ebwizardry\:curse_of_enfeeblement=Curse of Enfeeblement +potion.ebwizardry\:curse_of_undeath=Curse of Undeath +potion.ebwizardry\:containment=Containment +potion.ebwizardry\:frost_step=Frost Step + +enchantment.ebwizardry\:magic_sword=Imbuement +enchantment.ebwizardry\:magic_bow=Imbuement +enchantment.ebwizardry\:flaming_weapon=Fire Imbuement +enchantment.ebwizardry\:freezing_weapon=Frost Imbuement +enchantment.ebwizardry\:shocking_weapon=Lightning Imbuement + +enchantment.ebwizardry\:magic_protection=Magic Protection +enchantment.ebwizardry\:frost_protection=Frost Protection +enchantment.ebwizardry\:shock_protection=Shock Protection key.categories.ebwizardry=Wizardry @@ -627,140 +1011,268 @@ key.ebwizardry.previous_spell=Previous Spell death.attack.wizardry_magic=%1$s was killed by %2$s using magic death.attack.indirect_wizardry_magic=%1$s was killed by %2$s using magic -commands.ebwizardry:cast.usage=/%1$s [player] [damage multiplier] [range multiplier] [duration multiplier] [blast multiplier] -commands.ebwizardry:cast.success=Successfully cast %1$s -commands.ebwizardry:cast.success_continuous=Successfully cast %1$s; repeat the command to stop -commands.ebwizardry:cast.success_remote=Successfully cast %1$s as %2$s -commands.ebwizardry:cast.success_remote_continuous=Successfully cast %1$s as %2$s; repeat the command to stop -commands.ebwizardry:cast.fail=Unable to cast %1$s -commands.ebwizardry:cast.not_found=There is no such spell with ID %1$s -commands.ebwizardry:cast.tag_error=Data tag parsing failed: %s +soundCategory.ebwizardry\:spells=Spells -commands.ebwizardry:ally.usage=/%1$s [player] -commands.ebwizardry:ally.addally=%1$s has been added to %2$s's list of allies -commands.ebwizardry:ally.removeally=%1$s has been removed from %2$s's list of allies -commands.ebwizardry:ally.self=Players cannot be an ally of themselves! -commands.ebwizardry:ally.permission=You do not have permission to change other players' allies +commands.ebwizardry\:cast.usage=/%1$s [player | x y z direction] [duration] [modifiers] +commands.ebwizardry\:cast.success=Successfully cast %s +commands.ebwizardry\:cast.success_continuous=Successfully cast %s for %s seconds +commands.ebwizardry\:cast.success_remote=Successfully cast %s as %s +commands.ebwizardry\:cast.success_remote_continuous=Successfully cast %s as %s for %s seconds +commands.ebwizardry\:cast.success_position=Successfully cast %s at %s, %s, %s +commands.ebwizardry\:cast.success_position_continuous=Successfully cast %s at %s, %s, %s for %s seconds +commands.ebwizardry\:cast.fail=Unable to cast %1$s +commands.ebwizardry\:cast.not_found=There is no such spell with ID %1$s +commands.ebwizardry\:cast.invalid_direction=Invalid direction: %1$s (valid directions are: up, down, north, south, east, west) +commands.ebwizardry\:cast.tag_error=Data tag parsing failed\: %s +commands.ebwizardry\:cast.origin_not_specified=You must specify a player or location to cast the spell from +commands.ebwizardry\:cast.duration_not_specified=You must specify a duration for this spell -commands.ebwizardry:allies.usage=/%1$s [player] -commands.ebwizardry:allies.list=Players allied to you: %1$s -commands.ebwizardry:allies.list_other=Players allied to %1$s: %2$s -commands.ebwizardry:allies.permission=You do not have permission to view other players' allies -commands.ebwizardry:allies.none=None +commands.ebwizardry\:ally.usage=/%1$s [player] +commands.ebwizardry\:ally.addally=%1$s has been added to %2$s's list of allies +commands.ebwizardry\:ally.removeally=%1$s has been removed from %2$s's list of allies +commands.ebwizardry\:ally.self=Players cannot be an ally of themselves! +commands.ebwizardry\:ally.permission=You do not have permission to change other players' allies -commands.ebwizardry:discoverspell.usage=/%1$s [player] -commands.ebwizardry:discoverspell.not_found=There is no such spell with ID %1$s -commands.ebwizardry:discoverspell.clear=Cleared all spell discovery data for %1$s -commands.ebwizardry:discoverspell.all=Added all spells to %1$s's spell discovery data -commands.ebwizardry:discoverspell.addspell=Added %1$s to %2$s's spell discovery data -commands.ebwizardry:discoverspell.removespell=Removed %1$s from %2$s's spell discovery data +commands.ebwizardry\:allies.usage=/%1$s [player] +commands.ebwizardry\:allies.list=Players allied to you\: %1$s +commands.ebwizardry\:allies.list_other=Players allied to %1$s\: %2$s +commands.ebwizardry\:allies.permission=You do not have permission to view other players' allies +commands.ebwizardry\:allies.none=None + +commands.ebwizardry\:discoverspell.usage=/%1$s [player] +commands.ebwizardry\:discoverspell.not_found=There is no such spell with ID %1$s +commands.ebwizardry\:discoverspell.clear=Cleared all spell discovery data for %1$s +commands.ebwizardry\:discoverspell.all=Added all spells to %1$s's spell discovery data +commands.ebwizardry\:discoverspell.addspell=Added %1$s to %2$s's spell discovery data +commands.ebwizardry\:discoverspell.removespell=Removed %1$s from %2$s's spell discovery data config.ebwizardry.title.general=Mod Options +config.ebwizardry.generic.true=Enabled +config.ebwizardry.generic.false=Disabled + +config.ebwizardry.category.spells=Spell Configuration +config.ebwizardry.category.spells.tooltip=Select which spells are enabled +config.ebwizardry.title.spells=Spell Configuration +config.ebwizardry.subtitle.spells=Disabling a spell globally here will override the finer controls in the spell JSON file. + config.ebwizardry.category.gameplay=Gameplay Settings config.ebwizardry.category.gameplay.tooltip=Configure wizardry's general gameplay config.ebwizardry.title.gameplay=Gameplay Settings config.ebwizardry.subtitle.gameplay=Global settings that affect game mechanics. +config.ebwizardry.discovery_mode=Discovery Mode +config.ebwizardry.discovery_mode.tooltip=For those who like a sense of mystery! When enabled, spells you haven't cast yet will be unreadable until you cast them (on a per-world basis). Has no effect when in creative mode. Spells of identification will be unobtainable in survival mode if this is disabled. +config.ebwizardry.legacy_wand_levelling=Legacy Wand Levelling +config.ebwizardry.legacy_wand_levelling.tooltip=Controls whether wands are required to gain progression before they can be upgraded to the next tier. Enable this option to revert to the pre-4.2 system, which only requires tomes of arcana. Wands will still gain progression silently when this is enabled, so if you go back to the new system you won't lose any progress. +config.ebwizardry.legacy_wand_levelling.true=Yes - I liked it how it was! +config.ebwizardry.legacy_wand_levelling.false=No - Level me up! +config.ebwizardry.friendly_fire=Friendly Fire +config.ebwizardry.friendly_fire.tooltip=Controls which creatures may be damaged by your magic when allied to you. Your spells will not target your allies or creatures summoned/owned by them regardless of this setting, but this setting makes them completely immune if disabled. +config.ebwizardry.minion_revenge_targeting=Minion Revenge Targeting +config.ebwizardry.minion_revenge_targeting.tooltip=Whether summoned creatures can revenge-attack players or creatures that they would not otherwise be able to attack. +config.ebwizardry.minion_revenge_targeting.true=Yes - I'd never hurt them! +config.ebwizardry.minion_revenge_targeting.false=No - they must always obey me! +config.ebwizardry.players_move_each_other=Players Move Each Other +config.ebwizardry.players_move_each_other.tooltip=Whether to allow players to move other players around using magic. +config.ebwizardry.players_move_each_other.true=Yes - let the games begin! +config.ebwizardry.players_move_each_other.false=No - I won't be pushed around +config.ebwizardry.player_block_damage=Player Block Damage +config.ebwizardry.player_block_damage.tooltip=Whether spells cast by players can destroy blocks in the world. Disable this to prevent griefing. To prevent non-players from destroying blocks with magic, use the mobGriefing gamerule. +config.ebwizardry.player_block_damage.true=Yes - kaboom! +config.ebwizardry.player_block_damage.false=No - activate anti-grief (TM) +config.ebwizardry.telekinetic_disarmament=Telekinetic Disarmament +config.ebwizardry.telekinetic_disarmament.tooltip=Whether to allow players to disarm other players using the telekinesis spell. Disable to prevent stealing of items. +config.ebwizardry.telekinetic_disarmament.true=Yes - let people steal things +config.ebwizardry.telekinetic_disarmament.false=No - that's cheating! +config.ebwizardry.teleport_through_unbreakable_blocks=Teleport Through Unbreakable Blocks +config.ebwizardry.teleport_through_unbreakable_blocks.tooltip=Whether players are allowed to teleport through unbreakable blocks (e.g. bedrock) using the phase step spell. +config.ebwizardry.teleport_through_unbreakable_blocks.true=Yes - I wish to see the void! +config.ebwizardry.teleport_through_unbreakable_blocks.false=No - bedrock is impenetrable +config.ebwizardry.world_time_manipulation=World Time Manipulation +config.ebwizardry.world_time_manipulation.tooltip=Whether players are allowed to change the world time with the speed time spell. If disabled, the speed time spell will not change the world time but will still speed up nearby block, entity and tile entity ticks. +config.ebwizardry.world_time_manipulation.true=Yes - daytime, nighttime... +config.ebwizardry.world_time_manipulation.false=No - I need my sleep! +config.ebwizardry.replace_vanilla_fireballs=Replace Vanilla Fireballs +config.ebwizardry.replace_vanilla_fireballs.tooltip=Whether to replace Minecraft's own fireballs with wizardry fireballs. If this is disabled, only wizardry spells will use the custom fireballs. +config.ebwizardry.replace_vanilla_fireballs.true=Yes - give me FIRE! +config.ebwizardry.replace_vanilla_fireballs.false=No - blazes are mean enough +config.ebwizardry.replace_vanilla_fall_damage=Replace Vanilla Fall Damage +config.ebwizardry.replace_vanilla_fall_damage.tooltip=Whether to replace Minecraft's distance-based fall damage calculation with an equivalent, velocity-based one. This is done such that mobs in freefall will take exactly the same damage as normal, so it will not break falling-based mob farms. Disable this if you experience falling-related weirdness! If this is disabled, some spells revert to a more simplistic method of resetting the player's fall damage in certain cases. +config.ebwizardry.replace_vanilla_fall_damage.true=Yes - it's parkour time +config.ebwizardry.replace_vanilla_fall_damage.false=No - break my legs normally +config.ebwizardry.creative_bypasses_arcane_lock=Bypass Arcane Lock +config.ebwizardry.creative_bypasses_arcane_lock.tooltip=Determines which players can bypass arcane locks. +config.ebwizardry.creative_bypasses_arcane_lock.true=Anyone in creative mode +config.ebwizardry.creative_bypasses_arcane_lock.false=Only ops in creative mode +config.ebwizardry.slow_time_affects_players=Slow Time Affects Players +config.ebwizardry.slow_time_affects_players.tooltip=Whether players are slowed when another nearby player uses the slow time spell. If this is disabled, mobs and projectiles will still be affected but players will move at normal speed. +config.ebwizardry.mob_loot_table_whitelist=Mob Loot Table Whitelist +config.ebwizardry.mob_loot_table_whitelist.tooltip=Whitelist for loot tables to inject additional mob drops (as specified in loot_tables/entities/mob_additions.json) into. Wizardry makes a best guess as to which loot tables belong to hostile mobs, but this may not always be correct or appropriate; add loot table locations (not entity IDs) to this list to manually include them. +config.ebwizardry.mob_loot_table_blacklist=Mob Loot Table Blacklist +config.ebwizardry.mob_loot_table_blacklist.tooltip=Blacklist for loot tables to inject additional mob drops (as specified in loot_tables/entities/mob_additions.json) into. Wizardry makes a best guess as to which loot tables belong to hostile mobs, but this may not always be correct or appropriate; add loot table locations (not entity IDs) to this list to manually exclude them. +config.ebwizardry.mob_spawn_dimensions=Mob Spawning Dimensions +config.ebwizardry.mob_spawn_dimensions.tooltip=List of ids of dimensions in which wizardry's hostile mobs can spawn. +config.ebwizardry.mob_spawn_biome_blacklist=Mob Spawning Biome Blacklist +config.ebwizardry.mob_spawn_biome_blaclist.tooltip=List of names of biomes in which wizardry's hostile mobs cannot spawn. Biome names are not case-sensitive. For mod biomes, prefix with the mod ID (e.g. biomesoplenty\:mystic_grove). +config.ebwizardry.evil_wizard_spawn_rate=Evil Wizard Spawn Rate +config.ebwizardry.evil_wizard_spawn_rate.tooltip=Spawn rate for naturally-spawned evil wizards; higher numbers mean more evil wizards will spawn. 5 is equivalent to witches, 100 is equivalent to zombies, skeletons and creepers. Set to 0 to disable evil wizard spawning entirely. +config.ebwizardry.ice_wraith_spawn_rate=Ice Wraith Spawn Rate +config.ebwizardry.ice_wraith_spawn_rate.tooltip=Spawn rate for naturally-spawned ice wraiths; higher numbers mean more ice wraiths will spawn. 5 is equivalent to witches, 100 is equivalent to zombies, skeletons and creepers. Set to 0 to disable ice wraith spawning entirely. +config.ebwizardry.lightning_wraith_spawn_rate=Lightning Wraith Spawn Rate +config.ebwizardry.lightning_wraith_spawn_rate.tooltip=Spawn rate for naturally-spawned lightning wraiths; higher numbers mean more lightning wraiths will spawn. 5 is equivalent to witches, 100 is equivalent to zombies, skeletons and creepers. Set to 0 to disable lightning wraith spawning entirely. +config.ebwizardry.forfeit_chance=Forfeit Chance +config.ebwizardry.forfeit_chance.tooltip=The chance to 'misread' an undiscovered spell and trigger a forfeit instead. Setting this to 0 effectively disables the forfeit mechanic. Has no effect if discovery mode is disabled. +config.ebwizardry.player_damage_scaling=Player Damage Scaling Factor +config.ebwizardry.player_damage_scaling.tooltip=Global damage scaling factor for the damage dealt by players casting spells, relative to 1. +config.ebwizardry.npc_damage_scaling=NPC Damage Scaling Factor +config.ebwizardry.npc_damage_scaling.tooltip=Global damage scaling factor for the damage dealt by NPCs casting spells, relative to 1. +config.ebwizardry.summoned_creature_targets_whitelist=Summoned Creature Target Whitelist +config.ebwizardry.summoned_creature_targets_whitelist.tooltip=List of names of entities which summoned creatures and wizards are allowed to attack, in addition to the defaults. Add mod creatures to this list if you want summoned creatures to attack them and they aren't already doing so. Entity names are not case sensitive. For mod entities, prefix with the mod ID (e.g. ebwizardry\:wizard). +config.ebwizardry.summoned_creature_targets_blacklist=Summoned Creature Target Blacklist +config.ebwizardry.summoned_creature_targets_blacklist.tooltip=List of names of entities which summoned creatures and wizards are specifically not allowed to attack, overriding the defaults and the whitelist. Add creatures to this list if allowing them to be attacked causes problems or is too destructive (removing creepers from this list is done at your own risk!). Entity names are not case sensitive. For mod entities, prefix with the mod ID (e.g. ebwizardry\:wizard). +config.ebwizardry.mind_control_targets_blacklist=Mind Control Targets Blacklist +config.ebwizardry.mind_control_targets_blacklist.tooltip=List of names of entities which cannot be mind controlled, in addition to the defaults. Add creatures to this list if allowing them to be mind-controlled causes problems or could be exploited. Entity names are not case sensitive. For mod entities, prefix with the mod ID (e.g. ebwizardry\:wizard). +config.ebwizardry.pocket_furnace_item_blacklist=Pocket Furnace Item Blacklist +config.ebwizardry.pocket_furnace_item_blacklist.tooltip=List of registry names of blocks or items which cannot be smelted by the pocket furnace spell, in addition to armour, tools and weapons. Block/item names are not case sensitive. For mod items, prefix with the mod ID (e.g. ebwizardry\:crystal_ore). +config.ebwizardry.divination_ore_whitelist=Divination Ore Whitelist +config.ebwizardry.divination_ore_whitelist.tooltip=List of registry names of ore blocks which can be detected by the divination spell. Block names are not case sensitive. For mod blocks, prefix with the mod ID (e.g. ebwizardry\:crystal_ore). +config.ebwizardry.sword_item_whitelist=Sword Item Whitelist +config.ebwizardry.sword_item_whitelist.tooltip=List of registry names of items which should count as swords for imbuement spells. Most swords should work automatically, but those that don't can be added manually here. Item names are not case sensitive. For mod items, prefix with the mod ID (e.g. tconstruct:broadsword). +config.ebwizardry.bow_item_whitelist=Bow Item Whitelist +config.ebwizardry.bow_item_whitelist.tooltip=List of registry names of items which should count as bows for imbuement spells. Most bows should work automatically, but those that don't can be added manually here. Item names are not case sensitive. For mod items, prefix with the mod ID (e.g. tconstruct:shortbow). +config.ebwizardry.currency_items=Currency Items +config.ebwizardry.currency_items.tooltip=List of registry names of items which wizard trades can use as currency (in the first slot; the second slot is unaffected). Each entry in this list should consist of an item registry name, followed by a single space, then an integer which defines the 'value' of the item. Higher values mean fewer of that currency item are required for a given trade. + config.ebwizardry.category.worldgen=World Generation Settings config.ebwizardry.category.worldgen.tooltip=Configure wizardry's world generation features config.ebwizardry.title.worldgen=World Generation Settings config.ebwizardry.subtitle.worldgen=Settings that affect world generation. -config.ebwizardry.category.commands=Command Settings -config.ebwizardry.category.commands.tooltip=Configure wizardry's commands -config.ebwizardry.title.commands=Command Settings -config.ebwizardry.subtitle.commands=Settings for the commands added by Wizardry. +config.ebwizardry.fast_worldgen=Structure Generation +config.ebwizardry.fast_worldgen.tooltip=Controls which algorithm wizardry uses for structure generation. Fancy worldgen prevents structures on cliffs, in caves and intersecting other structures, and cleans up floating trees after generating. Fast worldgen sacrifices these improvements, potentially resulting in faster world generation. Performance improvement will vary depending on your setup. This option will affect randomisation; for any given seed, structures will not be the same as when it is turned off. +config.ebwizardry.fast_worldgen.true=Fast +config.ebwizardry.fast_worldgen.false=Fancy +config.ebwizardry.tower_dimensions=Tower Dimensions +config.ebwizardry.tower_dimensions.tooltip=List of ids of dimensions in which wizard towers will generate. +config.ebwizardry.tower_rarity=Tower Rarity +config.ebwizardry.tower_rarity.tooltip=Rarity of wizard towers. 1 in this many chunks will contain a wizard tower, meaning higher numbers are rarer. +config.ebwizardry.evil_wizard_chance=Evil Wizard Chance +config.ebwizardry.evil_wizard_chance.tooltip=The chance for wizard towers to generate with an evil wizard and chest inside, instead of a friendly wizard. +config.ebwizardry.tower_files=Tower Structure Files +config.ebwizardry.tower_files.tooltip=List of structure file locations for wizard towers without loot chests. One of these files will be randomly selected each time a wizard tower is generated. File locations are of the format [mod id]\:[filename], which refers to the file assets/[mod id]/structures/[filename].nbt. Duplicate entries are permitted, allowing for simple weighting without duplicating the structure files themselves. +config.ebwizardry.tower_with_chest_files=Tower With Chest Structure Files +config.ebwizardry.tower_with_chest_files.tooltip=List of structure file locations for wizard towers with loot chests. One of these files will be randomly selected each time a wizard tower is generated. File locations are of the format [mod id]\:[filename], which refers to the file assets/[mod id]/structures/[filename].nbt. Duplicate entries are permitted, allowing for simple weighting without duplicating the structure files themselves. +config.ebwizardry.obelisk_dimensions=Obelisk Dimensions +config.ebwizardry.obelisk_dimensions.tooltip=List of ids of dimensions in which obelisks will generate. +config.ebwizardry.obelisk_rarity=Obelisk Rarity +config.ebwizardry.obelisk_rarity.tooltip=Rarity of obelisks. 1 in this many chunks will contain an obelisk, meaning higher numbers are rarer. +config.ebwizardry.obelisk_files=Obelisk Structure Files +config.ebwizardry.obelisk_files.tooltip=List of structure file locations for obelisks. One of these files will be randomly selected each time an obelisk is generated. File locations are of the format [mod id]\:[filename], which refers to the file assets/[mod id]/structures/[filename].nbt. Duplicate entries are permitted, allowing for simple weighting without duplicating the structure files themselves. +config.ebwizardry.shrine_dimensions=Shrine Dimensions +config.ebwizardry.shrine_dimensions.tooltip=List of ids of dimensions in which shrines will generate. +config.ebwizardry.shrine_rarity=Shrine Rarity +config.ebwizardry.shrine_rarity.tooltip=Rarity of shrines. 1 in this many chunks will contain a shrine, meaning higher numbers are rarer. +config.ebwizardry.shrine_files=Shrine Structure Files +config.ebwizardry.shrine_files.tooltip=List of structure file locations for shrines. One of these files will be randomly selected each time a shrine is generated. File locations are of the format [mod id]\:[filename], which refers to the file assets/[mod id]/structures/[filename].nbt. Duplicate entries are permitted, allowing for simple weighting without duplicating the structure files themselves. +config.ebwizardry.ore_dimensions=Ore Dimensions +config.ebwizardry.ore_dimensions.tooltip=List of ids of dimensions in which crystal ore will generate. Note that removing the overworld (id 0) from this list will make the mod VERY difficult to play! +config.ebwizardry.flower_dimensions=Flower Dimensions +config.ebwizardry.flower_dimensions.tooltip=List of ids of dimensions in which crystal flowers will generate. +config.ebwizardry.loot_injection_locations=Loot Injection Locations +config.ebwizardry.loot_injection_locations.tooltip=List of loot tables to inject wizardry loot (as specified in loot_tables/chests/dungeon_additions.json) into. config.ebwizardry.category.client=Client Settings config.ebwizardry.category.client.tooltip=Configure wizardry's display and controls config.ebwizardry.title.client=Client Settings config.ebwizardry.subtitle.client=Client-side settings that only affect the local minecraft game. -config.ebwizardry.category.spells=Spell Configuration -config.ebwizardry.category.spells.tooltip=Select which spells are enabled -config.ebwizardry.title.spells=Spell Configuration -config.ebwizardry.subtitle.spells=Set a spell to false to disable it. +config.ebwizardry.shift_scrolling=Shift-scrolling +config.ebwizardry.shift_scrolling.tooltip=Whether you can switch between spells on a wand by scrolling with the mouse wheel while sneaking. Note that this will only affect you; other players connected to the same server obey their own settings. +config.ebwizardry.reverse_scroll_direction=Scroll Direction +config.ebwizardry.reverse_scroll_direction.tooltip=The scroll direction used to switch between spells on a wand while sneaking. +config.ebwizardry.reverse_scroll_direction.true=Reversed +config.ebwizardry.reverse_scroll_direction.false=Normal +config.ebwizardry.spell_hud_position=Spell HUD Position +config.ebwizardry.spell_hud_position.tooltip=The position of the spell HUD. +config.ebwizardry.spell_hud_skin=Spell HUD Skin +config.ebwizardry.spell_hud_skin.tooltip=Change the look of the spell HUD... +config.ebwizardry.spell_hud_skin.preview=Preview +config.ebwizardry.handbook_progression=Handbook Progression +config.ebwizardry.handbook_progression.tooltip=When enabled, to help guide players through the mod, sections of The Wizard's Handbook are unlocked when a player gains the advancement that triggers them, and are hidden otherwise. When disabled, the entire handbook is readable regardless of advancement progress. The entire handbook is always readable in creative mode. +config.ebwizardry.handbook_progression.true=Yes - teach me, Sensei! +config.ebwizardry.handbook_progression.false=No - I know what I'm doing +config.ebwizardry.books_pause_game=Books Pause Game +config.ebwizardry.books_pause_game.tooltip=Whether opening any of wizardry's books pauses the game in singleplayer. Has no effect on servers or LAN worlds. +config.ebwizardry.books_pause_game.true=Yes - I don't want any distractions! +config.ebwizardry.books_pause_game.false=No - I read to pass the time +config.ebwizardry.summoned_creature_names=Summoned Creature Names +config.ebwizardry.summoned_creature_names.tooltip=Controls whether summoned creatures' names and owners are displayed above their heads. +config.ebwizardry.summoned_creature_names.true=Shown +config.ebwizardry.summoned_creature_names.false=Hidden +config.ebwizardry.use_shaders=Use Custom Shaders +config.ebwizardry.use_shaders.tooltip=Whether to use custom shaders for certain spells. These use the vanilla shader system (like mob spectating shaders) and shouldn't have much of an effect on performance in most cases, but they may conflict with other shaders. +config.ebwizardry.use_shaders.true=Yes - gimme those sweet shaders! +config.ebwizardry.use_shaders.false=No - I'm running this on a potato + +config.ebwizardry.category.commands=Command Settings +config.ebwizardry.category.commands.tooltip=Configure wizardry's commands +config.ebwizardry.title.commands=Command Settings +config.ebwizardry.subtitle.commands=Settings for the commands added by Wizardry. + +config.ebwizardry.cast_command_multiplier_limit=Cast Command Multiplier Limit +config.ebwizardry.cast_command_multiplier_limit.tooltip=Upper limit for the multipliers passed into the /cast command. This is here to stop players from accidentally breaking a world/server. Large blast mutipliers can cause extreme lag - you have been warned! +config.ebwizardry.cast_command_name=Cast Spell Command Name +config.ebwizardry.cast_command_name.tooltip=The name of the /cast command. This is what you type directly after the /; for example if this was set to 'magic' then instead of typing /cast you would type /magic instead. +config.ebwizardry.discoverspell_command_name=Discover Spell Command Name +config.ebwizardry.discoverspell_command_name.tooltip=The name of the /discoverspell command. This is what you type directly after the /; for example if this was set to 'magic' then instead of typing /discoverspell you would type /magic instead. +config.ebwizardry.ally_command_name=Set Ally Command Name +config.ebwizardry.ally_command_name.tooltip=The name of the /ally command. This is what you type directly after the /; for example if this was set to 'magic' then instead of typing /ally you would type /magic instead. +config.ebwizardry.allies_command_name=View Allies Command Name +config.ebwizardry.allies_command_name.tooltip=The name of the /allies command. This is what you type directly after the /; for example if this was set to 'magic' then instead of typing /allies you would type /magic instead. config.ebwizardry.category.resistances=Resistance Configuration config.ebwizardry.category.resistances.tooltip=Configure which mobs are immune to different types of magic config.ebwizardry.title.resistances=Resistance Configuration config.ebwizardry.subtitle.resistances=Settings which allow entities to be made immune to certain types of magic. -config.ebwizardry.tower_rarity=Tower Rarity -config.ebwizardry.ore_dimensions=Ore Dimensions -config.ebwizardry.flower_dimensions=Flower Dimensions -config.ebwizardry.tower_dimensions=Tower Dimensions -config.ebwizardry.spell_book_drop_chance=Spell Book Drop Chance -config.ebwizardry.generate_loot=Generate Loot -config.ebwizardry.firebomb_is_craftable=Firebomb Is Craftable -config.ebwizardry.poison_bomb_is_craftable=Poison Bomb Is Craftable -config.ebwizardry.smoke_bomb_is_craftable=Smoke Bomb Is Craftable -config.ebwizardry.use_alternate_scroll_recipe=Use Alternate Scroll Recipe -config.ebwizardry.teleport_through_unbreakable_blocks=Teleport Through Unbreakable Blocks -config.ebwizardry.show_summoned_creature_names=Show Summoned Creature Names -config.ebwizardry.friendly_fire=Friendly Fire -config.ebwizardry.telekinetic_disarmament=Telekinetic Disarmament -config.ebwizardry.discovery_mode=Discovery Mode -config.ebwizardry.enable_shift_scrolling=Enable Shift-scrolling -config.ebwizardry.reverse_scroll_direction=Reverse Scroll Direction -config.ebwizardry.minion_revenge_targeting=Minion Revenge Targeting -config.ebwizardry.player_damage_scaling=Player Damage Scaling Factor -config.ebwizardry.npc_damage_scaling=NPC Damage Scaling Factor -config.ebwizardry.cast_command_multiplier_limit=Cast Command Multiplier Limit -config.ebwizardry.summoned_creature_targets_whitelist=Summoned Creature Target Whitelist -config.ebwizardry.summoned_creature_targets_blacklist=Summoned Creature Target Blacklist -config.ebwizardry.spell_hud_position=Spell HUD Position -config.ebwizardry.spell_hud_skin=Spell HUD Skin -config.ebwizardry.cast_command_name=Cast Spell Command Name -config.ebwizardry.discoverspell_command_name=Discover Spell Command Name -config.ebwizardry.ally_command_name=Set Ally Command Name -config.ebwizardry.allies_command_name=View Allies Command Name -config.ebwizardry.mind_control_targets_blacklist=Mind Control Targets Blacklist -config.ebwizardry.evil_wizard_dimensions=Evil Wizard Dimensions - config.ebwizardry.mobs_immune_to_fire=Mobs Immune To Fire +config.ebwizardry.mobs_immune_to_fire.tooltip=List of names of entities that are immune to fire, in addition to the defaults. Add mod creatures to this list if you want them to be immune to fire magic and they aren't already. Entity names are not case sensitive. For mod entities, prefix with the mod ID (e.g. ebwizardry\:wizard). config.ebwizardry.mobs_immune_to_ice=Mobs Immune To Ice +config.ebwizardry.mobs_immune_to_ice.tooltip=List of names of entities that are immune to ice, in addition to the defaults. Add mod creatures to this list if you want them to be immune to ice magic and they aren't already. Entity names are not case sensitive. For mod entities, prefix with the mod ID (e.g. ebwizardry\:wizard). config.ebwizardry.mobs_immune_to_lightning=Mobs Immune To Lightning +config.ebwizardry.mobs_immune_to_lightning.tooltip=List of names of entities that are immune to lightning, in addition to the defaults. Add mod creatures to this list if you want them to be immune to lightning magic and they aren't already. Entity names are not case sensitive. For mod entities, prefix with the mod ID (e.g. ebwizardry\:wizard). config.ebwizardry.mobs_immune_to_wither=Mobs Immune To Wither +config.ebwizardry.mobs_immune_to_wither.tooltip=List of names of entities that are immune to wither effects, in addition to the defaults. Add mod creatures to this list if you want them to be immune to withering magic and they aren't already. Entity names are not case sensitive. For mod entities, prefix with the mod ID (e.g. ebwizardry\:wizard). config.ebwizardry.mobs_immune_to_poison=Mobs Immune To Poison +config.ebwizardry.mobs_immune_to_poison.tooltip=List of names of entities that are immune to poison, in addition to the defaults. Add mod creatures to this list if you want them to be immune to poison magic and they aren't already. Entity names are not case sensitive. For mod entities, prefix with the mod ID (e.g. ebwizardry\:wizard). -config.ebwizardry.tower_rarity.tooltip=Rarity of wizard towers. Higher numbers are rarer. Set to 0 to disable wizard towers completely. -config.ebwizardry.ore_dimensions.tooltip=List of dimension ids in which crystal ore will generate. Note that removing the overworld (id 0) from this list will make the mod VERY difficult to play! -config.ebwizardry.flower_dimensions.tooltip=List of dimension ids in which crystal flowers will generate. -config.ebwizardry.tower_dimensions.tooltip=List of dimension ids in which wizard towers will generate. -config.ebwizardry.spell_book_drop_chance.tooltip=The chance for mobs to drop a spell book when killed. The greater this number, the more often they will drop. Set to 0 to disable spell book drops. Set to 200 for guaranteed drops. -config.ebwizardry.generate_loot.tooltip=Whether to generate wizardry loot in dungeon chests. -config.ebwizardry.firebomb_is_craftable.tooltip=Whether firebombs can be crafted or not. -config.ebwizardry.poison_bomb_is_craftable.tooltip=Whether poison bombs can be crafted or not. -config.ebwizardry.smoke_bomb_is_craftable.tooltip=Whether smoke bombs can be crafted or not. -config.ebwizardry.use_alternate_scroll_recipe.tooltip=Whether to require a magic crystal in the shapeless crafting recipe for blank scrolls. Set to true if another mod adds a conflicting recipe. -config.ebwizardry.teleport_through_unbreakable_blocks.tooltip=Whether players are allowed to teleport through unbreakable blocks (e.g. bedrock) using the phase step spell. -config.ebwizardry.show_summoned_creature_names.tooltip=Whether to show summoned creatures' names and owners above their heads. -config.ebwizardry.friendly_fire.tooltip=Whether to allow players to damage their designated allies using magic. -config.ebwizardry.telekinetic_disarmament.tooltip=Whether to allow players to disarm other players using the telekinesis spell. Set to false to prevent stealing of items. -config.ebwizardry.discovery_mode.tooltip=For those who like a sense of mystery! When set to true, spells you haven't cast yet will be unreadable until you cast them (on a per-world basis). Has no effect when in creative mode. Spells of identification will be unobtainable in survival mode if this is false. -config.ebwizardry.enable_shift_scrolling.tooltip=Whether you can switch between spells on a wand by scrolling with the mouse wheel while sneaking. Note that this will only affect you; other players connected to the same server obey their own settings. -config.ebwizardry.reverse_scroll_direction.tooltip=Whether to reverse the scroll direction used to switch between spells on a wand while sneaking. -config.ebwizardry.minion_revenge_targeting.tooltip=Whether summoned creatures can revenge attack their owner if their owner attacks them. -config.ebwizardry.player_damage_scaling.tooltip=Global damage scaling factor for the damage dealt by players casting spells, relative to 1. -config.ebwizardry.npc_damage_scaling.tooltip=Global damage scaling factor for the damage dealt by NPCs casting spells, relative to 1. -config.ebwizardry.cast_command_multiplier_limit.tooltip=Upper limit for the multipliers passed into the /cast command. This is here to stop players from accidentally breaking a world/server. Large blast mutipliers can cause extreme lag - you have been warned! -config.ebwizardry.summoned_creature_targets_whitelist.tooltip=List of names of entities which summoned creatures and wizards are allowed to attack, in addition to the defaults. Add mod creatures to this list if you want summoned creatures to attack them and they aren't already doing so. Entity names are not case sensitive. For mod entities, prefix with the mod ID (e.g. ebwizardry:wizard). -config.ebwizardry.summoned_creature_targets_blacklist.tooltip=List of names of entities which summoned creatures and wizards are specifically not allowed to attack, overriding the defaults and the whitelist. Add creatures to this list if allowing them to be attacked causes problems or is too destructive (removing creepers from this list is done at your own risk!). Entity names are not case sensitive. For mod entities, prefix with the mod ID (e.g. ebwizardry:wizard). -config.ebwizardry.spell_hud_position.tooltip=The position of the spell HUD. -config.ebwizardry.spell_hud_skin.tooltip=Change the look of the spell HUD... -config.ebwizardry.cast_command_name.tooltip=The name of the /cast command. This is what you type directly after the /; for example if this was set to 'magic' then instead of typing /cast you would type /magic instead. -config.ebwizardry.discoverspell_command_name.tooltip=The name of the /discoverspell command. This is what you type directly after the /; for example if this was set to 'magic' then instead of typing /discoverspell you would type /magic instead. -config.ebwizardry.ally_command_name.tooltip=The name of the /ally command. This is what you type directly after the /; for example if this was set to 'magic' then instead of typing /ally you would type /magic instead. -config.ebwizardry.allies_command_name.tooltip=The name of the /allies command. This is what you type directly after the /; for example if this was set to 'magic' then instead of typing /allies you would type /magic instead. -config.ebwizardry.mind_control_targets_blacklist.tooltip=List of names of entities which cannot be mind controlled, in addition to the defaults. Add creatures to this list if allowing them to be mind-controlled causes problems or could be exploited. Entity names are not case sensitive. For mod entities, prefix with the mod ID (e.g. ebwizardry:wizard). -config.ebwizardry.evil_wizard_dimensions.tooltip=List of dimension ids in which evil wizards can spawn. +config.ebwizardry.category.compatibility=Mod Compatibility Settings +config.ebwizardry.category.compatibility.tooltip=Configure how wizardry interacts with other mods +config.ebwizardry.title.compatibility=Mod Compatibility Settings +config.ebwizardry.subtitle.compatibility=Settings that affect how wizardry interacts with other mods -config.ebwizardry.mobs_immune_to_fire.tooltip=List of names of entities that are immune to fire, in addition to the defaults. Add mod creatures to this list if you want them to be immune to fire magic and they aren't already. Entity names are not case sensitive. For mod entities, prefix with the mod ID (e.g. ebwizardry:wizard). -config.ebwizardry.mobs_immune_to_ice.tooltip=List of names of entities that are immune to ice, in addition to the defaults. Add mod creatures to this list if you want them to be immune to ice magic and they aren't already. Entity names are not case sensitive. For mod entities, prefix with the mod ID (e.g. ebwizardry:wizard). -config.ebwizardry.mobs_immune_to_lightning.tooltip=List of names of entities that are immune to lightning, in addition to the defaults. Add mod creatures to this list if you want them to be immune to lightning magic and they aren't already. Entity names are not case sensitive. For mod entities, prefix with the mod ID (e.g. ebwizardry:wizard). -config.ebwizardry.mobs_immune_to_wither.tooltip=List of names of entities that are immune to wither effects, in addition to the defaults. Add mod creatures to this list if you want them to be immune to withering magic and they aren't already. Entity names are not case sensitive. For mod entities, prefix with the mod ID (e.g. ebwizardry:wizard). -config.ebwizardry.mobs_immune_to_poison.tooltip=List of names of entities that are immune to poison, in addition to the defaults. Add mod creatures to this list if you want them to be immune to poison magic and they aren't already. Entity names are not case sensitive. For mod entities, prefix with the mod ID (e.g. ebwizardry:wizard). +config.ebwizardry.damage_source_blacklist=Damage Source Blacklist +config.ebwizardry.damage_source_blacklist.tooltip=List of damage source string identifiers to be ignored when re-applying damage. Case-sensitive. A message will be logged if wizardry detects a damage source that should be added to this list. Otherwise, don't change unless instructed to do so. +config.ebwizardry.compatibility_warnings=Compatibility Warnings +config.ebwizardry.compatibility_warnings.tooltip=Whether to print compatibility warnings to the console. Set to false if excessive messages are being printed. +config.ebwizardry.baubles_integration=Baubles Integration +config.ebwizardry.baubles_integration.tooltip=If Baubles is installed, controls whether Baubles integration features are enabled. If this is disabled, wizardry will always behave as if Baubles is not installed. +config.ebwizardry.jei_integration=JEI Integration +config.ebwizardry.jei_integration.tooltip=If JEI (Just Enough Items) is installed, controls whether JEI integration features are enabled. If this is disabled, wizardry will always behave as if JEI is not installed. +config.ebwizardry.antique_atlas_integration=Antique Atlas Integration +config.ebwizardry.antique_atlas_integration.tooltip=If Antique Atlas is installed, controls whether Antique Atlas integration features are enabled. If this is disabled, wizardry will always behave as if Antique Atlas is not installed. +config.ebwizardry.auto_place_tower_markers=Auto-Place Tower Markers +config.ebwizardry.auto_place_tower_markers.tooltip=Controls whether wizardry automatically places antique atlas markers at the locations of wizard towers. +config.ebwizardry.auto_place_obelisk_markers=Auto-Place Obelisk Markers +config.ebwizardry.auto_place_obelisk_markers.tooltip=Controls whether wizardry automatically places antique atlas markers at the locations of obelisks. +config.ebwizardry.auto_place_shrine_markers=Auto-Place Shrine Markers +config.ebwizardry.auto_place_shrine_markers.tooltip=Controls whether wizardry automatically places antique atlas markers at the locations of shrines. + +integration.jei.category.ebwizardry\:arcane_workbench=Arcane Workbench + +integration.antiqueatlas.marker.ebwizardry\:wizard_tower=Wizard Tower +integration.antiqueatlas.marker.ebwizardry\:obelisk=Obelisk +integration.antiqueatlas.marker.ebwizardry\:shrine=Shrine wizard.debug=%1$s, %2$s, %3$s diff --git a/src/main/resources/assets/ebwizardry/lang/en_us.lang b/src/main/resources/assets/ebwizardry/lang/en_us.lang index a7acb7fb..bcc6666f 100644 --- a/src/main/resources/assets/ebwizardry/lang/en_us.lang +++ b/src/main/resources/assets/ebwizardry/lang/en_us.lang @@ -1,285 +1,515 @@ -tile.ebwizardry:arcane_workbench.name=Arcane Workbench -tile.ebwizardry:crystal_ore.name=Crystal Ore -tile.ebwizardry:petrified_stone.name=Petrified Stone -tile.ebwizardry:ice_statue.name=Ice Statue -tile.ebwizardry:crystal_flower.name=Crystal Flower -tile.ebwizardry:snare.name=Snare -tile.ebwizardry:transportation_stone.name=Stone of Transportation -tile.ebwizardry:spectral_block.name=Spectral Block -tile.ebwizardry:crystal_block.name=Block of Crystal +#PARSE_ESCAPES +tile.ebwizardry\:arcane_workbench.name=Arcane Workbench +tile.ebwizardry\:crystal_ore.name=Crystal Ore +tile.ebwizardry\:petrified_stone.name=Petrified Stone +tile.ebwizardry\:ice_statue.name=Ice Statue +tile.ebwizardry\:crystal_flower.name=Crystal Flower +tile.ebwizardry\:snare.name=Snare +tile.ebwizardry\:transportation_stone.name=Stone of Transportation +tile.ebwizardry\:transportation_stone.confirm=You will now be returned here upon casting %1$s +tile.ebwizardry\:transportation_stone.remember=Remembered the location %s, %s, %s in dimension %s +tile.ebwizardry\:transportation_stone.forget=Forgot the location %s, %s, %s in dimension %s +tile.ebwizardry\:transportation_stone.invalid=You must make a circle with 8 stones of transportation first! +tile.ebwizardry\:spectral_block.name=Spectral Block +tile.ebwizardry\:runestone.name=Runestone +tile.ebwizardry\:runestone_pedestal.name=Runestone Pedestal +tile.ebwizardry\:thorns.name=Thorns +tile.ebwizardry\:obsidian_crust.name=Obsidian Crust +tile.ebwizardry\:dry_frosted_ice.name=Dry Frosted Ice -item.ebwizardry:magic_crystal.name=Magic Crystal -item.ebwizardry:magic_wand.name=Magic Wand -item.ebwizardry:apprentice_wand.name=Apprentice Wand -item.ebwizardry:advanced_wand.name=Advanced Wand -item.ebwizardry:master_wand.name=Master Wand -item.ebwizardry:spell_book.name=Spell Book +tile.ebwizardry\:magic_crystal_block.name=Block of Crystal +tile.ebwizardry\:fire_crystal_block.name=Block of Fiery Crystal +tile.ebwizardry\:ice_crystal_block.name=Block of Icy Crystal +tile.ebwizardry\:lightning_crystal_block.name=Block of Stormy Crystal +tile.ebwizardry\:necromancy_crystal_block.name=Block of Dark Crystal +tile.ebwizardry\:earth_crystal_block.name=Block of Verdant Crystal +tile.ebwizardry\:sorcery_crystal_block.name=Block of Mystical Crystal +tile.ebwizardry\:healing_crystal_block.name=Block of Radiant Crystal -item.ebwizardry:spell_book.apply_to_wizard=Replaced %1$s's spell %2$s with %3$s +item.ebwizardry\:crystal_magic.name=Magic Crystal +item.ebwizardry\:crystal_fire.name=Fiery Crystal +item.ebwizardry\:crystal_ice.name=Icy Crystal +item.ebwizardry\:crystal_lightning.name=Stormy Crystal +item.ebwizardry\:crystal_necromancy.name=Dark Crystal +item.ebwizardry\:crystal_earth.name=Verdant Crystal +item.ebwizardry\:crystal_sorcery.name=Mystical Crystal +item.ebwizardry\:crystal_healing.name=Radiant Crystal -item.ebwizardry:arcane_tome.name=Tome of Arcana -item.ebwizardry:arcane_tome.desc1=Upgrades any %1$s -item.ebwizardry:arcane_tome.desc2=wand to %1$s tier +item.ebwizardry\:magic_wand.name=Magic Wand +item.ebwizardry\:apprentice_wand.name=Apprentice Wand +item.ebwizardry\:advanced_wand.name=Advanced Wand +item.ebwizardry\:master_wand.name=Master Wand +item.ebwizardry\:spell_book.name=Spell Book -item.ebwizardry:wizard_handbook.name=The Wizard's Handbook -item.ebwizardry:wizard_handbook.desc=by %1$s +item.ebwizardry\:spell_book.apply_to_wizard=Replaced %1$s's spell %2$s with %3$s -item.ebwizardry:wand.buff=+%1$s %2$s potency -item.ebwizardry:wand.spell=Current Spell: %1$s -item.ebwizardry:wand.mana=Mana: %1$s/%2$s +item.ebwizardry\:arcane_tome.name=Tome of Arcana +item.ebwizardry\:arcane_tome.desc1=Upgrades any %1$s +item.ebwizardry\:arcane_tome.desc2=wand to %1$s tier -item.ebwizardry:wand.addally=%1$s has been added to your list of allies -item.ebwizardry:wand.removeally=%1$s has been removed from your list of allies +item.ebwizardry\:wizard_handbook.name=The Wizard's Handbook +item.ebwizardry\:wizard_handbook.desc=by %1$s -item.ebwizardry:basic_fire_wand.name=Wand of Embers -item.ebwizardry:basic_ice_wand.name=Wand of Frost -item.ebwizardry:basic_lightning_wand.name=Wand of Sparks -item.ebwizardry:basic_necromancy_wand.name=Wand of Shadows -item.ebwizardry:basic_earth_wand.name=Wand of the Forest -item.ebwizardry:basic_sorcery_wand.name=Wand of Mystery -item.ebwizardry:basic_healing_wand.name=Wand of Healing +item.ebwizardry\:wand.generic=wand -item.ebwizardry:apprentice_fire_wand.name=Apprentice Pyromancer Wand -item.ebwizardry:apprentice_ice_wand.name=Apprentice Ice Mage Wand -item.ebwizardry:apprentice_lightning_wand.name=Apprentice Storm Mage Wand -item.ebwizardry:apprentice_necromancy_wand.name=Apprentice Necromancer Wand -item.ebwizardry:apprentice_earth_wand.name=Apprentice Earth Mage Wand -item.ebwizardry:apprentice_sorcery_wand.name=Apprentice Sorcerer Wand -item.ebwizardry:apprentice_healing_wand.name=Apprentice Healer Wand +item.ebwizardry\:wand.buff=+%1$s %2$s potency +item.ebwizardry\:wand.spell=Current Spell\: %1$s +item.ebwizardry\:wand.mana=Mana\: %1$s/%2$s +item.ebwizardry\:wand.progression=Progression\: %1$s/%2$s -item.ebwizardry:advanced_fire_wand.name=Wand of the Pyromancer -item.ebwizardry:advanced_ice_wand.name=Wand of the Ice Mage -item.ebwizardry:advanced_lightning_wand.name=Wand of the Storm Mage -item.ebwizardry:advanced_necromancy_wand.name=Wand of the Necromancer -item.ebwizardry:advanced_earth_wand.name=Wand of the Earth Mage -item.ebwizardry:advanced_sorcery_wand.name=Wand of the Sorcerer -item.ebwizardry:advanced_healing_wand.name=Wand of the Healer +item.ebwizardry\:wand.levelup=%1$s is ready to upgrade to %2$s tier -item.ebwizardry:master_fire_wand.name=Master Pyromancer Wand -item.ebwizardry:master_ice_wand.name=Master Ice Mage Wand -item.ebwizardry:master_lightning_wand.name=Master Storm Mage Wand -item.ebwizardry:master_necromancy_wand.name=Master Necromancer Wand -item.ebwizardry:master_earth_wand.name=Master Earth Mage Wand -item.ebwizardry:master_sorcery_wand.name=Master Sorcerer Wand -item.ebwizardry:master_healing_wand.name=Master Healer Wand +item.ebwizardry\:wand.addally=%1$s has been added to your list of allies +item.ebwizardry\:wand.removeally=%1$s has been removed from your list of allies -item.ebwizardry:spectral_sword.name=Spectral Sword -item.ebwizardry:spectral_pickaxe.name=Spectral Pickaxe -item.ebwizardry:spectral_bow.name=Spectral Bow +item.ebwizardry\:novice_fire_wand.name=Wand of Embers +item.ebwizardry\:novice_ice_wand.name=Wand of Frost +item.ebwizardry\:novice_lightning_wand.name=Wand of Sparks +item.ebwizardry\:novice_necromancy_wand.name=Wand of Shadows +item.ebwizardry\:novice_earth_wand.name=Wand of the Forest +item.ebwizardry\:novice_sorcery_wand.name=Wand of Mystery +item.ebwizardry\:novice_healing_wand.name=Wand of Healing -item.ebwizardry:mana_flask.name=Mana Flask -item.ebwizardry:storage_upgrade.name=Wand Storage Upgrade -item.ebwizardry:siphon_upgrade.name=Wand Siphon Upgrade -item.ebwizardry:condenser_upgrade.name=Wand Condenser Upgrade -item.ebwizardry:range_upgrade.name=Wand Range Upgrade -item.ebwizardry:duration_upgrade.name=Wand Duration Upgrade -item.ebwizardry:cooldown_upgrade.name=Wand Cooldown Upgrade -item.ebwizardry:blast_upgrade.name=Wand Blast Upgrade -item.ebwizardry:attunement_upgrade.name=Wand Attunement Upgrade +item.ebwizardry\:apprentice_fire_wand.name=Apprentice Pyromancer Wand +item.ebwizardry\:apprentice_ice_wand.name=Apprentice Ice Mage Wand +item.ebwizardry\:apprentice_lightning_wand.name=Apprentice Storm Mage Wand +item.ebwizardry\:apprentice_necromancy_wand.name=Apprentice Necromancer Wand +item.ebwizardry\:apprentice_earth_wand.name=Apprentice Earth Mage Wand +item.ebwizardry\:apprentice_sorcery_wand.name=Apprentice Sorcerer Wand +item.ebwizardry\:apprentice_healing_wand.name=Apprentice Healer Wand -item.ebwizardry:flaming_axe.name=Flaming Axe -item.ebwizardry:frost_axe.name=Frost Axe +item.ebwizardry\:advanced_fire_wand.name=Wand of the Pyromancer +item.ebwizardry\:advanced_ice_wand.name=Wand of the Ice Mage +item.ebwizardry\:advanced_lightning_wand.name=Wand of the Storm Mage +item.ebwizardry\:advanced_necromancy_wand.name=Wand of the Necromancer +item.ebwizardry\:advanced_earth_wand.name=Wand of the Earth Mage +item.ebwizardry\:advanced_sorcery_wand.name=Wand of the Sorcerer +item.ebwizardry\:advanced_healing_wand.name=Wand of the Healer -item.ebwizardry:firebomb.name=Firebomb -item.ebwizardry:poison_bomb.name=Poison Bomb -item.ebwizardry:smoke_bomb.name=Smoke Bomb +item.ebwizardry\:master_fire_wand.name=Master Pyromancer Wand +item.ebwizardry\:master_ice_wand.name=Master Ice Mage Wand +item.ebwizardry\:master_lightning_wand.name=Master Storm Mage Wand +item.ebwizardry\:master_necromancy_wand.name=Master Necromancer Wand +item.ebwizardry\:master_earth_wand.name=Master Earth Mage Wand +item.ebwizardry\:master_sorcery_wand.name=Master Sorcerer Wand +item.ebwizardry\:master_healing_wand.name=Master Healer Wand -item.ebwizardry:blank_scroll.name=Blank Scroll -item.ebwizardry:scroll.name=Scroll of %1$s -item.ebwizardry:scroll.undiscovered.name=Scroll "%1$s" -item.ebwizardry:identification_scroll.name=Scroll of Identification -item.ebwizardry:identification_scroll.desc1=%1$sIdentifies an unknown -item.ebwizardry:identification_scroll.desc2=%1$sspell book or scroll -item.ebwizardry:identification_scroll.nothing_to_identify=Nothing to identify! +item.ebwizardry\:spectral_sword.name=Spectral Sword +item.ebwizardry\:spectral_pickaxe.name=Spectral Pickaxe +item.ebwizardry\:spectral_bow.name=Spectral Bow -item.ebwizardry:armour_upgrade.name=Arcane Seal of Protection -item.ebwizardry:armour_upgrade.desc1=%1$sUpgrades any wizard armour -item.ebwizardry:armour_upgrade.desc2=%1$sto make it %2$slegendary +item.ebwizardry\:spectral_sword_upgraded.name=Spectral Sword +item.ebwizardry\:spectral_pickaxe_upgraded.name=Spectral Pickaxe -item.ebwizardry:magic_silk.name=Magical Silk +item.ebwizardry\:small_mana_flask.name=Small Mana Flask +item.ebwizardry\:medium_mana_flask.name=Medium Mana Flask +item.ebwizardry\:large_mana_flask.name=Large Mana Flask -item.ebwizardry:wizard_armour.legendary=Legendary -item.ebwizardry:wizard_armour.buff=-%1$s %2$s cost -item.ebwizardry:wizard_armour.mana=Mana: %1$s/%2$s +item.ebwizardry\:grand_crystal.name=Grand Magic Crystal +item.ebwizardry\:crystal_shard.name=Magic Crystal Shard -item.ebwizardry:wizard_hat.name=Wizard Hat -item.ebwizardry:wizard_robe.name=Wizard Robes -item.ebwizardry:wizard_leggings.name=Wizard Leggings -item.ebwizardry:wizard_boots.name=Wizard Boots +item.ebwizardry\:astral_diamond.name=Astral Diamond -item.ebwizardry:wizard_hat_fire.name=Pyromancer Hat -item.ebwizardry:wizard_robe_fire.name=Pyromancer Robes -item.ebwizardry:wizard_leggings_fire.name=Pyromancer Leggings -item.ebwizardry:wizard_boots_fire.name=Pyromancer Boots +item.ebwizardry\:purifying_elixir.name=Purifying Elixir +item.ebwizardry\:purifying_elixir.desc=Removes curses when consumed -item.ebwizardry:wizard_hat_ice.name=Ice Mage Hat -item.ebwizardry:wizard_robe_ice.name=Ice Mage Robes -item.ebwizardry:wizard_leggings_ice.name=Ice Mage Leggings -item.ebwizardry:wizard_boots_ice.name=Ice Mage Boots +item.ebwizardry\:storage_upgrade.name=Wand Storage Upgrade +item.ebwizardry\:siphon_upgrade.name=Wand Siphon Upgrade +item.ebwizardry\:condenser_upgrade.name=Wand Condenser Upgrade +item.ebwizardry\:range_upgrade.name=Wand Range Upgrade +item.ebwizardry\:duration_upgrade.name=Wand Duration Upgrade +item.ebwizardry\:cooldown_upgrade.name=Wand Cooldown Upgrade +item.ebwizardry\:blast_upgrade.name=Wand Blast Upgrade +item.ebwizardry\:attunement_upgrade.name=Wand Attunement Upgrade +item.ebwizardry\:melee_upgrade.name=Wand Melee Upgrade -item.ebwizardry:wizard_hat_lightning.name=Storm Mage Hat -item.ebwizardry:wizard_robe_lightning.name=Storm Mage Robes -item.ebwizardry:wizard_leggings_lightning.name=Storm Mage Leggings -item.ebwizardry:wizard_boots_lightning.name=Storm Mage Boots +item.ebwizardry\:storage_upgrade.desc=Upgrades the mana capacity of a wand +item.ebwizardry\:siphon_upgrade.desc=Upgrades a wand to extract mana from mobs when killed +item.ebwizardry\:condenser_upgrade.desc=Upgrades a wand to slowly regenerate mana over time +item.ebwizardry\:range_upgrade.desc=Upgrades the effective range of spells cast by a wand +item.ebwizardry\:duration_upgrade.desc=Upgrades the duration of effects cast by a wand +item.ebwizardry\:cooldown_upgrade.desc=Upgrades the spell cooldown speed of a wand +item.ebwizardry\:blast_upgrade.desc=Upgrades the area of effect of spells cast by a wand +item.ebwizardry\:attunement_upgrade.desc=Upgrades the number of spells that can be bound to a wand +item.ebwizardry\:melee_upgrade.desc=Upgrades a wand to use mana to deal more damage to mobs when hit -item.ebwizardry:wizard_hat_necromancy.name=Necromancer Hat -item.ebwizardry:wizard_robe_necromancy.name=Necromancer Robes -item.ebwizardry:wizard_leggings_necromancy.name=Necromancer Leggings -item.ebwizardry:wizard_boots_necromancy.name=Necromancer Boots +item.ebwizardry\:flaming_axe.name=Flaming Axe +item.ebwizardry\:frost_axe.name=Frost Axe -item.ebwizardry:wizard_hat_earth.name=Earth Mage Hat -item.ebwizardry:wizard_robe_earth.name=Earth Mage Robes -item.ebwizardry:wizard_leggings_earth.name=Earth Mage Leggings -item.ebwizardry:wizard_boots_earth.name=Earth Mage Boots +item.ebwizardry\:flaming_axe_upgraded.name=Flaming Axe +item.ebwizardry\:frost_axe_upgraded.name=Frost Axe -item.ebwizardry:wizard_hat_sorcery.name=Sorcerer Hat -item.ebwizardry:wizard_robe_sorcery.name=Sorcerer Robes -item.ebwizardry:wizard_leggings_sorcery.name=Sorcerer Leggings -item.ebwizardry:wizard_boots_sorcery.name=Sorcerer Boots +item.ebwizardry\:firebomb.name=Firebomb +item.ebwizardry\:poison_bomb.name=Poison Bomb +item.ebwizardry\:smoke_bomb.name=Smoke Bomb +item.ebwizardry\:spark_bomb.name=Spark Bomb -item.ebwizardry:wizard_hat_healing.name=Healer Hat -item.ebwizardry:wizard_robe_healing.name=Healer Robes -item.ebwizardry:wizard_leggings_healing.name=Healer Leggings -item.ebwizardry:wizard_boots_healing.name=Healer Boots +item.ebwizardry\:blank_scroll.name=Blank Scroll +item.ebwizardry\:scroll.generic=scroll +item.ebwizardry\:scroll.name=Scroll of %1$s +item.ebwizardry\:scroll.undiscovered.name=Scroll "%1$s" +item.ebwizardry\:identification_scroll.name=Scroll of Identification +item.ebwizardry\:identification_scroll.desc=Identifies an unknown spell book or scroll +item.ebwizardry\:identification_scroll.nothing_to_identify=Nothing to identify! -item.ebwizardry:spawn_wizard.name=Spawn Wizard -item.ebwizardry:spawn_evil_wizard.name=Spawn Evil Wizard +item.ebwizardry\:armour_upgrade.name=Arcane Seal of Protection +item.ebwizardry\:armour_upgrade.desc1=%1$sUpgrades any wizard armour +item.ebwizardry\:armour_upgrade.desc2=%1$sto make it %2$slegendary -item.ebwizardry:spectral_helmet.name=Spectral Helmet -item.ebwizardry:spectral_chestplate.name=Spectral Chestplate -item.ebwizardry:spectral_leggings.name=Spectral Leggings -item.ebwizardry:spectral_boots.name=Spectral Boots +item.ebwizardry\:magic_silk.name=Magical Silk -entity.ebwizardry:summonedcreature.nameplate=%1$s's %2$s -entity.ebwizardry:summonedcreature.nameplate_fallback=Someone's %1$s +item.ebwizardry\:wizard_armour.legendary=Legendary +item.ebwizardry\:wizard_armour.buff=-%1$s %2$s cost +item.ebwizardry\:wizard_armour.mana=Mana\: %1$s/%2$s -entity.ebwizardry:zombie_minion.name=Zombie -entity.ebwizardry:skeleton_minion.name=Skeleton -entity.ebwizardry:spider_minion.name=Spider -entity.ebwizardry:blaze_minion.name=Blaze -entity.ebwizardry:wither_skeleton_minion.name=Wither Skeleton -entity.ebwizardry:ice_wraith.name=Ice Wraith -entity.ebwizardry:lightning_wraith.name=Lightning Wraith -entity.ebwizardry:shadow_wraith.name=Shadow Wraith -entity.ebwizardry:spirit_wolf.name=Spirit Wolf -entity.ebwizardry:spirit_horse.name=Spirit Horse -entity.ebwizardry:ice_giant.name=Ice Giant -entity.ebwizardry:phoenix.name=Phoenix -entity.ebwizardry:wizard.name=Wizard -entity.ebwizardry:magic_slime.name=Magical Slime -entity.ebwizardry:silverfish_minion.name=Silverfish -entity.ebwizardry:storm_elemental.name=Storm Elemental -entity.ebwizardry:evil_wizard.name=Wizard -entity.ebwizardry:decoy.name=Decoy +item.ebwizardry\:wizard_hat.name=Wizard Hat +item.ebwizardry\:wizard_robe.name=Wizard Robes +item.ebwizardry\:wizard_leggings.name=Wizard Leggings +item.ebwizardry\:wizard_boots.name=Wizard Boots -entity.ebwizardry:magic_missile.name=Magic -entity.ebwizardry:arc.name=Magic -entity.ebwizardry:spark_bomb.name=Magic -entity.ebwizardry:ice_shard.name=Magic -entity.ebwizardry:firebomb.name=Magic -entity.ebwizardry:poison_bomb.name=Magic -entity.ebwizardry:force_orb.name=Magic -entity.ebwizardry:spark.name=Magic -entity.ebwizardry:darkness_orb.name=Magic -entity.ebwizardry:fire_sigil.name=Magic -entity.ebwizardry:frost_sigil.name=Magic -entity.ebwizardry:lightning_sigil.name=Magic -entity.ebwizardry:lightning_arrow.name=Magic -entity.ebwizardry:firebolt.name=Magic -entity.ebwizardry:ice_charge.name=Magic -entity.ebwizardry:force_arrow.name=Magic -entity.ebwizardry:dart.name=Magic -entity.ebwizardry:lightning_disc.name=Magic -entity.ebwizardry:thunderbolt.name=Magic -entity.ebwizardry:decay.name=Magic -entity.ebwizardry:ice_lance.name=Magic -entity.ebwizardry:smoke_bomb.name=Magic -entity.ebwizardry:ice_spike.name=Magic +item.ebwizardry\:wizard_hat_fire.name=Pyromancer Hat +item.ebwizardry\:wizard_robe_fire.name=Pyromancer Robes +item.ebwizardry\:wizard_leggings_fire.name=Pyromancer Leggings +item.ebwizardry\:wizard_boots_fire.name=Pyromancer Boots -entity.ebwizardry:black_hole.name=Black Hole -entity.ebwizardry:shield.name=Shield -entity.ebwizardry:meteor.name=Meteor -entity.ebwizardry:blizzard.name=Blizzard -entity.ebwizardry:bubble.name=Bubble -entity.ebwizardry:tornado.name=Tornado -entity.ebwizardry:lightning_hammer.name=Lightning Hammer -entity.ebwizardry:arrow_rain.name=Arrow Rain -entity.ebwizardry:healing_aura.name=Healing Aura -entity.ebwizardry:forcefield.name=Forcefield -entity.ebwizardry:ring_of_fire.name=Ring of Fire -entity.ebwizardry:earthquake.name=Earthquake -entity.ebwizardry:falling_grass.name=Falling Grass -entity.ebwizardry:hailstorm.name=Hailstorm -entity.ebwizardry:lightning_pulse.name=Lightning Pulse +item.ebwizardry\:wizard_hat_ice.name=Ice Mage Hat +item.ebwizardry\:wizard_robe_ice.name=Ice Mage Robes +item.ebwizardry\:wizard_leggings_ice.name=Ice Mage Leggings +item.ebwizardry\:wizard_boots_ice.name=Ice Mage Boots + +item.ebwizardry\:wizard_hat_lightning.name=Storm Mage Hat +item.ebwizardry\:wizard_robe_lightning.name=Storm Mage Robes +item.ebwizardry\:wizard_leggings_lightning.name=Storm Mage Leggings +item.ebwizardry\:wizard_boots_lightning.name=Storm Mage Boots + +item.ebwizardry\:wizard_hat_necromancy.name=Necromancer Hat +item.ebwizardry\:wizard_robe_necromancy.name=Necromancer Robes +item.ebwizardry\:wizard_leggings_necromancy.name=Necromancer Leggings +item.ebwizardry\:wizard_boots_necromancy.name=Necromancer Boots + +item.ebwizardry\:wizard_hat_earth.name=Earth Mage Hat +item.ebwizardry\:wizard_robe_earth.name=Earth Mage Robes +item.ebwizardry\:wizard_leggings_earth.name=Earth Mage Leggings +item.ebwizardry\:wizard_boots_earth.name=Earth Mage Boots + +item.ebwizardry\:wizard_hat_sorcery.name=Sorcerer Hat +item.ebwizardry\:wizard_robe_sorcery.name=Sorcerer Robes +item.ebwizardry\:wizard_leggings_sorcery.name=Sorcerer Leggings +item.ebwizardry\:wizard_boots_sorcery.name=Sorcerer Boots + +item.ebwizardry\:wizard_hat_healing.name=Healer Hat +item.ebwizardry\:wizard_robe_healing.name=Healer Robes +item.ebwizardry\:wizard_leggings_healing.name=Healer Leggings +item.ebwizardry\:wizard_boots_healing.name=Healer Boots + +item.ebwizardry\:spawn_wizard.name=Spawn Wizard +item.ebwizardry\:spawn_evil_wizard.name=Spawn Evil Wizard + +item.ebwizardry\:spectral_helmet.name=Spectral Helmet +item.ebwizardry\:spectral_chestplate.name=Spectral Chestplate +item.ebwizardry\:spectral_leggings.name=Spectral Leggings +item.ebwizardry\:spectral_boots.name=Spectral Boots + +item.ebwizardry\:lightning_hammer.name=Lightning Hammer + +item.ebwizardry\:ring_condensing.name=Ring of Condensing +item.ebwizardry\:ring_condensing.desc=Slowly regenerates mana for all wands on your hotbar +item.ebwizardry\:ring_siphoning.name=Ring of Siphoning +item.ebwizardry\:ring_siphoning.desc=Increases siphoned mana by 30%% +item.ebwizardry\:ring_battlemage.name=Ring of the Battlemage +item.ebwizardry\:ring_battlemage.desc=Holding a wand in your offhand and a sword in your main hand grants 10%% extra magic damage +item.ebwizardry\:ring_combustion.name=Ring of Combustion +item.ebwizardry\:ring_combustion.desc=Creatures killed by fire spells explode +item.ebwizardry\:ring_fire_melee.name=Ring of Fiery Touch +item.ebwizardry\:ring_fire_melee.desc=Hitting a creature with a fire wand sets it on fire +item.ebwizardry\:ring_fire_biome.name=Ring of the Desert Sun +item.ebwizardry\:ring_fire_biome.desc=Fire spells are 30%% more potent in hot biomes +item.ebwizardry\:ring_disintegration.name=Ring of Searing Embers +item.ebwizardry\:ring_disintegration.desc=All fire attack spells cause their victims to disintegrate +item.ebwizardry\:ring_ice_melee.name=Ring of Icy Touch +item.ebwizardry\:ring_ice_melee.desc=Hitting a creature with an ice wand gives it the frostbite effect +item.ebwizardry\:ring_ice_biome.name=Ring of Glaciation +item.ebwizardry\:ring_ice_biome.desc=Ice spells are 30%% more potent in snowy biomes +item.ebwizardry\:ring_arcane_frost.name=Ring of Arcane Frost +item.ebwizardry\:ring_arcane_frost.desc=Creatures killed by ice spells release ice shards in all directions +item.ebwizardry\:ring_shattering.name=Ring of Shattering +item.ebwizardry\:ring_shattering.desc=Melee attacks on mobs with the frostbite effect have a chance to shatter them into ice shards +item.ebwizardry\:ring_lightning_melee.name=Ring of Chaining +item.ebwizardry\:ring_lightning_melee.desc=Hitting a creature with a lightning wand shoots lightning at another nearby creature +item.ebwizardry\:ring_storm.name=Ring of the Gathering Storm +item.ebwizardry\:ring_storm.desc=During thunderstorms, lightning spells have dramatically reduced cooldowns +item.ebwizardry\:ring_seeking.name=Ring of Attraction +item.ebwizardry\:ring_seeking.desc=All projectile spells seek their targets +item.ebwizardry\:ring_hammer.name=Ring of Thalek the Almighty +item.ebwizardry\:ring_hammer.desc=Lightning hammers can be picked up and thrown +item.ebwizardry\:ring_soulbinding.name=Soulwalker's Ring +item.ebwizardry\:ring_soulbinding.desc=Creatures damaged by necromancy spells become soulbound to you +item.ebwizardry\:ring_leeching.name=Ring of Leeching +item.ebwizardry\:ring_leeching.desc=All necromancy attacks have a 30%% chance to trigger a life drain effect +item.ebwizardry\:ring_necromancy_melee.name=Ring of Necrotic Touch +item.ebwizardry\:ring_necromancy_melee.desc=Hitting a creature with a necromancy wand gives it the wither effect +item.ebwizardry\:ring_mind_control.name=Ring of the Psychic +item.ebwizardry\:ring_mind_control.desc=Mind-controlled creatures have a chance to mind control other nearby creatures +item.ebwizardry\:ring_poison.name=Serpentine Ring +item.ebwizardry\:ring_poison.desc=All earth spells poison their target +item.ebwizardry\:ring_earth_melee.name=Ring of Venomous Touch +item.ebwizardry\:ring_earth_melee.desc=Hitting a creature with an earth wand poisons it +item.ebwizardry\:ring_earth_biome.name=Dryad's Ring +item.ebwizardry\:ring_earth_biome.desc=Earth spells are 30%% more potent in forests and roofed forests +item.ebwizardry\:ring_full_moon.name=Ring of the Howling Wolf +item.ebwizardry\:ring_full_moon.desc=Earth spells have dramatically reduced cooldowns under a full moon +item.ebwizardry\:ring_extraction.name=Ring of Extraction +item.ebwizardry\:ring_extraction.desc=Kills with sorcery spells grant bonus mana +item.ebwizardry\:ring_mana_return.name=Ring of the Perfectionist +item.ebwizardry\:ring_mana_return.desc=Force arrows that miss their target return the mana they used to your wand +item.ebwizardry\:ring_blockwrangler.name=Blockwrangler's Ring +item.ebwizardry\:ring_blockwrangler.desc=Thrown blocks deal twice their normal damage +item.ebwizardry\:ring_conjurer.name=Conjurer's Ring +item.ebwizardry\:ring_conjurer.desc=Conjured items last twice as long +item.ebwizardry\:ring_defender.name=Ring of the Defender +item.ebwizardry\:ring_defender.desc=Your projectiles pass through forcefields belonging to you or an ally +item.ebwizardry\:ring_paladin.name=Paladin's Ring +item.ebwizardry\:ring_paladin.desc=When you heal yourself or an ally, nearby allies will also gain some health +item.ebwizardry\:ring_interdiction.name=Ring of Interdiction +item.ebwizardry\:ring_interdiction.desc=Your forcefield damages creatures that touch it + +item.ebwizardry\:amulet_arcane_defence.name=Amulet of Arcane Defense +item.ebwizardry\:amulet_arcane_defence.desc=Slowly regenerates mana for all worn wizard armor +item.ebwizardry\:amulet_warding.name=Amulet of Warding +item.ebwizardry\:amulet_warding.desc=Reduces all incoming magic damage by 10%% +item.ebwizardry\:amulet_wisdom.name=Amulet of Wisdom +item.ebwizardry\:amulet_wisdom.desc=Greatly reduces the chance of negative effects when using undiscovered spells +item.ebwizardry\:amulet_fire_protection.name=Flamefast Amulet +item.ebwizardry\:amulet_fire_protection.desc=Reduces fire damage by 30%% +item.ebwizardry\:amulet_fire_cloaking.name=Amulet of Cloaking Flame +item.ebwizardry\:amulet_fire_cloaking.desc=Reduces incoming damage by 75%% whilst standing within a ring of fire belonging to you or an ally +item.ebwizardry\:amulet_ice_immunity.name=Permafrost Amulet +item.ebwizardry\:amulet_ice_immunity.desc=Grants total immunity to frostbite effects +item.ebwizardry\:amulet_ice_protection.name=Frostbound Amulet +item.ebwizardry\:amulet_ice_protection.desc=Reduces frost damage by 30%% +item.ebwizardry\:amulet_potential.name=Amulet of Potential +item.ebwizardry\:amulet_potential.desc=Grants a 15%% chance to shoot lightning at creatures that melee attack you +item.ebwizardry\:amulet_channeling.name=Amulet of Channeling +item.ebwizardry\:amulet_channeling.desc=Grants a 30%% chance to negate incoming shock damage +item.ebwizardry\:amulet_lich.name=Amulet of the Lich +item.ebwizardry\:amulet_lich.desc=Grants a 15%% chance for incoming damage to be dealt to a nearby minion instead +item.ebwizardry\:amulet_wither_immunity.name=Wither Pearl Amulet +item.ebwizardry\:amulet_wither_immunity.desc=Grants total immunity to wither effects +item.ebwizardry\:amulet_glide.name=Windfeather Amulet +item.ebwizardry\:amulet_glide.desc=Falling more than 3 blocks has a 50%% chance to activate the glide effect +item.ebwizardry\:amulet_banishing.name=Enderbound Amulet +item.ebwizardry\:amulet_banishing.desc=Creatures that melee attack you have a 15%% chance to be teleported to a random nearby location +item.ebwizardry\:amulet_anchoring.name=Amulet of Anchoring +item.ebwizardry\:amulet_anchoring.desc=Grants immunity to being moved by magic +item.ebwizardry\:amulet_recovery.name=Amulet of Recovery +item.ebwizardry\:amulet_recovery.desc=When on less than 50%% health, mana from your armor will be used to heal you over time +item.ebwizardry\:amulet_transience.name=Amulet of Transience +item.ebwizardry\:amulet_transience.desc=Grants a 25%% chance to activate a transience effect when critically wounded +item.ebwizardry\:amulet_resurrection.name=Amulet of the Immortal +item.ebwizardry\:amulet_resurrection.desc=The resurrection spell can be used on yourself from beyond the grave +item.ebwizardry\:amulet_auto_shield.name=Hyeleth's Amulet +item.ebwizardry\:amulet_auto_shield.desc=Grants a 25%% chance to trigger the shield spell for a few seconds when bound to a wand on your hotbar + +item.ebwizardry\:charm_haggler.name=Haggler's Sign +item.ebwizardry\:charm_haggler.desc=Wizards are guaranteed to offer a new trade every time you trade with them +item.ebwizardry\:charm_experience_tome.name=Tome of the Diligent +item.ebwizardry\:charm_experience_tome.desc=Increases the rate at which wands gain progression by 40%% +item.ebwizardry\:charm_auto_smelt.name=Metallurgist's Mark +item.ebwizardry\:charm_auto_smelt.desc=Pocket furnace triggers automatically when bound to a wand on your hotbar +item.ebwizardry\:charm_lava_walking.name=Nether Ice Core +item.ebwizardry\:charm_lava_walking.desc=Frost step freezes lava to form an obsidian crust +item.ebwizardry\:charm_storm.name=Bottled Thundercloud +item.ebwizardry\:charm_storm.desc=Invoke weather is guaranteed to summon storms +item.ebwizardry\:charm_minion_health.name=Obsidian Zombie Head +item.ebwizardry\:charm_minion_health.desc=Summoned creatures are 25%% stronger +item.ebwizardry\:charm_minion_variants.name=Talisman of Transformation +item.ebwizardry\:charm_minion_variants.desc=Summoned zombies are husks; summoned skeletons are strays +item.ebwizardry\:charm_flight.name=Emerald Beetle Wing +item.ebwizardry\:charm_flight.desc=Flight and Glide are 50%% faster +item.ebwizardry\:charm_growth.name=Crystal Flower Charm +item.ebwizardry\:charm_growth.desc=Growth aura has a 35%% chance to instantly grow crops to fully-grown +item.ebwizardry\:charm_abseiling.name=Enchanted Twine +item.ebwizardry\:charm_abseiling.desc=Holding sneak whilst grappling slowly pays out the line +item.ebwizardry\:charm_silk_touch.name=Moonstone Orb +item.ebwizardry\:charm_silk_touch.desc=Blocks broken with the mine spell always drop themselves +item.ebwizardry\:charm_stop_time.name=Peculiar Pocketwatch +item.ebwizardry\:charm_stop_time.desc=The slow time spell makes time stand still +item.ebwizardry\:charm_light.name=Elevinia's Everburning Lantern +item.ebwizardry\:charm_light.desc=Conjured light sources last forever and may be dispelled by right-clicking with a wand +item.ebwizardry\:charm_transportation.name=Ancient Compass +item.ebwizardry\:charm_transportation.desc=Up to four stone circles may be remembered and selected from when using transportation +item.ebwizardry\:charm_feeding.name=Bottomless Provisions +item.ebwizardry\:charm_feeding.desc=Replenish hunger triggers automatically when bound to a wand on your hotbar + +item.charge_status.full=Full +item.charge_status.almost_full=Almost full +item.charge_status.mostly_full=Mostly full +item.charge_status.half_full=Half full +item.charge_status.mostly_empty=Mostly empty +item.charge_status.almost_empty=Almost empty +item.charge_status.empty=Empty + +entity.ebwizardry\:summonedcreature.nameplate=%1$s's %2$s +entity.ebwizardry\:summonedcreature.nameplate_fallback=Someone's %1$s + +entity.ebwizardry\:wizard.greeting_0=Good day, fellow wanderer. +entity.ebwizardry\:wizard.greeting_1=Greetings, traveller. What brings you here? +entity.ebwizardry\:wizard.greeting_2=Ah, nice to see another person around here. +entity.ebwizardry\:wizard.speech_0=Might I interest you in any spells, perhaps? +entity.ebwizardry\:wizard.speech_1=Magic is everywhere, if you know where to look. +entity.ebwizardry\:wizard.speech_2=There is still much to be learned about the arcane arts, adventurer. +entity.ebwizardry\:wizard.speech_3=Perhaps you have learned something yourself that you wish to share? +entity.ebwizardry\:wizard.speech_4=Studying the arcane is most fascinating, don't you think? +entity.ebwizardry\:wizard.farewell_0=Good luck in your quest, adventurer. +entity.ebwizardry\:wizard.farewell_1=I trust that we will meet again soon, friend. +entity.ebwizardry\:wizard.farewell_2=Goodbye then, traveller. +entity.ebwizardry\:wizard.combat_0=Be gone, foul creatures! +entity.ebwizardry\:wizard.combat_1=Leave me alone, pests! +entity.ebwizardry\:wizard.combat_2=Undead beings are not welcome here, shoo! +entity.ebwizardry\:wizard.combat_3=Away with you, creatures of darkness! +entity.ebwizardry\:wizard.combat_4=This is all I need! Get out of here, monsters! +entity.ebwizardry\:wizard.combat_5=Return to the caves from whence you came, evil creatures! +entity.ebwizardry\:wizard.player_combat_0=You will regret that decision, traveller! +entity.ebwizardry\:wizard.player_combat_1=What do you think you are doing?! +entity.ebwizardry\:wizard.player_combat_2=Only a fool dares to anger a wizard! +entity.ebwizardry\:wizard.player_combat_3=You will pay for your carelessness, adventurer! +entity.ebwizardry\:wizard.player_combat_4=Be ready to defend yourself, villain! +entity.ebwizardry\:wizard.player_combat_5=Prepare to feel my wrath! + +entity.ebwizardry\:zombie_minion.name=Zombie +entity.ebwizardry\:husk_minion.name=Husk +entity.ebwizardry\:skeleton_minion.name=Skeleton +entity.ebwizardry\:stray_minion.name=Stray +entity.ebwizardry\:spider_minion.name=Spider +entity.ebwizardry\:blaze_minion.name=Blaze +entity.ebwizardry\:wither_skeleton_minion.name=Wither Skeleton +entity.ebwizardry\:ice_wraith.name=Ice Wraith +entity.ebwizardry\:lightning_wraith.name=Lightning Wraith +entity.ebwizardry\:shadow_wraith.name=Shadow Wraith +entity.ebwizardry\:spirit_wolf.name=Spirit Wolf +entity.ebwizardry\:spirit_horse.name=Spirit Horse +entity.ebwizardry\:ice_giant.name=Ice Giant +entity.ebwizardry\:phoenix.name=Phoenix +entity.ebwizardry\:wizard.name=Wizard +entity.ebwizardry\:magic_slime.name=Magical Slime +entity.ebwizardry\:silverfish_minion.name=Silverfish +entity.ebwizardry\:storm_elemental.name=Storm Elemental +entity.ebwizardry\:evil_wizard.name=Wizard +entity.ebwizardry\:decoy.name=Decoy +entity.ebwizardry\:vex_minion.name=Vex + +entity.ebwizardry\:magic_missile.name=Magic +entity.ebwizardry\:arc.name=Magic +entity.ebwizardry\:spark_bomb.name=Magic +entity.ebwizardry\:ice_shard.name=Magic +entity.ebwizardry\:firebomb.name=Magic +entity.ebwizardry\:poison_bomb.name=Magic +entity.ebwizardry\:force_orb.name=Magic +entity.ebwizardry\:spark.name=Magic +entity.ebwizardry\:darkness_orb.name=Magic +entity.ebwizardry\:fire_sigil.name=Magic +entity.ebwizardry\:frost_sigil.name=Magic +entity.ebwizardry\:lightning_sigil.name=Magic +entity.ebwizardry\:lightning_arrow.name=Magic +entity.ebwizardry\:firebolt.name=Magic +entity.ebwizardry\:ice_charge.name=Magic +entity.ebwizardry\:force_arrow.name=Magic +entity.ebwizardry\:dart.name=Magic +entity.ebwizardry\:lightning_disc.name=Magic +entity.ebwizardry\:thunderbolt.name=Magic +entity.ebwizardry\:decay.name=Magic +entity.ebwizardry\:ice_lance.name=Magic +entity.ebwizardry\:smoke_bomb.name=Magic +entity.ebwizardry\:ice_spike.name=Magic +entity.ebwizardry\:combustion_rune.name=Magic + +entity.ebwizardry\:black_hole.name=Black Hole +entity.ebwizardry\:shield.name=Shield +entity.ebwizardry\:meteor.name=Meteor +entity.ebwizardry\:blizzard.name=Blizzard +entity.ebwizardry\:bubble.name=Bubble +entity.ebwizardry\:tornado.name=Tornado +entity.ebwizardry\:lightning_hammer.name=Lightning Hammer +entity.ebwizardry\:arrow_rain.name=Arrow Rain +entity.ebwizardry\:healing_aura.name=Healing Aura +entity.ebwizardry\:forcefield.name=Forcefield +entity.ebwizardry\:ring_of_fire.name=Ring of Fire +entity.ebwizardry\:earthquake.name=Earthquake +entity.ebwizardry\:hailstorm.name=Hailstorm +entity.ebwizardry\:lightning_pulse.name=Lightning Pulse itemGroup.ebwizardry=Wizardry itemGroup.ebwizardryspells=Spells +itemGroup.ebwizardrygear=Wizard Gear -advancement.wizardry:root=Wizardry -advancement.wizardry:root.desc=A wizard's journey to mastering the arcane -advancement.wizardry:crystal=A Curious Crystal... -advancement.wizardry:crystal.desc=Mine a magic crystal -advancement.wizardry:arcane_initiate=Arcane Initiate -advancement.wizardry:arcane_initiate.desc=Craft a magic wand with a gold nugget, a stick and a magic crystal -advancement.wizardry:apprentice=Wizard's Apprentice -advancement.wizardry:apprentice.desc=Use a tome of arcana to upgrade your wand -advancement.wizardry:master=Arcane Master -advancement.wizardry:master.desc=Obtain a master wand -advancement.wizardry:all_spells=Mage of All Trades -advancement.wizardry:all_spells.desc=Cast every single spell in the game -advancement.wizardry:wizard_trade=Magic Dealing -advancement.wizardry:wizard_trade.desc=Purchase an item from a wizard -advancement.wizardry:buy_master_spell=Knowledge is Power -advancement.wizardry:buy_master_spell.desc=Purchase a master spell from a wizard -advancement.wizardry:freeze_blaze=Not So Hot Now -advancement.wizardry:freeze_blaze.desc=Freeze a blaze solid -advancement.wizardry:charge_creeper=It's Gonna Blow -advancement.wizardry:charge_creeper.desc='Accidentally' charge a creeper -advancement.wizardry:frankenstein=Frankenstein -advancement.wizardry:frankenstein.desc=Turn a pig into a zombie pigman using the lightning bolt spell -advancement.wizardry:special_upgrade=Arcane Tinkering -advancement.wizardry:special_upgrade.desc=Apply a special upgrade to a wand -advancement.wizardry:craft_flask=It's Magic, Bottled! -advancement.wizardry:craft_flask.desc=Craft a mana flask -advancement.wizardry:elemental=Elemental -advancement.wizardry:elemental.desc=Obtain an elemental wand -advancement.wizardry:armour_set=Now You're a Proper Wizard -advancement.wizardry:armour_set.desc=Craft and equip a full set of wizard armor -advancement.wizardry:legendary=Legendary -advancement.wizardry:legendary.desc=Obtain a piece of legendary wizard armor -advancement.wizardry:self_destruct=That Backfired -advancement.wizardry:self_destruct.desc=Get killed by your own magic -advancement.wizardry:pig_tornado=Not Again... -advancement.wizardry:pig_tornado.desc=Ride a pig into a tornado -advancement.wizardry:jam_wizard=Jamming Session -advancement.wizardry:jam_wizard.desc=Use the arcane jammer spell on a wizard -advancement.wizardry:slime_skeleton=Sticky Situation -advancement.wizardry:slime_skeleton.desc=Engulf a skeleton in slime -advancement.wizardry:anger_wizard=You'll Regret That -advancement.wizardry:anger_wizard.desc=Make a wizard angry -advancement.wizardry:defeat_evil_wizard=Righteousness -advancement.wizardry:defeat_evil_wizard.desc=Defeat an evil wizard -advancement.wizardry:max_out_wand=Fully Equipped -advancement.wizardry:max_out_wand.desc=Apply the maximum number of upgrades to a master wand -advancement.wizardry:element_master=Element Mastery -advancement.wizardry:element_master.desc=Cast all the spells of any element -advancement.wizardry:identify_spell=Arcane Appraisal -advancement.wizardry:identify_spell.desc=Use a scroll of identification to identify a spell book or scroll +advancement.ebwizardry\:root=Wizardry +advancement.ebwizardry\:root.desc=A wizard's journey to mastering the arcane +advancement.ebwizardry\:crystal=A Curious Crystal... +advancement.ebwizardry\:crystal.desc=Mine a magic crystal +advancement.ebwizardry\:arcane_initiate=Arcane Initiate +advancement.ebwizardry\:arcane_initiate.desc=Craft a magic wand with a gold nugget, a stick and a magic crystal -tile.ebwizardry:transportation_stone.confirm=You will now be returned here upon casting %1$s -tile.ebwizardry:transportation_stone.invalid=You must make a circle with 8 stones of transportation first! +advancement.ebwizardry\:apprentice=Wizard's Apprentice +advancement.ebwizardry\:apprentice.desc=Use a tome of arcana to upgrade your wand +advancement.ebwizardry\:special_upgrade=Arcane Tinkering +advancement.ebwizardry\:special_upgrade.desc=Apply a special upgrade to a wand +advancement.ebwizardry\:advanced=Advancing Rapidly +advancement.ebwizardry\:advanced.desc=Upgrade your wand to advanced tier +advancement.ebwizardry\:master=Arcane Master +advancement.ebwizardry\:master.desc=Obtain a master wand +advancement.ebwizardry\:max_out_wand=Fully Equipped +advancement.ebwizardry\:max_out_wand.desc=Apply the maximum number of upgrades to a master wand +advancement.ebwizardry\:all_spells=Mage of All Trades +advancement.ebwizardry\:all_spells.desc=Cast every single spell in the game -container.ebwizardry:arcane_workbench=Arcane Workbench -container.ebwizardry:arcane_workbench.apply=Apply -container.ebwizardry:arcane_workbench.mana=Mana: -container.ebwizardry:arcane_workbench.upgrades=Applied Upgrades: +advancement.ebwizardry\:wizard_tower=Who Lives Here? +advancement.ebwizardry\:wizard_tower.desc=Visit a wizard's tower +advancement.ebwizardry\:wizard_trade=Magic Dealing +advancement.ebwizardry\:wizard_trade.desc=Purchase an item from a wizard +advancement.ebwizardry\:anger_wizard=You'll Regret That +advancement.ebwizardry\:anger_wizard.desc=Make a wizard angry +advancement.ebwizardry\:defeat_evil_wizard=Righteousness +advancement.ebwizardry\:defeat_evil_wizard.desc=Defeat an evil wizard +advancement.ebwizardry\:buy_master_spell=Knowledge is Power +advancement.ebwizardry\:buy_master_spell.desc=Purchase a master spell from a wizard -tier.basic=Novice +advancement.ebwizardry\:discover_spell=Trial And Error +advancement.ebwizardry\:discover_spell.desc=Identify an unknown spell by casting it and seeing what happens +advancement.ebwizardry\:identify_spell=Arcane Appraisal +advancement.ebwizardry\:identify_spell.desc=Find a more reliable way of identifying spells +advancement.ebwizardry\:spell_failure=That Backfired +advancement.ebwizardry\:spell_failure.desc=Find out the hard way how spells can go wrong +advancement.ebwizardry\:discover_master_spell=Dicing With Danger +advancement.ebwizardry\:discover_master_spell.desc=Successfully identify a master spell by trial and error + +advancement.ebwizardry\:visit_shrine=Enshrined +advancement.ebwizardry\:visit_shrine.desc=Enter a shrine and awaken its ancient magic +advancement.ebwizardry\:artefact=A Forgotten Relic +advancement.ebwizardry\:artefact.desc=Lift the protective enchantments from a shrine and claim the treasures within +advancement.ebwizardry\:all_artefacts=A Veritable Museum +advancement.ebwizardry\:all_artefacts.desc=Collect all of the rings, amulets and charms + +advancement.ebwizardry\:armour_set=Now You're a Proper Wizard +advancement.ebwizardry\:armour_set.desc=Craft and equip a full set of wizard armor +advancement.ebwizardry\:legendary=Legendary +advancement.ebwizardry\:legendary.desc=Obtain a piece of legendary wizard armor + +advancement.ebwizardry\:enchant_scroll=Scroll Up! +advancement.ebwizardry\:enchant_scroll.desc=Craft a blank scroll and enchant it with a spell at an arcane workbench + +handbook.toast.title=New Handbook Section Unlocked! + +container.ebwizardry\:arcane_workbench=Arcane Workbench +container.ebwizardry\:arcane_workbench.apply=Apply +container.ebwizardry\:arcane_workbench.mana=Mana\: +container.ebwizardry\:arcane_workbench.upgrades=Applied Upgrades\: + +tier.novice=Novice tier.apprentice=Apprentice tier.advanced=Advanced tier.master=Master -element.simple=None +element.magic=None element.fire=Fire element.ice=Ice element.lightning=Lightning @@ -288,7 +518,7 @@ element.earth=Earth element.sorcery=Sorcery element.healing=Healing -element.simple.wizard=Wizard +element.magic.wizard=Wizard element.fire.wizard=Pyromancer element.ice.wizard=Ice Mage element.lightning.wizard=Storm Mage @@ -301,323 +531,477 @@ spelltype.attack=Attack spelltype.defence=Defense spelltype.utility=Utility spelltype.minion=Minion +spelltype.buff=Buff +spelltype.construct=Construct +spelltype.projectile=Projectile +spelltype.alteration=Alteration spell.disabled=%1$s has been disabled in the config spell.resist=%1$s resisted %2$s spell.discover=Discovered the spell %1$s! -spell.ebwizardry:agility=Agility -spell.ebwizardry:arc=Arc -spell.ebwizardry:arcane_jammer=Arcane Jammer -spell.ebwizardry:arrow_rain=Arrow Rain -spell.ebwizardry:banish=Banish -spell.ebwizardry:black_hole=Black Hole -spell.ebwizardry:blink=Blink -spell.ebwizardry:blizzard=Blizzard -spell.ebwizardry:bubble=Bubble -spell.ebwizardry:chain_lightning=Chain Lightning -spell.ebwizardry:clairvoyance=Clairvoyance -spell.ebwizardry:cobwebs=Cobwebs -spell.ebwizardry:conjure_armour=Conjure Armor -spell.ebwizardry:conjure_bow=Conjure Bow -spell.ebwizardry:conjure_pickaxe=Conjure Pickaxe -spell.ebwizardry:conjure_sword=Conjure Sword -spell.ebwizardry:cure_effects=Cure Effects -spell.ebwizardry:curse_of_soulbinding=Curse of Soulbinding -spell.ebwizardry:darkness_orb=Darkness Orb -spell.ebwizardry:darkvision=Darkvision -spell.ebwizardry:dart=Dart -spell.ebwizardry:decay=Decay -spell.ebwizardry:decoy=Decoy -spell.ebwizardry:detonate=Detonate -spell.ebwizardry:diamondflesh=Diamondflesh -spell.ebwizardry:earthquake=Earthquake -spell.ebwizardry:entrapment=Entrapment -spell.ebwizardry:fireball=Fireball -spell.ebwizardry:firebolt=Firebolt -spell.ebwizardry:firebomb=Firebomb -spell.ebwizardry:fire_resistance=Fire Resistance -spell.ebwizardry:fire_sigil=Fire Sigil -spell.ebwizardry:fireskin=Fireskin -spell.ebwizardry:firestorm=Firestorm -spell.ebwizardry:flame_ray=Flame Ray -spell.ebwizardry:flaming_axe=Flaming Axe -spell.ebwizardry:flaming_weapon=Flaming Weapon -spell.ebwizardry:flight=Flight -spell.ebwizardry:font_of_mana=Font of Mana -spell.ebwizardry:font_of_vitality=Font of Vitality -spell.ebwizardry:force_arrow=Force Arrow -spell.ebwizardry:forcefield=Forcefield -spell.ebwizardry:force_orb=Force Orb -spell.ebwizardry:forests_curse=Forest's Curse -spell.ebwizardry:freeze=Freeze -spell.ebwizardry:freezing_weapon=Freezing Weapon -spell.ebwizardry:frost_axe=Frost Axe -spell.ebwizardry:frost_ray=Frost Ray -spell.ebwizardry:frost_sigil=Frost Sigil -spell.ebwizardry:glide=Glide -spell.ebwizardry:greater_fireball=Greater Fireball -spell.ebwizardry:greater_heal=Greater Heal -spell.ebwizardry:group_heal=Group Heal -spell.ebwizardry:growth_aura=Growth Aura -spell.ebwizardry:hailstorm=Hailstorm -spell.ebwizardry:heal=Heal -spell.ebwizardry:heal_ally=Heal Ally -spell.ebwizardry:healing_aura=Healing Aura -spell.ebwizardry:homing_spark=Homing Spark -spell.ebwizardry:ice_age=Ice Age -spell.ebwizardry:ice_charge=Ice Charge -spell.ebwizardry:ice_lance=Ice Lance -spell.ebwizardry:ice_shard=Ice Shard -spell.ebwizardry:ice_shroud=Ice Shroud -spell.ebwizardry:ice_spikes=Ice Spikes -spell.ebwizardry:ice_statue=Ice Statue -spell.ebwizardry:ignite=Ignite -spell.ebwizardry:imbue_weapon=Imbue Weapon -spell.ebwizardry:intimidate=Intimidate -spell.ebwizardry:invigorating_presence=Invigorating Presence -spell.ebwizardry:invisibility=Invisibility -spell.ebwizardry:invoke_weather=Invoke Weather -spell.ebwizardry:ironflesh=Ironflesh -spell.ebwizardry:leap=Leap -spell.ebwizardry:levitation=Levitation -spell.ebwizardry:life_drain=Life Drain -spell.ebwizardry:light=Light -spell.ebwizardry:lightning_arrow=Lightning Arrow -spell.ebwizardry:lightning_bolt=Lightning Bolt -spell.ebwizardry:lightning_disc=Lightning Disk -spell.ebwizardry:lightning_hammer=Lightning Hammer -spell.ebwizardry:lightning_pulse=Lightning Pulse -spell.ebwizardry:lightning_ray=Lightning Ray -spell.ebwizardry:lightning_sigil=Lightning Sigil -spell.ebwizardry:lightning_web=Lightning Web -spell.ebwizardry:magic_missile=Magic Missile -spell.ebwizardry:metamorphosis=Metamorphosis -spell.ebwizardry:meteor=Meteor -spell.ebwizardry:mind_control=Mind Control -spell.ebwizardry:mind_trick=Mind Trick -spell.ebwizardry:none=[Empty Slot] -spell.ebwizardry:oakflesh=Oakflesh -spell.ebwizardry:petrify=Petrify -spell.ebwizardry:phase_step=Phase Step -spell.ebwizardry:plague_of_darkness=Plague of Darkness -spell.ebwizardry:pocket_furnace=Pocket Furnace -spell.ebwizardry:pocket_workbench=Pocket Workbench -spell.ebwizardry:poison=Poison -spell.ebwizardry:poison_bomb=Poison Bomb -spell.ebwizardry:replenish_hunger=Replenish Hunger -spell.ebwizardry:ring_of_fire=Ring of Fire -spell.ebwizardry:shadow_ward=Shadow Ward -spell.ebwizardry:shield=Shield -spell.ebwizardry:shockwave=Shockwave -spell.ebwizardry:silverfish_swarm=Silverfish Swarm -spell.ebwizardry:sixth_sense=Sixth Sense -spell.ebwizardry:slime=Slime -spell.ebwizardry:smoke_bomb=Smoke Bomb -spell.ebwizardry:snare=Snare -spell.ebwizardry:snowball=Snowball -spell.ebwizardry:spark_bomb=Spark Bomb -spell.ebwizardry:spectral_pathway=Spectral Pathway -spell.ebwizardry:spider_swarm=Spider Swarm -spell.ebwizardry:static_aura=Static Aura -spell.ebwizardry:summon_blaze=Summon Blaze -spell.ebwizardry:summon_ice_giant=Summon Ice Giant -spell.ebwizardry:summon_ice_wraith=Summon Ice Wraith -spell.ebwizardry:summon_iron_golem=Summon Iron Golem -spell.ebwizardry:summon_lightning_wraith=Summon Lightning Wraith -spell.ebwizardry:summon_phoenix=Summon Phoenix -spell.ebwizardry:summon_shadow_wraith=Summon Shadow Wraith -spell.ebwizardry:summon_skeleton=Summon Skeleton -spell.ebwizardry:summon_skeleton_legion=Summon Skeleton Legion -spell.ebwizardry:summon_snow_golem=Summon Snow Golem -spell.ebwizardry:summon_spirit_horse=Summon Spirit Horse -spell.ebwizardry:summon_spirit_wolf=Summon Spirit Wolf -spell.ebwizardry:summon_storm_elemental=Summon Storm Elemental -spell.ebwizardry:summon_wither_skeleton=Summon Wither Skeleton -spell.ebwizardry:summon_zombie=Summon Zombie -spell.ebwizardry:telekinesis=Telekinesis -spell.ebwizardry:thunderbolt=Thunderbolt -spell.ebwizardry:thunderstorm=Thunderstorm -spell.ebwizardry:tornado=Tornado -spell.ebwizardry:transience=Transience -spell.ebwizardry:transportation=Transportation -spell.ebwizardry:vanishing_box=Vanishing Box -spell.ebwizardry:wall_of_frost=Wall of Frost -spell.ebwizardry:water_breathing=Water Breathing -spell.ebwizardry:whirlwind=Whirlwind -spell.ebwizardry:wither=Wither -spell.ebwizardry:wither_skull=Wither Skull +spell.ebwizardry\:agility=Agility +spell.ebwizardry\:arc=Arc +spell.ebwizardry\:arcane_jammer=Arcane Jammer +spell.ebwizardry\:arcane_lock=Arcane Lock +spell.ebwizardry\:arrow_rain=Arrow Rain +spell.ebwizardry\:banish=Banish +spell.ebwizardry\:black_hole=Black Hole +spell.ebwizardry\:blink=Blink +spell.ebwizardry\:blizzard=Blizzard +spell.ebwizardry\:bubble=Bubble +spell.ebwizardry\:chain_lightning=Chain Lightning +spell.ebwizardry\:charge=Charge +spell.ebwizardry\:clairvoyance=Clairvoyance +spell.ebwizardry\:cobwebs=Cobwebs +spell.ebwizardry\:combustion_rune=Combustion Rune +spell.ebwizardry\:conjure_armour=Conjure Armor +spell.ebwizardry\:conjure_block=Conjure Block +spell.ebwizardry\:conjure_bow=Conjure Bow +spell.ebwizardry\:conjure_pickaxe=Conjure Pickaxe +spell.ebwizardry\:conjure_sword=Conjure Sword +spell.ebwizardry\:containment=Containment +spell.ebwizardry\:cure_effects=Cure Effects +spell.ebwizardry\:curse_of_enfeeblement=Curse of Enfeeblement +spell.ebwizardry\:curse_of_soulbinding=Curse of Soulbinding +spell.ebwizardry\:curse_of_undeath=Curse of Undeath +spell.ebwizardry\:darkness_orb=Darkness Orb +spell.ebwizardry\:darkvision=Darkvision +spell.ebwizardry\:dart=Dart +spell.ebwizardry\:decay=Decay +spell.ebwizardry\:decoy=Decoy +spell.ebwizardry\:detonate=Detonate +spell.ebwizardry\:diamondflesh=Diamondflesh +spell.ebwizardry\:disintegration=Disintegration +spell.ebwizardry\:divination=Divination +spell.ebwizardry\:dragon_fireball=Dragon Fireball +spell.ebwizardry\:earthquake=Earthquake +spell.ebwizardry\:empowering_presence=Empowering Presence +spell.ebwizardry\:entrapment=Entrapment +spell.ebwizardry\:evade=Evade +spell.ebwizardry\:fireball=Fireball +spell.ebwizardry\:firebolt=Firebolt +spell.ebwizardry\:firebomb=Firebomb +spell.ebwizardry\:fire_resistance=Fire Resistance +spell.ebwizardry\:fire_sigil=Fire Sigil +spell.ebwizardry\:fireskin=Fireskin +spell.ebwizardry\:fire_breath=Fire Breath +spell.ebwizardry\:flame_ray=Flame Ray +spell.ebwizardry\:flaming_axe=Flaming Axe +spell.ebwizardry\:flaming_weapon=Flaming Weapon +spell.ebwizardry\:flight=Flight +spell.ebwizardry\:font_of_mana=Font of Mana +spell.ebwizardry\:font_of_vitality=Font of Vitality +spell.ebwizardry\:force_arrow=Force Arrow +spell.ebwizardry\:forcefield=Forcefield +spell.ebwizardry\:force_orb=Force Orb +spell.ebwizardry\:forests_curse=Forest's Curse +spell.ebwizardry\:forest_of_thorns=Forest of Thorns +spell.ebwizardry\:freeze=Freeze +spell.ebwizardry\:freezing_weapon=Freezing Weapon +spell.ebwizardry\:frost_axe=Frost Axe +spell.ebwizardry\:frost_ray=Frost Ray +spell.ebwizardry\:frost_sigil=Frost Sigil +spell.ebwizardry\:frost_step=Frost Step +spell.ebwizardry\:glide=Glide +spell.ebwizardry\:grapple=Grapple +spell.ebwizardry\:greater_fireball=Greater Fireball +spell.ebwizardry\:greater_heal=Greater Heal +spell.ebwizardry\:greater_telekinesis=Greater Telekinesis +spell.ebwizardry\:greater_ward=Greater Ward +spell.ebwizardry\:group_heal=Group Heal +spell.ebwizardry\:growth_aura=Growth Aura +spell.ebwizardry\:hailstorm=Hailstorm +spell.ebwizardry\:heal=Heal +spell.ebwizardry\:heal_ally=Heal Ally +spell.ebwizardry\:healing_aura=Healing Aura +spell.ebwizardry\:homing_spark=Homing Spark +spell.ebwizardry\:iceball=Iceball +spell.ebwizardry\:ice_age=Ice Age +spell.ebwizardry\:ice_charge=Ice Charge +spell.ebwizardry\:ice_lance=Ice Lance +spell.ebwizardry\:ice_shard=Ice Shard +spell.ebwizardry\:ice_shroud=Ice Shroud +spell.ebwizardry\:ice_spikes=Ice Spikes +spell.ebwizardry\:ice_statue=Ice Statue +spell.ebwizardry\:ignite=Ignite +spell.ebwizardry\:imbue_weapon=Imbue Weapon +spell.ebwizardry\:intimidate=Intimidate +spell.ebwizardry\:invigorating_presence=Invigorating Presence +spell.ebwizardry\:invisibility=Invisibility +spell.ebwizardry\:invoke_weather=Invoke Weather +spell.ebwizardry\:ironflesh=Ironflesh +spell.ebwizardry\:leap=Leap +spell.ebwizardry\:levitation=Levitation +spell.ebwizardry\:life_drain=Life Drain +spell.ebwizardry\:light=Light +spell.ebwizardry\:lightning_arrow=Lightning Arrow +spell.ebwizardry\:lightning_bolt=Lightning Bolt +spell.ebwizardry\:lightning_disc=Lightning Disk +spell.ebwizardry\:lightning_hammer=Lightning Hammer +spell.ebwizardry\:lightning_pulse=Lightning Pulse +spell.ebwizardry\:lightning_ray=Lightning Ray +spell.ebwizardry\:lightning_sigil=Lightning Sigil +spell.ebwizardry\:lightning_web=Lightning Web +spell.ebwizardry\:magic_missile=Magic Missile +spell.ebwizardry\:metamorphosis=Metamorphosis +spell.ebwizardry\:meteor=Meteor +spell.ebwizardry\:mind_control=Mind Control +spell.ebwizardry\:mind_trick=Mind Trick +spell.ebwizardry\:mine=Mine +spell.ebwizardry\:muffle=Muffle +spell.ebwizardry\:none=[Empty Slot] +spell.ebwizardry\:oakflesh=Oakflesh +spell.ebwizardry\:paralysis=Paralysis +spell.ebwizardry\:petrify=Petrify +spell.ebwizardry\:phase_step=Phase Step +spell.ebwizardry\:plague_of_darkness=Plague of Darkness +spell.ebwizardry\:pocket_furnace=Pocket Furnace +spell.ebwizardry\:pocket_workbench=Pocket Workbench +spell.ebwizardry\:poison=Poison +spell.ebwizardry\:poison_bomb=Poison Bomb +spell.ebwizardry\:possession=Possession +spell.ebwizardry\:ray_of_purification=Ray of Purification +spell.ebwizardry\:remove_curse=Remove Curse +spell.ebwizardry\:replenish_hunger=Replenish Hunger +spell.ebwizardry\:resurrection=Resurrection +spell.ebwizardry\:reversal=Reversal +spell.ebwizardry\:ring_of_fire=Ring of Fire +spell.ebwizardry\:satiety=Satiety +spell.ebwizardry\:shadow_ward=Shadow Ward +spell.ebwizardry\:shield=Shield +spell.ebwizardry\:shockwave=Shockwave +spell.ebwizardry\:shulker_bullet=Shulker Bullet +spell.ebwizardry\:silverfish_swarm=Silverfish Swarm +spell.ebwizardry\:sixth_sense=Sixth Sense +spell.ebwizardry\:slime=Slime +spell.ebwizardry\:slow_time=Slow Time +spell.ebwizardry\:smoke_bomb=Smoke Bomb +spell.ebwizardry\:snare=Snare +spell.ebwizardry\:snowball=Snowball +spell.ebwizardry\:spark_bomb=Spark Bomb +spell.ebwizardry\:spectral_pathway=Spectral Pathway +spell.ebwizardry\:speed_time=Speed Time +spell.ebwizardry\:spider_swarm=Spider Swarm +spell.ebwizardry\:static_aura=Static Aura +spell.ebwizardry\:summon_blaze=Summon Blaze +spell.ebwizardry\:summon_ice_giant=Summon Ice Giant +spell.ebwizardry\:summon_ice_wraith=Summon Ice Wraith +spell.ebwizardry\:summon_iron_golem=Summon Iron Golem +spell.ebwizardry\:summon_lightning_wraith=Summon Lightning Wraith +spell.ebwizardry\:summon_phoenix=Summon Phoenix +spell.ebwizardry\:summon_shadow_wraith=Summon Shadow Wraith +spell.ebwizardry\:summon_skeleton=Summon Skeleton +spell.ebwizardry\:summon_skeleton_legion=Summon Skeleton Legion +spell.ebwizardry\:summon_snow_golem=Summon Snow Golem +spell.ebwizardry\:summon_spirit_horse=Summon Spirit Horse +spell.ebwizardry\:summon_spirit_wolf=Summon Spirit Wolf +spell.ebwizardry\:summon_storm_elemental=Summon Storm Elemental +spell.ebwizardry\:summon_wither_skeleton=Summon Wither Skeleton +spell.ebwizardry\:summon_zombie=Summon Zombie +spell.ebwizardry\:telekinesis=Telekinesis +spell.ebwizardry\:thunderbolt=Thunderbolt +spell.ebwizardry\:thunderstorm=Thunderstorm +spell.ebwizardry\:tornado=Tornado +spell.ebwizardry\:transience=Transience +spell.ebwizardry\:transportation=Transportation +spell.ebwizardry\:vanishing_box=Vanishing Box +spell.ebwizardry\:vex_swarm=Vex Swarm +spell.ebwizardry\:wall_of_frost=Wall of Frost +spell.ebwizardry\:ward=Ward +spell.ebwizardry\:water_breathing=Water Breathing +spell.ebwizardry\:whirlwind=Whirlwind +spell.ebwizardry\:wither=Wither +spell.ebwizardry\:wither_skull=Wither Skull -spell.ebwizardry:agility.desc=Grants the caster faster movement speed and greater jump height for 30 seconds. -spell.ebwizardry:arc.desc=Fires a spark of lightning at the target. -spell.ebwizardry:arcane_jammer.desc=Prevents the target from using magic for 15 seconds. -spell.ebwizardry:arrow_rain.desc="Archers, fire!" -spell.ebwizardry:banish.desc=Teleports the target against its will to a random location within a certain range. -spell.ebwizardry:black_hole.desc=Tear reality asunder. -spell.ebwizardry:blink.desc=Teleports the caster over a short distance to where they are pointing. -spell.ebwizardry:blizzard.desc=Creates a zone of swirling icy wind which slows and continually damages anything trapped inside. The caster is immune to the damage but is still slowed. -spell.ebwizardry:bubble.desc=Fires a jet of bubbles which causes anything it hits to float upwards helplessly. The target will fall after a certain time or if it is damaged. -spell.ebwizardry:chain_lightning.desc=Fires a spark of lightning at the target, which then chains to additional targets up to twice. -spell.ebwizardry:clairvoyance.desc=Reveals the path to a remembered location. With this spell selected, sneak-right-click on a block to set the location. Cast this spell normally to reveal the path. The path will fade after 90 seconds. -spell.ebwizardry:cobwebs.desc=Creates cobwebs where you are pointing, which greatly hamper the movement of any creatures caught amongst them. The cobwebs will vanish after 20 seconds or if broken. -spell.ebwizardry:conjure_armour.desc=Creates spectral armor around the caster which offers protection equal to that of iron armor. The armor lasts for 60 seconds. The caster must have an empty armor slot. -spell.ebwizardry:conjure_bow.desc=Creates a spectral bow with unlimited arrows that lasts for 30 seconds. -spell.ebwizardry:conjure_pickaxe.desc=Creates a spectral pickaxe of equal strength to an iron pickaxe that lasts for 30 seconds. -spell.ebwizardry:conjure_sword.desc=Creates a spectral sword of equal strength to an iron sword that lasts for 30 seconds. -spell.ebwizardry:cure_effects.desc=Removes all potion effects currently affecting the caster, good or bad. -spell.ebwizardry:curse_of_soulbinding.desc=Causes the target's soul to be inextricably bound to that of the caster, meaning all damage dealt to the caster is also dealt to the victim. Lasts until either the victim or the caster dies. -spell.ebwizardry:darkness_orb.desc=Fires a slow moving bolt of dark energy in the direction you are pointing, which withers whatever it hits. -spell.ebwizardry:darkvision.desc=Grants the caster night vision for 45 seconds. -spell.ebwizardry:dart.desc=Fires a dart in the direction you are pointing which damages and weakens its target. -spell.ebwizardry:decay.desc=Creates a patch of decay on the ground which infects any creature that touches it, causing lingering damage over time and spreading more decay wherever it walks. -spell.ebwizardry:decoy.desc=Creates an illusory clone of the caster which tricks mobs into attacking it instead. The decoy will vanish after 30 seconds. -spell.ebwizardry:detonate.desc=Causes an explosion where you are pointing, damaging all nearby creatures - including the caster, if they are too close. -spell.ebwizardry:diamondflesh.desc="Your arrows are no match for me!" -spell.ebwizardry:earthquake.desc=A true master of earth magic can move mountains. -spell.ebwizardry:entrapment.desc=Traps the target in a sphere of darkness which pulls it helplessly upwards and continually damages it. -spell.ebwizardry:fireball.desc=Launches a fireball in the direction you are pointing. -spell.ebwizardry:firebolt.desc=Shoots a jet of fire a short distance in front of you. -spell.ebwizardry:firebomb.desc=Lanches a firebomb in the direction you are pointing which explodes on impact, setting targets on fire. -spell.ebwizardry:fire_resistance.desc=Grants the caster fire resistance for 30 seconds. -spell.ebwizardry:fire_sigil.desc=Places a magical fire trap on the ground which damages and sets on fire the creature that triggers it. -spell.ebwizardry:fireskin.desc=Cloaks the caster in flames for 30 seconds, causing anything that attacks them to catch fire. -spell.ebwizardry:firestorm.desc="I am the dragon." -spell.ebwizardry:flame_ray.desc=Creates a stream of flames in the direction you are pointing which sets on fire and continually damages targets. -spell.ebwizardry:flaming_axe.desc=Creates a flaming axe which sets enemies on fire when hit. Lasts for 30 seconds. -spell.ebwizardry:flaming_weapon.desc=Temporarily imbues the first weapon on the caster's hotbar with the power of flame, causing it to set fire to its victims. The magic wears off after 45 seconds. -spell.ebwizardry:flight.desc=Soar like an eagle. -spell.ebwizardry:font_of_mana.desc="We were filled with an intense magical energy appearing to emanate from the centre of the..." - Extract from the journal of a forgotten mage; the rest of the page has been burnt away. -spell.ebwizardry:font_of_vitality.desc=It feels amazing. -spell.ebwizardry:force_arrow.desc=Shoots an arrow of force in the direction you are pointing. -spell.ebwizardry:forcefield.desc=Creates a forcefield around the caster which repels creatures and deflects projectiles. -spell.ebwizardry:force_orb.desc=Launches a sphere of force which damages and repels nearby creatures on impact. -spell.ebwizardry:forests_curse.desc="How dare you enter my forest!" -spell.ebwizardry:freeze.desc=Freezes the target for 10 seconds. Will also freeze water and create snow on the ground. -spell.ebwizardry:freezing_weapon.desc=Temporarily imbues the first weapon on the caster's hotbar with the power of frost, causing it to freeze its victims. The magic wears off after 45 seconds. -spell.ebwizardry:frost_axe.desc=Creates a frozen axe which freezes enemies when hit. Lasts for 30 seconds. -spell.ebwizardry:frost_ray.desc=Creates a stream of frost in the direction you are pointing which slows and continually damages targets. -spell.ebwizardry:frost_sigil.desc=Places a magical ice trap on the ground which damages and freezes the creature that triggers it. -spell.ebwizardry:glide.desc=Allows the caster to glide downwards while in the air and holding the use item button. -spell.ebwizardry:greater_fireball.desc=Launches a large fireball in the direction you are pointing which explodes on impact. -spell.ebwizardry:greater_heal.desc=Heals the caster by 4 hearts. -spell.ebwizardry:group_heal.desc=Heals the caster and all nearby allies and summoned creatures by 3 hearts. -spell.ebwizardry:growth_aura.desc=Grows all crops near the caster. Also grows tall grass and flowers on grass. -spell.ebwizardry:hailstorm.desc=It was during the great winter of the third age that the ice mages discovered their true power. -spell.ebwizardry:heal.desc=Heals the caster by 2 hearts. -spell.ebwizardry:heal_ally.desc=Heals the target by 2 and a half hearts. -spell.ebwizardry:healing_aura.desc=Creates a zone of healing energy which regenerates the health of any ally inside it. Any undead inside the healing aura will slowly take damage. -spell.ebwizardry:homing_spark.desc=Creates a floating spark which moves towards enemies. -spell.ebwizardry:ice_age.desc="You shall be frozen for an eternity!" -spell.ebwizardry:ice_charge.desc=Launches an ice charge which explodes on impact, freezing nearby creatures and releasing shards in all directions. -spell.ebwizardry:ice_lance.desc=Fires a great spear of ice in the direction you are pointing which overpenetrates targets, damaging and freezing them in the process. -spell.ebwizardry:ice_shard.desc=Fires a shard of ice in the direction you are pointing which damages and slows targets when hit. -spell.ebwizardry:ice_shroud.desc=Creates a shroud of cold around the caster for 30 seconds, causing anything that attacks them to be frozen. -spell.ebwizardry:ice_spikes.desc=Causes razor-sharp ice spikes to rise from the ground where you are pointing, skewering any creatures caught amongst them. -spell.ebwizardry:ice_statue.desc=Freezes the target solid for 20 seconds or until broken out. The target cannot move or do anything while frozen but is also impervious to all damage. -spell.ebwizardry:ignite.desc=Sets the target on fire for 10 seconds. Also works like a flint and steel. -spell.ebwizardry:imbue_weapon.desc=Temporarily imbues the first weapon on the caster's hotbar with magic, rendering it more effective. The magic wears off after 45 seconds. -spell.ebwizardry:intimidate.desc=Emits an intimidating growl which causes nearby creatures to run away in fear. Fear stricken creatures will recover after 30 seconds. -spell.ebwizardry:invigorating_presence.desc=Grants the caster and all nearby allies increased strength for 45 seconds. -spell.ebwizardry:invisibility.desc=Makes the caster invisible for 30 seconds. -spell.ebwizardry:invoke_weather.desc=Changes the weather in the world. -spell.ebwizardry:ironflesh.desc=Greatly improves the caster's damage resistance for 30 seconds. -spell.ebwizardry:leap.desc=Causes the caster to jump upwards several blocks and slightly forward. -spell.ebwizardry:levitation.desc=Raises the caster upwards while the use item button is held. Will also negate fall damage if used before hitting the ground. -spell.ebwizardry:life_drain.desc=Creates a stream of withering energy in the direction you are pointing which drains the life of the target and uses it to gradually regenerate your health. -spell.ebwizardry:light.desc=Creates a magical point of light which illuminates the surrounding area. Lasts for 30 seconds. -spell.ebwizardry:lightning_arrow.desc=Shoots an arrow of lightning in the direction you are pointing. -spell.ebwizardry:lightning_bolt.desc=Causes lightning to strike where you are pointing. -spell.ebwizardry:lightning_disc.desc=Sends a disk of lightning flying off in the direction you are pointing, which seeks targets. -spell.ebwizardry:lightning_hammer.desc="I smite you by the wrath of the heavens!" -spell.ebwizardry:lightning_pulse.desc=Charges the ground around the caster with lightning, damaging and repelling nearby creatures. -spell.ebwizardry:lightning_ray.desc=Creates a stream of lightning in the direction you are pointing which continually damages targets. -spell.ebwizardry:lightning_sigil.desc=Places a magical lightning trap on the ground which damages the creature that triggers it and chains lightning to other nearby creatures. -spell.ebwizardry:lightning_web.desc="Focus. Channel the storm in your mind through your wand and unleash its fury." -spell.ebwizardry:magic_missile.desc=Fires a bolt of magical energy in the direction you are pointing. -spell.ebwizardry:metamorphosis.desc=Changes the target into another form. Only works on some creatures. -spell.ebwizardry:meteor.desc=Some wizards just want to see the world burn... -spell.ebwizardry:mind_control.desc=Takes control of the target's mind for 30 seconds, causing it switch sides and fight for the caster instead. Will not work on creatures that are too strong-willed. -spell.ebwizardry:mind_trick.desc=Confuses and disorients the target for 15 seconds, rendering it unable to attack effectively. The effect will be dispelled if the target takes damage. -spell.ebwizardry:none.desc=To get a spell book with the /give command, use metadata: /give [player] ebwizardry:spell_book 1 [spell id] (if you found this book in a chest, some other mod has messed things up). -spell.ebwizardry:oakflesh.desc=Improves the caster's damage resistance for 30 seconds. -spell.ebwizardry:petrify.desc=Turns the target to stone until broken out, with a chance for it to break out when it is dark. The target cannot move or do anything while petrified but is also impervious to all damage. -spell.ebwizardry:phase_step.desc=Teleports the caster through a 1 block thick wall in front of them. Range upgrades will increase the thickness you can teleport through. -spell.ebwizardry:plague_of_darkness.desc=The darkness will consume them all... -spell.ebwizardry:pocket_furnace.desc=Smelts up to 5 smeltable items in the caster's inventory. Items on the hotbar will be smelted first. -spell.ebwizardry:pocket_workbench.desc=Allows the caster to craft items as if they were at a crafting table. -spell.ebwizardry:poison.desc=Fires poison in the direction you are pointing. -spell.ebwizardry:poison_bomb.desc=Lanches a poison bomb in the direction you are pointing which explodes on impact, poisoning nearby creatures. -spell.ebwizardry:replenish_hunger.desc=Replenishes the caster's food level by 6 hunger points. -spell.ebwizardry:ring_of_fire.desc=Creates a ring of fire around the caster, damaging all nearby enemies and setting them on fire. -spell.ebwizardry:shadow_ward.desc=Creates a wall of darkness in front of the caster which causes half of all incoming damage to be inflicted upon the attacker instead. -spell.ebwizardry:shield.desc=Creates a protective barrier of force that blocks projectiles and magic. Also grants the caster a weak resistance effect. -spell.ebwizardry:shockwave.desc=Boom. -spell.ebwizardry:silverfish_swarm.desc="Ahhhh! They're MULTIPLYING!" -spell.ebwizardry:sixth_sense.desc=Allows the caster to sense the locations of nearby creatures, even through walls, for 20 seconds. -spell.ebwizardry:slime.desc=Engulfs the target in slime which slows and continually damages it. The slime bursts after 10 seconds. -spell.ebwizardry:smoke_bomb.desc=Launches a smoke bomb in the direction you are pointing which explodes on impact, releasing smoke and blinding nearby creatures for a short time. -spell.ebwizardry:snare.desc=Sets a trap on the ground which damages and briefly slows the creature that triggers it. -spell.ebwizardry:snowball.desc=Launches a snowball in the direction you are pointing. -spell.ebwizardry:spark_bomb.desc=Launches a shock charge in the direction you are pointing which releases sparks at nearby enemies on impact. -spell.ebwizardry:spectral_pathway.desc=Creates an indestructible magical bridge in front of you which extends for 15 blocks. The bridge vanishes after 60 seconds. -spell.ebwizardry:spider_swarm.desc=Summons a swarm of venomous spiders to fight for you. The spiders will disappear after 30 seconds or if they are killed. -spell.ebwizardry:static_aura.desc=Surrounds the caster with lightning for 30 seconds, firing a spark of lightning at anything that hits them. -spell.ebwizardry:summon_blaze.desc=Summons a blaze to fight for you. The blaze will disappear after 30 seconds or if it is killed. -spell.ebwizardry:summon_ice_giant.desc="Smash them!" -spell.ebwizardry:summon_ice_wraith.desc=Summons an ice wraith to fight for you. The ice wraith will disappear after 30 seconds or if it is killed. -spell.ebwizardry:summon_iron_golem.desc=Automatic automated autonomous automaton. -spell.ebwizardry:summon_lightning_wraith.desc=Summons a lightning wraith to fight for you. The lightning wraith will disappear after 30 seconds or if it is killed. -spell.ebwizardry:summon_phoenix.desc=From the ashes... -spell.ebwizardry:summon_shadow_wraith.desc=Summons a shadow wraith to fight for you. -spell.ebwizardry:summon_skeleton.desc=Summons a skeleton to fight for you. The skeleton will disappear after 30 seconds or if it is killed. -spell.ebwizardry:summon_skeleton_legion.desc="Rise, undead army!" -spell.ebwizardry:summon_snow_golem.desc=Creates a snow golem to fight for you. Lasts until the snow golem dies. -spell.ebwizardry:summon_spirit_horse.desc=Summons a spirit horse for you to ride. The spirit horse will vanish a short while after it is dismounted, or you can dismiss it by shift-right-clicking on it with any wand. -spell.ebwizardry:summon_spirit_wolf.desc=Summons a spirit wolf companion to fight for you. The spirit wolf will only disappear if it is killed, or you can dismiss it by shift-right-clicking on it with any wand. -spell.ebwizardry:summon_storm_elemental.desc="Storm Elemental: An ancient manifestation of the elements, it can hardly contain the raw power churning within it." - The Wizard's Guide to Arcane Beings, Volume I_i -spell.ebwizardry:summon_wither_skeleton.desc=Summons a wither skeleton to fight for you. The wither skeleton will disappear after 30 seconds or if it is killed. -spell.ebwizardry:summon_zombie.desc=Summons a zombie to fight for you. The zombie will disappear after 30 seconds or if it is killed. -spell.ebwizardry:telekinesis.desc=Moves an item or other small object towards you, or right-clicks the block you are looking at. Can also be used to disarm players. -spell.ebwizardry:thunderbolt.desc=Shoots a bolt of thunder which knocks back targets. -spell.ebwizardry:thunderstorm.desc="Mwahahahahahaha!" -spell.ebwizardry:tornado.desc=Unleashes a tornado in the direction you are pointing which hurls anything in its path skywards. -spell.ebwizardry:transience.desc=Makes the caster transient for 20 seconds. The caster is immune to all damage while transient but cannot break or place blocks or cause any damage. -spell.ebwizardry:transportation.desc=Transports the caster to their remembered stone circle. To use this spell, make a circle of stones of transportation, then right click it with a wand. -spell.ebwizardry:vanishing_box.desc=Grants the caster access to their ender chest storage. -spell.ebwizardry:wall_of_frost.desc=Winter at your fingertips. -spell.ebwizardry:water_breathing.desc=Allows the caster to breathe underwater for 60 seconds. -spell.ebwizardry:whirlwind.desc=Causes the target to be blown upwards and away from you at speed. -spell.ebwizardry:wither.desc=Fires a ray of darkness which withers anything it touches. -spell.ebwizardry:wither_skull.desc=Launches a wither skull in the direction you are pointing. +spell.ebwizardry\:agility.desc=Grants the caster faster movement speed and greater jump height for 30 seconds. +spell.ebwizardry\:arc.desc=Fires a spark of lightning at the target. +spell.ebwizardry\:arcane_jammer.desc=Prevents the target from using magic for 15 seconds. +spell.ebwizardry\:arcane_lock.desc=Creates an impenetrable barrier of force around a container, protecting it from being opened or destroyed. The caster and their allies may still open it, however. +spell.ebwizardry\:arrow_rain.desc="Archers, fire!" +spell.ebwizardry\:banish.desc=Teleports the target against its will to a random locations within a certain range. +spell.ebwizardry\:black_hole.desc=Tear reality asunder. +spell.ebwizardry\:blink.desc=Teleports the caster over a short distance to where they are pointing. +spell.ebwizardry\:blizzard.desc=Creates a zone of swirling icy wind which slows and continually damages anything trapped inside. The caster is immune to the damage but is still slowed. +spell.ebwizardry\:bubble.desc=Fires a jet of bubbles which causes anything it hits to float upwards helplessly. The target will fall after a certain time or if it is damaged. +spell.ebwizardry\:chain_lightning.desc=Fires a spark of lightning at the target, which then chains to additional targets up to twice. +spell.ebwizardry\:charge.desc=Causes the caster to charge rapidly in the direction they are looking, damaging and knocking back anything in their path. +spell.ebwizardry\:clairvoyance.desc=Reveals the path to a remembered locations. With this spell selected, sneak-right-click on a block to set the locations. Cast this spell normally to reveal the path. The path will fade after 90 seconds. +spell.ebwizardry\:cobwebs.desc=Creates cobwebs where you are pointing, which greatly hamper the movement of any creatures caught amongst them. The cobwebs will vanish after 20 seconds or if broken. +spell.ebwizardry\:combustion_rune.desc=Places a magical landmine on the ground where you are pointing, which explodes when stepped upon. +spell.ebwizardry\:conjure_armour.desc=Creates spectral armor around the caster which offers protection equal to that of iron armor. The armor lasts for 60 seconds. The caster must have an empty armor slot. +spell.ebwizardry\:conjure_block.desc=Conjures a spectral block where you are pointing. The spectral block disappears after 45 seconds, or you can dispel it by casting this spell at it again. +spell.ebwizardry\:conjure_bow.desc=Creates a spectral bow with unlimited arrows that lasts for 30 seconds. +spell.ebwizardry\:conjure_pickaxe.desc=Creates a spectral pickaxe of equal strength to an iron pickaxe that lasts for 30 seconds. +spell.ebwizardry\:conjure_sword.desc=Creates a spectral sword of equal strength to an iron sword that lasts for 30 seconds. +spell.ebwizardry\:containment.desc=Contains the target to within a short distance of its current position for 20 seconds. +spell.ebwizardry\:cure_effects.desc=Removes all potion effects currently affecting the caster, good or bad. +spell.ebwizardry\:curse_of_enfeeblement.desc="He was suddenly weakened, as if the life had been wrenched from within him." - Testimony of the only person known to have encountered a member of the soulwalker cult and survived. +spell.ebwizardry\:curse_of_soulbinding.desc=Causes the target's soul to be inextricably bound to that of the caster, meaning all damage dealt to the caster is also dealt to the victim. Lasts until either the victim or the caster dies. +spell.ebwizardry\:curse_of_undeath.desc=Curses the target with undeath, causing it to burn in sunlight, like zombies and skeletons. Lasts until the victim dies. Has no effect on undead creatures. +spell.ebwizardry\:darkness_orb.desc=Fires a slow moving bolt of dark energy in the direction you are pointing, which withers whatever it hits. +spell.ebwizardry\:darkvision.desc=Grants the caster night vision for 45 seconds. +spell.ebwizardry\:dart.desc=Fires a dart in the direction you are pointing which damages and weakens its target. +spell.ebwizardry\:decay.desc=Creates a patch of decay on the ground which infects any creature that touches it, causing lingering damage over time and spreading more decay wherever it walks. +spell.ebwizardry\:decoy.desc=Creates an illusory clone of the caster which tricks mobs into attacking it instead. The decoy will vanish after 30 seconds. +spell.ebwizardry\:detonate.desc=Causes an explosion where you are pointing, damaging all nearby creatures - including the caster, if they are too close. +spell.ebwizardry\:diamondflesh.desc="Your arrows are no match for me!" +spell.ebwizardry\:disintegration.desc=Shoots a powerful bolt of flame a short distance in front of you which causes targets to explode into burning embers when killed. Creatures that step on the embers will be set on fire. +spell.ebwizardry\:divination.desc=Guides the caster to nearby ores and resources. Potency will increase the chance of finding more valuable ores. +spell.ebwizardry\:dragon_fireball.desc=Launches an enderdragon fireball in the direction you are pointing, which releases lingering poisonous clouds on impact. +spell.ebwizardry\:earthquake.desc=A true master of earth magic can move mountains. +spell.ebwizardry\:empowering_presence.desc=Grants the caster and nearby allies increased magic damage for 30 seconds. +spell.ebwizardry\:entrapment.desc=Traps the target in a sphere of darkness which pulls it helplessly upwards and continually damages it. +spell.ebwizardry\:evade.desc=Causes the caster to quickly jump sideways to dodge incoming attacks. +spell.ebwizardry\:fireball.desc=Launches a fireball in the direction you are pointing. +spell.ebwizardry\:firebolt.desc=Shoots a jet of fire a short distance in front of you. +spell.ebwizardry\:firebomb.desc=Lanches a firebomb in the direction you are pointing which explodes on impact, setting targets on fire. +spell.ebwizardry\:fire_resistance.desc=Grants the caster fire resistance for 30 seconds. +spell.ebwizardry\:fire_sigil.desc=Places a magical fire trap on the ground which damages and sets on fire the creature that triggers it. +spell.ebwizardry\:fireskin.desc=Cloaks the caster in flames for 30 seconds, causing anything that attacks them to catch fire. +spell.ebwizardry\:fire_breath.desc="I am the dragon." +spell.ebwizardry\:flame_ray.desc=Creates a stream of flames in the direction you are pointing which sets on fire and continually damages targets. +spell.ebwizardry\:flaming_axe.desc=Creates a flaming axe which sets enemies on fire when hit. Lasts for 30 seconds. +spell.ebwizardry\:flaming_weapon.desc=Temporarily imbues the first weapon on the caster's hotbar with the power of flame, causing it to set fire to its victims. The magic wears off after 45 seconds. +spell.ebwizardry\:flight.desc=Soar like an eagle. +spell.ebwizardry\:font_of_mana.desc="We were filled with an intense magical energy appearing to emanate from the centre of the..." - Extract from the journal of a forgotten mage; the rest of the page has been burnt away. +spell.ebwizardry\:font_of_vitality.desc=It feels amazing. +spell.ebwizardry\:force_arrow.desc=Shoots an arrow of force in the direction you are pointing. +spell.ebwizardry\:forcefield.desc=Creates a forcefield around the caster which repels creatures and deflects projectiles. +spell.ebwizardry\:force_orb.desc=Launches a sphere of force which damages and repels nearby creatures on impact. +spell.ebwizardry\:forests_curse.desc="How dare you enter my forest!" +spell.ebwizardry\:forest_of_thorns.desc=Amidst the wood lies a hidden glade,\nIn the glade a wizard performs,\nMagical arts of an order untold,\nDeep within the forest of thorns. +spell.ebwizardry\:freeze.desc=Freezes the target for 10 seconds. Will also freeze water and create snow on the ground. +spell.ebwizardry\:freezing_weapon.desc=Temporarily imbues the first weapon on the caster's hotbar with the power of frost, causing it to freeze its victims. The magic wears off after 45 seconds. +spell.ebwizardry\:frost_axe.desc=Creates a frozen axe which freezes enemies when hit. Lasts for 30 seconds. +spell.ebwizardry\:frost_ray.desc=Creates a stream of frost in the direction you are pointing which slows and continually damages targets. +spell.ebwizardry\:frost_sigil.desc=Places a magical ice trap on the ground which damages and freezes the creature that triggers it. +spell.ebwizardry\:frost_step.desc=Allows the caster to freeze water as they walk for 30 seconds. +spell.ebwizardry\:grapple.desc=Shoots a magical vine which allows the caster to grapple towards blocks or reel in entities. Release the use item button to let go of the block or entity. +spell.ebwizardry\:glide.desc=Allows the caster to glide downwards while in the air and holding the use item button. +spell.ebwizardry\:greater_fireball.desc=Launches a large fireball in the direction you are pointing which explodes on impact. +spell.ebwizardry\:greater_heal.desc=Heals the caster by 4 hearts. +spell.ebwizardry\:greater_telekinesis.desc=Allows the caster to pick up a block or creature and hold it in the air for as long as the use item button is pressed. Sneaking whilst holding a block or creature will throw it a short distance. +spell.ebwizardry\:greater_ward.desc=Grants the caster a strong shielding effect that greatly reduces incoming magic damage for 30 seconds. +spell.ebwizardry\:group_heal.desc=Heals the caster and all nearby allies and summoned creatures by 3 hearts. +spell.ebwizardry\:growth_aura.desc=Grows all crops near the caster. Also grows tall grass and flowers on grass. +spell.ebwizardry\:hailstorm.desc=It was during the great winter of the third age that the ice mages discovered their true power. +spell.ebwizardry\:heal.desc=Heals the caster by 2 hearts. +spell.ebwizardry\:heal_ally.desc=Heals the target by 2 and a half hearts. +spell.ebwizardry\:healing_aura.desc=Creates a zone of healing energy which regenerates the health of any ally inside it. Any undead inside the healing aura will slowly take damage. +spell.ebwizardry\:homing_spark.desc=Creates a floating spark which moves towards enemies. +spell.ebwizardry\:iceball.desc=Launches an iceball in the direction you are pointing. +spell.ebwizardry\:ice_age.desc="You shall be frozen for an eternity!" +spell.ebwizardry\:ice_charge.desc=Launches an ice charge which explodes on impact, freezing nearby creatures and releasing shards in all directions. +spell.ebwizardry\:ice_lance.desc=Fires a great spear of ice in the direction you are pointing which overpenetrates targets, damaging and freezing them in the process. +spell.ebwizardry\:ice_shard.desc=Fires a shard of ice in the direction you are pointing which damages and slows targets when hit. +spell.ebwizardry\:ice_shroud.desc=Creates a shroud of cold around the caster for 30 seconds, causing anything that attacks them to be frozen. +spell.ebwizardry\:ice_spikes.desc=Causes razor-sharp ice spikes to rise from the ground where you are pointing, skewering any creatures caught amongst them. +spell.ebwizardry\:ice_statue.desc=Freezes the target solid for 20 seconds or until broken out. The target cannot move or do anything while frozen but is also impervious to all damage. +spell.ebwizardry\:ignite.desc=Sets the target on fire for 10 seconds. Also works like a flint and steel. +spell.ebwizardry\:imbue_weapon.desc=Temporarily imbues the first weapon on the caster's hotbar with magic, rendering it more effective. The magic wears off after 45 seconds. +spell.ebwizardry\:intimidate.desc=Emits an intimidating growl which causes nearby creatures to run away in fear. Fear stricken creatures will recover after 30 seconds. +spell.ebwizardry\:invigorating_presence.desc=Grants the caster and all nearby allies increased strength for 45 seconds. +spell.ebwizardry\:invisibility.desc=Makes the caster invisible for 30 seconds. +spell.ebwizardry\:invoke_weather.desc=Changes the weather in the world. +spell.ebwizardry\:ironflesh.desc=Greatly improves the caster's damage resistance for 30 seconds. +spell.ebwizardry\:leap.desc=Causes the caster to jump upwards several blocks and slightly forward. +spell.ebwizardry\:levitation.desc=Raises the caster upwards while the use item button is held. Will also negate fall damage if used before hitting the ground. +spell.ebwizardry\:life_drain.desc=Creates a stream of withering energy in the direction you are pointing which drains the life of the target and uses it to gradually regenerate your health. +spell.ebwizardry\:light.desc=Creates a magical point of light which illuminates the surrounding area. Lasts for 30 seconds. +spell.ebwizardry\:lightning_arrow.desc=Shoots an arrow of lightning in the direction you are pointing. +spell.ebwizardry\:lightning_bolt.desc=Causes lightning to strike where you are pointing. +spell.ebwizardry\:lightning_disc.desc=Sends a disk of lightning flying off in the direction you are pointing, which seeks targets. +spell.ebwizardry\:lightning_hammer.desc="I smite you by the wrath of the heavens!" +spell.ebwizardry\:lightning_pulse.desc=Charges the ground around the caster with lightning, damaging and repelling nearby creatures. +spell.ebwizardry\:lightning_ray.desc=Creates a stream of lightning in the direction you are pointing which continually damages targets. +spell.ebwizardry\:lightning_sigil.desc=Places a magical lightning trap on the ground which damages the creature that triggers it and chains lightning to other nearby creatures. +spell.ebwizardry\:lightning_web.desc="Focus. Channel the storm in your mind through your wand and unleash its fury." +spell.ebwizardry\:magic_missile.desc=Fires a bolt of magical energy in the direction you are pointing. +spell.ebwizardry\:metamorphosis.desc=Changes the target into another form. Only works on some creatures. +spell.ebwizardry\:meteor.desc=Some wizards just want to see the world burn... +spell.ebwizardry\:mind_control.desc=Takes control of the target's mind for 30 seconds, causing it switch sides and fight for the caster instead. Will not work on creatures that are too strong-willed. +spell.ebwizardry\:mind_trick.desc=Confuses and disorients the target for 15 seconds, rendering it unable to attack effectively. The effect will be dispelled if the target takes damage. +spell.ebwizardry\:mine.desc=Breaks the block the caster is looking at. Potency will allow harder blocks to be broken. +spell.ebwizardry\:muffle.desc=Silences any sounds made by the caster for 30 seconds. When muffled, mobs can only detect you when looking towards you. +spell.ebwizardry\:none.desc=To get a spell book with the /give command, use id\: /give [player] ebwizardry\:spell_book 1 [spell id] (if you found this book in a chest, some other mod has messed things up). +spell.ebwizardry\:oakflesh.desc=Improves the caster's damage resistance for 30 seconds. +spell.ebwizardry\:paralysis.desc=Delivers a powerful lightning bolt that paralyses targets for 5 seconds. Paralysed creatures cannot move and will still take damage - but too much will snap the creature out of paralysis. +spell.ebwizardry\:petrify.desc=Turns the target to stone until broken out, with a chance for it to break out when it is dark. The target cannot move or do anything while petrified but is also impervious to all damage. +spell.ebwizardry\:phase_step.desc=Teleports the caster a short distance in front of them, including through walls. Range upgrades will increase the wall thickness you can teleport through. +spell.ebwizardry\:plague_of_darkness.desc=The darkness will consume them all... +spell.ebwizardry\:pocket_furnace.desc=Smelts up to 5 smeltable items in the caster's inventory. Items on the hotbar will be smelted first. +spell.ebwizardry\:pocket_workbench.desc=Allows the caster to craft items as if they were at a crafting table. +spell.ebwizardry\:poison.desc=Fires poison in the direction you are pointing. +spell.ebwizardry\:poison_bomb.desc=Lanches a poison bomb in the direction you are pointing which explodes on impact, poisoning nearby creatures. +spell.ebwizardry\:possession.desc="Become thy enemy." +spell.ebwizardry\:ray_of_purification.desc=Emits a ray of blinding light that damages and blinds its targets. Undead creatures take double damage and are set on fire. +spell.ebwizardry\:remove_curse.desc=Removes any curse currently affecting the caster. +spell.ebwizardry\:replenish_hunger.desc=Replenishes the caster's food level by 4 hunger points. +spell.ebwizardry\:resurrection.desc=With a master healer by your side, being dead is... optional. +spell.ebwizardry\:reversal.desc=Removes a random negative potion effect and inflicts it upon the target, which will suffer that effect for the remaining duration. Potency increases the number of effects that are reversed. +spell.ebwizardry\:ring_of_fire.desc=Creates a ring of fire around the caster, damaging all nearby enemies and setting them on fire. +spell.ebwizardry\:satiety.desc=Replenishes the caster's food level by 8 hunger points. +spell.ebwizardry\:shadow_ward.desc=Creates a wall of darkness in front of the caster which causes half of all incoming damage to be inflicted upon the attacker instead. +spell.ebwizardry\:shield.desc=Creates a protective barrier of force that blocks projectiles and magic. Also grants the caster a weak resistance effect. +spell.ebwizardry\:shockwave.desc=Boom. +spell.ebwizardry\:shulker_bullet.desc=Shoots a shulker bullet which seeks targets and causes them to levitate when hit. +spell.ebwizardry\:silverfish_swarm.desc="Ahhhh! They're MULTIPLYING!" +spell.ebwizardry\:sixth_sense.desc=Allows the caster to sense the locations of nearby creatures, even through walls, for 20 seconds. +spell.ebwizardry\:slime.desc=Engulfs the target in slime which slows and continually damages it. The slime bursts after 10 seconds. +spell.ebwizardry\:slow_time.desc=Chronomancy is the art of manipulating time itself to fit one's needs. It was widely believed to be lost in the past... until now. +spell.ebwizardry\:smoke_bomb.desc=Launches a smoke bomb in the direction you are pointing which explodes on impact, releasing smoke and blinding nearby creatures for a short time. +spell.ebwizardry\:snare.desc=Sets a trap on the ground which damages and briefly slows the creature that triggers it. +spell.ebwizardry\:snowball.desc=Launches a snowball in the direction you are pointing. +spell.ebwizardry\:spark_bomb.desc=Launches a shock charge in the direction you are pointing which releases sparks at nearby enemies on impact. +spell.ebwizardry\:spectral_pathway.desc=Creates an indestructible magical bridge in front of you which extends for 15 blocks. The bridge vanishes after 60 seconds. +spell.ebwizardry\:speed_time.desc=...day, night, dawn, dusk, sunrise and sunset\: thus is the passage of time, which traps us in an endless cycle of... +spell.ebwizardry\:spider_swarm.desc=Summons a swarm of venomous spiders to fight for you. The spiders will disappear after 30 seconds or if they are killed. +spell.ebwizardry\:static_aura.desc=Surrounds the caster with lightning for 30 seconds, firing a spark of lightning at anything that hits them. +spell.ebwizardry\:summon_blaze.desc=Summons a blaze to fight for you. The blaze will disappear after 30 seconds or if it is killed. +spell.ebwizardry\:summon_ice_giant.desc="Smash them!" +spell.ebwizardry\:summon_ice_wraith.desc=Summons an ice wraith to fight for you. The ice wraith will disappear after 30 seconds or if it is killed. +spell.ebwizardry\:summon_iron_golem.desc=Automatic automated autonomous automaton. +spell.ebwizardry\:summon_lightning_wraith.desc=Summons a lightning wraith to fight for you. The lightning wraith will disappear after 30 seconds or if it is killed. +spell.ebwizardry\:summon_phoenix.desc=From the ashes... +spell.ebwizardry\:summon_shadow_wraith.desc=Summons a shadow wraith to fight for you. +spell.ebwizardry\:summon_skeleton.desc=Summons a skeleton to fight for you. The skeleton will disappear after 30 seconds or if it is killed. +spell.ebwizardry\:summon_skeleton_legion.desc="Rise, undead army!" +spell.ebwizardry\:summon_snow_golem.desc=Creates a snow golem to fight for you. Lasts until the snow golem dies. +spell.ebwizardry\:summon_spirit_horse.desc=Summons a spirit horse for you to ride. The spirit horse will vanish a short while after it is dismounted, or you can dismiss it by shift-right-clicking on it with any wand. +spell.ebwizardry\:summon_spirit_wolf.desc=Summons a spirit wolf companion to fight for you. The spirit wolf will only disappear if it is killed, or you can dismiss it by shift-right-clicking on it with any wand. +spell.ebwizardry\:summon_storm_elemental.desc="Storm Elemental\: An ancient manifestation of the elements, it can hardly contain the raw power churning within it." - The Wizard's Guide to Arcane Beings, Volume II +spell.ebwizardry\:summon_wither_skeleton.desc=Summons a wither skeleton to fight for you. The wither skeleton will disappear after 30 seconds or if it is killed. +spell.ebwizardry\:summon_zombie.desc=Summons a zombie to fight for you. The zombie will disappear after 30 seconds or if it is killed. +spell.ebwizardry\:telekinesis.desc=Moves an item or other small object towards you, or right-clicks the block you are looking at. Can also be used to disarm players. +spell.ebwizardry\:thunderbolt.desc=Shoots a bolt of thunder which knocks back targets. +spell.ebwizardry\:thunderstorm.desc="Mwahahahahahaha!" +spell.ebwizardry\:tornado.desc=Unleashes a tornado in the direction you are pointing which hurls anything in its path skywards. +spell.ebwizardry\:transience.desc=Makes the caster transient for 20 seconds. The caster is immune to all damage while transient but cannot break or place blocks or cause any damage. +spell.ebwizardry\:transportation.desc=Transports the caster to their remembered stone circle. To use this spell, make a circle of stones of transportation, then right click it with a wand. +spell.ebwizardry\:vanishing_box.desc=Grants the caster access to their ender chest storage. +spell.ebwizardry\:vex_swarm.desc=Summons a swarm of flying vexes to fight for you. The vexes will disappear after 30 seconds or if they are killed. +spell.ebwizardry\:wall_of_frost.desc=Winter at your fingertips. +spell.ebwizardry\:ward.desc=Grants the caster a shielding effect that reduces incoming magic damage for 30 seconds. +spell.ebwizardry\:water_breathing.desc=Allows the caster to breathe underwater for 60 seconds. +spell.ebwizardry\:whirlwind.desc=Causes the target to be blown upwards and away from you at speed. +spell.ebwizardry\:wither.desc=Fires a ray of darkness which withers anything it touches. +spell.ebwizardry\:wither_skull.desc=Launches a wither skull in the direction you are pointing. -spell.ebwizardry:invoke_weather.sun=The rain begins to stop... -spell.ebwizardry:invoke_weather.rain=The heavens open... -spell.ebwizardry:transportation.missing=Your remembered stone circle is missing or obstructed... -spell.ebwizardry:transportation.undefined=You must remember the location of a stone circle first! -spell.ebwizardry:transportation.wrongdimension=Your remembered stone circle is in another dimension... -spell.ebwizardry:clairvoyance.searching=Searching... -spell.ebwizardry:clairvoyance.confirm=The path revealed upon casting %1$s will now lead back to this point -spell.ebwizardry:clairvoyance.outofrange=Your remembered location is too far away or inaccessible... -spell.ebwizardry:clairvoyance.undefined=You must remember a location first! -spell.ebwizardry:clairvoyance.wrongdimension=Your remembered location is in another dimension... +spell.ebwizardry\:invoke_weather.sun=The rain begins to stop... +spell.ebwizardry\:invoke_weather.rain=The heavens open... +spell.ebwizardry\:transportation.missing=The stone circle is missing or obstructed... +spell.ebwizardry\:transportation.undefined=You must remember the location of a stone circle first! +spell.ebwizardry\:transportation.wrongdimension=No remembered stone circle in this dimension... +spell.ebwizardry\:clairvoyance.searching=Searching... +spell.ebwizardry\:clairvoyance.confirm=The path revealed upon casting %1$s will now lead back to this point +spell.ebwizardry\:clairvoyance.outofrange=Your remembered locations is too far away or inaccessible... +spell.ebwizardry\:clairvoyance.undefined=You must remember a locations first! +spell.ebwizardry\:clairvoyance.wrongdimension=Your remembered locations is in another dimension... +spell.ebwizardry\:possession.insufficienthealth=You don't have enough health to possess %1$s! +spell.ebwizardry\:possession.success=Press %s to stop possessing +spell.ebwizardry\:divination.nothing=Nothing happened. +spell.ebwizardry\:divination.weak=You can just feel your wand twitching %s. +spell.ebwizardry\:divination.moderate=You feel your wand being tugged %s. +spell.ebwizardry\:divination.strong=Your wand pulls %s strongly. +spell.ebwizardry\:divination.very_strong=Your wand lurches %s sharply. +spell.ebwizardry\:divination.down=downwards +spell.ebwizardry\:divination.up=upwards +spell.ebwizardry\:divination.front=forwards +spell.ebwizardry\:divination.back=backwards +spell.ebwizardry\:divination.left=to the left +spell.ebwizardry\:divination.right=to the right +spell.ebwizardry\:resurrection.resurrect_ally=%s was resurrected by %s +spell.ebwizardry\:resurrection.resurrect_self=%s came back to life +spell.ebwizardry\:resurrection.button_wait=Resurrect (%ss) +spell.ebwizardry\:resurrection.button_ready=Resurrect -potion.ebwizardry:frost=Frostbite -potion.ebwizardry:fireskin=Fireskin -potion.ebwizardry:ice_shroud=Ice Shroud -potion.ebwizardry:static_aura=Static Aura -potion.ebwizardry:transience=Transience -potion.ebwizardry:decay=Decay -potion.ebwizardry:sixth_sense=Sixth Sense -potion.ebwizardry:arcane_jammer=Arcane Jammer -potion.ebwizardry:mind_trick=Mind Trick -potion.ebwizardry:mind_control=Mind Control -potion.ebwizardry:font_of_mana=Font of Mana -potion.ebwizardry:fear=Fear +forfeit.ebwizardry\:do_nothing=Nothing happened. -enchantment.ebwizardry:magic_sword=Imbuement -enchantment.ebwizardry:magic_bow=Imbuement -enchantment.ebwizardry:flaming_weapon=Fire Imbuement -enchantment.ebwizardry:freezing_weapon=Frost Imbuement +forfeit.ebwizardry\:burn_self=The %s bursts into flames in your hand! +forfeit.ebwizardry\:fireball=A fireball materializes in front of you! +forfeit.ebwizardry\:firebomb=A firebomb appears right above you! +forfeit.ebwizardry\:explode=A sudden explosion knocks you to the ground! +forfeit.ebwizardry\:blazes=Suddenly, hostile blazes materialize around you! +forfeit.ebwizardry\:burn_surroundings=The area around you is set ablaze! +forfeit.ebwizardry\:meteors=Fiery armageddon rains from the sky! + +forfeit.ebwizardry\:freeze_self=You feel an icy chill rush through you! +forfeit.ebwizardry\:freeze_self_2=From the %s emanates a cold so intense that it roots you to the spot! +forfeit.ebwizardry\:ice_spikes=Ice spikes rise from the ground beneath your feet! +forfeit.ebwizardry\:blizzard=You are suddenly surrounded by a raging blizzard! +forfeit.ebwizardry\:ice_wraiths=Suddenly, hostile ice wraiths materialize around you! +forfeit.ebwizardry\:hailstorm=Razor-sharp ice starts raining down upon you! +forfeit.ebwizardry\:ice_giant=A hostile ice giant materializes in front of you! + +forfeit.ebwizardry\:thunder=The scroll emits a deafening noise, knocking you to the ground! +forfeit.ebwizardry\:storm=Looks like a storm is brewing! +forfeit.ebwizardry\:lightning_sigils=Watch your step! +forfeit.ebwizardry\:lightning=You are struck by lightning! +forfeit.ebwizardry\:paralyse_self=You are paralysed! +forfeit.ebwizardry\:lightning_wraiths=Suddenly, hostile lightning wraiths materialise around you! +forfeit.ebwizardry\:storm_elementals=Hostile storm elementals materialize on all sides! + +forfeit.ebwizardry\:nausea=...huh? What just happened? Where am I? +forfeit.ebwizardry\:zombie_horde=A horde of zombies rises from the ground around you! +forfeit.ebwizardry\:wither_self=Darkness withers your soul! +forfeit.ebwizardry\:cripple_self=The %s emits a deathly howl, and you are crippled to within an inch of your life! +forfeit.ebwizardry\:shadow_wraiths=Hostile shadow wraiths materialise on all sides! + +forfeit.ebwizardry\:snares=It's a trap! +forfeit.ebwizardry\:squid=Squid! +forfeit.ebwizardry\:uproot_plants=All nearby plants are suddenly uprooted! +forfeit.ebwizardry\:poison_self=You are poisoned! +forfeit.ebwizardry\:flood=Water materialises around you! +forfeit.ebwizardry\:bury_self=The ground collapses beneath you! + +forfeit.ebwizardry\:spill_inventory=Your items spill themselves everywhere! +forfeit.ebwizardry\:teleport_self=You are instantly teleported somewhere! +forfeit.ebwizardry\:levitate_self=You begin to float upwards helplessly! +forfeit.ebwizardry\:vex_horde=A horde of vexes materializes around you! +forfeit.ebwizardry\:black_hole=A swirling vortex appears in front of you! +forfeit.ebwizardry\:arrow_rain=A barrage of arrows starts raining down upon you! + +forfeit.ebwizardry\:damage_self=Ouch! +forfeit.ebwizardry\:spill_armour=All your armour falls off! +forfeit.ebwizardry\:hunger=You suddenly feel very hungry! +forfeit.ebwizardry\:blind_self=You are blinded! +forfeit.ebwizardry\:weaken_self=You are severely weakened! +forfeit.ebwizardry\:jam_self=Your magic is rendered useless! +forfeit.ebwizardry\:curse_self=You are cursed with undeath! + +potion.ebwizardry\:frost=Frostbite +potion.ebwizardry\:fireskin=Fireskin +potion.ebwizardry\:ice_shroud=Ice Shroud +potion.ebwizardry\:static_aura=Static Aura +potion.ebwizardry\:transience=Transience +potion.ebwizardry\:decay=Decay +potion.ebwizardry\:sixth_sense=Sixth Sense +potion.ebwizardry\:arcane_jammer=Arcane Jammer +potion.ebwizardry\:mind_trick=Mind Trick +potion.ebwizardry\:mind_control=Mind Control +potion.ebwizardry\:font_of_mana=Font of Mana +potion.ebwizardry\:fear=Fear +potion.ebwizardry\:curse_of_soulbinding=Curse of Soulbinding +potion.ebwizardry\:paralysis=Paralysis +potion.ebwizardry\:muffle=Muffle +potion.ebwizardry\:ward=Ward +potion.ebwizardry\:slow_time=Slow Time +potion.ebwizardry\:empowerment=Empowerment +potion.ebwizardry\:curse_of_enfeeblement=Curse of Enfeeblement +potion.ebwizardry\:curse_of_undeath=Curse of Undeath +potion.ebwizardry\:containment=Containment +potion.ebwizardry\:frost_step=Frost Step + +enchantment.ebwizardry\:magic_sword=Imbuement +enchantment.ebwizardry\:magic_bow=Imbuement +enchantment.ebwizardry\:flaming_weapon=Fire Imbuement +enchantment.ebwizardry\:freezing_weapon=Frost Imbuement +enchantment.ebwizardry\:shocking_weapon=Lightning Imbuement + +enchantment.ebwizardry\:magic_protection=Magic Protection +enchantment.ebwizardry\:frost_protection=Frost Protection +enchantment.ebwizardry\:shock_protection=Shock Protection key.categories.ebwizardry=Wizardry @@ -627,140 +1011,268 @@ key.ebwizardry.previous_spell=Previous Spell death.attack.wizardry_magic=%1$s was killed by %2$s using magic death.attack.indirect_wizardry_magic=%1$s was killed by %2$s using magic -commands.ebwizardry:cast.usage=/%1$s [player] [damage multiplier] [range multiplier] [duration multiplier] [blast multiplier] -commands.ebwizardry:cast.success=Successfully cast %1$s -commands.ebwizardry:cast.success_continuous=Successfully cast %1$s; repeat the command to stop -commands.ebwizardry:cast.success_remote=Successfully cast %1$s as %2$s -commands.ebwizardry:cast.success_remote_continuous=Successfully cast %1$s as %2$s; repeat the command to stop -commands.ebwizardry:cast.fail=Unable to cast %1$s -commands.ebwizardry:cast.not_found=There is no such spell with ID %1$s -commands.ebwizardry:cast.tag_error=Data tag parsing failed: %s +soundCategory.ebwizardry\:spells=Spells -commands.ebwizardry:ally.usage=/%1$s [player] -commands.ebwizardry:ally.addally=%1$s has been added to %2$s's list of allies -commands.ebwizardry:ally.removeally=%1$s has been removed from %2$s's list of allies -commands.ebwizardry:ally.self=Players cannot be an ally of themselves! -commands.ebwizardry:ally.permission=You do not have permission to change other players' allies +commands.ebwizardry\:cast.usage=/%1$s [player | x y z direction] [duration] [modifiers] +commands.ebwizardry\:cast.success=Successfully cast %s +commands.ebwizardry\:cast.success_continuous=Successfully cast %s for %s seconds +commands.ebwizardry\:cast.success_remote=Successfully cast %s as %s +commands.ebwizardry\:cast.success_remote_continuous=Successfully cast %s as %s for %s seconds +commands.ebwizardry\:cast.success_position=Successfully cast %s at %s, %s, %s +commands.ebwizardry\:cast.success_position_continuous=Successfully cast %s at %s, %s, %s for %s seconds +commands.ebwizardry\:cast.fail=Unable to cast %1$s +commands.ebwizardry\:cast.not_found=There is no such spell with ID %1$s +commands.ebwizardry\:cast.invalid_direction=Invalid direction: %1$s (valid directions are: up, down, north, south, east, west) +commands.ebwizardry\:cast.tag_error=Data tag parsing failed\: %s +commands.ebwizardry\:cast.origin_not_specified=You must specify a player or location to cast the spell from +commands.ebwizardry\:cast.duration_not_specified=You must specify a duration for this spell -commands.ebwizardry:allies.usage=/%1$s [player] -commands.ebwizardry:allies.list=Players allied to you: %1$s -commands.ebwizardry:allies.list_other=Players allied to %1$s: %2$s -commands.ebwizardry:allies.permission=You do not have permission to view other players' allies -commands.ebwizardry:allies.none=None +commands.ebwizardry\:ally.usage=/%1$s [player] +commands.ebwizardry\:ally.addally=%1$s has been added to %2$s's list of allies +commands.ebwizardry\:ally.removeally=%1$s has been removed from %2$s's list of allies +commands.ebwizardry\:ally.self=Players cannot be an ally of themselves! +commands.ebwizardry\:ally.permission=You do not have permission to change other players' allies -commands.ebwizardry:discoverspell.usage=/%1$s [player] -commands.ebwizardry:discoverspell.not_found=There is no such spell with ID %1$s -commands.ebwizardry:discoverspell.clear=Cleared all spell discovery data for %1$s -commands.ebwizardry:discoverspell.all=Added all spells to %1$s's spell discovery data -commands.ebwizardry:discoverspell.addspell=Added %1$s to %2$s's spell discovery data -commands.ebwizardry:discoverspell.removespell=Removed %1$s from %2$s's spell discovery data +commands.ebwizardry\:allies.usage=/%1$s [player] +commands.ebwizardry\:allies.list=Players allied to you\: %1$s +commands.ebwizardry\:allies.list_other=Players allied to %1$s\: %2$s +commands.ebwizardry\:allies.permission=You do not have permission to view other players' allies +commands.ebwizardry\:allies.none=None + +commands.ebwizardry\:discoverspell.usage=/%1$s [player] +commands.ebwizardry\:discoverspell.not_found=There is no such spell with ID %1$s +commands.ebwizardry\:discoverspell.clear=Cleared all spell discovery data for %1$s +commands.ebwizardry\:discoverspell.all=Added all spells to %1$s's spell discovery data +commands.ebwizardry\:discoverspell.addspell=Added %1$s to %2$s's spell discovery data +commands.ebwizardry\:discoverspell.removespell=Removed %1$s from %2$s's spell discovery data config.ebwizardry.title.general=Mod Options +config.ebwizardry.generic.true=Enabled +config.ebwizardry.generic.false=Disabled + +config.ebwizardry.category.spells=Spell Configuration +config.ebwizardry.category.spells.tooltip=Select which spells are enabled +config.ebwizardry.title.spells=Spell Configuration +config.ebwizardry.subtitle.spells=Disabling a spell globally here will override the finer controls in the spell JSON file. + config.ebwizardry.category.gameplay=Gameplay Settings config.ebwizardry.category.gameplay.tooltip=Configure wizardry's general gameplay config.ebwizardry.title.gameplay=Gameplay Settings config.ebwizardry.subtitle.gameplay=Global settings that affect game mechanics. +config.ebwizardry.discovery_mode=Discovery Mode +config.ebwizardry.discovery_mode.tooltip=For those who like a sense of mystery! When enabled, spells you haven't cast yet will be unreadable until you cast them (on a per-world basis). Has no effect when in creative mode. Spells of identification will be unobtainable in survival mode if this is disabled. +config.ebwizardry.legacy_wand_levelling=Legacy Wand Levelling +config.ebwizardry.legacy_wand_levelling.tooltip=Controls whether wands are required to gain progression before they can be upgraded to the next tier. Enable this option to revert to the pre-4.2 system, which only requires tomes of arcana. Wands will still gain progression silently when this is enabled, so if you go back to the new system you won't lose any progress. +config.ebwizardry.legacy_wand_levelling.true=Yes - I liked it how it was! +config.ebwizardry.legacy_wand_levelling.false=No - Level me up! +config.ebwizardry.friendly_fire=Friendly Fire +config.ebwizardry.friendly_fire.tooltip=Controls which creatures may be damaged by your magic when allied to you. Your spells will not target your allies or creatures summoned/owned by them regardless of this setting, but this setting makes them completely immune if disabled. +config.ebwizardry.minion_revenge_targeting=Minion Revenge Targeting +config.ebwizardry.minion_revenge_targeting.tooltip=Whether summoned creatures can revenge-attack players or creatures that they would not otherwise be able to attack. +config.ebwizardry.minion_revenge_targeting.true=Yes - I'd never hurt them! +config.ebwizardry.minion_revenge_targeting.false=No - they must always obey me! +config.ebwizardry.players_move_each_other=Players Move Each Other +config.ebwizardry.players_move_each_other.tooltip=Whether to allow players to move other players around using magic. +config.ebwizardry.players_move_each_other.true=Yes - let the games begin! +config.ebwizardry.players_move_each_other.false=No - I won't be pushed around +config.ebwizardry.player_block_damage=Player Block Damage +config.ebwizardry.player_block_damage.tooltip=Whether spells cast by players can destroy blocks in the world. Disable this to prevent griefing. To prevent non-players from destroying blocks with magic, use the mobGriefing gamerule. +config.ebwizardry.player_block_damage.true=Yes - kaboom! +config.ebwizardry.player_block_damage.false=No - activate anti-grief (TM) +config.ebwizardry.telekinetic_disarmament=Telekinetic Disarmament +config.ebwizardry.telekinetic_disarmament.tooltip=Whether to allow players to disarm other players using the telekinesis spell. Disable to prevent stealing of items. +config.ebwizardry.telekinetic_disarmament.true=Yes - let people steal things +config.ebwizardry.telekinetic_disarmament.false=No - that's cheating! +config.ebwizardry.teleport_through_unbreakable_blocks=Teleport Through Unbreakable Blocks +config.ebwizardry.teleport_through_unbreakable_blocks.tooltip=Whether players are allowed to teleport through unbreakable blocks (e.g. bedrock) using the phase step spell. +config.ebwizardry.teleport_through_unbreakable_blocks.true=Yes - I wish to see the void! +config.ebwizardry.teleport_through_unbreakable_blocks.false=No - bedrock is impenetrable +config.ebwizardry.world_time_manipulation=World Time Manipulation +config.ebwizardry.world_time_manipulation.tooltip=Whether players are allowed to change the world time with the speed time spell. If disabled, the speed time spell will not change the world time but will still speed up nearby block, entity and tile entity ticks. +config.ebwizardry.world_time_manipulation.true=Yes - daytime, nighttime... +config.ebwizardry.world_time_manipulation.false=No - I need my sleep! +config.ebwizardry.replace_vanilla_fireballs=Replace Vanilla Fireballs +config.ebwizardry.replace_vanilla_fireballs.tooltip=Whether to replace Minecraft's own fireballs with wizardry fireballs. If this is disabled, only wizardry spells will use the custom fireballs. +config.ebwizardry.replace_vanilla_fireballs.true=Yes - give me FIRE! +config.ebwizardry.replace_vanilla_fireballs.false=No - blazes are mean enough +config.ebwizardry.replace_vanilla_fall_damage=Replace Vanilla Fall Damage +config.ebwizardry.replace_vanilla_fall_damage.tooltip=Whether to replace Minecraft's distance-based fall damage calculation with an equivalent, velocity-based one. This is done such that mobs in freefall will take exactly the same damage as normal, so it will not break falling-based mob farms. Disable this if you experience falling-related weirdness! If this is disabled, some spells revert to a more simplistic method of resetting the player's fall damage in certain cases. +config.ebwizardry.replace_vanilla_fall_damage.true=Yes - it's parkour time +config.ebwizardry.replace_vanilla_fall_damage.false=No - break my legs normally +config.ebwizardry.creative_bypasses_arcane_lock=Bypass Arcane Lock +config.ebwizardry.creative_bypasses_arcane_lock.tooltip=Determines which players can bypass arcane locks. +config.ebwizardry.creative_bypasses_arcane_lock.true=Anyone in creative mode +config.ebwizardry.creative_bypasses_arcane_lock.false=Only ops in creative mode +config.ebwizardry.slow_time_affects_players=Slow Time Affects Players +config.ebwizardry.slow_time_affects_players.tooltip=Whether players are slowed when another nearby player uses the slow time spell. If this is disabled, mobs and projectiles will still be affected but players will move at normal speed. +config.ebwizardry.mob_loot_table_whitelist=Mob Loot Table Whitelist +config.ebwizardry.mob_loot_table_whitelist.tooltip=Whitelist for loot tables to inject additional mob drops (as specified in loot_tables/entities/mob_additions.json) into. Wizardry makes a best guess as to which loot tables belong to hostile mobs, but this may not always be correct or appropriate; add loot table locations (not entity IDs) to this list to manually include them. +config.ebwizardry.mob_loot_table_blacklist=Mob Loot Table Blacklist +config.ebwizardry.mob_loot_table_blacklist.tooltip=Blacklist for loot tables to inject additional mob drops (as specified in loot_tables/entities/mob_additions.json) into. Wizardry makes a best guess as to which loot tables belong to hostile mobs, but this may not always be correct or appropriate; add loot table locations (not entity IDs) to this list to manually exclude them. +config.ebwizardry.mob_spawn_dimensions=Mob Spawning Dimensions +config.ebwizardry.mob_spawn_dimensions.tooltip=List of ids of dimensions in which wizardry's hostile mobs can spawn. +config.ebwizardry.mob_spawn_biome_blacklist=Mob Spawning Biome Blacklist +config.ebwizardry.mob_spawn_biome_blaclist.tooltip=List of names of biomes in which wizardry's hostile mobs cannot spawn. Biome names are not case-sensitive. For mod biomes, prefix with the mod ID (e.g. biomesoplenty\:mystic_grove). +config.ebwizardry.evil_wizard_spawn_rate=Evil Wizard Spawn Rate +config.ebwizardry.evil_wizard_spawn_rate.tooltip=Spawn rate for naturally-spawned evil wizards; higher numbers mean more evil wizards will spawn. 5 is equivalent to witches, 100 is equivalent to zombies, skeletons and creepers. Set to 0 to disable evil wizard spawning entirely. +config.ebwizardry.ice_wraith_spawn_rate=Ice Wraith Spawn Rate +config.ebwizardry.ice_wraith_spawn_rate.tooltip=Spawn rate for naturally-spawned ice wraiths; higher numbers mean more ice wraiths will spawn. 5 is equivalent to witches, 100 is equivalent to zombies, skeletons and creepers. Set to 0 to disable ice wraith spawning entirely. +config.ebwizardry.lightning_wraith_spawn_rate=Lightning Wraith Spawn Rate +config.ebwizardry.lightning_wraith_spawn_rate.tooltip=Spawn rate for naturally-spawned lightning wraiths; higher numbers mean more lightning wraiths will spawn. 5 is equivalent to witches, 100 is equivalent to zombies, skeletons and creepers. Set to 0 to disable lightning wraith spawning entirely. +config.ebwizardry.forfeit_chance=Forfeit Chance +config.ebwizardry.forfeit_chance.tooltip=The chance to 'misread' an undiscovered spell and trigger a forfeit instead. Setting this to 0 effectively disables the forfeit mechanic. Has no effect if discovery mode is disabled. +config.ebwizardry.player_damage_scaling=Player Damage Scaling Factor +config.ebwizardry.player_damage_scaling.tooltip=Global damage scaling factor for the damage dealt by players casting spells, relative to 1. +config.ebwizardry.npc_damage_scaling=NPC Damage Scaling Factor +config.ebwizardry.npc_damage_scaling.tooltip=Global damage scaling factor for the damage dealt by NPCs casting spells, relative to 1. +config.ebwizardry.summoned_creature_targets_whitelist=Summoned Creature Target Whitelist +config.ebwizardry.summoned_creature_targets_whitelist.tooltip=List of names of entities which summoned creatures and wizards are allowed to attack, in addition to the defaults. Add mod creatures to this list if you want summoned creatures to attack them and they aren't already doing so. Entity names are not case sensitive. For mod entities, prefix with the mod ID (e.g. ebwizardry\:wizard). +config.ebwizardry.summoned_creature_targets_blacklist=Summoned Creature Target Blacklist +config.ebwizardry.summoned_creature_targets_blacklist.tooltip=List of names of entities which summoned creatures and wizards are specifically not allowed to attack, overriding the defaults and the whitelist. Add creatures to this list if allowing them to be attacked causes problems or is too destructive (removing creepers from this list is done at your own risk!). Entity names are not case sensitive. For mod entities, prefix with the mod ID (e.g. ebwizardry\:wizard). +config.ebwizardry.mind_control_targets_blacklist=Mind Control Targets Blacklist +config.ebwizardry.mind_control_targets_blacklist.tooltip=List of names of entities which cannot be mind controlled, in addition to the defaults. Add creatures to this list if allowing them to be mind-controlled causes problems or could be exploited. Entity names are not case sensitive. For mod entities, prefix with the mod ID (e.g. ebwizardry\:wizard). +config.ebwizardry.pocket_furnace_item_blacklist=Pocket Furnace Item Blacklist +config.ebwizardry.pocket_furnace_item_blacklist.tooltip=List of registry names of blocks or items which cannot be smelted by the pocket furnace spell, in addition to armour, tools and weapons. Block/item names are not case sensitive. For mod items, prefix with the mod ID (e.g. ebwizardry\:crystal_ore). +config.ebwizardry.divination_ore_whitelist=Divination Ore Whitelist +config.ebwizardry.divination_ore_whitelist.tooltip=List of registry names of ore blocks which can be detected by the divination spell. Block names are not case sensitive. For mod blocks, prefix with the mod ID (e.g. ebwizardry\:crystal_ore). +config.ebwizardry.sword_item_whitelist=Sword Item Whitelist +config.ebwizardry.sword_item_whitelist.tooltip=List of registry names of items which should count as swords for imbuement spells. Most swords should work automatically, but those that don't can be added manually here. Item names are not case sensitive. For mod items, prefix with the mod ID (e.g. tconstruct:broadsword). +config.ebwizardry.bow_item_whitelist=Bow Item Whitelist +config.ebwizardry.bow_item_whitelist.tooltip=List of registry names of items which should count as bows for imbuement spells. Most bows should work automatically, but those that don't can be added manually here. Item names are not case sensitive. For mod items, prefix with the mod ID (e.g. tconstruct:shortbow). +config.ebwizardry.currency_items=Currency Items +config.ebwizardry.currency_items.tooltip=List of registry names of items which wizard trades can use as currency (in the first slot; the second slot is unaffected). Each entry in this list should consist of an item registry name, followed by a single space, then an integer which defines the 'value' of the item. Higher values mean fewer of that currency item are required for a given trade. + config.ebwizardry.category.worldgen=World Generation Settings config.ebwizardry.category.worldgen.tooltip=Configure wizardry's world generation features config.ebwizardry.title.worldgen=World Generation Settings config.ebwizardry.subtitle.worldgen=Settings that affect world generation. -config.ebwizardry.category.commands=Command Settings -config.ebwizardry.category.commands.tooltip=Configure wizardry's commands -config.ebwizardry.title.commands=Command Settings -config.ebwizardry.subtitle.commands=Settings for the commands added by Wizardry. +config.ebwizardry.fast_worldgen=Structure Generation +config.ebwizardry.fast_worldgen.tooltip=Controls which algorithm wizardry uses for structure generation. Fancy worldgen prevents structures on cliffs, in caves and intersecting other structures, and cleans up floating trees after generating. Fast worldgen sacrifices these improvements, potentially resulting in faster world generation. Performance improvement will vary depending on your setup. This option will affect randomisation; for any given seed, structures will not be the same as when it is turned off. +config.ebwizardry.fast_worldgen.true=Fast +config.ebwizardry.fast_worldgen.false=Fancy +config.ebwizardry.tower_dimensions=Tower Dimensions +config.ebwizardry.tower_dimensions.tooltip=List of ids of dimensions in which wizard towers will generate. +config.ebwizardry.tower_rarity=Tower Rarity +config.ebwizardry.tower_rarity.tooltip=Rarity of wizard towers. 1 in this many chunks will contain a wizard tower, meaning higher numbers are rarer. +config.ebwizardry.evil_wizard_chance=Evil Wizard Chance +config.ebwizardry.evil_wizard_chance.tooltip=The chance for wizard towers to generate with an evil wizard and chest inside, instead of a friendly wizard. +config.ebwizardry.tower_files=Tower Structure Files +config.ebwizardry.tower_files.tooltip=List of structure file locations for wizard towers without loot chests. One of these files will be randomly selected each time a wizard tower is generated. File locations are of the format [mod id]\:[filename], which refers to the file assets/[mod id]/structures/[filename].nbt. Duplicate entries are permitted, allowing for simple weighting without duplicating the structure files themselves. +config.ebwizardry.tower_with_chest_files=Tower With Chest Structure Files +config.ebwizardry.tower_with_chest_files.tooltip=List of structure file locations for wizard towers with loot chests. One of these files will be randomly selected each time a wizard tower is generated. File locations are of the format [mod id]\:[filename], which refers to the file assets/[mod id]/structures/[filename].nbt. Duplicate entries are permitted, allowing for simple weighting without duplicating the structure files themselves. +config.ebwizardry.obelisk_dimensions=Obelisk Dimensions +config.ebwizardry.obelisk_dimensions.tooltip=List of ids of dimensions in which obelisks will generate. +config.ebwizardry.obelisk_rarity=Obelisk Rarity +config.ebwizardry.obelisk_rarity.tooltip=Rarity of obelisks. 1 in this many chunks will contain an obelisk, meaning higher numbers are rarer. +config.ebwizardry.obelisk_files=Obelisk Structure Files +config.ebwizardry.obelisk_files.tooltip=List of structure file locations for obelisks. One of these files will be randomly selected each time an obelisk is generated. File locations are of the format [mod id]\:[filename], which refers to the file assets/[mod id]/structures/[filename].nbt. Duplicate entries are permitted, allowing for simple weighting without duplicating the structure files themselves. +config.ebwizardry.shrine_dimensions=Shrine Dimensions +config.ebwizardry.shrine_dimensions.tooltip=List of ids of dimensions in which shrines will generate. +config.ebwizardry.shrine_rarity=Shrine Rarity +config.ebwizardry.shrine_rarity.tooltip=Rarity of shrines. 1 in this many chunks will contain a shrine, meaning higher numbers are rarer. +config.ebwizardry.shrine_files=Shrine Structure Files +config.ebwizardry.shrine_files.tooltip=List of structure file locations for shrines. One of these files will be randomly selected each time a shrine is generated. File locations are of the format [mod id]\:[filename], which refers to the file assets/[mod id]/structures/[filename].nbt. Duplicate entries are permitted, allowing for simple weighting without duplicating the structure files themselves. +config.ebwizardry.ore_dimensions=Ore Dimensions +config.ebwizardry.ore_dimensions.tooltip=List of ids of dimensions in which crystal ore will generate. Note that removing the overworld (id 0) from this list will make the mod VERY difficult to play! +config.ebwizardry.flower_dimensions=Flower Dimensions +config.ebwizardry.flower_dimensions.tooltip=List of ids of dimensions in which crystal flowers will generate. +config.ebwizardry.loot_injection_locations=Loot Injection Locations +config.ebwizardry.loot_injection_locations.tooltip=List of loot tables to inject wizardry loot (as specified in loot_tables/chests/dungeon_additions.json) into. config.ebwizardry.category.client=Client Settings config.ebwizardry.category.client.tooltip=Configure wizardry's display and controls config.ebwizardry.title.client=Client Settings config.ebwizardry.subtitle.client=Client-side settings that only affect the local minecraft game. -config.ebwizardry.category.spells=Spell Configuration -config.ebwizardry.category.spells.tooltip=Select which spells are enabled -config.ebwizardry.title.spells=Spell Configuration -config.ebwizardry.subtitle.spells=Set a spell to false to disable it. +config.ebwizardry.shift_scrolling=Shift-scrolling +config.ebwizardry.shift_scrolling.tooltip=Whether you can switch between spells on a wand by scrolling with the mouse wheel while sneaking. Note that this will only affect you; other players connected to the same server obey their own settings. +config.ebwizardry.reverse_scroll_direction=Scroll Direction +config.ebwizardry.reverse_scroll_direction.tooltip=The scroll direction used to switch between spells on a wand while sneaking. +config.ebwizardry.reverse_scroll_direction.true=Reversed +config.ebwizardry.reverse_scroll_direction.false=Normal +config.ebwizardry.spell_hud_position=Spell HUD Position +config.ebwizardry.spell_hud_position.tooltip=The position of the spell HUD. +config.ebwizardry.spell_hud_skin=Spell HUD Skin +config.ebwizardry.spell_hud_skin.tooltip=Change the look of the spell HUD... +config.ebwizardry.spell_hud_skin.preview=Preview +config.ebwizardry.handbook_progression=Handbook Progression +config.ebwizardry.handbook_progression.tooltip=When enabled, to help guide players through the mod, sections of The Wizard's Handbook are unlocked when a player gains the advancement that triggers them, and are hidden otherwise. When disabled, the entire handbook is readable regardless of advancement progress. The entire handbook is always readable in creative mode. +config.ebwizardry.handbook_progression.true=Yes - teach me, Sensei! +config.ebwizardry.handbook_progression.false=No - I know what I'm doing +config.ebwizardry.books_pause_game=Books Pause Game +config.ebwizardry.books_pause_game.tooltip=Whether opening any of wizardry's books pauses the game in singleplayer. Has no effect on servers or LAN worlds. +config.ebwizardry.books_pause_game.true=Yes - I don't want any distractions! +config.ebwizardry.books_pause_game.false=No - I read to pass the time +config.ebwizardry.summoned_creature_names=Summoned Creature Names +config.ebwizardry.summoned_creature_names.tooltip=Controls whether summoned creatures' names and owners are displayed above their heads. +config.ebwizardry.summoned_creature_names.true=Shown +config.ebwizardry.summoned_creature_names.false=Hidden +config.ebwizardry.use_shaders=Use Custom Shaders +config.ebwizardry.use_shaders.tooltip=Whether to use custom shaders for certain spells. These use the vanilla shader system (like mob spectating shaders) and shouldn't have much of an effect on performance in most cases, but they may conflict with other shaders. +config.ebwizardry.use_shaders.true=Yes - gimme those sweet shaders! +config.ebwizardry.use_shaders.false=No - I'm running this on a potato + +config.ebwizardry.category.commands=Command Settings +config.ebwizardry.category.commands.tooltip=Configure wizardry's commands +config.ebwizardry.title.commands=Command Settings +config.ebwizardry.subtitle.commands=Settings for the commands added by Wizardry. + +config.ebwizardry.cast_command_multiplier_limit=Cast Command Multiplier Limit +config.ebwizardry.cast_command_multiplier_limit.tooltip=Upper limit for the multipliers passed into the /cast command. This is here to stop players from accidentally breaking a world/server. Large blast mutipliers can cause extreme lag - you have been warned! +config.ebwizardry.cast_command_name=Cast Spell Command Name +config.ebwizardry.cast_command_name.tooltip=The name of the /cast command. This is what you type directly after the /; for example if this was set to 'magic' then instead of typing /cast you would type /magic instead. +config.ebwizardry.discoverspell_command_name=Discover Spell Command Name +config.ebwizardry.discoverspell_command_name.tooltip=The name of the /discoverspell command. This is what you type directly after the /; for example if this was set to 'magic' then instead of typing /discoverspell you would type /magic instead. +config.ebwizardry.ally_command_name=Set Ally Command Name +config.ebwizardry.ally_command_name.tooltip=The name of the /ally command. This is what you type directly after the /; for example if this was set to 'magic' then instead of typing /ally you would type /magic instead. +config.ebwizardry.allies_command_name=View Allies Command Name +config.ebwizardry.allies_command_name.tooltip=The name of the /allies command. This is what you type directly after the /; for example if this was set to 'magic' then instead of typing /allies you would type /magic instead. config.ebwizardry.category.resistances=Resistance Configuration config.ebwizardry.category.resistances.tooltip=Configure which mobs are immune to different types of magic config.ebwizardry.title.resistances=Resistance Configuration config.ebwizardry.subtitle.resistances=Settings which allow entities to be made immune to certain types of magic. -config.ebwizardry.tower_rarity=Tower Rarity -config.ebwizardry.ore_dimensions=Ore Dimensions -config.ebwizardry.flower_dimensions=Flower Dimensions -config.ebwizardry.tower_dimensions=Tower Dimensions -config.ebwizardry.spell_book_drop_chance=Spell Book Drop Chance -config.ebwizardry.generate_loot=Generate Loot -config.ebwizardry.firebomb_is_craftable=Firebomb Is Craftable -config.ebwizardry.poison_bomb_is_craftable=Poison Bomb Is Craftable -config.ebwizardry.smoke_bomb_is_craftable=Smoke Bomb Is Craftable -config.ebwizardry.use_alternate_scroll_recipe=Use Alternate Scroll Recipe -config.ebwizardry.teleport_through_unbreakable_blocks=Teleport Through Unbreakable Blocks -config.ebwizardry.show_summoned_creature_names=Show Summoned Creature Names -config.ebwizardry.friendly_fire=Friendly Fire -config.ebwizardry.telekinetic_disarmament=Telekinetic Disarmament -config.ebwizardry.discovery_mode=Discovery Mode -config.ebwizardry.enable_shift_scrolling=Enable Shift-scrolling -config.ebwizardry.reverse_scroll_direction=Reverse Scroll Direction -config.ebwizardry.minion_revenge_targeting=Minion Revenge Targeting -config.ebwizardry.player_damage_scaling=Player Damage Scaling Factor -config.ebwizardry.npc_damage_scaling=NPC Damage Scaling Factor -config.ebwizardry.cast_command_multiplier_limit=Cast Command Multiplier Limit -config.ebwizardry.summoned_creature_targets_whitelist=Summoned Creature Target Whitelist -config.ebwizardry.summoned_creature_targets_blacklist=Summoned Creature Target Blacklist -config.ebwizardry.spell_hud_position=Spell HUD Position -config.ebwizardry.spell_hud_skin=Spell HUD Skin -config.ebwizardry.cast_command_name=Cast Spell Command Name -config.ebwizardry.discoverspell_command_name=Discover Spell Command Name -config.ebwizardry.ally_command_name=Set Ally Command Name -config.ebwizardry.allies_command_name=View Allies Command Name -config.ebwizardry.mind_control_targets_blacklist=Mind Control Targets Blacklist -config.ebwizardry.evil_wizard_dimensions=Evil Wizard Dimensions - config.ebwizardry.mobs_immune_to_fire=Mobs Immune To Fire +config.ebwizardry.mobs_immune_to_fire.tooltip=List of names of entities that are immune to fire, in addition to the defaults. Add mod creatures to this list if you want them to be immune to fire magic and they aren't already. Entity names are not case sensitive. For mod entities, prefix with the mod ID (e.g. ebwizardry\:wizard). config.ebwizardry.mobs_immune_to_ice=Mobs Immune To Ice +config.ebwizardry.mobs_immune_to_ice.tooltip=List of names of entities that are immune to ice, in addition to the defaults. Add mod creatures to this list if you want them to be immune to ice magic and they aren't already. Entity names are not case sensitive. For mod entities, prefix with the mod ID (e.g. ebwizardry\:wizard). config.ebwizardry.mobs_immune_to_lightning=Mobs Immune To Lightning +config.ebwizardry.mobs_immune_to_lightning.tooltip=List of names of entities that are immune to lightning, in addition to the defaults. Add mod creatures to this list if you want them to be immune to lightning magic and they aren't already. Entity names are not case sensitive. For mod entities, prefix with the mod ID (e.g. ebwizardry\:wizard). config.ebwizardry.mobs_immune_to_wither=Mobs Immune To Wither +config.ebwizardry.mobs_immune_to_wither.tooltip=List of names of entities that are immune to wither effects, in addition to the defaults. Add mod creatures to this list if you want them to be immune to withering magic and they aren't already. Entity names are not case sensitive. For mod entities, prefix with the mod ID (e.g. ebwizardry\:wizard). config.ebwizardry.mobs_immune_to_poison=Mobs Immune To Poison +config.ebwizardry.mobs_immune_to_poison.tooltip=List of names of entities that are immune to poison, in addition to the defaults. Add mod creatures to this list if you want them to be immune to poison magic and they aren't already. Entity names are not case sensitive. For mod entities, prefix with the mod ID (e.g. ebwizardry\:wizard). -config.ebwizardry.tower_rarity.tooltip=Rarity of wizard towers. Higher numbers are rarer. Set to 0 to disable wizard towers completely. -config.ebwizardry.ore_dimensions.tooltip=List of dimension ids in which crystal ore will generate. Note that removing the overworld (id 0) from this list will make the mod VERY difficult to play! -config.ebwizardry.flower_dimensions.tooltip=List of dimension ids in which crystal flowers will generate. -config.ebwizardry.tower_dimensions.tooltip=List of dimension ids in which wizard towers will generate. -config.ebwizardry.spell_book_drop_chance.tooltip=The chance for mobs to drop a spell book when killed. The greater this number, the more often they will drop. Set to 0 to disable spell book drops. Set to 200 for guaranteed drops. -config.ebwizardry.generate_loot.tooltip=Whether to generate wizardry loot in dungeon chests. -config.ebwizardry.firebomb_is_craftable.tooltip=Whether firebombs can be crafted or not. -config.ebwizardry.poison_bomb_is_craftable.tooltip=Whether poison bombs can be crafted or not. -config.ebwizardry.smoke_bomb_is_craftable.tooltip=Whether smoke bombs can be crafted or not. -config.ebwizardry.use_alternate_scroll_recipe.tooltip=Whether to require a magic crystal in the shapeless crafting recipe for blank scrolls. Set to true if another mod adds a conflicting recipe. -config.ebwizardry.teleport_through_unbreakable_blocks.tooltip=Whether players are allowed to teleport through unbreakable blocks (e.g. bedrock) using the phase step spell. -config.ebwizardry.show_summoned_creature_names.tooltip=Whether to show summoned creatures' names and owners above their heads. -config.ebwizardry.friendly_fire.tooltip=Whether to allow players to damage their designated allies using magic. -config.ebwizardry.telekinetic_disarmament.tooltip=Whether to allow players to disarm other players using the telekinesis spell. Set to false to prevent stealing of items. -config.ebwizardry.discovery_mode.tooltip=For those who like a sense of mystery! When set to true, spells you haven't cast yet will be unreadable until you cast them (on a per-world basis). Has no effect when in creative mode. Spells of identification will be unobtainable in survival mode if this is false. -config.ebwizardry.enable_shift_scrolling.tooltip=Whether you can switch between spells on a wand by scrolling with the mouse wheel while sneaking. Note that this will only affect you; other players connected to the same server obey their own settings. -config.ebwizardry.reverse_scroll_direction.tooltip=Whether to reverse the scroll direction used to switch between spells on a wand while sneaking. -config.ebwizardry.minion_revenge_targeting.tooltip=Whether summoned creatures can revenge attack their owner if their owner attacks them. -config.ebwizardry.player_damage_scaling.tooltip=Global damage scaling factor for the damage dealt by players casting spells, relative to 1. -config.ebwizardry.npc_damage_scaling.tooltip=Global damage scaling factor for the damage dealt by NPCs casting spells, relative to 1. -config.ebwizardry.cast_command_multiplier_limit.tooltip=Upper limit for the multipliers passed into the /cast command. This is here to stop players from accidentally breaking a world/server. Large blast mutipliers can cause extreme lag - you have been warned! -config.ebwizardry.summoned_creature_targets_whitelist.tooltip=List of names of entities which summoned creatures and wizards are allowed to attack, in addition to the defaults. Add mod creatures to this list if you want summoned creatures to attack them and they aren't already doing so. Entity names are not case sensitive. For mod entities, prefix with the mod ID (e.g. ebwizardry:wizard). -config.ebwizardry.summoned_creature_targets_blacklist.tooltip=List of names of entities which summoned creatures and wizards are specifically not allowed to attack, overriding the defaults and the whitelist. Add creatures to this list if allowing them to be attacked causes problems or is too destructive (removing creepers from this list is done at your own risk!). Entity names are not case sensitive. For mod entities, prefix with the mod ID (e.g. ebwizardry:wizard). -config.ebwizardry.spell_hud_position.tooltip=The position of the spell HUD. -config.ebwizardry.spell_hud_skin.tooltip=Change the look of the spell HUD... -config.ebwizardry.cast_command_name.tooltip=The name of the /cast command. This is what you type directly after the /; for example if this was set to 'magic' then instead of typing /cast you would type /magic instead. -config.ebwizardry.discoverspell_command_name.tooltip=The name of the /discoverspell command. This is what you type directly after the /; for example if this was set to 'magic' then instead of typing /discoverspell you would type /magic instead. -config.ebwizardry.ally_command_name.tooltip=The name of the /ally command. This is what you type directly after the /; for example if this was set to 'magic' then instead of typing /ally you would type /magic instead. -config.ebwizardry.allies_command_name.tooltip=The name of the /allies command. This is what you type directly after the /; for example if this was set to 'magic' then instead of typing /allies you would type /magic instead. -config.ebwizardry.mind_control_targets_blacklist.tooltip=List of names of entities which cannot be mind controlled, in addition to the defaults. Add creatures to this list if allowing them to be mind-controlled causes problems or could be exploited. Entity names are not case sensitive. For mod entities, prefix with the mod ID (e.g. ebwizardry:wizard). -config.ebwizardry.evil_wizard_dimensions.tooltip=List of dimension ids in which evil wizards can spawn. +config.ebwizardry.category.compatibility=Mod Compatibility Settings +config.ebwizardry.category.compatibility.tooltip=Configure how wizardry interacts with other mods +config.ebwizardry.title.compatibility=Mod Compatibility Settings +config.ebwizardry.subtitle.compatibility=Settings that affect how wizardry interacts with other mods -config.ebwizardry.mobs_immune_to_fire.tooltip=List of names of entities that are immune to fire, in addition to the defaults. Add mod creatures to this list if you want them to be immune to fire magic and they aren't already. Entity names are not case sensitive. For mod entities, prefix with the mod ID (e.g. ebwizardry:wizard). -config.ebwizardry.mobs_immune_to_ice.tooltip=List of names of entities that are immune to ice, in addition to the defaults. Add mod creatures to this list if you want them to be immune to ice magic and they aren't already. Entity names are not case sensitive. For mod entities, prefix with the mod ID (e.g. ebwizardry:wizard). -config.ebwizardry.mobs_immune_to_lightning.tooltip=List of names of entities that are immune to lightning, in addition to the defaults. Add mod creatures to this list if you want them to be immune to lightning magic and they aren't already. Entity names are not case sensitive. For mod entities, prefix with the mod ID (e.g. ebwizardry:wizard). -config.ebwizardry.mobs_immune_to_wither.tooltip=List of names of entities that are immune to wither effects, in addition to the defaults. Add mod creatures to this list if you want them to be immune to withering magic and they aren't already. Entity names are not case sensitive. For mod entities, prefix with the mod ID (e.g. ebwizardry:wizard). -config.ebwizardry.mobs_immune_to_poison.tooltip=List of names of entities that are immune to poison, in addition to the defaults. Add mod creatures to this list if you want them to be immune to poison magic and they aren't already. Entity names are not case sensitive. For mod entities, prefix with the mod ID (e.g. ebwizardry:wizard). +config.ebwizardry.damage_source_blacklist=Damage Source Blacklist +config.ebwizardry.damage_source_blacklist.tooltip=List of damage source string identifiers to be ignored when re-applying damage. Case-sensitive. A message will be logged if wizardry detects a damage source that should be added to this list. Otherwise, don't change unless instructed to do so. +config.ebwizardry.compatibility_warnings=Compatibility Warnings +config.ebwizardry.compatibility_warnings.tooltip=Whether to print compatibility warnings to the console. Set to false if excessive messages are being printed. +config.ebwizardry.baubles_integration=Baubles Integration +config.ebwizardry.baubles_integration.tooltip=If Baubles is installed, controls whether Baubles integration features are enabled. If this is disabled, wizardry will always behave as if Baubles is not installed. +config.ebwizardry.jei_integration=JEI Integration +config.ebwizardry.jei_integration.tooltip=If JEI (Just Enough Items) is installed, controls whether JEI integration features are enabled. If this is disabled, wizardry will always behave as if JEI is not installed. +config.ebwizardry.antique_atlas_integration=Antique Atlas Integration +config.ebwizardry.antique_atlas_integration.tooltip=If Antique Atlas is installed, controls whether Antique Atlas integration features are enabled. If this is disabled, wizardry will always behave as if Antique Atlas is not installed. +config.ebwizardry.auto_place_tower_markers=Auto-Place Tower Markers +config.ebwizardry.auto_place_tower_markers.tooltip=Controls whether wizardry automatically places antique atlas markers at the locations of wizard towers. +config.ebwizardry.auto_place_obelisk_markers=Auto-Place Obelisk Markers +config.ebwizardry.auto_place_obelisk_markers.tooltip=Controls whether wizardry automatically places antique atlas markers at the locations of obelisks. +config.ebwizardry.auto_place_shrine_markers=Auto-Place Shrine Markers +config.ebwizardry.auto_place_shrine_markers.tooltip=Controls whether wizardry automatically places antique atlas markers at the locations of shrines. + +integration.jei.category.ebwizardry\:arcane_workbench=Arcane Workbench + +integration.antiqueatlas.marker.ebwizardry\:wizard_tower=Wizard Tower +integration.antiqueatlas.marker.ebwizardry\:obelisk=Obelisk +integration.antiqueatlas.marker.ebwizardry\:shrine=Shrine wizard.debug=%1$s, %2$s, %3$s diff --git a/src/main/resources/assets/ebwizardry/lang/es_es.lang b/src/main/resources/assets/ebwizardry/lang/es_es.lang index 3287ca13..ae625e31 100644 --- a/src/main/resources/assets/ebwizardry/lang/es_es.lang +++ b/src/main/resources/assets/ebwizardry/lang/es_es.lang @@ -29,13 +29,13 @@ item.ebwizardry:wand.mana=Mana: %1$s/%2$s item.ebwizardry:wand.addally=%1$s ha sido anadido a tu lista de aliados item.ebwizardry:wand.removeally=%1$s ha sido removido a tu lista de aliados -item.ebwizardry:basic_fire_wand.name=Varita de Ascuas -item.ebwizardry:basic_ice_wand.name=Varita de Escarcha -item.ebwizardry:basic_lightning_wand.name=Varita de Chispas -item.ebwizardry:basic_necromancy_wand.name=Varita de las Sombras -item.ebwizardry:basic_earth_wand.name=Varita del Bosque -item.ebwizardry:basic_sorcery_wand.name=Varita del Misterio -item.ebwizardry:basic_healing_wand.name=Varita de la Curacion +item.ebwizardry:novice_fire_wand.name=Varita de Ascuas +item.ebwizardry:novice_ice_wand.name=Varita de Escarcha +item.ebwizardry:novice_lightning_wand.name=Varita de Chispas +item.ebwizardry:novice_necromancy_wand.name=Varita de las Sombras +item.ebwizardry:novice_earth_wand.name=Varita del Bosque +item.ebwizardry:novice_sorcery_wand.name=Varita del Misterio +item.ebwizardry:novice_healing_wand.name=Varita de la Curacion item.ebwizardry:apprentice_fire_wand.name=Varita del Piromano Aprendiz item.ebwizardry:apprentice_ice_wand.name=Varita del Mago de Hielo Aprendiz @@ -212,56 +212,56 @@ entity.ebwizardry:lightning_pulse.name=Pulso de Relampago item_group.ebwizardry=Wizardry item_group.wizardryspells=Hechizos de Wizardry -advancement.wizardry:root=Wizardry -advancement.wizardry:root.desc=Avances -advancement.wizardry:crystal=Un Cristral Curioso... -advancement.wizardry:crystal.desc=Pica un Cristal Magico -advancement.wizardry:arcane_initiate=Inicio Arcano -advancement.wizardry:arcane_initiate.desc=Craftea una varita magica con una pepita de oro, un palo y un cristal magico -advancement.wizardry:apprentice=Aprendiz de Mago -advancement.wizardry:apprentice.desc=Usa un tomo de lo arcano para mejorar tu varita -advancement.wizardry:master=Maestro Arcano -advancement.wizardry:master.desc=Obten una varita de maestro -advancement.wizardry:all_spells=Mago de Todos los Oficios -advancement.wizardry:all_spells.desc=Lanza todos los hechizos disponibles -advancement.wizardry:wizard_trade=Comercio Magico -advancement.wizardry:wizard_trade.desc=Compra un objeto a un mago -advancement.wizardry:buy_master_spell=El Conocimiento es Poder -advancement.wizardry:buy_master_spell.desc=Compra un hechizo maestro a un mago -advancement.wizardry:freeze_blaze=Ya No Estas Tan Caliente -advancement.wizardry:freeze_blaze.desc=Congela a un blaze -advancement.wizardry:charge_creeper=Va a Explotar!! -advancement.wizardry:charge_creeper.desc='Accidentalmente' carga un creeper -advancement.wizardry:frankenstein=Frankenstein -advancement.wizardry:frankenstein.desc=Convierte a un cerdo en un hombrecerdo zombi usando el hechizo de rayo -advancement.wizardry:special_upgrade=Remiendo Arcano -advancement.wizardry:special_upgrade.desc=Aplica una mejora a una varita -advancement.wizardry:craft_flask=Es Magia, Embotellada! -advancement.wizardry:craft_flask.desc=Craftea un frasco de mana -advancement.wizardry:elemental=Elemental -advancement.wizardry:elemental.desc=Obten una varita elemental -advancement.wizardry:armour_set=Now Eres un Mago Apropiado -advancement.wizardry:armour_set.desc=Craftea y equipa el set completo de armadura de mago -advancement.wizardry:legendary=Legendario -advancement.wizardry:legendary.desc=Obten una pieza de armadura de mago legendaria -advancement.wizardry:self_destruct=Tiro por la culata -advancement.wizardry:self_destruct.desc=Muere por tu propia magia -advancement.wizardry:pig_tornado=No De Nuevo... -advancement.wizardry:pig_tornado.desc=Monta un cerdo hacia un tornado -advancement.wizardry:jam_wizard=Sesion de Interferencia -advancement.wizardry:jam_wizard.desc=Usa el hechizo arcano de interferencia en un mago -advancement.wizardry:slime_skeleton=Situacion Pegajosa -advancement.wizardry:slime_skeleton.desc=Sumerge un esqueleto en slime -advancement.wizardry:anger_wizard=Te Arrepentiras de Eso -advancement.wizardry:anger_wizard.desc=Haz que un mago se enoje -advancement.wizardry:defeat_evil_wizard=Justicia -advancement.wizardry:defeat_evil_wizard.desc=Derrota a un mago malvado -advancement.wizardry:max_out_wand=Equipada Al Maximo! -advancement.wizardry:max_out_wand.desc=Aplica el maximo numero de mejoras a una varita maestra -advancement.wizardry:element_master=Maestria Elemental -advancement.wizardry:element_master.desc=Lanza todos los hechizos de cualquier elemento -advancement.wizardry:identify_spell=Apreciacion Arcana -advancement.wizardry:identify_spell.desc=Usa un pergamino de la identificacion para identificar un libro de hechizos o pergamino +advancement.ebwizardry:root=Wizardry +advancement.ebwizardry:root.desc=Avances +advancement.ebwizardry:crystal=Un Cristral Curioso... +advancement.ebwizardry:crystal.desc=Pica un Cristal Magico +advancement.ebwizardry:arcane_initiate=Inicio Arcano +advancement.ebwizardry:arcane_initiate.desc=Craftea una varita magica con una pepita de oro, un palo y un cristal magico +advancement.ebwizardry:apprentice=Aprendiz de Mago +advancement.ebwizardry:apprentice.desc=Usa un tomo de lo arcano para mejorar tu varita +advancement.ebwizardry:master=Maestro Arcano +advancement.ebwizardry:master.desc=Obten una varita de maestro +advancement.ebwizardry:all_spells=Mago de Todos los Oficios +advancement.ebwizardry:all_spells.desc=Lanza todos los hechizos disponibles +advancement.ebwizardry:wizard_trade=Comercio Magico +advancement.ebwizardry:wizard_trade.desc=Compra un objeto a un mago +advancement.ebwizardry:buy_master_spell=El Conocimiento es Poder +advancement.ebwizardry:buy_master_spell.desc=Compra un hechizo maestro a un mago +advancement.ebwizardry:freeze_blaze=Ya No Estas Tan Caliente +advancement.ebwizardry:freeze_blaze.desc=Congela a un blaze +advancement.ebwizardry:charge_creeper=Va a Explotar!! +advancement.ebwizardry:charge_creeper.desc='Accidentalmente' carga un creeper +advancement.ebwizardry:frankenstein=Frankenstein +advancement.ebwizardry:frankenstein.desc=Convierte a un cerdo en un hombrecerdo zombi usando el hechizo de rayo +advancement.ebwizardry:special_upgrade=Remiendo Arcano +advancement.ebwizardry:special_upgrade.desc=Aplica una mejora a una varita +advancement.ebwizardry:craft_flask=Es Magia, Embotellada! +advancement.ebwizardry:craft_flask.desc=Craftea un frasco de mana +advancement.ebwizardry:elemental=Elemental +advancement.ebwizardry:elemental.desc=Obten una varita elemental +advancement.ebwizardry:armour_set=Now Eres un Mago Apropiado +advancement.ebwizardry:armour_set.desc=Craftea y equipa el set completo de armadura de mago +advancement.ebwizardry:legendary=Legendario +advancement.ebwizardry:legendary.desc=Obten una pieza de armadura de mago legendaria +advancement.ebwizardry:self_destruct=Tiro por la culata +advancement.ebwizardry:self_destruct.desc=Muere por tu propia magia +advancement.ebwizardry:pig_tornado=No De Nuevo... +advancement.ebwizardry:pig_tornado.desc=Monta un cerdo hacia un tornado +advancement.ebwizardry:jam_wizard=Sesion de Interferencia +advancement.ebwizardry:jam_wizard.desc=Usa el hechizo arcano de interferencia en un mago +advancement.ebwizardry:slime_skeleton=Situacion Pegajosa +advancement.ebwizardry:slime_skeleton.desc=Sumerge un esqueleto en slime +advancement.ebwizardry:anger_wizard=Te Arrepentiras de Eso +advancement.ebwizardry:anger_wizard.desc=Haz que un mago se enoje +advancement.ebwizardry:defeat_evil_wizard=Justicia +advancement.ebwizardry:defeat_evil_wizard.desc=Derrota a un mago malvado +advancement.ebwizardry:max_out_wand=Equipada Al Maximo! +advancement.ebwizardry:max_out_wand.desc=Aplica el maximo numero de mejoras a una varita maestra +advancement.ebwizardry:element_master=Maestria Elemental +advancement.ebwizardry:element_master.desc=Lanza todos los hechizos de cualquier elemento +advancement.ebwizardry:identify_spell=Apreciacion Arcana +advancement.ebwizardry:identify_spell.desc=Usa un pergamino de la identificacion para identificar un libro de hechizos o pergamino tile.ebwizardry:transportation_stone.confirm=A partir de ahora retornaras a este lugar cuando lances %1$s tile.ebwizardry:transportation_stone.invalid=Primero debes hacer un circulo con 8 piedras de transportacion! @@ -271,7 +271,7 @@ container.ebwizardry:arcane_workbench.apply=Aplicar container.ebwizardry:arcane_workbench.mana=Mana: container.ebwizardry:arcane_workbench.upgrades=Mejoras Aplicadas: -tier.basic=Novato +tier.novice=Novato tier.apprentice=Aprendiz tier.advanced=Avanzado tier.master=Maestro @@ -535,7 +535,7 @@ spell.ebwizardry:metamorphosis.desc=Cambia la forma del objetivo. Solo funciona spell.ebwizardry:meteor.desc=Algunos magos solo quieren ver el mundo arder... spell.ebwizardry:mind_control.desc=Toma control de la mente del objetivo por 30 segundos, provocando que cambie de bando y peleen a tu favor. No funciona con criaturas de voluntad muy fuerte. spell.ebwizardry:mind_trick.desc=Confunde y desorienta al objetivo por 15 segundos, volviendolo incapaz de atacar. El efecto se desactiva si el objetivo recibe dano. -spell.ebwizardry:none.desc=Para obtener un libro de hechizo con el comando /give, usa la metadata: /give [player] ebwizardry:spell_book 1 [spell id] (_si encontraste este libro en un cofre significa que otro mod esta alterando las cosas). +spell.ebwizardry:none.desc=Para obtener un libro de hechizo con el comando /give, usa la id: /give [player] ebwizardry:spell_book 1 [spell id] (_si encontraste este libro en un cofre significa que otro mod esta alterando las cosas). spell.ebwizardry:oakflesh.desc=Mejora la resistencia del amgo durante 30 segundos. spell.ebwizardry:petrify.desc=Convierte al objetivo en piedra hasta que se libere, con un chance de liberarse cuando se pone de noche. El objetivo no se puede mover ni atacar y no puede ser atacado. spell.ebwizardry:phase_step.desc=Transporta al mago a traves de una pared de 1 bloque de grosor. El rango mejora el grosor por el cual te puedes transportar. diff --git a/src/main/resources/assets/ebwizardry/lang/es_mx.lang b/src/main/resources/assets/ebwizardry/lang/es_mx.lang index 3287ca13..ae625e31 100644 --- a/src/main/resources/assets/ebwizardry/lang/es_mx.lang +++ b/src/main/resources/assets/ebwizardry/lang/es_mx.lang @@ -29,13 +29,13 @@ item.ebwizardry:wand.mana=Mana: %1$s/%2$s item.ebwizardry:wand.addally=%1$s ha sido anadido a tu lista de aliados item.ebwizardry:wand.removeally=%1$s ha sido removido a tu lista de aliados -item.ebwizardry:basic_fire_wand.name=Varita de Ascuas -item.ebwizardry:basic_ice_wand.name=Varita de Escarcha -item.ebwizardry:basic_lightning_wand.name=Varita de Chispas -item.ebwizardry:basic_necromancy_wand.name=Varita de las Sombras -item.ebwizardry:basic_earth_wand.name=Varita del Bosque -item.ebwizardry:basic_sorcery_wand.name=Varita del Misterio -item.ebwizardry:basic_healing_wand.name=Varita de la Curacion +item.ebwizardry:novice_fire_wand.name=Varita de Ascuas +item.ebwizardry:novice_ice_wand.name=Varita de Escarcha +item.ebwizardry:novice_lightning_wand.name=Varita de Chispas +item.ebwizardry:novice_necromancy_wand.name=Varita de las Sombras +item.ebwizardry:novice_earth_wand.name=Varita del Bosque +item.ebwizardry:novice_sorcery_wand.name=Varita del Misterio +item.ebwizardry:novice_healing_wand.name=Varita de la Curacion item.ebwizardry:apprentice_fire_wand.name=Varita del Piromano Aprendiz item.ebwizardry:apprentice_ice_wand.name=Varita del Mago de Hielo Aprendiz @@ -212,56 +212,56 @@ entity.ebwizardry:lightning_pulse.name=Pulso de Relampago item_group.ebwizardry=Wizardry item_group.wizardryspells=Hechizos de Wizardry -advancement.wizardry:root=Wizardry -advancement.wizardry:root.desc=Avances -advancement.wizardry:crystal=Un Cristral Curioso... -advancement.wizardry:crystal.desc=Pica un Cristal Magico -advancement.wizardry:arcane_initiate=Inicio Arcano -advancement.wizardry:arcane_initiate.desc=Craftea una varita magica con una pepita de oro, un palo y un cristal magico -advancement.wizardry:apprentice=Aprendiz de Mago -advancement.wizardry:apprentice.desc=Usa un tomo de lo arcano para mejorar tu varita -advancement.wizardry:master=Maestro Arcano -advancement.wizardry:master.desc=Obten una varita de maestro -advancement.wizardry:all_spells=Mago de Todos los Oficios -advancement.wizardry:all_spells.desc=Lanza todos los hechizos disponibles -advancement.wizardry:wizard_trade=Comercio Magico -advancement.wizardry:wizard_trade.desc=Compra un objeto a un mago -advancement.wizardry:buy_master_spell=El Conocimiento es Poder -advancement.wizardry:buy_master_spell.desc=Compra un hechizo maestro a un mago -advancement.wizardry:freeze_blaze=Ya No Estas Tan Caliente -advancement.wizardry:freeze_blaze.desc=Congela a un blaze -advancement.wizardry:charge_creeper=Va a Explotar!! -advancement.wizardry:charge_creeper.desc='Accidentalmente' carga un creeper -advancement.wizardry:frankenstein=Frankenstein -advancement.wizardry:frankenstein.desc=Convierte a un cerdo en un hombrecerdo zombi usando el hechizo de rayo -advancement.wizardry:special_upgrade=Remiendo Arcano -advancement.wizardry:special_upgrade.desc=Aplica una mejora a una varita -advancement.wizardry:craft_flask=Es Magia, Embotellada! -advancement.wizardry:craft_flask.desc=Craftea un frasco de mana -advancement.wizardry:elemental=Elemental -advancement.wizardry:elemental.desc=Obten una varita elemental -advancement.wizardry:armour_set=Now Eres un Mago Apropiado -advancement.wizardry:armour_set.desc=Craftea y equipa el set completo de armadura de mago -advancement.wizardry:legendary=Legendario -advancement.wizardry:legendary.desc=Obten una pieza de armadura de mago legendaria -advancement.wizardry:self_destruct=Tiro por la culata -advancement.wizardry:self_destruct.desc=Muere por tu propia magia -advancement.wizardry:pig_tornado=No De Nuevo... -advancement.wizardry:pig_tornado.desc=Monta un cerdo hacia un tornado -advancement.wizardry:jam_wizard=Sesion de Interferencia -advancement.wizardry:jam_wizard.desc=Usa el hechizo arcano de interferencia en un mago -advancement.wizardry:slime_skeleton=Situacion Pegajosa -advancement.wizardry:slime_skeleton.desc=Sumerge un esqueleto en slime -advancement.wizardry:anger_wizard=Te Arrepentiras de Eso -advancement.wizardry:anger_wizard.desc=Haz que un mago se enoje -advancement.wizardry:defeat_evil_wizard=Justicia -advancement.wizardry:defeat_evil_wizard.desc=Derrota a un mago malvado -advancement.wizardry:max_out_wand=Equipada Al Maximo! -advancement.wizardry:max_out_wand.desc=Aplica el maximo numero de mejoras a una varita maestra -advancement.wizardry:element_master=Maestria Elemental -advancement.wizardry:element_master.desc=Lanza todos los hechizos de cualquier elemento -advancement.wizardry:identify_spell=Apreciacion Arcana -advancement.wizardry:identify_spell.desc=Usa un pergamino de la identificacion para identificar un libro de hechizos o pergamino +advancement.ebwizardry:root=Wizardry +advancement.ebwizardry:root.desc=Avances +advancement.ebwizardry:crystal=Un Cristral Curioso... +advancement.ebwizardry:crystal.desc=Pica un Cristal Magico +advancement.ebwizardry:arcane_initiate=Inicio Arcano +advancement.ebwizardry:arcane_initiate.desc=Craftea una varita magica con una pepita de oro, un palo y un cristal magico +advancement.ebwizardry:apprentice=Aprendiz de Mago +advancement.ebwizardry:apprentice.desc=Usa un tomo de lo arcano para mejorar tu varita +advancement.ebwizardry:master=Maestro Arcano +advancement.ebwizardry:master.desc=Obten una varita de maestro +advancement.ebwizardry:all_spells=Mago de Todos los Oficios +advancement.ebwizardry:all_spells.desc=Lanza todos los hechizos disponibles +advancement.ebwizardry:wizard_trade=Comercio Magico +advancement.ebwizardry:wizard_trade.desc=Compra un objeto a un mago +advancement.ebwizardry:buy_master_spell=El Conocimiento es Poder +advancement.ebwizardry:buy_master_spell.desc=Compra un hechizo maestro a un mago +advancement.ebwizardry:freeze_blaze=Ya No Estas Tan Caliente +advancement.ebwizardry:freeze_blaze.desc=Congela a un blaze +advancement.ebwizardry:charge_creeper=Va a Explotar!! +advancement.ebwizardry:charge_creeper.desc='Accidentalmente' carga un creeper +advancement.ebwizardry:frankenstein=Frankenstein +advancement.ebwizardry:frankenstein.desc=Convierte a un cerdo en un hombrecerdo zombi usando el hechizo de rayo +advancement.ebwizardry:special_upgrade=Remiendo Arcano +advancement.ebwizardry:special_upgrade.desc=Aplica una mejora a una varita +advancement.ebwizardry:craft_flask=Es Magia, Embotellada! +advancement.ebwizardry:craft_flask.desc=Craftea un frasco de mana +advancement.ebwizardry:elemental=Elemental +advancement.ebwizardry:elemental.desc=Obten una varita elemental +advancement.ebwizardry:armour_set=Now Eres un Mago Apropiado +advancement.ebwizardry:armour_set.desc=Craftea y equipa el set completo de armadura de mago +advancement.ebwizardry:legendary=Legendario +advancement.ebwizardry:legendary.desc=Obten una pieza de armadura de mago legendaria +advancement.ebwizardry:self_destruct=Tiro por la culata +advancement.ebwizardry:self_destruct.desc=Muere por tu propia magia +advancement.ebwizardry:pig_tornado=No De Nuevo... +advancement.ebwizardry:pig_tornado.desc=Monta un cerdo hacia un tornado +advancement.ebwizardry:jam_wizard=Sesion de Interferencia +advancement.ebwizardry:jam_wizard.desc=Usa el hechizo arcano de interferencia en un mago +advancement.ebwizardry:slime_skeleton=Situacion Pegajosa +advancement.ebwizardry:slime_skeleton.desc=Sumerge un esqueleto en slime +advancement.ebwizardry:anger_wizard=Te Arrepentiras de Eso +advancement.ebwizardry:anger_wizard.desc=Haz que un mago se enoje +advancement.ebwizardry:defeat_evil_wizard=Justicia +advancement.ebwizardry:defeat_evil_wizard.desc=Derrota a un mago malvado +advancement.ebwizardry:max_out_wand=Equipada Al Maximo! +advancement.ebwizardry:max_out_wand.desc=Aplica el maximo numero de mejoras a una varita maestra +advancement.ebwizardry:element_master=Maestria Elemental +advancement.ebwizardry:element_master.desc=Lanza todos los hechizos de cualquier elemento +advancement.ebwizardry:identify_spell=Apreciacion Arcana +advancement.ebwizardry:identify_spell.desc=Usa un pergamino de la identificacion para identificar un libro de hechizos o pergamino tile.ebwizardry:transportation_stone.confirm=A partir de ahora retornaras a este lugar cuando lances %1$s tile.ebwizardry:transportation_stone.invalid=Primero debes hacer un circulo con 8 piedras de transportacion! @@ -271,7 +271,7 @@ container.ebwizardry:arcane_workbench.apply=Aplicar container.ebwizardry:arcane_workbench.mana=Mana: container.ebwizardry:arcane_workbench.upgrades=Mejoras Aplicadas: -tier.basic=Novato +tier.novice=Novato tier.apprentice=Aprendiz tier.advanced=Avanzado tier.master=Maestro @@ -535,7 +535,7 @@ spell.ebwizardry:metamorphosis.desc=Cambia la forma del objetivo. Solo funciona spell.ebwizardry:meteor.desc=Algunos magos solo quieren ver el mundo arder... spell.ebwizardry:mind_control.desc=Toma control de la mente del objetivo por 30 segundos, provocando que cambie de bando y peleen a tu favor. No funciona con criaturas de voluntad muy fuerte. spell.ebwizardry:mind_trick.desc=Confunde y desorienta al objetivo por 15 segundos, volviendolo incapaz de atacar. El efecto se desactiva si el objetivo recibe dano. -spell.ebwizardry:none.desc=Para obtener un libro de hechizo con el comando /give, usa la metadata: /give [player] ebwizardry:spell_book 1 [spell id] (_si encontraste este libro en un cofre significa que otro mod esta alterando las cosas). +spell.ebwizardry:none.desc=Para obtener un libro de hechizo con el comando /give, usa la id: /give [player] ebwizardry:spell_book 1 [spell id] (_si encontraste este libro en un cofre significa que otro mod esta alterando las cosas). spell.ebwizardry:oakflesh.desc=Mejora la resistencia del amgo durante 30 segundos. spell.ebwizardry:petrify.desc=Convierte al objetivo en piedra hasta que se libere, con un chance de liberarse cuando se pone de noche. El objetivo no se puede mover ni atacar y no puede ser atacado. spell.ebwizardry:phase_step.desc=Transporta al mago a traves de una pared de 1 bloque de grosor. El rango mejora el grosor por el cual te puedes transportar. diff --git a/src/main/resources/assets/ebwizardry/lang/fr_fr.lang b/src/main/resources/assets/ebwizardry/lang/fr_fr.lang new file mode 100644 index 00000000..b51fa23d --- /dev/null +++ b/src/main/resources/assets/ebwizardry/lang/fr_fr.lang @@ -0,0 +1,760 @@ +tile.ebwizardry:arcane_workbench.name=Table des arcanes +tile.ebwizardry:crystal_ore.name=Minerais de cristal +tile.ebwizardry:petrified_stone.name=Roche pétrifiée +tile.ebwizardry:ice_statue.name=Statue de glace +tile.ebwizardry:crystal_flower.name=Fleur de cristal +tile.ebwizardry:snare.name=Ronces +tile.ebwizardry:transportation_stone.name=Pierre de Transportation +tile.ebwizardry:spectral_block.name=Bloc spectrale +tile.ebwizardry:crystal_block.name=Bloc de cristal + +item.ebwizardry:magic_crystal.name=Cristal magique +item.ebwizardry:magic_wand.name=Baguette magique +item.ebwizardry:apprentice_wand.name=Baguette d'apprenti +item.ebwizardry:advanced_wand.name=Baguette d'expert +item.ebwizardry:master_wand.name=Baguette de maître +item.ebwizardry:spell_book.name=Livre de sort + +item.ebwizardry:arcane_tome.name=Tome des arcanes +item.ebwizardry:arcane_tome.desc1=Améliore n'importe quelle +item.ebwizardry:arcane_tome.desc2=baguette du tier %1$s au tier %1$s + +item.ebwizardry:wizard_handbook.name=Le manuel du sorcier +item.ebwizardry:wizard_handbook.desc=par %1$s + +item.ebwizardry:wand.buff=+%1$s de puissance de %2$s +item.ebwizardry:wand.spell=Sort actuel: %1$s +item.ebwizardry:wand.mana=Mana: %1$s/%2$s + +item.ebwizardry:wand.addally=%1$s a été ajouté a vote liste d'alliés +item.ebwizardry:wand.removeally=%1$s a été retiré de votre liste d'alliés + +item.ebwizardry:basic_fire_wand.name=Baguette de braise +item.ebwizardry:basic_ice_wand.name=Baguette de gel +item.ebwizardry:basic_lightning_wand.name=Baguette d'étincelle +item.ebwizardry:basic_necromancy_wand.name=Baguette d'ombre +item.ebwizardry:basic_earth_wand.name=Bagette de bourgeon +item.ebwizardry:basic_sorcery_wand.name=Baguette de mystère +item.ebwizardry:basic_healing_wand.name=Baguette de soin + +item.ebwizardry:apprentice_fire_wand.name=Baguette d'apprenti pyromancien +item.ebwizardry:apprentice_ice_wand.name=Baguette d'apprenti cryomancien +item.ebwizardry:apprentice_lightning_wand.name=Baguette d'apprenti electromancien +item.ebwizardry:apprentice_necromancy_wand.name=Baguette d'apprenti necromancien +item.ebwizardry:apprentice_earth_wand.name=Baguette d'apprenti Geomancien +item.ebwizardry:apprentice_sorcery_wand.name=Baguette d'apprenti sorcier +item.ebwizardry:apprentice_healing_wand.name=Baguette d'apprenti soigneur + +item.ebwizardry:advanced_fire_wand.name=Baguette de brasier +item.ebwizardry:advanced_ice_wand.name=Baguette de blizzard +item.ebwizardry:advanced_lightning_wand.name=Baguette de foudre +item.ebwizardry:advanced_necromancy_wand.name=Baguette de necromancie +item.ebwizardry:advanced_earth_wand.name=Baguette de forêt +item.ebwizardry:advanced_sorcery_wand.name=Baguette de sorcier +item.ebwizardry:advanced_healing_wand.name=Baguette de soigneur + +item.ebwizardry:master_fire_wand.name=Baguette de maître pyromancien +item.ebwizardry:master_ice_wand.name=Baguette de maître cryomancien +item.ebwizardry:master_lightning_wand.name=Baguette de maître electromancien +item.ebwizardry:master_necromancy_wand.name=Baguette de maître necromancien +item.ebwizardry:master_earth_wand.name=Baguette de maître Geomancien +item.ebwizardry:master_sorcery_wand.name=Baguette de maître sorcier +item.ebwizardry:master_healing_wand.name=Baguette de maître soigneur + +item.ebwizardry:spectral_sword.name=Epée spectrale +item.ebwizardry:spectral_pickaxe.name=Pioche spectrale +item.ebwizardry:spectral_bow.name=Arc spectral + +item.ebwizardry:mana_flask.name=Fiole de mana +item.ebwizardry:storage_upgrade.name=Amélioration de baguette de capacité de mana +item.ebwizardry:siphon_upgrade.name=Amélioration de baguette de siphon de mana +item.ebwizardry:condenser_upgrade.name=Amélioration de puissance de baguette +item.ebwizardry:range_upgrade.name=Amélioration de portée de baguette +item.ebwizardry:duration_upgrade.name=Amélioration de durée de sort +item.ebwizardry:cooldown_upgrade.name=Amélioration de temps de rechargement de baguette +item.ebwizardry:blast_upgrade.name=Amélioration d'explosion de sort +item.ebwizardry:attunement_upgrade.name=Amélioration d'harmonisation de baguette + +item.ebwizardry:flaming_axe.name=Hache enflammée +item.ebwizardry:frost_axe.name=Hache gelée + +item.ebwizardry:firebomb.name=Bombe de feu +item.ebwizardry:poison_bomb.name=Bombe de poison +item.ebwizardry:smoke_bomb.name=Bombe de fumée + +item.ebwizardry:blank_scroll.name=Parchemin vierge +item.ebwizardry:scroll.name=Parchemin de %1$s +item.ebwizardry:scroll.undiscovered.name=Parchemin de "%1$s" +item.ebwizardry:identification_scroll.name=Parchemin d'identification +item.ebwizardry:identification_scroll.desc1=%1$sIdentifie un livre ou un +item.ebwizardry:identification_scroll.desc2=%1$sparchemin de sort inconnu +item.ebwizardry:identification_scroll.nothing_to_identify=Il n'y a rien à identifier! + +item.ebwizardry:armour_upgrade.name=Sceau arcanique de protection +item.ebwizardry:armour_upgrade.desc1=%1$sAméliore n'importe quelle +item.ebwizardry:armour_upgrade.desc2=%1$srobe au tier %2$slegendaire + +item.ebwizardry:magic_silk.name=Soie magique + +item.ebwizardry:wizard_armour.legendary=Legendaire +item.ebwizardry:wizard_armour.buff=-%1$s en coût de %2$s +item.ebwizardry:wizard_armour.mana=Mana: %1$s/%2$s + +item.ebwizardry:wizard_hat.name=Chapeau de sorcier +item.ebwizardry:wizard_robe.name=Robe de sorcier +item.ebwizardry:wizard_leggings.name=Pantalon de sorcier +item.ebwizardry:wizard_boots.name=Chaussures de sorcier + +item.ebwizardry:wizard_hat_fire.name=Chapeau de pyromancien +item.ebwizardry:wizard_robe_fire.name=Robe de pyromancien +item.ebwizardry:wizard_leggings_fire.name=Pantalon de pyromancien +item.ebwizardry:wizard_boots_fire.name=Bottes de pyromancien + +item.ebwizardry:wizard_hat_ice.name=Chapeau de cryomancien +item.ebwizardry:wizard_robe_ice.name=Robe de cryomancien +item.ebwizardry:wizard_leggings_ice.name=Pentalon de cryomancien +item.ebwizardry:wizard_boots_ice.name=Bottes de cryomancien + +item.ebwizardry:wizard_hat_lightning.name=Chapeau d'electomancien +item.ebwizardry:wizard_robe_lightning.name=Robe d'electromancien +item.ebwizardry:wizard_leggings_lightning.name=Pentalon d'electromancien +item.ebwizardry:wizard_boots_lightning.name=Bottes d'electromancien + +item.ebwizardry:wizard_hat_necromancy.name=Chapeau de necromancie +item.ebwizardry:wizard_robe_necromancy.name=Robe de necromancien +item.ebwizardry:wizard_leggings_necromancy.name=Pentalon de necromacien +item.ebwizardry:wizard_boots_necromancy.name=Bottes de necromancie + +item.ebwizardry:wizard_hat_earth.name=Chapeau de Geomancien +item.ebwizardry:wizard_robe_earth.name=Robe de Geomancien +item.ebwizardry:wizard_leggings_earth.name=Pentalon de Geomancien +item.ebwizardry:wizard_boots_earth.name=Bottes de Geomancien + +item.ebwizardry:wizard_hat_sorcery.name=Chapeau de sorcier +item.ebwizardry:wizard_robe_sorcery.name=Robe de sorcier +item.ebwizardry:wizard_leggings_sorcery.name=Pentalon de sorcier +item.ebwizardry:wizard_boots_sorcery.name=Bottes de sorcier + +item.ebwizardry:wizard_hat_healing.name=Chapeau de soigneur +item.ebwizardry:wizard_robe_healing.name=Robe de soigneur +item.ebwizardry:wizard_leggings_healing.name=Pentalon de soigneur +item.ebwizardry:wizard_boots_healing.name=Bottes de soigneur + +item.ebwizardry:spawn_wizard.name=Oeuf de sorcier +item.ebwizardry:spawn_evil_wizard.name=Oeuf de sorcier maléfique + +item.ebwizardry:spectral_helmet.name=Casque spectral +item.ebwizardry:spectral_chestplate.name=Plastron spectral +item.ebwizardry:spectral_leggings.name=Jambières spectrales +item.ebwizardry:spectral_boots.name=Bottes spectrales + +entity.ebwizardry:summonedcreature.nameplate=%1$s's %2$s +entity.ebwizardry:summonedcreature.nameplate_fallback=Someone's %1$s + +entity.ebwizardry:zombie_minion.name=Zombie +entity.ebwizardry:skeleton_minion.name=Squelette +entity.ebwizardry:spider_minion.name=Araignée +entity.ebwizardry:blaze_minion.name=Blaze +entity.ebwizardry:wither_skeleton_minion.name=Wither squelette +entity.ebwizardry:ice_wraith.name=Spectre de glace +entity.ebwizardry:lightning_wraith.name=Spectre de foudre +entity.ebwizardry:shadow_wraith.name=Spectre d'ombre +entity.ebwizardry:spirit_wolf.name=Esprit de loup +entity.ebwizardry:spirit_horse.name=Esprit de cheval +entity.ebwizardry:ice_giant.name=Geant de glace +entity.ebwizardry:phoenix.name=Phoenix +entity.ebwizardry:wizard.name=Sorcier +entity.ebwizardry:magic_slime.name=Slime magique +entity.ebwizardry:silverfish_minion.name=Poisson d'argent +entity.ebwizardry:storm_elemental.name=Tempête elementaire +entity.ebwizardry:evil_wizard.name=Sorcier +entity.ebwizardry:decoy.name=Leurre + +entity.ebwizardry:magic_missile.name=Magique +entity.ebwizardry:arc.name=Magique +entity.ebwizardry:spark_bomb.name=Magique +entity.ebwizardry:ice_shard.name=Magique +entity.ebwizardry:firebomb.name=Magique +entity.ebwizardry:poison_bomb.name=Magique +entity.ebwizardry:force_orb.name=Magique +entity.ebwizardry:spark.name=Magique +entity.ebwizardry:darkness_orb.name=Magique +entity.ebwizardry:fire_sigil.name=Magique +entity.ebwizardry:frost_sigil.name=Magique +entity.ebwizardry:lightning_sigil.name=Magique +entity.ebwizardry:lightning_arrow.name=Magique +entity.ebwizardry:firebolt.name=Magique +entity.ebwizardry:ice_charge.name=Magique +entity.ebwizardry:force_arrow.name=Magique +entity.ebwizardry:dart.name=Magique +entity.ebwizardry:lightning_disc.name=Magique +entity.ebwizardry:thunderbolt.name=Magique +entity.ebwizardry:decay.name=Magique +entity.ebwizardry:ice_lance.name=Magique +entity.ebwizardry:smoke_bomb.name=Magique +entity.ebwizardry:ice_spike.name=Magique + +entity.ebwizardry:black_hole.name=Trou noir +entity.ebwizardry:shield.name=Bouclier +entity.ebwizardry:meteor.name=Meteor +entity.ebwizardry:blizzard.name=Blizzard +entity.ebwizardry:bubble.name=Bulle +entity.ebwizardry:tornado.name=Tornade +entity.ebwizardry:lightning_hammer.name=Marteau de foudre +entity.ebwizardry:arrow_rain.name=Pluie de flèches +entity.ebwizardry:healing_aura.name=Aura de soin +entity.ebwizardry:forcefield.name=Champ de force +entity.ebwizardry:ring_of_fire.name=Anneau de feu +entity.ebwizardry:earthquake.name=Seisme +entity.ebwizardry:falling_grass.name=Chute d'herbe +entity.ebwizardry:hailstorm.name=Grêle +entity.ebwizardry:lightning_pulse.name=Pulsation electrique + +itemGroup.ebwizardry=Wizardry +itemGroup.ebwizardryspells=Spells + +advancement.ebwizardry:root=Sorcier +advancement.ebwizardry:root.desc=Le voyage d'un sorcier pour maîtriser les arcanes +advancement.ebwizardry:crystal=Un mystérieux cristal... +advancement.ebwizardry:crystal.desc=Miner un cristal magique +advancement.ebwizardry:arcane_initiate=Initiation arcanique +advancement.ebwizardry:arcane_initiate.desc=Fabriquer une baguette magique avec une pépite d'or, un bâton et un cristal magique +advancement.ebwizardry:apprentice=Apprenti Magicien +advancement.ebwizardry:apprentice.desc=Utilisez un tome d'arcane pour améliorer votre baguette +advancement.ebwizardry:master=Maître des Arcanes +advancement.ebwizardry:master.desc=Obtenir une baguette de maître +advancement.ebwizardry:all_spells=Mage de tous les métiers +advancement.ebwizardry:all_spells.desc=Lancer chaque sort du jeu +advancement.ebwizardry:wizard_trade=Transaction magique +advancement.ebwizardry:wizard_trade.desc=Acheter un objet auprès d'un sorcier +advancement.ebwizardry:buy_master_spell=Le savoir c'est le pouvoir +advancement.ebwizardry:buy_master_spell.desc=Acheter un sort de maître auprès d'un sorcier +advancement.ebwizardry:freeze_blaze=Petite brise... +advancement.ebwizardry:freeze_blaze.desc=Geler un blaze +advancement.ebwizardry:charge_creeper=Ça va peter! +advancement.ebwizardry:charge_creeper.desc=Charger accidentellement un creeper +advancement.ebwizardry:frankenstein=Frankenstein +advancement.ebwizardry:frankenstein.desc=Transformer un cochon en zombie cochon avec un éclair +advancement.ebwizardry:special_upgrade=Bricolage arcanique +advancement.ebwizardry:special_upgrade.desc=Appliquer une amélioration à une baguette +advancement.ebwizardry:craft_flask=De la magie en bouteille! +advancement.ebwizardry:craft_flask.desc=Fabriquer une fiole de mana +advancement.ebwizardry:elemental=Elementaire +advancement.ebwizardry:elemental.desc=Obtenir une baguette elementaire +advancement.ebwizardry:armour_set=Tu est un sorcier, Harry +advancement.ebwizardry:armour_set.desc=Fabriquer et equiper un set complet de sorcier +advancement.ebwizardry:legendary=Legendaire +advancement.ebwizardry:legendary.desc=Obtenir une pièce d'armure légendaire de sorcier +advancement.ebwizardry:self_destruct=Retour de flammes +advancement.ebwizardry:self_destruct.desc=Mourrir de sa propre magie +advancement.ebwizardry:pig_tornado=Pas encore... +advancement.ebwizardry:pig_tornado.desc=Monter un cochon dans une tornade +advancement.ebwizardry:jam_wizard=Perturbation arcanique +advancement.ebwizardry:jam_wizard.desc=Utiliser le sort de perturbation sur un sorcier +advancement.ebwizardry:slime_skeleton=Situation collante +advancement.ebwizardry:slime_skeleton.desc=Engluer un squelette dans un slime +advancement.ebwizardry:anger_wizard=Tu va le regreter... +advancement.ebwizardry:anger_wizard.desc=Enerver un sorcier +advancement.ebwizardry:defeat_evil_wizard=Mage vertueux +advancement.ebwizardry:defeat_evil_wizard.desc=Tuer un sorcier maléfique +advancement.ebwizardry:max_out_wand=Equipé de pied en cap +advancement.ebwizardry:max_out_wand.desc=Appliquer le maximum d'amélioration à une baguette de maître +advancement.ebwizardry:element_master=Maître des éléments +advancement.ebwizardry:element_master.desc=Lancer tout les sorts d'un élément +advancement.ebwizardry:identify_spell=Examin arcanique +advancement.ebwizardry:identify_spell.desc=Utiliser un parchemin pour identifier un livre ou un autre parchemin + +tile.ebwizardry:transportation_stone.confirm=Vous pouvez désormais revenir ici plus tard en lançant le sort %1$s +tile.ebwizardry:transportation_stone.invalid=Vous devez dabord faire un carré avec 8 pierres de transportation et vous y lier avec une baguette! + +container.ebwizardry:arcane_workbench=Table des arcanes +container.ebwizardry:arcane_workbench.apply=Appliquer +container.ebwizardry:arcane_workbench.mana=Mana: +container.ebwizardry:arcane_workbench.upgrades=Amélioration appliquée: + +tier.basic=Novice +tier.apprentice=Apprenti +tier.advanced=Expert +tier.master=Maître + +element.simple=Aucun +element.fire=Feu +element.ice=Glace +element.lightning=Foudre +element.necromancy=Necromancie +element.earth=Terra +element.sorcery=Sorcellerie +element.healing=Soin + +element.simple.wizard=Sorcier +element.fire.wizard=Pyromancien +element.ice.wizard=Cryomancien +element.lightning.wizard=Electromancien +element.necromancy.wizard=Necromancien +element.earth.wizard=Geomancien +element.sorcery.wizard=Sorcier +element.healing.wizard=Soigneur + +spelltype.attack=Attaque +spelltype.defence=Defense +spelltype.utility=Utilité +spelltype.minion=Sbire + +spell.disabled=%1$s a été désactivé dans la config! +spell.resist=%1$s a résisté à %2$s +spell.discover=Le sort %1$s a été découvert! + +spell.ebwizardry:agility=Agilité +spell.ebwizardry:arc=Arc +spell.ebwizardry:arcane_jammer=Perturbation arcanique +spell.ebwizardry:arrow_rain=Pluie de flèche +spell.ebwizardry:banish=Banissement +spell.ebwizardry:black_hole=Trou noir +spell.ebwizardry:blink=Teleportation +spell.ebwizardry:blizzard=Blizzard +spell.ebwizardry:bubble=Bulle +spell.ebwizardry:chain_lightning=Chaîne d'éclair +spell.ebwizardry:clairvoyance=Clairvoyance +spell.ebwizardry:cobwebs=Toile +spell.ebwizardry:conjure_armour=Conjuration d'armure +spell.ebwizardry:conjure_bow=Conjuration d'arc +spell.ebwizardry:conjure_pickaxe=Conjuration de pioche +spell.ebwizardry:conjure_sword=Conjuration d'épée +spell.ebwizardry:cure_effects=Curation +spell.ebwizardry:curse_of_soulbinding=Malédiction de liaison d'âme +spell.ebwizardry:darkness_orb=Orbe de ténèbre +spell.ebwizardry:darkvision=Nyctalopie +spell.ebwizardry:dart=Dard +spell.ebwizardry:decay=Decomposition +spell.ebwizardry:decoy=Leurre +spell.ebwizardry:detonate=Detonation +spell.ebwizardry:diamondflesh=Peau de diamant +spell.ebwizardry:earthquake=Seisme +spell.ebwizardry:entrapment=Piège de ténèbre +spell.ebwizardry:fireball=Boule de feu +spell.ebwizardry:firebolt=Eclair de feu +spell.ebwizardry:firebomb=Bombe de feu +spell.ebwizardry:fire_resistance=Resistance aux flammes +spell.ebwizardry:fire_sigil=Rune de feu +spell.ebwizardry:fireskin=Aura de feu +spell.ebwizardry:firestorm=Tempête de feu +spell.ebwizardry:flame_ray=Trait de feu +spell.ebwizardry:flaming_axe=Hache enflammé +spell.ebwizardry:flaming_weapon=Enflamment d'arme +spell.ebwizardry:flight=Vol +spell.ebwizardry:font_of_mana=Fontaine de mana +spell.ebwizardry:font_of_vitality=Fontaine de vitalité +spell.ebwizardry:force_arrow=Flèche de force +spell.ebwizardry:forcefield=Champ de force +spell.ebwizardry:force_orb=Orbe de force +spell.ebwizardry:forests_curse=Malédiction de la forêt +spell.ebwizardry:freeze=Gel +spell.ebwizardry:freezing_weapon=Gel d'arme +spell.ebwizardry:frost_axe=Hache de glace +spell.ebwizardry:frost_ray=Trait de glace +spell.ebwizardry:frost_sigil=Rune de glace +spell.ebwizardry:glide=Vol plané +spell.ebwizardry:greater_fireball=Grosse boule de feu +spell.ebwizardry:greater_heal=Soin magistral +spell.ebwizardry:group_heal=Soin de groupe +spell.ebwizardry:growth_aura=Aura de croissance +spell.ebwizardry:hailstorm=Grêle +spell.ebwizardry:heal=Soin +spell.ebwizardry:heal_ally=Touché soignant +spell.ebwizardry:healing_aura=Aura de soin +spell.ebwizardry:homing_spark=Etincelle auto-guidé +spell.ebwizardry:ice_age=Âge de glace +spell.ebwizardry:ice_charge=Charge de glace +spell.ebwizardry:ice_lance=Lance de glace +spell.ebwizardry:ice_shard=Eclat de glace +spell.ebwizardry:ice_shroud=Aura de glace +spell.ebwizardry:ice_spikes=Pic de glace +spell.ebwizardry:ice_statue=Statue de glace +spell.ebwizardry:ignite=Enflammer +spell.ebwizardry:imbue_weapon=imprégnation d'arme +spell.ebwizardry:intimidate=Intimidation +spell.ebwizardry:invigorating_presence=Présance tonifiante +spell.ebwizardry:invisibility=Invisibilité +spell.ebwizardry:invoke_weather=Tempête +spell.ebwizardry:ironflesh=Peau de fer +spell.ebwizardry:leap=Saut +spell.ebwizardry:levitation=Levitation +spell.ebwizardry:life_drain=Drain de vie +spell.ebwizardry:light=Lumière +spell.ebwizardry:lightning_arrow=Flèche de foudre +spell.ebwizardry:lightning_bolt=Eclair +spell.ebwizardry:lightning_disc=Disque de foudre +spell.ebwizardry:lightning_hammer=Marteau de foudre +spell.ebwizardry:lightning_pulse=Pulsation electrique +spell.ebwizardry:lightning_ray=Trait de foudre +spell.ebwizardry:lightning_sigil=Rune de foudre +spell.ebwizardry:lightning_web=Eclair en chaîne +spell.ebwizardry:magic_missile=Missile magique +spell.ebwizardry:metamorphosis=Metamorphose +spell.ebwizardry:meteor=Meteor +spell.ebwizardry:mind_control=Hypnose +spell.ebwizardry:mind_trick=Confusion +spell.ebwizardry:none=[Emplacement vide] +spell.ebwizardry:oakflesh=Peau de chêne +spell.ebwizardry:petrify=Petrification +spell.ebwizardry:phase_step=Passe muraille +spell.ebwizardry:plague_of_darkness=Peste ténébreuse +spell.ebwizardry:pocket_furnace=Cuisson +spell.ebwizardry:pocket_workbench=Conjuration d'etabli +spell.ebwizardry:poison=Poison +spell.ebwizardry:poison_bomb=Bombe de poison +spell.ebwizardry:replenish_hunger=Restoration +spell.ebwizardry:ring_of_fire=Anneau de feu +spell.ebwizardry:shadow_ward=Miroir d'ombre +spell.ebwizardry:shield=Barrière +spell.ebwizardry:shockwave=Onde de choc +spell.ebwizardry:silverfish_swarm=Essaim de poisson d'argent +spell.ebwizardry:sixth_sense=Sixième sense +spell.ebwizardry:slime=Slime +spell.ebwizardry:smoke_bomb=Bombe de fumée +spell.ebwizardry:snare=Ronce +spell.ebwizardry:snowball=Boule de neige +spell.ebwizardry:spark_bomb=Bombe electrique +spell.ebwizardry:spectral_pathway=Chemin spectral +spell.ebwizardry:spider_swarm=Essaim d'araignées +spell.ebwizardry:static_aura=Aura electrique +spell.ebwizardry:summon_blaze=Invocation de blaize +spell.ebwizardry:summon_ice_giant=Invocation de geant de glace +spell.ebwizardry:summon_ice_wraith=Invocation de spectre de glace +spell.ebwizardry:summon_iron_golem=Invocation de golem de fer +spell.ebwizardry:summon_lightning_wraith=Invocation de spectre de foudre +spell.ebwizardry:summon_phoenix=Invocation de Phoenix +spell.ebwizardry:summon_shadow_wraith=Invocation de spectre d'ombre +spell.ebwizardry:summon_skeleton=Invocation de squelette +spell.ebwizardry:summon_skeleton_legion=Invocation de legion de squelette +spell.ebwizardry:summon_snow_golem=Invocation de golem de neige +spell.ebwizardry:summon_spirit_horse=Invocation de cheval spectral +spell.ebwizardry:summon_spirit_wolf=Invocation de chien spectral +spell.ebwizardry:summon_storm_elemental=Invocation d'élémentaire de foudre +spell.ebwizardry:summon_wither_skeleton=Invocation de squelette wither +spell.ebwizardry:summon_zombie=Invocation de zombie +spell.ebwizardry:telekinesis=Telekinesie +spell.ebwizardry:thunderbolt=Coup de tonnerre +spell.ebwizardry:thunderstorm=Orage +spell.ebwizardry:tornado=Tornade +spell.ebwizardry:transience=Forme éthérée +spell.ebwizardry:transportation=Transportation +spell.ebwizardry:vanishing_box=Conjuration de coffre de l'ender +spell.ebwizardry:wall_of_frost=Mur de glace +spell.ebwizardry:water_breathing=Respiration aquatique +spell.ebwizardry:whirlwind=Bourrasque +spell.ebwizardry:wither=Wither +spell.ebwizardry:wither_skull=Crâne de wither + +spell.ebwizardry:agility.desc=Augmente la vitesse de déplacement et la hauteur de saut du lanceur pendant 30 secondes. +spell.ebwizardry:arc.desc=Tire une étincelle de foudre sur la cible. +spell.ebwizardry:arcane_jammer.desc=Empêche la cible d'utiliser la magie pendant 15 secondes. +spell.ebwizardry:arrow_rain.desc="Archers, tirez!" +spell.ebwizardry:banish.desc=Téléporte la cible contre sa volonté vers un emplacement aléatoire dans une certaine distance. +spell.ebwizardry:black_hole.desc=Déchirez la réalité. +spell.ebwizardry:blink.desc=Téléporte le lanceur sur une courte distance à l'endroit où il se vise. +spell.ebwizardry:blizzard.desc=Crée une zone de vent glacé tourbillonnant qui ralentit et endommage continuellement tout ce qui est piégé à l'intérieur. Le lanceur est immunisé contre les dégâts, mais il est quand même ralenti. +spell.ebwizardry:bubble.desc=Lance un jet de bulles qui capture tout ce qu’il frappe dans une bulle qui flottera vers le haut. La cible tombera après un certain temps ou si la bulle est endommagée. +spell.ebwizardry:chain_lightning.desc=Lance une étincelle de foudre sur la cible, qui frappe ensuite deux cibles supplémentaires. +spell.ebwizardry:clairvoyance.desc=Révèle le chemin vers un lieu mémorisé. Avec ce sort sélectionné, sneak-cliquez sur un bloc pour définir l'emplacement. Jetez ce sort normalement pour révéler le chemin. Le chemin disparaîtra au bout de 90 secondes. +spell.ebwizardry:cobwebs.desc=Crée des toiles d'araignées à l'endroit que vous visez, ce qui gêne grandement le mouvement des créatures prises dedans. Les toiles d'araignées disparaîtront après 20 secondes ou si elles sont cassées. +spell.ebwizardry:conjure_armour.desc=Crée une armure spectrale autour du lanceur qui offre une protection égale à celle d’une armure de fer. L'armure dure 60 secondes. Le lanceur doit avoir un emplacement d'armure vide. +spell.ebwizardry:conjure_bow.desc=Crée un arc spectral avec des flèches illimitées qui dure 30 secondes. +spell.ebwizardry:conjure_pickaxe.desc=Crée une pioche spectrale de force égale à une pioche de fer qui dure 30 secondes. +spell.ebwizardry:conjure_sword.desc=Crée une épée spectrale de force égale à une épée de fer qui dure 30 secondes. +spell.ebwizardry:cure_effects.desc=Supprime tous les effets de potion affectant actuellement le lanceur, bons ou mauvais. +spell.ebwizardry:curse_of_soulbinding.desc=Fait en sorte que l'âme de la cible soit inextricablement liée à celle du lanceur, ce qui signifie que tous les dommages qui lui sont infligés sont également infligés à la victime. Dure jusqu'à ce que la victime ou le lanceur meurt. +spell.ebwizardry:darkness_orb.desc=Tire un orbe d'énergie sombre se déplaçant lentement dans la direction que vous visez, causant l'effet wither à ce qu'il frappera. +spell.ebwizardry:darkvision.desc=Donne la vision nocturne au lanceur pendant 45 secondes. +spell.ebwizardry:dart.desc=Tire une flèche dans la direction que vous visez qui endommage et affaiblit sa cible. +spell.ebwizardry:decay.desc=Crée une flaque de décomposition sur le sol qui infecte toute créature qui la touche, causant des dégâts persistants au fil du temps et générant d'avantage de décomposition partout où elle se promène. +spell.ebwizardry:decoy.desc=Crée un clone illusoire du lanceur qui incite les monstres à l'attaquer à la place. Le leurre disparaîtra au bout de 30 secondes. +spell.ebwizardry:detonate.desc=Provoque une explosion à l'endroit où vous vous visez, causant des dommages à toutes les créatures proches, y compris le lanceur, si il est trop proche. +spell.ebwizardry:diamondflesh.desc="Vos flèches ne sont pas de taille contre moi!" +spell.ebwizardry:earthquake.desc=Un vrai maître de la magie de la terre peut déplacer des montagnes. +spell.ebwizardry:entrapment.desc=Enferme la cible dans une sphère de ténèbres qui la tire de façon impuissante vers le haut et l’endommage continuellement. +spell.ebwizardry:fireball.desc=Lance une boule de feu dans la direction que vous pointez. +spell.ebwizardry:firebolt.desc=Lance un jet de feu à une courte distance de vous. +spell.ebwizardry:firebomb.desc=Déclenche une bombe incendiaire dans la direction que vous pointez qui explose sous l’impact, ce qui met le feu à vos cibles. +spell.ebwizardry:fire_resistance.desc=Confère au lanceur une résistance au feu pendant 30 secondes. +spell.ebwizardry:fire_sigil.desc=Place un piège magique sur le sol qui endommage et met le feu à la créature qui le déclenche. +spell.ebwizardry:fireskin.desc=Le lanceur s'enveloppe de feu pendant 30 secondes, ce qui fait s'enflammer tout ce qui l'attaque. +spell.ebwizardry:firestorm.desc="Je suis le Dragon" +spell.ebwizardry:flame_ray.desc=Crée un souffle de flammes dans la direction que vous pointez qui enflamme et endommage continuellement les cibles. +spell.ebwizardry:flaming_axe.desc=Crée une hache enflammée qui met le feu à l'ennemi lorsqu'il est touché. Dure 30 secondes. +spell.ebwizardry:flaming_weapon.desc=La première arme de la barre de raccourci du lanceur est temporairement imprégnée du pouvoir de la flamme, ce qui incendie ses victimes. L'effet disparaît après 45 secondes. +spell.ebwizardry:flight.desc=Volez comme un aigle. +spell.ebwizardry:font_of_mana.desc="Nous étions remplis d'une intense énergie magique semblant émaner du centre de la ..." - Extrait du journal d'un mage oublié; le reste de la page a été brûlé. +spell.ebwizardry:font_of_vitality.desc=C'est incroyable. +spell.ebwizardry:force_arrow.desc=Tire une flèche de force dans la direction que vous pointez. +spell.ebwizardry:forcefield.desc=Crée un champ de force autour du lanceur qui repousse les créatures et dévie les projectiles. +spell.ebwizardry:force_orb.desc=Lance une sphère de force qui endommage et repousse les créatures proches lors de l'impact. +spell.ebwizardry:forests_curse.desc="Comment osez-vous entrer dans ma forêt!" +spell.ebwizardry:freeze.desc=Gèle la cible pendant 10 secondes. Peut également geler l'eau et créer de la neige sur le sol. +spell.ebwizardry:freezing_weapon.desc=La première arme située sur la barre de raccourci du lanceur est temporairement imprégnée de gel, ce qui gèle ses victimes. L'effet disparaît après 45 secondes. +spell.ebwizardry:frost_axe.desc=Crée une hache gelée qui gèle les ennemis quand ils sont touchés. Dure 30 secondes. +spell.ebwizardry:frost_ray.desc=Crée un jet de givre dans la direction que vous visez, ce qui ralentit et endommage continuellement les cibles. +spell.ebwizardry:frost_sigil.desc=Place un piège de glace magique sur le sol qui endommage et gèle la créature qui le déclenche. +spell.ebwizardry:glide.desc=Permet au lanceur de planer en l'air tout en maintenant enfoncé le bouton d'utilisation. +spell.ebwizardry:greater_fireball.desc=Lance une grosse boule de feu dans la direction que vous pointez qui explose à l’impact. +spell.ebwizardry:greater_heal.desc=Soigne le lanceur de 4 coeurs. +spell.ebwizardry:group_heal.desc=Soigne le lanceur et tous les alliés proches et les créatures invoquées de 3 coeurs. +spell.ebwizardry:growth_aura.desc=Fais pousser toutes les cultures près du lanceur. Fais pousser également des herbes hautes et des fleurs sur l’herbe. +spell.ebwizardry:hailstorm.desc=C'est au cours du grand hiver du troisième âge que les mages de glace ont découvert leur véritable pouvoir. +spell.ebwizardry:heal.desc=Soigne le lanceur de sorts de 2 coeurs. +spell.ebwizardry:heal_ally.desc=Soigne la cible de 2 cœurs et demi. +spell.ebwizardry:healing_aura.desc=Crée une zone d'énergie de guérison qui régénère la santé de tous les alliés qui s'y trouvent. Tout mort-vivant à l'intérieur de l'aura de guérison subira lentement des dégâts. +spell.ebwizardry:homing_spark.desc=Crée une étincelle flottante qui se déplace vers les ennemis. +spell.ebwizardry:ice_age.desc="Vous serez gelés pour une éternité!" +spell.ebwizardry:ice_charge.desc=Lance une charge de glace qui explose à l’impact, gèle les créatures proches et libère des éclats dans toutes les directions. +spell.ebwizardry:ice_lance.desc=Tire une grande lance de glace dans la direction que vous pointez, qui transperce les cibles, les endommageant et les gelant. +spell.ebwizardry:ice_shard.desc=Tire un éclat de glace dans la direction que vous pointez qui endommage et ralentit les cibles. +spell.ebwizardry:ice_shroud.desc=Crée un voile de froid autour du lanceur pendant 30 secondes, ce qui bloque tout les attaques. +spell.ebwizardry:ice_spikes.desc=Invoque des pointes de glace acérées comme des lames de rasoir qui s'élèvent du sol à l'endroit où vous visez, embrochant ainsi toutes les créatures dans la zone. +spell.ebwizardry:ice_statue.desc=Congèle entierement la cible pendant 20 secondes ou jusqu'à ce qu'elle soit cassée. La cible ne peut pas bouger ni faire quoi que ce soit tant qu'elle est gelée, mais est également insensible à tous les dégâts. +spell.ebwizardry:ignite.desc=Met le feu à la cible pendant 10 secondes. Fonctionne également comme un briquet. +spell.ebwizardry:imbue_weapon.desc=Imprègne temporairement la première arme de la barre de raccourci du lanceur pour la rendre plus efficace. L'effet disparaît après 45 secondes. +spell.ebwizardry:intimidate.desc=Émet un grondement intimidant qui provoque la peur des créatures proches. Les créatures frappées par la peur vont récupérer leur état normal après 30 secondes. +spell.ebwizardry:invigorating_presence.desc=Confère au lanceur et à tous les alliés à proximité une force accrue pendant 45 secondes. +spell.ebwizardry:invisibility.desc=Rend le lanceur invisible pendant 30 secondes. +spell.ebwizardry:invoke_weather.desc=Change la météo dans le monde. +spell.ebwizardry:ironflesh.desc=Améliore considérablement la résistance aux dégâts du lanceur pendant 30 secondes. +spell.ebwizardry:leap.desc=Le lanceur effectue un super saut. +spell.ebwizardry:levitation.desc=Fait léviter le lanceur vers le haut pendant que le bouton d'utilisation est maintenu enfoncé. Annulera également les dégâts de chute si utilisé avant de heurter le sol. +spell.ebwizardry:life_drain.desc=Crée un flux d’énergie de wither dans la direction que vous visez qui draine la vie de la cible et l’utilise pour régénérer progressivement votre santé. +spell.ebwizardry:light.desc=Crée un point de lumière magique qui illumine les environs. Dure 30 secondes. +spell.ebwizardry:lightning_arrow.desc=Tire une flèche de foudre dans la direction que vous visez. +spell.ebwizardry:lightning_bolt.desc=Fait frapper la foudre là où vous visez. +spell.ebwizardry:lightning_disc.desc=Envoie un disque de foudre dans la direction que vous pointez, qui cherche des cibles. +spell.ebwizardry:lightning_hammer.desc="Je te frappe par la colère des cieux!" +spell.ebwizardry:lightning_pulse.desc=Charge le sol autour du lanceur avec la foudre, endommageant et repoussant les créatures proches. +spell.ebwizardry:lightning_ray.desc=Crée un flot de foudre dans la direction que vous pointez qui endommage continuellement les cibles. +spell.ebwizardry:lightning_sigil.desc=Place un piège de foudre magique sur le sol qui endommage la créature qui le déclenche et diffuse la foudre en chaine à d'autres créatures proches. +spell.ebwizardry:lightning_web.desc="Concentre-toi. Canalise la tempête dans ton esprit à travers ta baguette et déchaîne sa fureur." +spell.ebwizardry:magic_missile.desc=Tire un éclair d'énergie magique dans la direction que vous pointez. +spell.ebwizardry:metamorphosis.desc=Change la cible en une autre variante. Ne fonctionne que sur certaines créatures. +spell.ebwizardry:meteor.desc=Certains sorciers veulent juste voir le monde brûler ... +spell.ebwizardry:mind_control.desc=Prend le contrôle de l'esprit de la cible pendant 30 secondes, la faisant changer de côté et se battre pour le lanceur à sa place. Ne fonctionnera pas sur des créatures à la volonté trop forte. +spell.ebwizardry:mind_trick.desc=Confond et désoriente la cible pendant 15 secondes, la rendant incapable d’attaquer efficacement. L'effet sera dissipé si la cible subit des dégâts. +spell.ebwizardry:none.desc=Pour obtenir un livre de sorts avec la commande / give, utilisez les métadonnées: / give [joueur] ebwizardry: spell_book 1 [nom de sort] (si vous avez trouvé ce livre dans un coffre, un autre mod a tout gâché). +spell.ebwizardry:oakflesh.desc=Améliore la résistance aux dégâts du lanceur pendant 30 secondes. +spell.ebwizardry:petrify.desc=Transforme la cible en pierre jusqu'à ce qu'elle soit éclatée, avec une chance pour qu'elle éclate quand il fait noir. La cible ne peut ni bouger ni faire quoi que ce soit tant qu'elle est pétrifiée, mais est également insensible à tous les dégâts. +spell.ebwizardry:phase_step.desc=Téléporte le lanceur à travers un mur épais d'un bloc devant eux. Les améliorations de portée augmenteront l'épaisseur à travers laquelle vous pourrez vous téléporter. +spell.ebwizardry:plague_of_darkness.desc=Les ténèbres les dévoreront tous ... +spell.ebwizardry:pocket_furnace.desc=Fait cuire jusqu'à 5 objets dans l'inventaire du lanceur. Les objets sur la barre de raccourci seront cuit en premier. +spell.ebwizardry:pocket_workbench.desc=Permet au lanceur de fabriquer des objets comme s'il était à une table d'artisanat. +spell.ebwizardry:poison.desc=Tire du poison dans la direction que vous pointez. +spell.ebwizardry:poison_bomb.desc=Lance une bombe empoisonnée dans la direction que vous visez, qui explose à l’impact et empoisonne les créatures proches. +spell.ebwizardry:replenish_hunger.desc=Remonte le niveau de nourriture du lanceur de 6 points de stamina. +spell.ebwizardry:ring_of_fire.desc=Crée un anneau de feu autour du lanceur, infligeant des dégâts à tous les ennemis proches et les incendiant. +spell.ebwizardry:shadow_ward.desc=Crée un mur de ténèbres devant le lanceur de sorts, qui inflige la moitié des dégâts à l'attaquant. +spell.ebwizardry:shield.desc=Crée une barrière protectrice de force qui bloque les projectiles et la magie. Confère également au lanceur un faible effet de résistance. +spell.ebwizardry:shockwave.desc=Boom. +spell.ebwizardry:silverfish_swarm.desc="Ahhhh! Ils se MULTIPLIENT!" +spell.ebwizardry:sixth_sense.desc=Permet au lanceur de détecter les emplacements des créatures proches, même à travers les murs, pendant 20 secondes. +spell.ebwizardry:slime.desc=Embourbe la cible dans la boue qui le ralentit et l’endommage continuellement. La boue éclate après 10 secondes. +spell.ebwizardry:smoke_bomb.desc=Lance une bombe de fumée dans la direction que vous pointez qui explose sous l’impact, libérant de la fumée et aveuglant les créatures à proximité pendant un court instant. +spell.ebwizardry:snare.desc=Met au sol un piège qui endommage et ralentit brièvement la créature qui le déclenche. +spell.ebwizardry:snowball.desc=Lance une boule de neige dans la direction que vous visez. +spell.ebwizardry:spark_bomb.desc=Lance une charge de choc dans la direction que vous pointez, ce qui libère des étincelles chez les ennemis proches lors de l’impact. +spell.ebwizardry:spectral_pathway.desc=Crée devant vous un pont magique indestructible qui s'étend sur 15 blocs. Le pont disparaît après 60 secondes. +spell.ebwizardry:spider_swarm.desc=Invoque un essaim d'araignées venimeuses qui se battent pour vous. Les araignées disparaîtront au bout de 30 secondes ou si elles sont tuées. +spell.ebwizardry:static_aura.desc=Entoure le lanceur avec un éclair pendant 30 secondes, projetant une étincelle sur tout ce qui le frappe. +spell.ebwizardry:summon_blaze.desc=Invoque un blaze pour se battre à vos côtés. Le blaze disparaîtra après 30 secondes ou s'il est tué. +spell.ebwizardry:summon_ice_giant.desc="Ecrasez les !" +spell.ebwizardry:summon_ice_wraith.desc=Invoque un spectre de glace qui se bat pour vous. Le spectre de glace disparaîtra après 30 secondes ou s'il est tué. +spell.ebwizardry:summon_iron_golem.desc=Automate autonome automatiquement automatisé. +spell.ebwizardry:summon_lightning_wraith.desc=Invoque un spectre de foudre pour qu'il se batte pour vous. Le spectre de foudre disparaîtra au bout de 30 secondes ou s'il est tué. +spell.ebwizardry:summon_phoenix.desc=De la cendre ... +spell.ebwizardry:summon_shadow_wraith.desc=Invoque un spectre de l'ombre qui se bat pour vous. +spell.ebwizardry:summon_skeleton.desc=Invoque un squelette pour qu'il se batte pour vous. Le squelette disparaîtra après 30 secondes ou s'il est tué. +spell.ebwizardry:summon_skeleton_legion.desc="Lèvez-vous, armée de morts-vivants!" +spell.ebwizardry:summon_snow_golem.desc=Crée un golem de neige qui se bat pour vous. Dure jusqu'à la mort du golem des neiges. +spell.ebwizardry:summon_spirit_horse.desc=Invoque un cheval spirituel à monter. Le cheval spirituel disparaîtra peu de temps après en être descendu, ou vous pouvez le renvoyer en faisant un shift-clic droit dessus avec n'importe quelle baguette. +spell.ebwizardry:summon_spirit_wolf.desc=Invoque un loup spirituel qui se bat pour vous. L'esprit loup ne disparaîtra que s'il est tué, ou vous pouvez le renvoyer en faisant un shift-clic droit dessus avec n'importe quelle baguette. +spell.ebwizardry:summon_storm_elemental.desc="Elementaire de foudre: Une ancienne manifestation des éléments, il peut difficilement contenir la puissance brute qu'il contient." - Le guide du sorcier sur les êtres arcaniques, volume I_i +spell.ebwizardry:summon_wither_skeleton.desc=Invoque un squelette wither qui se bat pour vous. Le squelette flétri disparaîtra après 30 secondes ou s'il est tué. +spell.ebwizardry:summon_zombie.desc=Invoque un zombie pour qu'il se batte pour vous. Le zombie disparaîtra au bout de 30 secondes ou s'il est tué. +spell.ebwizardry:telekinesis.desc=Déplace un objet ou un autre petit objet vers vous, ou cliquez avec le bouton droit sur le bloc que vous regardez. Peut également être utilisé pour désarmer les joueurs. +spell.ebwizardry:thunderbolt.desc=Tire un coup de tonnerre qui repousse les cibles. +spell.ebwizardry:thunderstorm.desc="Mwahahahahahaha!" +spell.ebwizardry:tornado.desc=Libère une tornade dans la direction que vous pointez qui projette tout ce qui se trouve sur son chemin vers le ciel. +spell.ebwizardry:transience.desc=Rend la lanceur éthéré pendant 20 secondes. Le lanceur est à l'abri de tous les dégâts en forme éthérée mais ne peut pas casser, placer de blocs ou causer des dégâts. +spell.ebwizardry:transportation.desc=Transporte le lanceur vers son cercle de pierres mémorisé. Pour utiliser ce sort, faites un cercle de pierres de transport, puis faites un clic droit dessus avec une baguette. +spell.ebwizardry:vanishing_box.desc=Donne au lanceur accès à son coffre de l'end. +spell.ebwizardry:wall_of_frost.desc=L'hiver au bout des doigts. +spell.ebwizardry:water_breathing.desc=Permet au lanceur de respirer sous l'eau pendant 60 secondes. +spell.ebwizardry:whirlwind.desc=Propulse la cible. +spell.ebwizardry:wither.desc=Tire un rayon d'obscurité qui inflige l'effet wither à tout ce qu'il touche. +spell.ebwizardry:wither_skull.desc=Lance un crâne de wither dans la direction que vous pointez. + +spell.ebwizardry:invoke_weather.sun=La pluie a cessé... +spell.ebwizardry:invoke_weather.rain=Le ciel se couvre... +spell.ebwizardry:transportation.missing=Vos pierres de téléportation sont obstruées ou inaccessible +spell.ebwizardry:transportation.undefined=Vous devez vous lier à un cercle de pierre de téléportation avant! +spell.ebwizardry:transportation.wrongdimension=Votre cercle de téléportation est dans une autre dimension... +spell.ebwizardry:clairvoyance.searching=Recherche... +spell.ebwizardry:clairvoyance.confirm=Une marque a été laissé. Utilisez le sort %1$s pour vous montrer le chemin pour y revenir plus tard. +spell.ebwizardry:clairvoyance.outofrange=La marque est trop loin ou est inaccessible... +spell.ebwizardry:clairvoyance.undefined=Vous devez dabord deposer une marque avec sneak-clic droit! +spell.ebwizardry:clairvoyance.wrongdimension=Votre marque est dans une dimension... + +potion.ebwizardry:frost=Morsure du froid +potion.ebwizardry:fireskin=Aura de feu +potion.ebwizardry:ice_shroud=Aura de glace +potion.ebwizardry:static_aura=Aura electrique +potion.ebwizardry:transience=Forme etheree +potion.ebwizardry:decay=Decomposition +potion.ebwizardry:sixth_sense=Sixième sense +potion.ebwizardry:arcane_jammer=Pertubation arcanique +potion.ebwizardry:mind_trick=Confusion +potion.ebwizardry:mind_control=Hypnose +potion.ebwizardry:font_of_mana=Fontaine de mana +potion.ebwizardry:fear=Peur + +enchantment.ebwizardry:magic_sword=Imprégné +enchantment.ebwizardry:magic_bow=Imprégné +enchantment.ebwizardry:flaming_weapon=Imprégné de feu +enchantment.ebwizardry:freezing_weapon=Imprégné de gel + +key.categories.ebwizardry=Wizardry + +key.ebwizardry.next_spell=Prochain sort +key.ebwizardry.previous_spell=Sort précédent + +death.attack.wizardry_magic=%1$s a été tué par %2$s avec de la magie +death.attack.indirect_wizardry_magic=%1$s a été tué par %2$s avec de la magie + +commands.ebwizardry:cast.usage=/%1$s [joueur] [multiplicateur dommage] [multiplicateur distance] [multiplicateur durée] [multiplicateur explosion] +commands.ebwizardry:cast.success=Sort %1$s lancé avec succès +commands.ebwizardry:cast.success_continuous=Sort %1$s lancé; recommencer la commande pour arreter +commands.ebwizardry:cast.success_remote=Sort %1$s lancé en tant que %2$s +commands.ebwizardry:cast.success_remote_continuous=Sort %1$s lancé en tant que %2$s; recommencer la commande pour arreter +commands.ebwizardry:cast.fail=Impossible de lancer %1$s +commands.ebwizardry:cast.not_found=Il n'y a pas de sort avec le nom %1$s +commands.ebwizardry:cast.tag_error=L'analyse des balises de données a échoué: %s + +commands.ebwizardry:ally.usage=/%1$s [joueur] +commands.ebwizardry:ally.addally=%1$s a été ajouté à la liste d'alliés de %2$s +commands.ebwizardry:ally.removeally=%1$s a été retiré de la liste d'alliés de %2$s +commands.ebwizardry:ally.self=Les joueurs ne peuvent pas être allié à eux même! +commands.ebwizardry:ally.permission=Vous n'avez pas la permission de changer les alliés des autres joueurs + +commands.ebwizardry:allies.usage=/%1$s [joueur] +commands.ebwizardry:allies.list=Vos alliés %1$s +commands.ebwizardry:allies.list_other=Joueurs alliés de %1$s: %2$s +commands.ebwizardry:allies.permission=Vous n'avez pas la permission de voir les alliés des autres +commands.ebwizardry:allies.none=Aucun + +commands.ebwizardry:discoverspell.usage=/%1$s [joueur] +commands.ebwizardry:discoverspell.not_found=Il n'y a pas de sort avec le nom: %1$s +commands.ebwizardry:discoverspell.clear=%1$s a oublié tout ses sortilèges +commands.ebwizardry:discoverspell.all=%1$s a appris tout les sortilèges +commands.ebwizardry:discoverspell.addspell=Ajout de %1$s à la mémoire de %2$s +commands.ebwizardry:discoverspell.removespell=Retrait de %1$s à la mémoire %2$s + +config.ebwizardry.title.general=Mod Options + +config.ebwizardry.category.gameplay=Paramètre de gameplay +config.ebwizardry.category.gameplay.tooltip=Configuration général de wizardry +config.ebwizardry.title.gameplay=Paramètre de gameplay +config.ebwizardry.subtitle.gameplay=Paramètres globaux qui affecte les mécaniques de jeu + +config.ebwizardry.category.worldgen=Paramètre de génération de monde +config.ebwizardry.category.worldgen.tooltip=Configuration des paramètre de génération de wizardry +config.ebwizardry.title.worldgen=Paramètre de génération de monde +config.ebwizardry.subtitle.worldgen=Paramètres qui affecte la génération du monde + +config.ebwizardry.category.commands=Paramètre de commande +config.ebwizardry.category.commands.tooltip=Configuration des commandes de wizardry +config.ebwizardry.title.commands=Paramètre de commande +config.ebwizardry.subtitle.commands=Paramètres pour les commandes ajoutés par wizardry + +config.ebwizardry.category.client=Paramètre personnel +config.ebwizardry.category.client.tooltip=Configuration coté client +config.ebwizardry.title.client=Paramètre personnel +config.ebwizardry.subtitle.client=Paramètres personnel qui n'affecte que votre jeu et non le serveur + +config.ebwizardry.category.spells=Configuration des sortilèges +config.ebwizardry.category.spells.tooltip=Selection du sort activé +config.ebwizardry.title.spells=Configuration des sortilèges +config.ebwizardry.subtitle.spells=Mettez un sort sur 'false' pour le desactiver + +config.ebwizardry.category.resistances=Configuration de la resistance +config.ebwizardry.category.resistances.tooltip=Configuration de quel mob est resistant a quel type de magie +config.ebwizardry.title.resistances=Configuration de la resistance +config.ebwizardry.subtitle.resistances=Paramètres permettant à certain monstres d'être résistant à tel sort + +config.ebwizardry.tower_rarity=Rareté des tours de sorcier +config.ebwizardry.ore_dimensions=Rareté des minerais +config.ebwizardry.flower_dimensions=Rareté des fleurs de cristal +config.ebwizardry.tower_dimensions=Rareté des tours +config.ebwizardry.spell_book_drop_chance=Chance de loot des livres de sorts +config.ebwizardry.generate_loot=Generation de loot +config.ebwizardry.firebomb_is_craftable=Bombe de feu fabricable +config.ebwizardry.poison_bomb_is_craftable=Bombe de poison fabricable +config.ebwizardry.smoke_bomb_is_craftable=Bombe de fumée fabricable +config.ebwizardry.use_alternate_scroll_recipe=Utilisation alternative de la recette du parchemin +config.ebwizardry.teleport_through_unbreakable_blocks=Teleportation au travers des blocs indestructible +config.ebwizardry.show_summoned_creature_names=Montrer les noms des invocations +config.ebwizardry.friendly_fire=Friendly Fire +config.ebwizardry.telekinetic_disarmament=Desarmement avec le sort de telekinesie +config.ebwizardry.discovery_mode=Mode decouverte +config.ebwizardry.enable_shift_scrolling=Permettre le Shift-scrolling +config.ebwizardry.minion_revenge_targeting=Les sbires peuvent se venger +config.ebwizardry.player_damage_scaling=Degats en fonction du joueur +config.ebwizardry.npc_damage_scaling=Degats en fonction du npc +config.ebwizardry.cast_command_multiplier_limit=Limite de multiplieur de la commande de cast +config.ebwizardry.summoned_creature_targets_whitelist=Whitelist des creatures ciblé par les invocations +config.ebwizardry.summoned_creature_targets_blacklist=Blacklist des creatures ciblé par les invocations +config.ebwizardry.spell_hud_position=Sortilège HUD Position +config.ebwizardry.cast_command_name=Nom de la commande de cast +config.ebwizardry.discoverspell_command_name=Nom de la commande de decouverte de sort +config.ebwizardry.ally_command_name=Nom de la commande pour s'ajouter des alliés +config.ebwizardry.allies_command_name=Nom de la commande pour voir les alliés +config.ebwizardry.mind_control_targets_blacklist=Blacklist des entités pouvant être controlé +config.ebwizardry.evil_wizard_dimensions=Dimension des sorcier maléfique + +config.ebwizardry.mobs_immune_to_fire=Monstre immunisé au feu +config.ebwizardry.mobs_immune_to_ice=Monstre immunisé à la glace +config.ebwizardry.mobs_immune_to_lightning=Monstre immunisé à la foudre +config.ebwizardry.mobs_immune_to_wither=Monstre immunisé au wither +config.ebwizardry.mobs_immune_to_poison=Monstre immunisé au poison + +config.ebwizardry.tower_rarity.tooltip=Rareté des tour de sorcier. Plus le chiffre est élevé, plus les tours sont rare. mettez la valeur sur 0 pour desactiver les tours completement. +config.ebwizardry.ore_dimensions.tooltip=La liste des dimensions où les minerais de cristaux peuvent apparaitre. Note: Enlever l'overworld (id:0) rendra le mod tres difficile! +config.ebwizardry.flower_dimensions.tooltip=La liste des dimensions où les fleurs de cristal peuvent apparaitre. +config.ebwizardry.tower_dimensions.tooltip=La liste des dimensions où les tours de sorcier peuvent apparaitre. +config.ebwizardry.spell_book_drop_chance.tooltip=La chance que les monstres drop un livre de sort. Plus le chiffre est élevé, plus vous avez de chance d'en loot. Valeur sur 0 = Aucun loot, valeur sur 200 = loot assuré +config.ebwizardry.generate_loot.tooltip=Generation des loot de wizardry dans les coffre de donjon ou non +config.ebwizardry.firebomb_is_craftable.tooltip=Frabrication des bombes de feu ou non +config.ebwizardry.poison_bomb_is_craftable.tooltip=Frabrication des bombes de poison ou non +config.ebwizardry.smoke_bomb_is_craftable.tooltip=Frabrication des bombes de fumée ou non +config.ebwizardry.use_alternate_scroll_recipe.tooltip=Ajouter ou non un cristal magic a la recette des parchemins. Mettez la valeur sur true si il y a un conflit. +config.ebwizardry.teleport_through_unbreakable_blocks.tooltip=Teleportation possible ou non au traver des blocs indestructible(exemple bedrock) en utilisant le sort de passe muraille. (phase) +config.ebwizardry.show_summoned_creature_names.tooltip=Montrer ou non le nom des créatures invoqué ainsi que ceux de leur invocateur au dessus de celle-ci +config.ebwizardry.friendly_fire.tooltip=Autorise ou non les joueurs à blesser leurs alliés avec de la magie. +config.ebwizardry.telekinetic_disarmament.tooltip=Autorise ou non un joueur à desarmer un autre joueur avec le sort de telekinesie (false pour empecher les vols) +config.ebwizardry.discovery_mode.tooltip=Pour ceux qui aime un peu de mystères! Mettez la valeur sur true pour cacher le nom des sorts jusqu'a leur utilisation. Si la valeur est sur false, les parchemins d'identification ne pourrons plus être obtenable en survie. +config.ebwizardry.enable_shift_scrolling.tooltip=Configuration client, n'affecte pas les autres joueurs. Permet de switcher facilement entre les sorts en maintenant sneak et en scrollant la roulette de la souris. +config.ebwizardry.minion_revenge_targeting.tooltip=Vengeance ou non des invocations sur les invocateur si ceux ci les ont attaqué +config.ebwizardry.player_damage_scaling.tooltip=Facteur d’échelle de dommage global pour les dégâts infligés par les joueurs qui lancent des sorts, par rapport à 1. +config.ebwizardry.npc_damage_scaling.tooltip=Facteur d'échelle de dégâts global pour les dégâts infligés par les PNJ qui lancent des sorts, par rapport à 1. +config.ebwizardry.cast_command_multiplier_limit.tooltip=Limite supérieure pour les multiplicateurs passés dans la commande / cast. Ceci existe pour empêcher les joueurs de casser accidentellement un monde / serveur. Les multiplicateurs de grosses explosions peuvent causer un lag extrême - vous avez été prévenu! +config.ebwizardry.summoned_creature_targets_whitelist.tooltip=Liste des noms des entités que les créatures invoquées et les sorciers sont autorisés à attaquer, en plus des valeurs par défaut. Ajoutez des créatures de mod à cette liste si vous voulez que les créatures invoquées les attaquent et qu'elles ne le font pas déjà. Les noms d'entité ne sont pas sensibles à la case. Pour les entités de mod, préfixez l’ID du mod (par exemple, ebwizardry:wizard). +config.ebwizardry.summoned_creature_targets_blacklist.tooltip=Liste des noms des entités que les créatures invoquées et les sorciers ont l'interdiction d'attaquer, outrepassant ainsi les valeurs par défaut et la liste blanche. Ajouter des créatures à cette liste si les laisser se faire attaquer provoque des problèmes ou est trop destructif (le retrait des creeper de cette liste se fait à vos risques et périls!). Les noms d'entité ne sont pas sensibles à la case. Pour les entités de mod, préfixez l’ID du mod (par exemple, ebwizardry:wizard). +config.ebwizardry.spell_hud_position.tooltip=La position du HUD des sorts. +config.ebwizardry.cast_command_name.tooltip=Le nom de la commande /cast. C'est ce que vous tapez directement après le /; Par exemple, si cela était réglé sur 'magic', au lieu de taper /cast, vous taperiez plutôt /magic. +config.ebwizardry.discoverspell_command_name.tooltip=Le nom de la commande /discoverspell. C'est ce que vous tapez directement après le /; Par exemple, si cela était réglé sur 'magic', au lieu de taper /discoverspell, vous taperiez plutôt /magic. +config.ebwizardry.ally_command_name.tooltip=Le nom de la commande /ally. C'est ce que vous tapez directement après le /; Par exemple, si cette option est définie sur 'magic', au lieu de taper /allié, vous devez taper /magic à la place. +config.ebwizardry.allies_command_name.tooltip=Le nom de la commande /allies. C'est ce que vous tapez directement après le /; Par exemple, si cela était réglé sur 'magic', au lieu de taper /allies, vous taperiez plutôt /magic. +config.ebwizardry.mind_control_targets_blacklist.tooltip=Liste des noms d'entités qui ne peuvent pas être contrôlées par l'esprit, en plus des valeurs par défaut. Ajouter des créatures à cette liste si leur permettre d'être contrôlées par l'esprit crée des problèmes ou peut être exploité. Les noms d'entité ne sont pas sensibles à la case. Pour les entités de mod, préfixez l’ID du mod (par exemple, ebwizardry:wizard). +config.ebwizardry.evil_wizard_dimensions.tooltip=Liste des dimensions où les sorciers maléfiques peuvent apparaitre + +config.ebwizardry.mobs_immune_to_fire.tooltip=Liste des noms des entités immunisées au feu, en plus des valeurs par défaut. Ajoutez des créatures de mod à cette liste si vous voulez qu'elles soient immunisées à la magie de feu et qu'elles ne le sont pas déjà. Les noms d'entité ne sont pas sensibles à la case. Pour les entités de mod, préfixez l’ID du mod (par exemple, ebwizardry:wizard). +config.ebwizardry.mobs_immune_to_ice.tooltip=Liste des noms des entités immunisées contre la glace, en plus des valeurs par défaut. Ajoutez des créatures de mod à cette liste si vous voulez qu'elles soient immunisées contre la magie de glace et qu'elles ne le sont pas déjà. Les noms d'entité ne sont pas sensibles à la case. Pour les entités de mod, préfixez l’ID du mod (par exemple, ebwizardry:wizard). +config.ebwizardry.mobs_immune_to_lightning.tooltip=Liste des noms des entités immunisées contre la foudre, en plus des valeurs par défaut. Ajoutez des créatures de mod à cette liste si vous voulez qu'elles soient immunisées contre la magie de foudre et qu'elles ne le sont pas déjà. Les noms d'entité ne sont pas sensibles à la case. Pour les entités de mod, préfixez l’ID du mod (par exemple, ebwizardry:wizard).. +config.ebwizardry.mobs_immune_to_wither.tooltip=Liste des noms des entités immunisées contre l'effet wither, en plus des valeurs par défaut. Ajoutez des créatures de mod à cette liste si vous voulez qu'elles soient immunisées contre la magie de wither et qu'elles ne le sont pas déjà. Les noms d'entité ne sont pas sensibles à la case. Pour les entités de mod, préfixez l’ID du mod (par exemple, ebwizardry:wizard). +config.ebwizardry.mobs_immune_to_poison.tooltip=Liste des noms des entités immunisées contre le poison, en plus des valeurs par défaut. Ajoutez des créatures de mod à cette liste si vous voulez qu'elles soient immunisées contre la magie de poison et qu'elles ne le sont pas déjà. Les noms d'entité ne sont pas sensibles à la case. Pour les entités de mod, préfixez l’ID du mod (par exemple, ebwizardry:wizard). + +wizard.debug=%1$s, %2$s, %3$s diff --git a/src/main/resources/assets/ebwizardry/lang/ko_kr.lang b/src/main/resources/assets/ebwizardry/lang/ko_kr.lang new file mode 100644 index 00000000..468dd01f --- /dev/null +++ b/src/main/resources/assets/ebwizardry/lang/ko_kr.lang @@ -0,0 +1,760 @@ +tile.ebwizardry:arcane_workbench.name=아케인 작업대 +tile.ebwizardry:crystal_ore.name=수정 광석 +tile.ebwizardry:petrified_stone.name=석화된 돌 +tile.ebwizardry:ice_statue.name=얼음 기둥 +tile.ebwizardry:crystal_flower.name=수정 꽃 +tile.ebwizardry:snare.name=덫 +tile.ebwizardry:transportation_stone.name=전이의 돌 +tile.ebwizardry:spectral_block.name=허상 블록 +tile.ebwizardry:crystal_block.name=수정 블록 + +item.ebwizardry:magic_crystal.name=마법 수정 +item.ebwizardry:magic_wand.name=시작의 지팡이 +item.ebwizardry:apprentice_wand.name=마법 지팡이 +item.ebwizardry:advanced_wand.name=고급 지팡이 +item.ebwizardry:master_wand.name=대가의 지팡이 +item.ebwizardry:spell_book.name=주문서 + +item.ebwizardry:arcane_tome.name=마도서 +item.ebwizardry:arcane_tome.desc1=아무 %1$s 지팡이를 +item.ebwizardry:arcane_tome.desc2=%1$s급으로 강화합니다 + +item.ebwizardry:wizard_handbook.name=마법사의 안내서 +item.ebwizardry:wizard_handbook.desc=by %1$s + +item.ebwizardry:wand.buff=+%1$s %2$s 강화 +item.ebwizardry:wand.spell=대기중인 주문: %1$s +item.ebwizardry:wand.mana=마나: %1$s/%2$s + +item.ebwizardry:wand.addally=%1$s has been added to your list of allies +item.ebwizardry:wand.removeally=%1$s has been removed from your list of allies + +item.ebwizardry:basic_fire_wand.name=따뜻한 지팡이 +item.ebwizardry:basic_ice_wand.name=차가운 지팡이 +item.ebwizardry:basic_lightning_wand.name=먹구름 지팡이 +item.ebwizardry:basic_necromancy_wand.name=음산한 지팡이 +item.ebwizardry:basic_earth_wand.name=단단한 지팡이 +item.ebwizardry:basic_sorcery_wand.name=신기한 지팡이 +item.ebwizardry:basic_healing_wand.name=온화한 지팡이 + +item.ebwizardry:apprentice_fire_wand.name=불꽃 지팡이 +item.ebwizardry:apprentice_ice_wand.name=서리 지팡이 +item.ebwizardry:apprentice_lightning_wand.name=번개 지팡이 +item.ebwizardry:apprentice_necromancy_wand.name=그림자 지팡이 +item.ebwizardry:apprentice_earth_wand.name=숲의 지팡이 +item.ebwizardry:apprentice_sorcery_wand.name=힘의 지팡이 +item.ebwizardry:apprentice_healing_wand.name=기력의 지팡이 + +item.ebwizardry:advanced_fire_wand.name=화염 지팡이 +item.ebwizardry:advanced_ice_wand.name=얼음 지팡이 +item.ebwizardry:advanced_lightning_wand.name=벼락 지팡이 +item.ebwizardry:advanced_necromancy_wand.name=암흑 지팡이 +item.ebwizardry:advanced_earth_wand.name=대지 지팡이 +item.ebwizardry:advanced_sorcery_wand.name=환영 지팡이 +item.ebwizardry:advanced_healing_wand.name=치유 지팡이 + +item.ebwizardry:master_fire_wand.name=겁화의 지팡이 +item.ebwizardry:master_ice_wand.name=빙결의 지팡이 +item.ebwizardry:master_lightning_wand.name=폭풍의 지팡이 +item.ebwizardry:master_necromancy_wand.name=심연의 지팡이 +item.ebwizardry:master_earth_wand.name=자연의 지팡이 +item.ebwizardry:master_sorcery_wand.name=미지의 지팡이 +item.ebwizardry:master_healing_wand.name=성자의 지팡이 + +item.ebwizardry:spectral_sword.name=허상의 검 +item.ebwizardry:spectral_pickaxe.name=허상의 곡괭이 +item.ebwizardry:spectral_bow.name=허상의 활 + +item.ebwizardry:mana_flask.name=마나 플라스크 +item.ebwizardry:storage_upgrade.name=마나 수용량 증가 +item.ebwizardry:siphon_upgrade.name=Wand Siphon Upgrade +item.ebwizardry:condenser_upgrade.name=마력 수복 +item.ebwizardry:range_upgrade.name=주문 사거리 증가 +item.ebwizardry:duration_upgrade.name=지속시간 증가 +item.ebwizardry:cooldown_upgrade.name=Wand Cooldown Upgrade +item.ebwizardry:blast_upgrade.name=Wand Blast Upgrade +item.ebwizardry:attunement_upgrade.name=주문 허용량 증가 + +item.ebwizardry:flaming_axe.name=불타오르는 도끼 +item.ebwizardry:frost_axe.name=얼어붙은 도끼 + +item.ebwizardry:firebomb.name=화염탄 +item.ebwizardry:poison_bomb.name=독 폭탄 +item.ebwizardry:smoke_bomb.name=연막탄 + +item.ebwizardry:blank_scroll.name=빈 두루마리 +item.ebwizardry:scroll.name=%1$s의 두루마리 +item.ebwizardry:scroll.undiscovered.name=Scroll "%1$s" +item.ebwizardry:identification_scroll.name=지식의 두루마리 +item.ebwizardry:identification_scroll.desc1=%1$s주문서나 두루마리를 +item.ebwizardry:identification_scroll.desc2=%1$s확인할 수 있습니다 +item.ebwizardry:identification_scroll.nothing_to_identify=알아볼 주문이 없습니다! + +item.ebwizardry:armour_upgrade.name=보호의 문양 +item.ebwizardry:armour_upgrade.desc1=%1$s아무 마법사의 보호구를 +item.ebwizardry:armour_upgrade.desc2=%1$s전설급으로 강화합니다 + +item.ebwizardry:magic_silk.name=마법 천 + +item.ebwizardry:wizard_armour.legendary=전설급 +item.ebwizardry:wizard_armour.buff=-%1$s %2$s 비용 +item.ebwizardry:wizard_armour.mana=마나: %1$s/%2$s + +item.ebwizardry:wizard_hat.name=마법사 모자 +item.ebwizardry:wizard_robe.name=마법사 로브 +item.ebwizardry:wizard_leggings.name=마법사 바지 +item.ebwizardry:wizard_boots.name=마법사 부츠 + +item.ebwizardry:wizard_hat_fire.name=화염술사의 모자 +item.ebwizardry:wizard_robe_fire.name=화염술사의 로브 +item.ebwizardry:wizard_leggings_fire.name=화염술사의 바지 +item.ebwizardry:wizard_boots_fire.name=화염술사의 부츠 + +item.ebwizardry:wizard_hat_ice.name=빙결술사의 모자 +item.ebwizardry:wizard_robe_ice.name=빙결술사의 로브 +item.ebwizardry:wizard_leggings_ice.name=빙결술사의 바지 +item.ebwizardry:wizard_boots_ice.name=빙결술사의 부츠 + +item.ebwizardry:wizard_hat_lightning.name=전격술사의 모자 +item.ebwizardry:wizard_robe_lightning.name=전격술사의 로브 +item.ebwizardry:wizard_leggings_lightning.name=전격술사의 바지 +item.ebwizardry:wizard_boots_lightning.name=전격술사의 부츠 + +item.ebwizardry:wizard_hat_necromancy.name=사령술사의 모자 +item.ebwizardry:wizard_robe_necromancy.name=사령술사의 로브 +item.ebwizardry:wizard_leggings_necromancy.name=사령술사의 바지 +item.ebwizardry:wizard_boots_necromancy.name=사령술사의 부츠 + +item.ebwizardry:wizard_hat_earth.name=자연술사의 모자 +item.ebwizardry:wizard_robe_earth.name=자연술사의 로브 +item.ebwizardry:wizard_leggings_earth.name=자연술사의 바지 +item.ebwizardry:wizard_boots_earth.name=자연술사의 부츠 + +item.ebwizardry:wizard_hat_sorcery.name=신비술사의 모자 +item.ebwizardry:wizard_robe_sorcery.name=신비술사의 로브 +item.ebwizardry:wizard_leggings_sorcery.name=신비술사의 바지 +item.ebwizardry:wizard_boots_sorcery.name=신비술사의 부츠 + +item.ebwizardry:wizard_hat_healing.name=치유사의 모자 +item.ebwizardry:wizard_robe_healing.name=치유사의 로브 +item.ebwizardry:wizard_leggings_healing.name=치유사의 바지 +item.ebwizardry:wizard_boots_healing.name=치유사의 부츠 + +item.ebwizardry:spawn_wizard.name=마법사 소환 +item.ebwizardry:spawn_evil_wizard.name=사악한 마법사 소환 + +item.ebwizardry:spectral_helmet.name=허상의 투구 +item.ebwizardry:spectral_chestplate.name=허상의 흉갑 +item.ebwizardry:spectral_leggings.name=허상의 각반 +item.ebwizardry:spectral_boots.name=허상의 부츠 + +entity.ebwizardry:summonedcreature.nameplate=%1$s의 %2$s +entity.ebwizardry:summonedcreature.nameplate_fallback=누군가의 %1$s + +entity.ebwizardry:zombie_minion.name=좀비 +entity.ebwizardry:skeleton_minion.name=스켈레톤 +entity.ebwizardry:spider_minion.name=독 거미 +entity.ebwizardry:blaze_minion.name=블레이즈 +entity.ebwizardry:wither_skeleton_minion.name=위더 스켈레톤 +entity.ebwizardry:ice_wraith.name=빙령 +entity.ebwizardry:lightning_wraith.name=뇌령 +entity.ebwizardry:shadow_wraith.name=암령 +entity.ebwizardry:spirit_wolf.name=늑대 혼령 +entity.ebwizardry:spirit_horse.name=말 혼령 +entity.ebwizardry:ice_giant.name=얼음 거인 +entity.ebwizardry:phoenix.name=피닉스 +entity.ebwizardry:wizard.name=마법사 +entity.ebwizardry:magic_slime.name=마법 슬라임 +entity.ebwizardry:silverfish_minion.name=좀벌레 +entity.ebwizardry:storm_elemental.name=폭풍 정령 +entity.ebwizardry:evil_wizard.name=사악한 마법사 +entity.ebwizardry:decoy.name=분신 + +entity.ebwizardry:magic_missile.name=마법 +entity.ebwizardry:arc.name=마법 +entity.ebwizardry:spark_bomb.name=마법 +entity.ebwizardry:ice_shard.name=마법 +entity.ebwizardry:firebomb.name=마법 +entity.ebwizardry:poison_bomb.name=마법 +entity.ebwizardry:force_orb.name=마법 +entity.ebwizardry:spark.name=마법 +entity.ebwizardry:darkness_orb.name=마법 +entity.ebwizardry:fire_sigil.name=마법 +entity.ebwizardry:frost_sigil.name=마법 +entity.ebwizardry:lightning_sigil.name=마법 +entity.ebwizardry:lightning_arrow.name=마법 +entity.ebwizardry:firebolt.name=마법 +entity.ebwizardry:ice_charge.name=마법 +entity.ebwizardry:force_arrow.name=마법 +entity.ebwizardry:dart.name=마법 +entity.ebwizardry:lightning_disc.name=마법 +entity.ebwizardry:thunderbolt.name=마법 +entity.ebwizardry:decay.name=마법 +entity.ebwizardry:ice_lance.name=마법 +entity.ebwizardry:smoke_bomb.name=마법 +entity.ebwizardry:ice_spike.name=마법 + +entity.ebwizardry:black_hole.name=블랙홀 +entity.ebwizardry:shield.name=방어막 +entity.ebwizardry:meteor.name=메테오 +entity.ebwizardry:blizzard.name=눈보라 +entity.ebwizardry:bubble.name=물방울 +entity.ebwizardry:tornado.name=회오리바람 +entity.ebwizardry:lightning_hammer.name=벼락 망치 +entity.ebwizardry:arrow_rain.name=화살 세례 +entity.ebwizardry:healing_aura.name=치유 공간 +entity.ebwizardry:forcefield.name=역장 +entity.ebwizardry:ring_of_fire.name=화염의 고리 +entity.ebwizardry:earthquake.name=지진 +entity.ebwizardry:falling_grass.name=떨어지는 풀 +entity.ebwizardry:hailstorm.name=얼음 폭풍 +entity.ebwizardry:lightning_pulse.name=번개 파동 + +itemGroup.ebwizardry=마법의 길 +itemGroup.ebwizardryspells=주문 + +advancement.ebwizardry:root=마법의 길 +advancement.ebwizardry:root.desc=마도를 걷는 여정길 +advancement.ebwizardry:crystal=신기한 수정이군... +advancement.ebwizardry:crystal.desc=마법 수정을 캐세요 +advancement.ebwizardry:arcane_initiate=마법 시작! +advancement.ebwizardry:arcane_initiate.desc=황금 조각, 막대기, 마법 수정 한개로 마법 지팡이를 만드세요 +advancement.ebwizardry:apprentice=마법사의 제자 +advancement.ebwizardry:apprentice.desc=마도서를 사용해 지팡이를 강화하세요 +advancement.ebwizardry:master=마법의 대가 +advancement.ebwizardry:master.desc=대가의 지팡이를 얻으세요 +advancement.ebwizardry:all_spells=현자 +advancement.ebwizardry:all_spells.desc=모든 주문을 시전하세요 +advancement.ebwizardry:wizard_trade=마법 거래 +advancement.ebwizardry:wizard_trade.desc=마법사에게서 아이템 한개를 구입하세요 +advancement.ebwizardry:buy_master_spell=지식은 힘이다 +advancement.ebwizardry:buy_master_spell.desc=마법사에게서 대가의 주문을 구입하세요 +advancement.ebwizardry:freeze_blaze=이젠 안 뜨거워 +advancement.ebwizardry:freeze_blaze.desc=블레이즈를 얼리세요 +advancement.ebwizardry:charge_creeper=바람이 부나? +advancement.ebwizardry:charge_creeper.desc='사고로' 충전된 크리퍼를 만드세요 +advancement.ebwizardry:frankenstein=프랑켄슈타인 +advancement.ebwizardry:frankenstein.desc='벼락' 주문으로 돼지를 좀비 피그맨으로 만드세요 +advancement.ebwizardry:special_upgrade=마개조 +advancement.ebwizardry:special_upgrade.desc=지팡이에 특별한 개조를 하세요 +advancement.ebwizardry:craft_flask=플라스크 속의 마법 +advancement.ebwizardry:craft_flask.desc=마나 플라스크를 만드세요 +advancement.ebwizardry:elemental=속성? +advancement.ebwizardry:elemental.desc=속성 지팡이 한개를 얻으세요 +advancement.ebwizardry:armour_set=이제야 제대로 된 마법사 같네 +advancement.ebwizardry:armour_set.desc=마법사 방어구 세트를 입으세요 +advancement.ebwizardry:legendary=전설! +advancement.ebwizardry:legendary.desc=전설급 마법사 방어구 한개를 얻으세요 +advancement.ebwizardry:self_destruct=마법은 돌아오는 거야 +advancement.ebwizardry:self_destruct.desc=자신의 마법에 죽으세요 +advancement.ebwizardry:pig_tornado=다시는... +advancement.ebwizardry:pig_tornado.desc=돼지를 타고 토네이도로 뛰어드세요 +advancement.ebwizardry:jam_wizard=방해 시간 +advancement.ebwizardry:jam_wizard.desc='마법 방해' 주문을 마법사에게 사용하세요 +advancement.ebwizardry:slime_skeleton=끈적한 상황 +advancement.ebwizardry:slime_skeleton.desc=스켈레톤에게 슬라임을 씌우세요 +advancement.ebwizardry:anger_wizard=후회할걸 +advancement.ebwizardry:anger_wizard.desc=마법사를 화나게 하세요 +advancement.ebwizardry:defeat_evil_wizard=당연한 일이야 +advancement.ebwizardry:defeat_evil_wizard.desc=사악한 마법사를 물리치세요 +advancement.ebwizardry:max_out_wand=강력하군! +advancement.ebwizardry:max_out_wand.desc=대가의 지팡이를 한계까지 개조하세요 +advancement.ebwizardry:element_master=Element Mastery +advancement.ebwizardry:element_master.desc=Cast all the spells of any element +advancement.ebwizardry:identify_spell=마법 감정 +advancement.ebwizardry:identify_spell.desc=지식의 두루마리로 미확인 주문을 확인하세요 + +tile.ebwizardry:transportation_stone.confirm=이제 %1$s을 사용하면 이곳으로 귀환합니다. +tile.ebwizardry:transportation_stone.invalid=먼저 전이의 돌 8개로 귀환진을 만들어야 합니다. + +container.ebwizardry:arcane_workbench=아케인 작업대 +container.ebwizardry:arcane_workbench.apply=완료 +container.ebwizardry:arcane_workbench.mana=마나: +container.ebwizardry:arcane_workbench.upgrades=개조 내역: + +tier.basic=초보자 +tier.apprentice=견습생 +tier.advanced=숙련자 +tier.master=대가 + +element.simple=무 +element.fire=화염 +element.ice=빙결 +element.lightning=전격 +element.necromancy=사령 +element.earth=자연 +element.sorcery=신비 +element.healing=치유 + +element.simple.wizard=마법사 +element.fire.wizard=화염술사 +element.ice.wizard=빙결술사 +element.lightning.wizard=전격술사 +element.necromancy.wizard=사령술사 +element.earth.wizard=자연술사 +element.sorcery.wizard=신비술사 +element.healing.wizard=치유사 + +spelltype.attack=공격 +spelltype.defence=수비 +spelltype.utility=보조 +spelltype.minion=소환 + +spell.disabled=%1$s은 config에 의해 비활성화 되었습니다. +spell.resist=%1$s(이)가 %2$s에 저항했습니다 +spell.discover=%1$s 주문을 알아냈습니다! + +spell.ebwizardry:agility=민첩 강화 +spell.ebwizardry:arc=전격파 +spell.ebwizardry:arcane_jammer=마법 방해 +spell.ebwizardry:arrow_rain=화살 세례 +spell.ebwizardry:banish=강제 전이 +spell.ebwizardry:black_hole=블랙홀 +spell.ebwizardry:blink=점멸 +spell.ebwizardry:blizzard=눈보라 +spell.ebwizardry:bubble=물방울 +spell.ebwizardry:chain_lightning=연쇄 번개 +spell.ebwizardry:clairvoyance=자연의 인도 +spell.ebwizardry:cobwebs=옭아매는 거미줄 +spell.ebwizardry:conjure_armour=허상의 갑옷 +spell.ebwizardry:conjure_bow=허상의 활 +spell.ebwizardry:conjure_pickaxe=허상의 곡괭이 +spell.ebwizardry:conjure_sword=허상의 검 +spell.ebwizardry:cure_effects=회복의 바람 +spell.ebwizardry:curse_of_soulbinding=묶여있는 영혼 +spell.ebwizardry:darkness_orb=암흑의 보주 +spell.ebwizardry:darkvision=암흑 시야 +spell.ebwizardry:dart=다트 +spell.ebwizardry:decay=부패하는 역병 +spell.ebwizardry:decoy=분산 +spell.ebwizardry:detonate=폭렬 +spell.ebwizardry:diamondflesh=불멸의 신체 +spell.ebwizardry:earthquake=지진 +spell.ebwizardry:entrapment=공포의 손아귀 +spell.ebwizardry:fireball=화염구 +spell.ebwizardry:firebolt=화염 탄환 +spell.ebwizardry:firebomb=화염탄 +spell.ebwizardry:fire_resistance=화염 저항 +spell.ebwizardry:fire_sigil=불의 표식 +spell.ebwizardry:fireskin=불타는 피부 +spell.ebwizardry:firestorm=불의 세례 +spell.ebwizardry:flame_ray=불꽃 광선 +spell.ebwizardry:flaming_axe=타오르는도끼 +spell.ebwizardry:flaming_weapon=타오르는무기 +spell.ebwizardry:flight=창공의 가호 +spell.ebwizardry:font_of_mana=마나의 축복 +spell.ebwizardry:font_of_vitality=생명의 축복 +spell.ebwizardry:force_arrow=인력의 화살 +spell.ebwizardry:forcefield=역장 +spell.ebwizardry:force_orb=반발의 보주 +spell.ebwizardry:forests_curse=자연의 저주 +spell.ebwizardry:freeze=서리바람 +spell.ebwizardry:freezing_weapon=얼어붙은 무기 +spell.ebwizardry:frost_axe=얼어붙은 도끼 +spell.ebwizardry:frost_ray=서리 광선 +spell.ebwizardry:frost_sigil=냉기의 표식 +spell.ebwizardry:glide=바람의 호의 +spell.ebwizardry:greater_fireball=불덩이 작렬 +spell.ebwizardry:greater_heal=대 치유 +spell.ebwizardry:group_heal=광역 치유 +spell.ebwizardry:growth_aura=수확의 축복 +spell.ebwizardry:hailstorm=얼음 폭풍 +spell.ebwizardry:heal=치유 +spell.ebwizardry:heal_ally=치유의 손길 +spell.ebwizardry:healing_aura=차오르는 체력 +spell.ebwizardry:homing_spark=전기 추적자 +spell.ebwizardry:ice_age=빙하기 +spell.ebwizardry:ice_charge=얼음 폭탄 +spell.ebwizardry:ice_lance=얼음창 +spell.ebwizardry:ice_shard=얼음 화살 +spell.ebwizardry:ice_shroud=서리 가호 +spell.ebwizardry:ice_spikes=차가운 가시밭 +spell.ebwizardry:ice_statue=결빙 +spell.ebwizardry:ignite=모닥불 +spell.ebwizardry:imbue_weapon=마력 부여 +spell.ebwizardry:intimidate=공포 유발 +spell.ebwizardry:invigorating_presence=강력한 손아귀 +spell.ebwizardry:invisibility=투명화 +spell.ebwizardry:invoke_weather=뇌우 +spell.ebwizardry:ironflesh=강철같은 신체 +spell.ebwizardry:leap=도약 +spell.ebwizardry:levitation=중력 반발 +spell.ebwizardry:life_drain=생명력 흡수 +spell.ebwizardry:light=빛 +spell.ebwizardry:lightning_arrow=번개 화살 +spell.ebwizardry:lightning_bolt=벼락 +spell.ebwizardry:lightning_disc=번개의 고리 +spell.ebwizardry:lightning_hammer=벼락 망치 +spell.ebwizardry:lightning_pulse=번개 파동 +spell.ebwizardry:lightning_ray=번개 광선 +spell.ebwizardry:lightning_sigil=번개의 표식 +spell.ebwizardry:lightning_web=이어지는 번개 +spell.ebwizardry:magic_missile=마법 화살 +spell.ebwizardry:metamorphosis=형태의 변이 +spell.ebwizardry:meteor=메테오 +spell.ebwizardry:mind_control=정신지배 +spell.ebwizardry:mind_trick=정신착란 +spell.ebwizardry:none=[빈 주문] +spell.ebwizardry:oakflesh=나무의 단단함 +spell.ebwizardry:petrify=석화 +spell.ebwizardry:phase_step=벽 안의 길 +spell.ebwizardry:plague_of_darkness=잠식하는 어둠 +spell.ebwizardry:pocket_furnace=마법 화로 +spell.ebwizardry:pocket_workbench=허상 작업대 +spell.ebwizardry:poison=독 +spell.ebwizardry:poison_bomb=독 폭탄 +spell.ebwizardry:replenish_hunger=풍족한 식사 +spell.ebwizardry:ring_of_fire=화염의 고리 +spell.ebwizardry:shadow_ward=마주하는 고통 +spell.ebwizardry:shield=방어막 +spell.ebwizardry:shockwave=충격 파동 +spell.ebwizardry:silverfish_swarm=소환 : 좀벌레 무리 +spell.ebwizardry:sixth_sense=제육감 +spell.ebwizardry:slime=바람의 거부 +spell.ebwizardry:smoke_bomb=연막탄 +spell.ebwizardry:snare=구속의 올가미 +spell.ebwizardry:snowball=눈덩이 +spell.ebwizardry:spark_bomb=전기 폭탄 +spell.ebwizardry:spectral_pathway=허상의 길 +spell.ebwizardry:spider_swarm=늪의 분노 +spell.ebwizardry:static_aura=벼락의 기운 +spell.ebwizardry:summon_blaze=소환 : 블레이즈 +spell.ebwizardry:summon_ice_giant=소환 : 얼음 거인 +spell.ebwizardry:summon_ice_wraith=소환 : 빙령 +spell.ebwizardry:summon_iron_golem=소환 : 철 골렘 +spell.ebwizardry:summon_lightning_wraith=소환 : 뇌령 +spell.ebwizardry:summon_phoenix=소환 : 피닉스 +spell.ebwizardry:summon_shadow_wraith=소환 : 암령 +spell.ebwizardry:summon_skeleton=소환 : 스켈레톤 +spell.ebwizardry:summon_skeleton_legion=소환 : 스켈레톤 군단 +spell.ebwizardry:summon_snow_golem=소환 : 눈 골렘 +spell.ebwizardry:summon_spirit_horse=소환 : 말 혼령 +spell.ebwizardry:summon_spirit_wolf=소환 : 늑대 혼령 +spell.ebwizardry:summon_storm_elemental=소환 : 폭풍 정령 +spell.ebwizardry:summon_wither_skeleton=소환 : 위더 스켈레톤 +spell.ebwizardry:summon_zombie=소환 : 좀비 +spell.ebwizardry:telekinesis=염동력 +spell.ebwizardry:thunderbolt=번개 충격 +spell.ebwizardry:thunderstorm=번개폭풍 +spell.ebwizardry:tornado=회오리바람 +spell.ebwizardry:transience=공허의 보호 +spell.ebwizardry:transportation=귀환 +spell.ebwizardry:vanishing_box=아공간 +spell.ebwizardry:wall_of_frost=서리 장벽 +spell.ebwizardry:water_breathing=수중 호흡 +spell.ebwizardry:whirlwind=땅의 추방 +spell.ebwizardry:wither=쇠약의 물결 +spell.ebwizardry:wither_skull=사악한 폭격 + +spell.ebwizardry:agility.desc=시전자에게 신속과 점프 강화를 30초 부여합니다. +spell.ebwizardry:arc.desc=대상에게 전기충격을 가합니다. +spell.ebwizardry:arcane_jammer.desc=대상의 마법 사용을 15초 막습니다. +spell.ebwizardry:arrow_rain.desc="궁수! 발사!" +spell.ebwizardry:banish.desc=대상을 일정 범위 내에 무작위로 전이시킵니다. +spell.ebwizardry:black_hole.desc="도망쳐 보시지..." +spell.ebwizardry:blink.desc=시전자를 약간 앞으로 전이시킵니다 +spell.ebwizardry:blizzard.desc=휘몰아치는 눈보라를 만들어 범위 내의 대상을 느리게 하고 지속적인 피해를 줍니다. 시전자는 피해는 입지 않지만 느려집니다. +spell.ebwizardry:bubble.desc=닿은 대상을 하늘로 떠올리는 물거품을 발사합니다. 지속시간이 다 되거나 피해를 입으면 사라집니다. +spell.ebwizardry:chain_lightning.desc=발사된 번개가 대상과 근처 적에게 피해를 입힙니다. +spell.ebwizardry:clairvoyance.desc=지정된 위치를 안내하는 빛무리를 보여줍니다. 이 주문을 든 상태에서 지정할 위치의 블록을 쉬프트-우클릭 하세요. 빛무리는 90동안 유지됩니다. +spell.ebwizardry:cobwebs.desc=사용한 위치에 20초간 유지되는 거미줄을 만듭니다. +spell.ebwizardry:conjure_armour.desc=철 갑옷과 같은 방어도를 갖는 허상의 갑옷을 착용합니다. 갑옷은 1분동안 유지되며 빈 장비칸이 필요합니다. +spell.ebwizardry:conjure_bow.desc=30초 동안 유지되는 무한한 허상의 활을 만듭니다. +spell.ebwizardry:conjure_pickaxe.desc=30초 동안 유지되는 철 곡괭이와 동급의 허상의 곡괭이를 만듭니다. +spell.ebwizardry:conjure_sword.desc=30초 동안 유지되는 철 검과 동급의 허상의 검을 만듭니다. +spell.ebwizardry:cure_effects.desc=시전자에게 적용된 모든 상태이상을 제거합니다. +spell.ebwizardry:curse_of_soulbinding.desc=대상과 자신의 영혼을 묶습니다. 모든 피해를 공유하며 누구 하나가 죽을 때까지 지속됩니다. +spell.ebwizardry:darkness_orb.desc=느리게 움직이는 암흑 에너지로 된 구체를 날립니다. 맞은 대상은 시듦 상태에 빠집니다. +spell.ebwizardry:darkvision.desc=야간 투시 45초를 얻습니다. +spell.ebwizardry:dart.desc=피해와 나약함을 입히는 다트를 발사합니다. +spell.ebwizardry:decay.desc=부패된 땅을 만들고 그 위를 지나는 모든 생물체에게 '부패'를 입힙니다. 부패된 생물체가 움직이면 그곳에도 '부패'가 퍼집니다. +spell.ebwizardry:decoy.desc=30초 동안 유지되는 시전자와 똑같이 생긴 분신을 만들어 적을 혼란시킵니다. +spell.ebwizardry:detonate.desc=시전한 지점에 폭발을 일으켜 주변의 모든 크리쳐를 공격합니다. +spell.ebwizardry:diamondflesh.desc="네 공격은 통하지 않는다!" +spell.ebwizardry:earthquake.desc="진정한 자연의 마법사는 산을 옮길수도 있지." +spell.ebwizardry:entrapment.desc=대상을 어둠에 구체에 가둬 지속 피해를 주며 하늘로 띄웁니다. +spell.ebwizardry:fireball.desc=시전한 방향으로 화염구를 발사합니다. +spell.ebwizardry:firebolt.desc=전방으로 짧은 불꽃 탄환을 발사합니다. +spell.ebwizardry:firebomb.desc=시전한 방향으로 화염탄을 던져서 주변 적을 불태웁니다. +spell.ebwizardry:fire_resistance.desc=화염 저항 30초를 얻습니다. +spell.ebwizardry:fire_sigil.desc=약간의 피해와 화상을 입히는 마법 함정을 설치합니다. +spell.ebwizardry:fireskin.desc=30초 동안 시전자를 화염으로 감싸, 공격하는 적에게 화상을 입힙니다. +spell.ebwizardry:firestorm.desc="내가 바로 화염룡이다!" +spell.ebwizardry:flame_ray.desc=불타는 광선을 내뿜어 땅과 적을 불태웁니다. +spell.ebwizardry:flaming_axe.desc=30초 동안 유지되는 적을 불태우는 도끼를 만듭니다. +spell.ebwizardry:flaming_weapon.desc=시전자의 핫바에 존재하는 무기 하나에 45초 동안 지속되는 '불꽃의 마력' 인챈트를 부여합니다. +spell.ebwizardry:flight.desc="날기를 매와 같이." +spell.ebwizardry:font_of_mana.desc="우리를 가득 채운 강력한 에너지는 중앙..." - 잊혀진 마법사의 일지에서 발췌, 나머지 페이지는 불타 사라졌다. +spell.ebwizardry:font_of_vitality.desc="끝내주는 기분이군." +spell.ebwizardry:force_arrow.desc=시전한 방향으로 나아가는 힘의 화살을 발사합니다. +spell.ebwizardry:forcefield.desc=시전자를 중심으로 허가받지 못한 모든 것을 거부하는 공간을 만듭니다. +spell.ebwizardry:force_orb.desc=주변을 밀쳐내며 피해를 주는 힘의 구체를 던집니다. +spell.ebwizardry:forests_curse.desc="이곳이 어디라고 발을 디디느냐!" +spell.ebwizardry:freeze.desc=대상을 10초 동안 얼립니다. 또는 물을 얼리거나 눈을 내릴 수 있습니다. +spell.ebwizardry:freezing_weapon.desc=시전자의 핫바에 존재하는 무기 하나에 45초 동안 지속되는 '서리의 마력' 인챈트를 부여합니다. +spell.ebwizardry:frost_axe.desc=30초 동안 유지되는 적을 얼리는 도끼를 만듭니다. +spell.ebwizardry:frost_ray.desc=대상에게 피해와 동상을 주는 서리 광선을 발사합니다. +spell.ebwizardry:frost_sigil.desc=약간의 피해와 동상을 입히는 마법 함정을 설치합니다. +spell.ebwizardry:glide.desc=낙하중 사용하는 동안 부드럽게 활강합니다. +spell.ebwizardry:greater_fireball.desc=주변을 파괴하고 충격을 주는 거대한 화염구를 발사합니다. +spell.ebwizardry:greater_heal.desc=시전자의 하트 4칸을 회복합니다. +spell.ebwizardry:group_heal.desc=시전자와 주변 생명의 하트 3칸을 회복합니다. +spell.ebwizardry:growth_aura.desc=시전자 주변의 모든 식물이 자라납니다. +spell.ebwizardry:hailstorm.desc="빙결술사들이 진정한 힘을 깨닳은건 3번째 겨울이었습니다." +spell.ebwizardry:heal.desc=시전자의 하트 2칸을 회복합니다. +spell.ebwizardry:heal_ally.desc=대상의 하트 2개 반을 회복시킵니다. +spell.ebwizardry:healing_aura.desc=체력을 서서히 회복하는 신성한 공간을 만듭니다. 범위 내의 언데드는 지속 피해를 입습니다. +spell.ebwizardry:homing_spark.desc=주변 적으로 움직이는 전기 구슬을 발사합니다. +spell.ebwizardry:ice_age.desc="내가, 겨울이다." +spell.ebwizardry:ice_charge.desc=산산조각나 주변에 한기와 얼음 파편을 뿌리는 얼음 폭탄을 던집니다. +spell.ebwizardry:ice_lance.desc=맞은 대상에게 피해와 감속을 입히는 관통하는 얼음의 창을 발사합니다. +spell.ebwizardry:ice_shard.desc=피해와 감속을 입히는 얼음 파편을 날립니다. +spell.ebwizardry:ice_shroud.desc=30초 동안 시전자를 서리로 감싸 공격하는 적을 얼어붙게 합니다. +spell.ebwizardry:ice_spikes.desc=날카로운 얼음 가시들을 땅에서 솟게합니다. +spell.ebwizardry:ice_statue.desc=대상을 20초 동안이나 얼음이 깨질때 까지 얼음 기둥에 가둡니다. 갖힌 대상은 피해를 받지 않습니다. +spell.ebwizardry:ignite.desc=사용 지점에 불을 붙입니다. 라이터와 같습니다. +spell.ebwizardry:imbue_weapon.desc=시전자의 핫바에 존재하는 무기 하나에 45초 동안 마력을 부여합니다. +spell.ebwizardry:intimidate.desc=주변 크리쳐들을 공포를 주어 도망가게 합니다. 대상은 30초 뒤에 회복됩니다. +spell.ebwizardry:invigorating_presence.desc=시전자와 주변 동맹에 힘2를 부여합니다. +spell.ebwizardry:invisibility.desc=투명화 30초를 얻습니다. +spell.ebwizardry:invoke_weather.desc=날씨를 바꿉니다. +spell.ebwizardry:ironflesh.desc=저항3 30초를 얻습니다. +spell.ebwizardry:leap.desc=약간 앞으로 나아가며 높이 도약합니다. +spell.ebwizardry:levitation.desc=주문을 유지하는 동안 시전자를 하늘로 떠오르게 합니다. +spell.ebwizardry:life_drain.desc=쇠약의 기운을 발사해 대상의 체력을 뺏어와 시전자의 체력을 보충합니다. +spell.ebwizardry:light.desc=30초 동안 유지되는 마법적인 조명을 생성합니다. +spell.ebwizardry:lightning_arrow.desc=전방으로 번개의 화살을 발사합니다. +spell.ebwizardry:lightning_bolt.desc=사용 지점에 벼락을 내리꽂습니다. +spell.ebwizardry:lightning_disc.desc=고리모양의 번개를 빠른 속도로 날립니다. +spell.ebwizardry:lightning_hammer.desc="신의 망치를 받아라!" +spell.ebwizardry:lightning_pulse.desc=시전자를 중심으로 번개를 방출하여 주변 적에게 피해를 주고 밀쳐냅니다. +spell.ebwizardry:lightning_ray.desc=적을 감전시켜 피해를 입히는 번개를 지속적으로 방출합니다. +spell.ebwizardry:lightning_sigil.desc=연쇄 번개를 내뿜는 마법 함정을 설치합니다. +spell.ebwizardry:lightning_web.desc="집중해. 네 안의 폭풍을 지팡이 밖으로 내뿜는거야." +spell.ebwizardry:magic_missile.desc=약간의 피해를 입히는 기본적인 마법 화살을 발사합니다. +spell.ebwizardry:metamorphosis.desc=대상을 같은 종류의 다른 형태로 바꿉니다. +spell.ebwizardry:meteor.desc="가끔은 이 세상이 불타는걸 보고싶기도 하지..." +spell.ebwizardry:mind_control.desc=의지가 약한 대상의 정신을 사로잡아 30초 동안 시전자를 위해 싸우게 합니다. +spell.ebwizardry:mind_trick.desc=대상의 정신에 충격을 가해 15초가 지나거나 공격을 받을때 까지 아무것도 하지 못하게 합니다. +spell.ebwizardry:none.desc=주문서를 얻으세요. /give command, use id: /give [player] ebwizardry:spell_book 1 [spell id] (if you found this book in a chest, some other mod has messed things up). +spell.ebwizardry:oakflesh.desc=저항2 30초를 얻습니다. +spell.ebwizardry:petrify.desc=대상을 돌에 가둬 아무것도 할수 없지만 피해 또한 받지 않게 합니다. 캐거나 어두운 곳에 있을때 까지 지속됩니다. +spell.ebwizardry:phase_step.desc=전방의 1칸 두깨의 벽을 통과합니다. 사거리 추가 개조로 강화할 수 있습니다. +spell.ebwizardry:plague_of_darkness.desc="어둠이 모든것을 먹어 치우리라..." +spell.ebwizardry:pocket_furnace.desc=인벤토리의 제련할 수 있는 아이템을 5개씩 제련합니다. 핫바를 우선 합니다. +spell.ebwizardry:pocket_workbench.desc=어디서든 작업대를 열 수 있습니다. +spell.ebwizardry:poison.desc=전방으로 독을 발사합니다. +spell.ebwizardry:poison_bomb.desc=약간의 피해와 주변에 독을 뿌리는 폭탄을 던집니다. +spell.ebwizardry:replenish_hunger.desc=시전자의 배고픔을 6점(3칸) 회복합니다. +spell.ebwizardry:ring_of_fire.desc=시전자 주위로 화염의 고리를 만들어서 들어오는 적을 불태웁니다. +spell.ebwizardry:shadow_ward.desc=시전자 전방에 어둠의 방패를 만들어 적이 가하는 공격의 절반을 돌려줍니다. +spell.ebwizardry:shield.desc=발사체와 마법을 막는 방패를 소환합니다. 유지되는 동안 저항을 얻습니다. +spell.ebwizardry:shockwave.desc="펑." +spell.ebwizardry:silverfish_swarm.desc="으아아! 벌레다!!!" +spell.ebwizardry:sixth_sense.desc=20초 동안 주변의 모든 크리쳐를 어디에 있던 볼 수 있습니다. +spell.ebwizardry:slime.desc=대상에게 10초 동안 슬라임을 씌워 느리게 하고 피해를 입힙니다. +spell.ebwizardry:smoke_bomb.desc=연막을 터트려 짧은 시간 대상을 실명 시킵니다. +spell.ebwizardry:snare.desc=피해와 구속을 거는 덫을 설치합니다. +spell.ebwizardry:snowball.desc=눈덩이를 던집니다. +spell.ebwizardry:spark_bomb.desc=주변 적에게 전기 충격을 가하는 전기 덩어리를 던집니다. +spell.ebwizardry:spectral_pathway.desc=전방에 60초 동안 유지되는 파괴할 수 없는 마법의 다리를 만듭니다. +spell.ebwizardry:spider_swarm.desc=30초 동안 시전자를 위해 싸우는 독 거미 무리를 소환합니다. +spell.ebwizardry:static_aura.desc=시전자를 전기로 감싸 공격하는 적들을 지집니다. +spell.ebwizardry:summon_blaze.desc=30초 동안 시전자를 위해 싸우는 블레이즈를 소환합니다. +spell.ebwizardry:summon_ice_giant.desc="날려버려!" +spell.ebwizardry:summon_ice_wraith.desc=30초 동안 시전자를 위해 싸우는 얼어붙은 귀신을 소환합니다. +spell.ebwizardry:summon_iron_golem.desc="시스템, 정상 가동 중." +spell.ebwizardry:summon_lightning_wraith.desc=30초 동안 시전자를 위해 싸우는 번개의 귀신을 소환합니다. +spell.ebwizardry:summon_phoenix.desc="잿더미에서 다시 타오르리라." +spell.ebwizardry:summon_shadow_wraith.desc="어둠이, 함께한다..." +spell.ebwizardry:summon_skeleton.desc=30초 동안 시전자를 위해 싸우는 스켈레톤을 소환합니다. +spell.ebwizardry:summon_skeleton_legion.desc="어둠의 병사들이여! 명을 받들라!" +spell.ebwizardry:summon_snow_golem.desc=죽을때 까지 남아있는 눈 골렘을 소환합니다. +spell.ebwizardry:summon_spirit_horse.desc=조련된 유령마를 소환합니다. 유령마는 내린 후 잠시 뒤 사라지거나 아무 지팡이로 쉬프트-우클릭을 통해 송환할 수 있습니다. +spell.ebwizardry:summon_spirit_wolf.desc=죽을때 까지 시전자를 위해 싸우는 유령 늑대를 소환합니다. 아무 지팡이로 쉬프트-우클릭을 통해 송환할 수 있습니다. +spell.ebwizardry:summon_storm_elemental.desc="폭풍의 정령 : 원소의 순수한 형태. 그 힘을 억제할 수 없다." - 마법의 길 : 원소의 서 발췌 +spell.ebwizardry:summon_wither_skeleton.desc=30초 동안 시전자를 위해 싸우는 위더 스켈레톤을 소환합니다. +spell.ebwizardry:summon_zombie.desc=30초 동안 시전자를 위해 싸우는 좀비를 소환합니다. +spell.ebwizardry:telekinesis.desc=멀리 있는 아이템을 가져옵니다. +spell.ebwizardry:thunderbolt.desc=적을 밀치는 빠른 전기 구슬을 발사합니다. +spell.ebwizardry:thunderstorm.desc="으하하하하하하하!" +spell.ebwizardry:tornado.desc=앞으로 나아가는 회오리를 내보내, 적을 날려버립니다. +spell.ebwizardry:transience.desc=20초 동안 공허에 숨어 모든 피해를 무시합니다. +spell.ebwizardry:transportation.desc=전이의 진을 만들고 전이의 돌을 우클릭해 위치를 기록합니다. 다시 우클릭을 하면 귀환진으로 귀환합니다. +spell.ebwizardry:vanishing_box.desc=어디서든 엔더 상자를 열 수 있습니다. +spell.ebwizardry:wall_of_frost.desc="겨울이 온다..." +spell.ebwizardry:water_breathing.desc=수중 호흡 60초를 얻습니다. +spell.ebwizardry:whirlwind.desc=대상을 빠르게 당신에게서 밀쳐냅니다. +spell.ebwizardry:wither.desc=암흑의 광선을 쏘아 닿는 크리쳐에게 위더를 부여합니다. +spell.ebwizardry:wither_skull.desc=위더 폭탄을 발사합니다. + +spell.ebwizardry:invoke_weather.sun=뇌우가 물러갑니다. +spell.ebwizardry:invoke_weather.rain=뇌우가 몰려듭니다. +spell.ebwizardry:transportation.missing=귀환진이 사라졌거나 파괴되었습니다. +spell.ebwizardry:transportation.undefined=먼저 귀환진을 만드세요! +spell.ebwizardry:transportation.wrongdimension=귀환진이 다른 세계에 있습니다. +spell.ebwizardry:clairvoyance.searching=탐색중... +spell.ebwizardry:clairvoyance.confirm=이제 %1$s를 사용하면 이곳을 알려줍니다. +spell.ebwizardry:clairvoyance.outofrange=장소가 너무 멀거나 연결된 길이 없습니다. +spell.ebwizardry:clairvoyance.undefined=먼저 위치를 지정하세요! +spell.ebwizardry:clairvoyance.wrongdimension=장소가 다른 세계에 있습니다... + +potion.ebwizardry:frost=동상 +potion.ebwizardry:fireskin=불타는 피부 +potion.ebwizardry:ice_shroud=서리 가호 +potion.ebwizardry:static_aura=벼락의 기운 +potion.ebwizardry:transience=공허의 보호 +potion.ebwizardry:decay=부패하는 역병 +potion.ebwizardry:sixth_sense=제육감 +potion.ebwizardry:arcane_jammer=마법 방해 +potion.ebwizardry:mind_trick=정신착란 +potion.ebwizardry:mind_control=정신지배 +potion.ebwizardry:font_of_mana=마나의 축복 +potion.ebwizardry:fear=공포 + +enchantment.ebwizardry:magic_sword=마력 부여 +enchantment.ebwizardry:magic_bow=마력 부여 +enchantment.ebwizardry:flaming_weapon=불꽃의 마력 +enchantment.ebwizardry:freezing_weapon=서리의 마력 + +key.categories.ebwizardry=마법의 길 + +key.ebwizardry.next_spell=다음 주문 +key.ebwizardry.previous_spell=이전 주문 + +death.attack.wizardry_magic=%1$s(은)는 %2$s(이)가 사용한 마법에 살해당했습니다. +death.attack.indirect_wizardry_magic=%1$s(은)는 %2$s(이)가 사용한 마법에 살해당했습니다. + +commands.ebwizardry:cast.usage=/%1$s [player] [damage multiplier] [range multiplier] [duration multiplier] [blast multiplier] +commands.ebwizardry:cast.success=Successfully cast %1$s +commands.ebwizardry:cast.success_continuous=Successfully cast %1$s; repeat the command to stop +commands.ebwizardry:cast.success_remote=Successfully cast %1$s as %2$s +commands.ebwizardry:cast.success_remote_continuous=Successfully cast %1$s as %2$s; repeat the command to stop +commands.ebwizardry:cast.fail=Unable to cast %1$s +commands.ebwizardry:cast.not_found=There is no such spell with ID %1$s +commands.ebwizardry:cast.tag_error=Data tag parsing failed: %s + +commands.ebwizardry:ally.usage=/%1$s [player] +commands.ebwizardry:ally.addally=%1$s has been added to %2$s's list of allies +commands.ebwizardry:ally.removeally=%1$s has been removed from %2$s's list of allies +commands.ebwizardry:ally.self=Players cannot be an ally of themselves! +commands.ebwizardry:ally.permission=You do not have permission to change other players' allies + +commands.ebwizardry:allies.usage=/%1$s [player] +commands.ebwizardry:allies.list=Players allied to you: %1$s +commands.ebwizardry:allies.list_other=Players allied to %1$s: %2$s +commands.ebwizardry:allies.permission=You do not have permission to view other players' allies +commands.ebwizardry:allies.none=None + +commands.ebwizardry:discoverspell.usage=/%1$s [player] +commands.ebwizardry:discoverspell.not_found=There is no such spell with ID %1$s +commands.ebwizardry:discoverspell.clear=Cleared all spell discovery data for %1$s +commands.ebwizardry:discoverspell.all=Added all spells to %1$s's spell discovery data +commands.ebwizardry:discoverspell.addspell=Added %1$s to %2$s's spell discovery data +commands.ebwizardry:discoverspell.removespell=Removed %1$s from %2$s's spell discovery data + +config.ebwizardry.title.general=Mod Options + +config.ebwizardry.category.gameplay=Gameplay Settings +config.ebwizardry.category.gameplay.tooltip=Configure wizardry's general gameplay +config.ebwizardry.title.gameplay=Gameplay Settings +config.ebwizardry.subtitle.gameplay=Global settings that affect game mechanics. + +config.ebwizardry.category.worldgen=World Generation Settings +config.ebwizardry.category.worldgen.tooltip=Configure wizardry's world generation features +config.ebwizardry.title.worldgen=World Generation Settings +config.ebwizardry.subtitle.worldgen=Settings that affect world generation. + +config.ebwizardry.category.commands=Command Settings +config.ebwizardry.category.commands.tooltip=Configure wizardry's commands +config.ebwizardry.title.commands=Command Settings +config.ebwizardry.subtitle.commands=Settings for the commands added by Wizardry. + +config.ebwizardry.category.client=Client Settings +config.ebwizardry.category.client.tooltip=Configure wizardry's display and controls +config.ebwizardry.title.client=Client Settings +config.ebwizardry.subtitle.client=Client-side settings that only affect the local minecraft game. + +config.ebwizardry.category.spells=Spell Configuration +config.ebwizardry.category.spells.tooltip=Select which spells are enabled +config.ebwizardry.title.spells=Spell Configuration +config.ebwizardry.subtitle.spells=Set a spell to false to disable it. + +config.ebwizardry.category.resistances=Resistance Configuration +config.ebwizardry.category.resistances.tooltip=Configure which mobs are immune to different types of magic +config.ebwizardry.title.resistances=Resistance Configuration +config.ebwizardry.subtitle.resistances=Settings which allow entities to be made immune to certain types of magic. + +config.ebwizardry.tower_rarity=Tower Rarity +config.ebwizardry.ore_dimensions=Ore Dimensions +config.ebwizardry.flower_dimensions=Flower Dimensions +config.ebwizardry.tower_dimensions=Tower Dimensions +config.ebwizardry.spell_book_drop_chance=Spell Book Drop Chance +config.ebwizardry.generate_loot=Generate Loot +config.ebwizardry.firebomb_is_craftable=Firebomb Is Craftable +config.ebwizardry.poison_bomb_is_craftable=Poison Bomb Is Craftable +config.ebwizardry.smoke_bomb_is_craftable=Smoke Bomb Is Craftable +config.ebwizardry.use_alternate_scroll_recipe=Use Alternate Scroll Recipe +config.ebwizardry.teleport_through_unbreakable_blocks=Teleport Through Unbreakable Blocks +config.ebwizardry.show_summoned_creature_names=Show Summoned Creature Names +config.ebwizardry.friendly_fire=Friendly Fire +config.ebwizardry.telekinetic_disarmament=Telekinetic Disarmament +config.ebwizardry.discovery_mode=Discovery Mode +config.ebwizardry.enable_shift_scrolling=Enable Shift-scrolling +config.ebwizardry.minion_revenge_targeting=Minion Revenge Targeting +config.ebwizardry.player_damage_scaling=Player Damage Scaling Factor +config.ebwizardry.npc_damage_scaling=NPC Damage Scaling Factor +config.ebwizardry.cast_command_multiplier_limit=Cast Command Multiplier Limit +config.ebwizardry.summoned_creature_targets_whitelist=Summoned Creature Target Whitelist +config.ebwizardry.summoned_creature_targets_blacklist=Summoned Creature Target Blacklist +config.ebwizardry.spell_hud_position=Spell HUD Position +config.ebwizardry.cast_command_name=Cast Spell Command Name +config.ebwizardry.discoverspell_command_name=Discover Spell Command Name +config.ebwizardry.ally_command_name=Set Ally Command Name +config.ebwizardry.allies_command_name=View Allies Command Name +config.ebwizardry.mind_control_targets_blacklist=Mind Control Targets Blacklist +config.ebwizardry.evil_wizard_dimensions=Evil Wizard Dimensions + +config.ebwizardry.mobs_immune_to_fire=Mobs Immune To Fire +config.ebwizardry.mobs_immune_to_ice=Mobs Immune To Ice +config.ebwizardry.mobs_immune_to_lightning=Mobs Immune To Lightning +config.ebwizardry.mobs_immune_to_wither=Mobs Immune To Wither +config.ebwizardry.mobs_immune_to_poison=Mobs Immune To Poison + +config.ebwizardry.tower_rarity.tooltip=Rarity of wizard towers. Higher numbers are rarer. Set to 0 to disable wizard towers completely. +config.ebwizardry.ore_dimensions.tooltip=List of dimension ids in which crystal ore will generate. Note that removing the overworld (id 0) from this list will make the mod VERY difficult to play! +config.ebwizardry.flower_dimensions.tooltip=List of dimension ids in which crystal flowers will generate. +config.ebwizardry.tower_dimensions.tooltip=List of dimension ids in which wizard towers will generate. +config.ebwizardry.spell_book_drop_chance.tooltip=The chance for mobs to drop a spell book when killed. The greater this number, the more often they will drop. Set to 0 to disable spell book drops. Set to 200 for guaranteed drops. +config.ebwizardry.generate_loot.tooltip=Whether to generate wizardry loot in dungeon chests. +config.ebwizardry.firebomb_is_craftable.tooltip=Whether firebombs can be crafted or not. +config.ebwizardry.poison_bomb_is_craftable.tooltip=Whether poison bombs can be crafted or not. +config.ebwizardry.smoke_bomb_is_craftable.tooltip=Whether smoke bombs can be crafted or not. +config.ebwizardry.use_alternate_scroll_recipe.tooltip=Whether to require a magic crystal in the shapeless crafting recipe for blank scrolls. Set to true if another mod adds a conflicting recipe. +config.ebwizardry.teleport_through_unbreakable_blocks.tooltip=Whether players are allowed to teleport through unbreakable blocks (e.g. bedrock) using the phase step spell. +config.ebwizardry.show_summoned_creature_names.tooltip=Whether to show summoned creatures' names and owners above their heads. +config.ebwizardry.friendly_fire.tooltip=Whether to allow players to damage their designated allies using magic. +config.ebwizardry.telekinetic_disarmament.tooltip=Whether to allow players to disarm other players using the telekinesis spell. Set to false to prevent stealing of items. +config.ebwizardry.discovery_mode.tooltip=For those who like a sense of mystery! When set to true, spells you haven't cast yet will be unreadable until you cast them (on a per-world basis). Has no effect when in creative mode. Spells of identification will be unobtainable in survival mode if this is false. +config.ebwizardry.enable_shift_scrolling.tooltip=Whether you can switch between spells on a wand by scrolling with the mouse wheel while sneaking. Note that this will only affect you; other players connected to the same server obey their own settings. +config.ebwizardry.minion_revenge_targeting.tooltip=Whether summoned creatures can revenge attack their owner if their owner attacks them. +config.ebwizardry.player_damage_scaling.tooltip=Global damage scaling factor for the damage dealt by players casting spells, relative to 1. +config.ebwizardry.npc_damage_scaling.tooltip=Global damage scaling factor for the damage dealt by NPCs casting spells, relative to 1. +config.ebwizardry.cast_command_multiplier_limit.tooltip=Upper limit for the multipliers passed into the /cast command. This is here to stop players from accidentally breaking a world/server. Large blast mutipliers can cause extreme lag - you have been warned! +config.ebwizardry.summoned_creature_targets_whitelist.tooltip=List of names of entities which summoned creatures and wizards are allowed to attack, in addition to the defaults. Add mod creatures to this list if you want summoned creatures to attack them and they aren't already doing so. Entity names are not case sensitive. For mod entities, prefix with the mod ID (e.g. ebwizardry:wizard). +config.ebwizardry.summoned_creature_targets_blacklist.tooltip=List of names of entities which summoned creatures and wizards are specifically not allowed to attack, overriding the defaults and the whitelist. Add creatures to this list if allowing them to be attacked causes problems or is too destructive (removing creepers from this list is done at your own risk!). Entity names are not case sensitive. For mod entities, prefix with the mod ID (e.g. ebwizardry:wizard). +config.ebwizardry.spell_hud_position.tooltip=The position of the spell HUD. +config.ebwizardry.cast_command_name.tooltip=The name of the /cast command. This is what you type directly after the /; for example if this was set to 'magic' then instead of typing /cast you would type /magic instead. +config.ebwizardry.discoverspell_command_name.tooltip=The name of the /discoverspell command. This is what you type directly after the /; for example if this was set to 'magic' then instead of typing /discoverspell you would type /magic instead. +config.ebwizardry.ally_command_name.tooltip=The name of the /ally command. This is what you type directly after the /; for example if this was set to 'magic' then instead of typing /ally you would type /magic instead. +config.ebwizardry.allies_command_name.tooltip=The name of the /allies command. This is what you type directly after the /; for example if this was set to 'magic' then instead of typing /allies you would type /magic instead. +config.ebwizardry.mind_control_targets_blacklist.tooltip=List of names of entities which cannot be mind controlled, in addition to the defaults. Add creatures to this list if allowing them to be mind-controlled causes problems or could be exploited. Entity names are not case sensitive. For mod entities, prefix with the mod ID (e.g. ebwizardry:wizard). +config.ebwizardry.evil_wizard_dimensions.tooltip=List of dimension ids in which evil wizards can spawn. + +config.ebwizardry.mobs_immune_to_fire.tooltip=List of names of entities that are immune to fire, in addition to the defaults. Add mod creatures to this list if you want them to be immune to fire magic and they aren't already. Entity names are not case sensitive. For mod entities, prefix with the mod ID (e.g. ebwizardry:wizard). +config.ebwizardry.mobs_immune_to_ice.tooltip=List of names of entities that are immune to ice, in addition to the defaults. Add mod creatures to this list if you want them to be immune to ice magic and they aren't already. Entity names are not case sensitive. For mod entities, prefix with the mod ID (e.g. ebwizardry:wizard). +config.ebwizardry.mobs_immune_to_lightning.tooltip=List of names of entities that are immune to lightning, in addition to the defaults. Add mod creatures to this list if you want them to be immune to lightning magic and they aren't already. Entity names are not case sensitive. For mod entities, prefix with the mod ID (e.g. ebwizardry:wizard). +config.ebwizardry.mobs_immune_to_wither.tooltip=List of names of entities that are immune to wither effects, in addition to the defaults. Add mod creatures to this list if you want them to be immune to withering magic and they aren't already. Entity names are not case sensitive. For mod entities, prefix with the mod ID (e.g. ebwizardry:wizard). +config.ebwizardry.mobs_immune_to_poison.tooltip=List of names of entities that are immune to poison, in addition to the defaults. Add mod creatures to this list if you want them to be immune to poison magic and they aren't already. Entity names are not case sensitive. For mod entities, prefix with the mod ID (e.g. ebwizardry:wizard). + +wizard.debug=%1$s, %2$s, %3$s diff --git a/src/main/resources/assets/ebwizardry/lang/ru_ru.lang b/src/main/resources/assets/ebwizardry/lang/ru_ru.lang index d7d2ec74..0a5fdac1 100644 --- a/src/main/resources/assets/ebwizardry/lang/ru_ru.lang +++ b/src/main/resources/assets/ebwizardry/lang/ru_ru.lang @@ -26,13 +26,13 @@ item.ebwizardry:wand.buff=+%1$s %2$s эффективность item.ebwizardry:wand.spell=Текущее Заклинание: %1$s item.ebwizardry:wand.mana=Мана: %1$s/%2$s -item.ebwizardry:basic_fire_wand.name=Жезл Огня -item.ebwizardry:basic_ice_wand.name=Жезл Мороза -item.ebwizardry:basic_lightning_wand.name=Жезл Искр -item.ebwizardry:basic_necromancy_wand.name=Жезл Теней -item.ebwizardry:basic_earth_wand.name=Жезл Леса -item.ebwizardry:basic_sorcery_wand.name=Жезл Тайн -item.ebwizardry:basic_healing_wand.name=Жезл Лечения +item.ebwizardry:novice_fire_wand.name=Жезл Огня +item.ebwizardry:novice_ice_wand.name=Жезл Мороза +item.ebwizardry:novice_lightning_wand.name=Жезл Искр +item.ebwizardry:novice_necromancy_wand.name=Жезл Теней +item.ebwizardry:novice_earth_wand.name=Жезл Леса +item.ebwizardry:novice_sorcery_wand.name=Жезл Тайн +item.ebwizardry:novice_healing_wand.name=Жезл Лечения item.ebwizardry:apprentice_fire_wand.name=Жезл Ученика Пироманта item.ebwizardry:apprentice_ice_wand.name=Жезл Ученика Ледяного Мага @@ -189,56 +189,56 @@ entity.ebwizardry:ring_of_fire.name=Кольцо Огня item_group.ebwizardry=Волшебство item_group.wizardryspells=Волшебные Заклинания -advancement.wizardry:root=Wizardry -advancement.wizardry:root.desc=достижения -advancement.wizardry:crystal=Любопытный Кристалл... -advancement.wizardry:crystal.desc=Добудьте Магический Кристалл -advancement.wizardry:arcane_initiate=Посвящение В Магию -advancement.wizardry:arcane_initiate.desc=Создайте Волшебную Палочку Из Золотого Самородка И Магического Кристалла -advancement.wizardry:apprentice=Ученик Волшебника -advancement.wizardry:apprentice.desc=Используйте Фолиант Арканы Для Улучшения Жезла -advancement.wizardry:master=Мастер Магии -advancement.wizardry:master.desc=Получите Жезл Мастера -advancement.wizardry:all_spells=Маг Всех Профессий -advancement.wizardry:all_spells.desc=Используйте Каждое Заклинание В Игре -advancement.wizardry:wizard_trade=Магическая Сделка -advancement.wizardry:wizard_trade.desc=Купите Предмет У Волшебника -advancement.wizardry:buy_master_spell=Знание-сила -advancement.wizardry:buy_master_spell.desc=Купите заклинание мастера у волшебника -advancement.wizardry:freeze_blaze=Не Так Жарко -advancement.wizardry:freeze_blaze.desc=Заморозьте Блейза -advancement.wizardry:charge_creeper=Это Сейчас Взорвётся -advancement.wizardry:charge_creeper.desc="Случайно" Зарядите Крипира -advancement.wizardry:frankenstein=Франкенштейн -advancement.wizardry:frankenstein.desc=Привратите Свинью В Свинозомби С Помощью Молнии -advancement.wizardry:special_upgrade=Чародейское Ремесло -advancement.wizardry:special_upgrade.desc=Применить Специальное Улучшение Для Жезла -advancement.wizardry:craft_flask=Это Магия В Бутылке! -advancement.wizardry:craft_flask.desc=Создайте Ману В Бутылке -advancement.wizardry:elemental=Стихии -advancement.wizardry:elemental.desc=Получите Стихийный Жезл -advancement.wizardry:armour_set=Теперь Ты Настоящий Волшебник -advancement.wizardry:armour_set.desc=Создайте И Экипируйте Полный Набор Одеяния Волшебника -advancement.wizardry:legendary=Легендарный -advancement.wizardry:legendary.desc=Получите Часть Легендарного Одеяния Волшебника -advancement.wizardry:self_destruct=Обратно -advancement.wizardry:self_destruct.desc=Убейся Собственной Магией -advancement.wizardry:pig_tornado=Не Сейчас... -advancement.wizardry:pig_tornado.desc=Заедьте На Свинье В Торнадо -advancement.wizardry:max_out_wand=Полное Оснощение -advancement.wizardry:max_out_wand.desc=Примените максимальное количество улучшений к жезлу мастера -advancement.wizardry:slime_skeleton=Липкая Ситуация -advancement.wizardry:slime_skeleton.desc=Захватите скелета слизьнем -advancement.wizardry:jam_wizard=Помехи -advancement.wizardry:jam_wizard.desc=Используйте заклинание магическая глушилка на волшебнике -advancement.wizardry:identify_spell=Тайная Экспертиза -advancement.wizardry:identify_spell.desc=Используйте свиток идентификации для неизвестной книги заклинания или свитка -advancement.wizardry:element_master=Мастер Элементов -advancement.wizardry:element_master.desc=Используйте все заклинания любого элемента -advancement.wizardry:anger_wizard=Ты пожалеешь об этом -advancement.wizardry:anger_wizard.desc=Разозлите волшебника -advancement.wizardry:defeat_evil_wizard=Праведность -advancement.wizardry:defeat_evil_wizard.desc=Победите злого волшебника +advancement.ebwizardry:root=Wizardry +advancement.ebwizardry:root.desc=достижения +advancement.ebwizardry:crystal=Любопытный Кристалл... +advancement.ebwizardry:crystal.desc=Добудьте Магический Кристалл +advancement.ebwizardry:arcane_initiate=Посвящение В Магию +advancement.ebwizardry:arcane_initiate.desc=Создайте Волшебную Палочку Из Золотого Самородка И Магического Кристалла +advancement.ebwizardry:apprentice=Ученик Волшебника +advancement.ebwizardry:apprentice.desc=Используйте Фолиант Арканы Для Улучшения Жезла +advancement.ebwizardry:master=Мастер Магии +advancement.ebwizardry:master.desc=Получите Жезл Мастера +advancement.ebwizardry:all_spells=Маг Всех Профессий +advancement.ebwizardry:all_spells.desc=Используйте Каждое Заклинание В Игре +advancement.ebwizardry:wizard_trade=Магическая Сделка +advancement.ebwizardry:wizard_trade.desc=Купите Предмет У Волшебника +advancement.ebwizardry:buy_master_spell=Знание-сила +advancement.ebwizardry:buy_master_spell.desc=Купите заклинание мастера у волшебника +advancement.ebwizardry:freeze_blaze=Не Так Жарко +advancement.ebwizardry:freeze_blaze.desc=Заморозьте Блейза +advancement.ebwizardry:charge_creeper=Это Сейчас Взорвётся +advancement.ebwizardry:charge_creeper.desc="Случайно" Зарядите Крипира +advancement.ebwizardry:frankenstein=Франкенштейн +advancement.ebwizardry:frankenstein.desc=Привратите Свинью В Свинозомби С Помощью Молнии +advancement.ebwizardry:special_upgrade=Чародейское Ремесло +advancement.ebwizardry:special_upgrade.desc=Применить Специальное Улучшение Для Жезла +advancement.ebwizardry:craft_flask=Это Магия В Бутылке! +advancement.ebwizardry:craft_flask.desc=Создайте Ману В Бутылке +advancement.ebwizardry:elemental=Стихии +advancement.ebwizardry:elemental.desc=Получите Стихийный Жезл +advancement.ebwizardry:armour_set=Теперь Ты Настоящий Волшебник +advancement.ebwizardry:armour_set.desc=Создайте И Экипируйте Полный Набор Одеяния Волшебника +advancement.ebwizardry:legendary=Легендарный +advancement.ebwizardry:legendary.desc=Получите Часть Легендарного Одеяния Волшебника +advancement.ebwizardry:self_destruct=Обратно +advancement.ebwizardry:self_destruct.desc=Убейся Собственной Магией +advancement.ebwizardry:pig_tornado=Не Сейчас... +advancement.ebwizardry:pig_tornado.desc=Заедьте На Свинье В Торнадо +advancement.ebwizardry:max_out_wand=Полное Оснощение +advancement.ebwizardry:max_out_wand.desc=Примените максимальное количество улучшений к жезлу мастера +advancement.ebwizardry:slime_skeleton=Липкая Ситуация +advancement.ebwizardry:slime_skeleton.desc=Захватите скелета слизьнем +advancement.ebwizardry:jam_wizard=Помехи +advancement.ebwizardry:jam_wizard.desc=Используйте заклинание магическая глушилка на волшебнике +advancement.ebwizardry:identify_spell=Тайная Экспертиза +advancement.ebwizardry:identify_spell.desc=Используйте свиток идентификации для неизвестной книги заклинания или свитка +advancement.ebwizardry:element_master=Мастер Элементов +advancement.ebwizardry:element_master.desc=Используйте все заклинания любого элемента +advancement.ebwizardry:anger_wizard=Ты пожалеешь об этом +advancement.ebwizardry:anger_wizard.desc=Разозлите волшебника +advancement.ebwizardry:defeat_evil_wizard=Праведность +advancement.ebwizardry:defeat_evil_wizard.desc=Победите злого волшебника @@ -250,7 +250,7 @@ container.ebwizardry:arcane_workbench.apply=Применить container.ebwizardry:arcane_workbench.mana=Мана: container.ebwizardry:arcane_workbench.upgrades=Применённые Улучшения: -tier.basic=Начинающий +tier.novice=Начинающий tier.apprentice=Ученик tier.advanced=Продвинутый tier.master=Мастер diff --git a/src/main/resources/assets/ebwizardry/lang/zh_cn.lang b/src/main/resources/assets/ebwizardry/lang/zh_cn.lang index 5ad2ffae..353baa89 100644 --- a/src/main/resources/assets/ebwizardry/lang/zh_cn.lang +++ b/src/main/resources/assets/ebwizardry/lang/zh_cn.lang @@ -29,13 +29,13 @@ item.ebwizardry:wand.mana=魔力: %1$s/%2$s item.ebwizardry:wand.addally=%1$s 已添加到你的盟友名单 item.ebwizardry:wand.removeally=%1$s 已移出你的盟友名单 -item.ebwizardry:basic_fire_wand.name=余火法杖 -item.ebwizardry:basic_ice_wand.name=寒霜法杖 -item.ebwizardry:basic_lightning_wand.name=星火法杖 -item.ebwizardry:basic_necromancy_wand.name=暗影法杖 -item.ebwizardry:basic_earth_wand.name=森林法杖 -item.ebwizardry:basic_sorcery_wand.name=神秘法杖 -item.ebwizardry:basic_healing_wand.name=治愈法杖 +item.ebwizardry:novice_fire_wand.name=余火法杖 +item.ebwizardry:novice_ice_wand.name=寒霜法杖 +item.ebwizardry:novice_lightning_wand.name=星火法杖 +item.ebwizardry:novice_necromancy_wand.name=暗影法杖 +item.ebwizardry:novice_earth_wand.name=森林法杖 +item.ebwizardry:novice_sorcery_wand.name=神秘法杖 +item.ebwizardry:novice_healing_wand.name=治愈法杖 item.ebwizardry:apprentice_fire_wand.name=学徒烈焰法杖 item.ebwizardry:apprentice_ice_wand.name=学徒冰霜法杖 @@ -213,56 +213,56 @@ entity.ebwizardry:lightning_pulse.name=闪电脉冲 itemGroup.ebwizardry=巫术学 itemGroup.ebwizardryspells=卷轴 -advancement.wizardry:root=新兴巫术 -advancement.wizardry:root.desc=一个巫师掌握奥术的旅程 -advancement.wizardry:crystal=一个奇异的水晶... -advancement.wizardry:crystal.desc=挖掘一个魔法水晶 -advancement.wizardry:arcane_initiate=奥术启程 -advancement.wizardry:arcane_initiate.desc=利用金锭,木棍和魔法水晶制造一根法杖 -advancement.wizardry:apprentice=见习巫师 -advancement.wizardry:apprentice.desc=使用奥法宝典来升级你的法杖 -advancement.wizardry:master=大师级巫师 -advancement.wizardry:master.desc=获得大师级法杖 -advancement.wizardry:all_spells=巫师的自我修养 -advancement.wizardry:all_spells.desc=在游戏中施放所有法术 -advancement.wizardry:wizard_trade=魔法交易 -advancement.wizardry:wizard_trade.desc=向巫师购买物品 -advancement.wizardry:buy_master_spell=知识就是力量 -advancement.wizardry:buy_master_spell.desc=向巫师购买一个大师级卷轴 -advancement.wizardry:freeze_blaze=现在不太热了 -advancement.wizardry:freeze_blaze.desc=把烈焰人冻成傻子 -advancement.wizardry:charge_creep=它要炸了 -advancement.wizardry:charge_creeper.desc='意外' 捕获爬行者 -advancement.wizardry:frankenstein=弗兰肯斯坦 -advancement.wizardry:frankenstein.desc=用闪电法术将猪变成僵尸猪人 -advancement.wizardry:special_upgrade=奥术工匠 -advancement.wizardry:special_upgrade.desc=对法杖进行特殊升级 -advancement.wizardry:craft_flask=这是魔力,装瓶! -advancement.wizardry:craft_flask.desc=制作一个魔力瓶 -advancement.wizardry:elemental=元素 -advancement.wizardry:elemental.desc=获得元素法杖 -advancement.wizardry:armour_set=现在你是一个正确的巫师 -advancement.wizardry:armour_set.desc=制作并装备全套巫师护具 -advancement.wizardry:legendary=传奇! -advancement.wizardry:legendary.desc=获得一件传奇级装备 -advancement.wizardry:self_destruct=真是倒霉 -advancement.wizardry:self_destruct.desc=被自己的魔法杀死 -advancement.wizardry:pig_tornado=不会再次... -advancement.wizardry:pig_tornado.desc=骑着猪卷进飓风 -advancement.wizardry:jam_wizard=扰乱会议 -advancement.wizardry:jam_wizard.desc=对一个巫师使用奥术干扰 -advancement.wizardry:slime_skeleton=棘手局面 -advancement.wizardry:slime_skeleton.desc=利用史莱姆吞噬骷髅 -advancement.wizardry:anger_wizard=你会后悔的 -advancement.wizardry:anger_wizard.desc=使一个巫师发怒 -advancement.wizardry:defeat_evil_wizard=正义降临 -advancement.wizardry:defeat_evil_wizard.desc=击败邪恶巫师 -advancement.wizardry:max_out_wand=整装上阵 -advancement.wizardry:max_out_wand.desc=将大师级法杖升级到最强 -advancement.wizardry:element_master=元素掌控 -advancement.wizardry:element_master.desc=施放任何元素的法术 -advancement.wizardry:identify_spell=奥术鉴定 -advancement.wizardry:identify_spell.desc=使用鉴定卷轴来鉴定法术书或卷轴 +advancement.ebwizardry:root=新兴巫术 +advancement.ebwizardry:root.desc=一个巫师掌握奥术的旅程 +advancement.ebwizardry:crystal=一个奇异的水晶... +advancement.ebwizardry:crystal.desc=挖掘一个魔法水晶 +advancement.ebwizardry:arcane_initiate=奥术启程 +advancement.ebwizardry:arcane_initiate.desc=利用金锭,木棍和魔法水晶制造一根法杖 +advancement.ebwizardry:apprentice=见习巫师 +advancement.ebwizardry:apprentice.desc=使用奥法宝典来升级你的法杖 +advancement.ebwizardry:master=大师级巫师 +advancement.ebwizardry:master.desc=获得大师级法杖 +advancement.ebwizardry:all_spells=巫师的自我修养 +advancement.ebwizardry:all_spells.desc=在游戏中施放所有法术 +advancement.ebwizardry:wizard_trade=魔法交易 +advancement.ebwizardry:wizard_trade.desc=向巫师购买物品 +advancement.ebwizardry:buy_master_spell=知识就是力量 +advancement.ebwizardry:buy_master_spell.desc=向巫师购买一个大师级卷轴 +advancement.ebwizardry:freeze_blaze=现在不太热了 +advancement.ebwizardry:freeze_blaze.desc=把烈焰人冻成傻子 +advancement.ebwizardry:charge_creep=它要炸了 +advancement.ebwizardry:charge_creeper.desc='意外' 捕获爬行者 +advancement.ebwizardry:frankenstein=弗兰肯斯坦 +advancement.ebwizardry:frankenstein.desc=用闪电法术将猪变成僵尸猪人 +advancement.ebwizardry:special_upgrade=奥术工匠 +advancement.ebwizardry:special_upgrade.desc=对法杖进行特殊升级 +advancement.ebwizardry:craft_flask=这是魔力,装瓶! +advancement.ebwizardry:craft_flask.desc=制作一个魔力瓶 +advancement.ebwizardry:elemental=元素 +advancement.ebwizardry:elemental.desc=获得元素法杖 +advancement.ebwizardry:armour_set=现在你是一个正确的巫师 +advancement.ebwizardry:armour_set.desc=制作并装备全套巫师护具 +advancement.ebwizardry:legendary=传奇! +advancement.ebwizardry:legendary.desc=获得一件传奇级装备 +advancement.ebwizardry:self_destruct=真是倒霉 +advancement.ebwizardry:self_destruct.desc=被自己的魔法杀死 +advancement.ebwizardry:pig_tornado=不会再次... +advancement.ebwizardry:pig_tornado.desc=骑着猪卷进飓风 +advancement.ebwizardry:jam_wizard=扰乱会议 +advancement.ebwizardry:jam_wizard.desc=对一个巫师使用奥术干扰 +advancement.ebwizardry:slime_skeleton=棘手局面 +advancement.ebwizardry:slime_skeleton.desc=利用史莱姆吞噬骷髅 +advancement.ebwizardry:anger_wizard=你会后悔的 +advancement.ebwizardry:anger_wizard.desc=使一个巫师发怒 +advancement.ebwizardry:defeat_evil_wizard=正义降临 +advancement.ebwizardry:defeat_evil_wizard.desc=击败邪恶巫师 +advancement.ebwizardry:max_out_wand=整装上阵 +advancement.ebwizardry:max_out_wand.desc=将大师级法杖升级到最强 +advancement.ebwizardry:element_master=元素掌控 +advancement.ebwizardry:element_master.desc=施放任何元素的法术 +advancement.ebwizardry:identify_spell=奥术鉴定 +advancement.ebwizardry:identify_spell.desc=使用鉴定卷轴来鉴定法术书或卷轴 tile.ebwizardry:transportation_stone.confirm=施展法术时你将会回到这里 %1$s tile.ebwizardry:transportation_stone.invalid=你必须先将八个传送石围成圆圈! @@ -272,7 +272,7 @@ container.ebwizardry:arcane_workbench.apply=应用 container.ebwizardry:arcane_workbench.mana=魔力: container.ebwizardry:arcane_workbench.upgrades=应用升级: -tier.basic=新手 +tier.novice=新手 tier.apprentice=学徒 tier.advanced=进阶 tier.master=大师 diff --git a/src/main/resources/assets/ebwizardry/loot_tables/chests/dungeon_additions.json b/src/main/resources/assets/ebwizardry/loot_tables/chests/dungeon_additions.json index 354086ff..db383025 100644 --- a/src/main/resources/assets/ebwizardry/loot_tables/chests/dungeon_additions.json +++ b/src/main/resources/assets/ebwizardry/loot_tables/chests/dungeon_additions.json @@ -3,34 +3,34 @@ { "name": "wizardry", "rolls": { - "min": 3, - "max": 7 + "min": 1, + "max": 3 }, "entries": [ { "type": "loot_table", - "name": "ebwizardry:subsets/novice_wands", - "weight": 3 + "name": "ebwizardry:subsets/elemental_crystals", + "weight": 6 }, { "type": "loot_table", "name": "ebwizardry:subsets/wizard_armour", - "weight": 6 + "weight": 10 }, { "type": "loot_table", "name": "ebwizardry:subsets/arcane_tomes", - "weight": 6 + "weight": 8 }, { "type": "loot_table", "name": "ebwizardry:subsets/wand_upgrades", - "weight": 2 + "weight": 4 }, { "type": "item", "name": "ebwizardry:magic_crystal", - "weight": 5, + "weight": 10, "functions": [ { "function": "set_count", @@ -44,23 +44,57 @@ { "type": "item", "name": "ebwizardry:spell_book", - "weight": 20, + "weight": 40, "functions": [ { - "function": "ebwizardry:random_spell" + "function": "ebwizardry:random_spell", + "undiscovered_bias": 0.3 } ] }, { "type": "item", "name": "ebwizardry:scroll", - "weight": 10, + "weight": 14, "functions": [ { - "function": "ebwizardry:random_spell" + "function": "ebwizardry:random_spell", + "undiscovered_bias": 0.3 + }, + { + "function": "set_count", + "count": { + "min": 1, + "max": 5 + } } ] }, + { + "type": "item", + "name": "ebwizardry:identification_scroll", + "weight": 6 + }, + { + "type": "item", + "name": "ebwizardry:firebomb", + "weight": 8 + }, + { + "type": "item", + "name": "ebwizardry:poison_bomb", + "weight": 8 + }, + { + "type": "item", + "name": "ebwizardry:smoke_bomb", + "weight": 8 + }, + { + "type": "item", + "name": "ebwizardry:spark_bomb", + "weight": 8 + }, { "type": "item", "name": "ebwizardry:armour_upgrade", @@ -68,23 +102,18 @@ }, { "type": "item", - "name": "ebwizardry:identification_scroll", - "weight": 3 + "name": "ebwizardry:astral_diamond", + "weight": 1 }, { "type": "item", - "name": "ebwizardry:firebomb", - "weight": 4 + "name": "ebwizardry:purifying_elixir", + "weight": 1 }, { "type": "item", - "name": "ebwizardry:poison_bomb", - "weight": 4 - }, - { - "type": "item", - "name": "ebwizardry:smoke_bomb", - "weight": 4 + "name": "ebwizardry:grand_crystal", + "weight": 1 } ] } diff --git a/src/main/resources/assets/ebwizardry/loot_tables/chests/jungle_dispenser_additions.json b/src/main/resources/assets/ebwizardry/loot_tables/chests/jungle_dispenser_additions.json new file mode 100644 index 00000000..c517f0fb --- /dev/null +++ b/src/main/resources/assets/ebwizardry/loot_tables/chests/jungle_dispenser_additions.json @@ -0,0 +1,65 @@ +{ + "pools": [ + { + "name": "wizardry_dispenser", + "rolls": 1, + "conditions": [ + { + "condition": "random_chance", + "chance": 0.4 + } + ], + "entries": [ + { + "type": "item", + "name": "ebwizardry:scroll", + "weight": 1, + "functions": [ + { + "function": "ebwizardry:random_spell", + "spells": [ + "magic_missile", + "arc", + "thunderbolt", + "summon_zombie", + "dart", + "ice_shard", + "firebolt", + "poison", + "flame_ray", + "frost_ray" + ] + }, + { + "function": "set_count", + "count": { + "min": 1, + "max": 5 + } + } + ] + }, + { + "type": "item", + "name": "ebwizardry:firebomb", + "weight": 3 + }, + { + "type": "item", + "name": "ebwizardry:poison_bomb", + "weight": 3 + }, + { + "type": "item", + "name": "ebwizardry:smoke_bomb", + "weight": 3 + }, + { + "type": "item", + "name": "ebwizardry:spark_bomb", + "weight": 3 + } + ] + } + ] +} \ No newline at end of file diff --git a/src/main/resources/assets/ebwizardry/loot_tables/chests/obelisk.json b/src/main/resources/assets/ebwizardry/loot_tables/chests/obelisk.json new file mode 100644 index 00000000..7a0a73a4 --- /dev/null +++ b/src/main/resources/assets/ebwizardry/loot_tables/chests/obelisk.json @@ -0,0 +1,195 @@ +{ + "pools": [ + { + "name": "high_value", + "rolls": { + "min": 1, + "max": 1 + }, + "entries": [ + { + "type": "loot_table", + "name": "ebwizardry:subsets/arcane_tomes", + "weight": 3 + }, + { + "type": "loot_table", + "name": "ebwizardry:subsets/wand_upgrades", + "weight": 2 + }, + { + "type": "item", + "name": "ebwizardry:spell_book", + "weight": 20, + "functions": [ + { + "function": "ebwizardry:random_spell", + "tiers": [ + "novice", + "apprentice", + "advanced" + ], + "undiscovered_bias": 0.3 + } + ] + }, + { + "type": "item", + "name": "ebwizardry:scroll", + "weight": 7, + "functions": [ + { + "function": "ebwizardry:random_spell", + "tiers": [ + "novice", + "apprentice", + "advanced" + ], + "undiscovered_bias": 0.3 + }, + { + "function": "set_count", + "count": { + "min": 1, + "max": 5 + } + } + ] + }, + { + "type": "item", + "name": "ebwizardry:identification_scroll", + "weight": 3 + }, + { + "type": "item", + "name": "minecraft:gold_nugget", + "weight": 5, + "functions": [ + { + "function": "set_count", + "count": { + "min": 1, + "max": 4 + } + } + ] + }, + { + "type": "item", + "name": "minecraft:emerald", + "weight": 1 + }, + { + "type": "item", + "name": "ebwizardry:grand_crystal", + "weight": 1 + } + ] + }, + { + "name": "low_value", + "rolls": { + "min": 3, + "max": 5 + }, + "entries": [ + { + "type": "loot_table", + "name": "ebwizardry:subsets/elemental_crystals", + "weight": 1 + }, + { + "type": "item", + "name": "ebwizardry:magic_crystal", + "weight": 5, + "functions": [ + { + "function": "set_count", + "count": { + "min": 1, + "max": 4 + } + } + ] + }, + { + "type": "item", + "name": "ebwizardry:firebomb", + "weight": 4 + }, + { + "type": "item", + "name": "ebwizardry:poison_bomb", + "weight": 4 + }, + { + "type": "item", + "name": "ebwizardry:smoke_bomb", + "weight": 4 + }, + { + "type": "item", + "name": "ebwizardry:spark_bomb", + "weight": 4 + }, + { + "type": "item", + "name": "minecraft:book", + "weight": 2, + "functions": [ + { + "function": "set_count", + "count": { + "min": 1, + "max": 2 + } + } + ] + }, + { + "type": "item", + "name": "minecraft:string", + "weight": 2, + "functions": [ + { + "function": "set_count", + "count": { + "min": 1, + "max": 5 + } + } + ] + }, + { + "type": "item", + "name": "minecraft:paper", + "weight": 2, + "functions": [ + { + "function": "set_count", + "count": { + "min": 1, + "max": 5 + } + } + ] + }, + { + "type": "item", + "name": "ebwizardry:crystal_shard", + "weight": 2, + "functions": [ + { + "function": "set_count", + "count": { + "min": 1, + "max": 5 + } + } + ] + } + ] + } + ] +} \ No newline at end of file diff --git a/src/main/resources/assets/ebwizardry/loot_tables/chests/shrine.json b/src/main/resources/assets/ebwizardry/loot_tables/chests/shrine.json new file mode 100644 index 00000000..76af240f --- /dev/null +++ b/src/main/resources/assets/ebwizardry/loot_tables/chests/shrine.json @@ -0,0 +1,210 @@ +{ + "pools": [ + { + "name": "artefact", + "rolls": 1, + "entries": [ + { + "type": "loot_table", + "name": "ebwizardry:subsets/uncommon_artefacts", + "weight": 5 + }, + { + "type": "loot_table", + "name": "ebwizardry:subsets/rare_artefacts", + "weight": 3 + }, + { + "type": "loot_table", + "name": "ebwizardry:subsets/epic_artefacts", + "weight": 1 + } + ] + }, + { + "name": "high_value", + "rolls": { + "min": 1, + "max": 2 + }, + "entries": [ + { + "type": "loot_table", + "name": "ebwizardry:subsets/arcane_tomes", + "weight": 6 + }, + { + "type": "loot_table", + "name": "ebwizardry:subsets/wand_upgrades", + "weight": 4 + }, + { + "type": "item", + "name": "ebwizardry:spell_book", + "weight": 40, + "functions": [ + { + "function": "ebwizardry:random_spell", + "undiscovered_bias": 0.3 + } + ] + }, + { + "type": "item", + "name": "ebwizardry:scroll", + "weight": 14, + "functions": [ + { + "function": "ebwizardry:random_spell", + "undiscovered_bias": 0.3 + }, + { + "function": "set_count", + "count": { + "min": 1, + "max": 5 + } + } + ] + }, + { + "type": "item", + "name": "ebwizardry:identification_scroll", + "weight": 6 + }, + { + "type": "item", + "name": "minecraft:gold_ingot", + "weight": 6, + "functions": [ + { + "function": "set_count", + "count": { + "min": 1, + "max": 6 + } + } + ] + }, + { + "type": "item", + "name": "minecraft:emerald", + "weight": 2, + "functions": [ + { + "function": "set_count", + "count": { + "min": 1, + "max": 3 + } + } + ] + }, + { + "type": "item", + "name": "ebwizardry:armour_upgrade", + "weight": 1 + }, + { + "type": "item", + "name": "ebwizardry:astral_diamond", + "weight": 1 + }, + { + "type": "item", + "name": "ebwizardry:purifying_elixir", + "weight": 1 + }, + { + "type": "item", + "name": "ebwizardry:grand_crystal", + "weight": 1 + } + ] + }, + { + "name": "low_value", + "rolls": { + "min": 2, + "max": 4 + }, + "entries": [ + { + "type": "loot_table", + "name": "ebwizardry:subsets/elemental_crystals", + "weight": 1 + }, + { + "type": "item", + "name": "ebwizardry:magic_crystal", + "weight": 5, + "functions": [ + { + "function": "set_count", + "count": { + "min": 1, + "max": 12 + } + } + ] + }, + { + "type": "item", + "name": "minecraft:book", + "weight": 2, + "functions": [ + { + "function": "set_count", + "count": { + "min": 1, + "max": 2 + } + } + ] + }, + { + "type": "item", + "name": "minecraft:string", + "weight": 2, + "functions": [ + { + "function": "set_count", + "count": { + "min": 1, + "max": 5 + } + } + ] + }, + { + "type": "item", + "name": "minecraft:paper", + "weight": 2, + "functions": [ + { + "function": "set_count", + "count": { + "min": 1, + "max": 5 + } + } + ] + }, + { + "type": "item", + "name": "ebwizardry:crystal_shard", + "weight": 2, + "functions": [ + { + "function": "set_count", + "count": { + "min": 1, + "max": 5 + } + } + ] + } + ] + } + ] +} \ No newline at end of file diff --git a/src/main/resources/assets/ebwizardry/loot_tables/chests/wizard_tower.json b/src/main/resources/assets/ebwizardry/loot_tables/chests/wizard_tower.json index 6e6dc805..4bb9c235 100644 --- a/src/main/resources/assets/ebwizardry/loot_tables/chests/wizard_tower.json +++ b/src/main/resources/assets/ebwizardry/loot_tables/chests/wizard_tower.json @@ -9,7 +9,7 @@ "entries": [ { "type": "loot_table", - "name": "ebwizardry:subsets/novice_wands", + "name": "ebwizardry:subsets/elemental_crystals", "weight": 3 }, { @@ -20,7 +20,7 @@ { "type": "loot_table", "name": "ebwizardry:subsets/arcane_tomes", - "weight": 6 + "weight": 4 }, { "type": "loot_table", @@ -47,17 +47,26 @@ "weight": 20, "functions": [ { - "function": "ebwizardry:random_spell" + "function": "ebwizardry:random_spell", + "undiscovered_bias": 0.3 } ] }, { "type": "item", "name": "ebwizardry:scroll", - "weight": 10, + "weight": 7, "functions": [ { - "function": "ebwizardry:random_spell" + "function": "ebwizardry:random_spell", + "undiscovered_bias": 0.3 + }, + { + "function": "set_count", + "count": { + "min": 1, + "max": 5 + } } ] }, diff --git a/src/main/resources/assets/ebwizardry/loot_tables/entities/mob_additions.json b/src/main/resources/assets/ebwizardry/loot_tables/entities/mob_additions.json index bf5c34d1..fa25f7e6 100644 --- a/src/main/resources/assets/ebwizardry/loot_tables/entities/mob_additions.json +++ b/src/main/resources/assets/ebwizardry/loot_tables/entities/mob_additions.json @@ -1,6 +1,7 @@ { "pools": [ { + "name": "wizardry", "conditions": [ { "condition": "killed_by_player" @@ -19,7 +20,12 @@ "weight": 1, "functions": [ { - "function": "ebwizardry:random_spell" + "function": "ebwizardry:random_spell", + "tiers": [ + "novice", + "apprentice", + "advanced" + ] } ] } diff --git a/src/main/resources/assets/ebwizardry/loot_tables/subsets/elemental_crystals.json b/src/main/resources/assets/ebwizardry/loot_tables/subsets/elemental_crystals.json new file mode 100644 index 00000000..56631c6d --- /dev/null +++ b/src/main/resources/assets/ebwizardry/loot_tables/subsets/elemental_crystals.json @@ -0,0 +1,24 @@ +{ + "pools": [ + { + "name": "crystals", + "rolls": 1, + "entries": [ + { + "type": "item", + "name": "ebwizardry:magic_crystal", + "weight": 1, + "functions": [ + { + "function": "set_data", + "data": { + "min": 1, + "max": 7 + } + } + ] + } + ] + } + ] +} \ No newline at end of file diff --git a/src/main/resources/assets/ebwizardry/loot_tables/subsets/epic_artefacts.json b/src/main/resources/assets/ebwizardry/loot_tables/subsets/epic_artefacts.json new file mode 100644 index 00000000..dd8cd8cb --- /dev/null +++ b/src/main/resources/assets/ebwizardry/loot_tables/subsets/epic_artefacts.json @@ -0,0 +1,75 @@ +{ + "pools": [ + { + "name": "epic_artefacts", + "rolls": 1, + "entries": [ + { + "type": "item", + "name": "ebwizardry:ring_combustion", + "weight": 1 + }, + { + "type": "item", + "name": "ebwizardry:ring_arcane_frost", + "weight": 1 + }, + { + "type": "item", + "name": "ebwizardry:ring_seeking", + "weight": 1 + }, + { + "type": "item", + "name": "ebwizardry:ring_hammer", + "weight": 1 + }, + { + "type": "item", + "name": "ebwizardry:ring_mana_return", + "weight": 1 + }, + { + "type": "item", + "name": "ebwizardry:ring_interdiction", + "weight": 1 + }, + { + "type": "item", + "name": "ebwizardry:amulet_ice_immunity", + "weight": 1 + }, + { + "type": "item", + "name": "ebwizardry:amulet_wither_immunity", + "weight": 1 + }, + { + "type": "item", + "name": "ebwizardry:amulet_glide", + "weight": 1 + }, + { + "type": "item", + "name": "ebwizardry:amulet_resurrection", + "weight": 1 + }, + { + "type": "item", + "name": "ebwizardry:charm_experience_tome", + "weight": 1 + }, + { + "type": "item", + "name": "ebwizardry:charm_silk_touch", + "weight": 1 + }, + { + "type": "item", + "name": "ebwizardry:charm_stop_time", + "weight": 1 + } + ] + } + ] +} \ No newline at end of file diff --git a/src/main/resources/assets/ebwizardry/loot_tables/subsets/novice_wands.json b/src/main/resources/assets/ebwizardry/loot_tables/subsets/novice_wands.json deleted file mode 100644 index 8ed04e9b..00000000 --- a/src/main/resources/assets/ebwizardry/loot_tables/subsets/novice_wands.json +++ /dev/null @@ -1,50 +0,0 @@ -{ - "pools": [ - { - "name": "wands", - "rolls": 1, - "entries": [ - { - "type": "item", - "name": "ebwizardry:magic_wand", - "weight": 1 - }, - { - "type": "item", - "name": "ebwizardry:basic_fire_wand", - "weight": 1 - }, - { - "type": "item", - "name": "ebwizardry:basic_ice_wand", - "weight": 1 - }, - { - "type": "item", - "name": "ebwizardry:basic_lightning_wand", - "weight": 1 - }, - { - "type": "item", - "name": "ebwizardry:basic_necromancy_wand", - "weight": 1 - }, - { - "type": "item", - "name": "ebwizardry:basic_earth_wand", - "weight": 1 - }, - { - "type": "item", - "name": "ebwizardry:basic_sorcery_wand", - "weight": 1 - }, - { - "type": "item", - "name": "ebwizardry:basic_healing_wand", - "weight": 1 - } - ] - } - ] -} \ No newline at end of file diff --git a/src/main/resources/assets/ebwizardry/loot_tables/subsets/rare_artefacts.json b/src/main/resources/assets/ebwizardry/loot_tables/subsets/rare_artefacts.json new file mode 100644 index 00000000..24a74e24 --- /dev/null +++ b/src/main/resources/assets/ebwizardry/loot_tables/subsets/rare_artefacts.json @@ -0,0 +1,145 @@ +{ + "pools": [ + { + "name": "rare_artefacts", + "rolls": 1, + "entries": [ + { + "type": "item", + "name": "ebwizardry:ring_condensing", + "weight": 1 + }, + { + "type": "item", + "name": "ebwizardry:ring_battlemage", + "weight": 1 + }, + { + "type": "item", + "name": "ebwizardry:ring_disintegration", + "weight": 1 + }, + { + "type": "item", + "name": "ebwizardry:ring_shattering", + "weight": 1 + }, + { + "type": "item", + "name": "ebwizardry:ring_storm", + "weight": 1 + }, + { + "type": "item", + "name": "ebwizardry:ring_soulbinding", + "weight": 1 + }, + { + "type": "item", + "name": "ebwizardry:ring_leeching", + "weight": 1 + }, + { + "type": "item", + "name": "ebwizardry:ring_mind_control", + "weight": 1 + }, + { + "type": "item", + "name": "ebwizardry:ring_poison", + "weight": 1 + }, + { + "type": "item", + "name": "ebwizardry:ring_full_moon", + "weight": 1 + }, + { + "type": "item", + "name": "ebwizardry:ring_blockwrangler", + "weight": 1 + }, + { + "type": "item", + "name": "ebwizardry:ring_conjurer", + "weight": 1 + }, + { + "type": "item", + "name": "ebwizardry:ring_defender", + "weight": 1 + }, + { + "type": "item", + "name": "ebwizardry:amulet_arcane_defence", + "weight": 1 + }, + { + "type": "item", + "name": "ebwizardry:amulet_wisdom", + "weight": 1 + }, + { + "type": "item", + "name": "ebwizardry:amulet_fire_cloaking", + "weight": 1 + }, + { + "type": "item", + "name": "ebwizardry:amulet_potential", + "weight": 1 + }, + { + "type": "item", + "name": "ebwizardry:amulet_anchoring", + "weight": 1 + }, + { + "type": "item", + "name": "ebwizardry:amulet_transience", + "weight": 1 + }, + { + "type": "item", + "name": "ebwizardry:amulet_auto_shield", + "weight": 1 + }, + { + "type": "item", + "name": "ebwizardry:charm_haggler", + "weight": 1 + }, + { + "type": "item", + "name": "ebwizardry:charm_auto_smelt", + "weight": 1 + }, + { + "type": "item", + "name": "ebwizardry:charm_storm", + "weight": 1 + }, + { + "type": "item", + "name": "ebwizardry:charm_minion_variants", + "weight": 1 + }, + { + "type": "item", + "name": "ebwizardry:charm_flight", + "weight": 1 + }, + { + "type": "item", + "name": "ebwizardry:charm_abseiling", + "weight": 1 + }, + { + "type": "item", + "name": "ebwizardry:charm_light", + "weight": 1 + } + ] + } + ] +} \ No newline at end of file diff --git a/src/main/resources/assets/ebwizardry/loot_tables/subsets/uncommon_artefacts.json b/src/main/resources/assets/ebwizardry/loot_tables/subsets/uncommon_artefacts.json new file mode 100644 index 00000000..c52abb3d --- /dev/null +++ b/src/main/resources/assets/ebwizardry/loot_tables/subsets/uncommon_artefacts.json @@ -0,0 +1,115 @@ +{ + "pools": [ + { + "name": "uncommon_artefacts", + "rolls": 1, + "entries": [ + { + "type": "item", + "name": "ebwizardry:ring_siphoning", + "weight": 1 + }, + { + "type": "item", + "name": "ebwizardry:ring_fire_melee", + "weight": 1 + }, + { + "type": "item", + "name": "ebwizardry:ring_fire_biome", + "weight": 1 + }, + { + "type": "item", + "name": "ebwizardry:ring_ice_melee", + "weight": 1 + }, + { + "type": "item", + "name": "ebwizardry:ring_ice_biome", + "weight": 1 + }, + { + "type": "item", + "name": "ebwizardry:ring_lightning_melee", + "weight": 1 + }, + { + "type": "item", + "name": "ebwizardry:ring_necromancy_melee", + "weight": 1 + }, + { + "type": "item", + "name": "ebwizardry:ring_earth_melee", + "weight": 1 + }, + { + "type": "item", + "name": "ebwizardry:ring_earth_biome", + "weight": 1 + }, + { + "type": "item", + "name": "ebwizardry:ring_extraction", + "weight": 1 + }, + { + "type": "item", + "name": "ebwizardry:ring_paladin", + "weight": 1 + }, + { + "type": "item", + "name": "ebwizardry:amulet_warding", + "weight": 1 + }, + { + "type": "item", + "name": "ebwizardry:amulet_fire_protection", + "weight": 1 + }, + { + "type": "item", + "name": "ebwizardry:amulet_ice_protection", + "weight": 1 + }, + { + "type": "item", + "name": "ebwizardry:amulet_channeling", + "weight": 1 + }, + { + "type": "item", + "name": "ebwizardry:amulet_lich", + "weight": 1 + }, + { + "type": "item", + "name": "ebwizardry:amulet_banishing", + "weight": 1 + }, + { + "type": "item", + "name": "ebwizardry:amulet_recovery", + "weight": 1 + }, + { + "type": "item", + "name": "ebwizardry:charm_minion_health", + "weight": 1 + }, + { + "type": "item", + "name": "ebwizardry:charm_growth", + "weight": 1 + }, + { + "type": "item", + "name": "ebwizardry:charm_feeding", + "weight": 1 + } + ] + } + ] +} \ No newline at end of file diff --git a/src/main/resources/assets/ebwizardry/loot_tables/subsets/wand_upgrades.json b/src/main/resources/assets/ebwizardry/loot_tables/subsets/wand_upgrades.json index 3409fd48..327c379b 100644 --- a/src/main/resources/assets/ebwizardry/loot_tables/subsets/wand_upgrades.json +++ b/src/main/resources/assets/ebwizardry/loot_tables/subsets/wand_upgrades.json @@ -43,7 +43,12 @@ "type": "item", "name": "ebwizardry:attunement_upgrade", "weight": 1 - } + }, + { + "type": "item", + "name": "ebwizardry:melee_upgrade", + "weight": 1 + } ] } ] diff --git a/src/main/resources/assets/ebwizardry/models/block/earth_crystal_block.json b/src/main/resources/assets/ebwizardry/models/block/earth_crystal_block.json new file mode 100644 index 00000000..c0baec0f --- /dev/null +++ b/src/main/resources/assets/ebwizardry/models/block/earth_crystal_block.json @@ -0,0 +1,6 @@ +{ + "parent": "block/cube_all", + "textures": { + "all": "ebwizardry:blocks/crystal_block_earth" + } +} diff --git a/src/main/resources/assets/ebwizardry/models/block/earth_runestone_1.json b/src/main/resources/assets/ebwizardry/models/block/earth_runestone_1.json new file mode 100644 index 00000000..105a76c9 --- /dev/null +++ b/src/main/resources/assets/ebwizardry/models/block/earth_runestone_1.json @@ -0,0 +1,8 @@ +{ + "parent": "ebwizardry:block/runestone", + "textures": { + "side": "ebwizardry:blocks/runestone_earth_0", + "rune": "ebwizardry:blocks/runestone_earth_1", + "overlay": "ebwizardry:blocks/runestone_earth_1_overlay" + } +} diff --git a/src/main/resources/assets/ebwizardry/models/block/earth_runestone_2.json b/src/main/resources/assets/ebwizardry/models/block/earth_runestone_2.json new file mode 100644 index 00000000..5cba9240 --- /dev/null +++ b/src/main/resources/assets/ebwizardry/models/block/earth_runestone_2.json @@ -0,0 +1,8 @@ +{ + "parent": "ebwizardry:block/runestone", + "textures": { + "side": "ebwizardry:blocks/runestone_earth_0", + "rune": "ebwizardry:blocks/runestone_earth_2", + "overlay": "ebwizardry:blocks/runestone_earth_2_overlay" + } +} diff --git a/src/main/resources/assets/ebwizardry/models/block/earth_runestone_3.json b/src/main/resources/assets/ebwizardry/models/block/earth_runestone_3.json new file mode 100644 index 00000000..72f72fd0 --- /dev/null +++ b/src/main/resources/assets/ebwizardry/models/block/earth_runestone_3.json @@ -0,0 +1,8 @@ +{ + "parent": "ebwizardry:block/runestone", + "textures": { + "side": "ebwizardry:blocks/runestone_earth_0", + "rune": "ebwizardry:blocks/runestone_earth_3", + "overlay": "ebwizardry:blocks/runestone_earth_3_overlay" + } +} diff --git a/src/main/resources/assets/ebwizardry/models/block/earth_runestone_4.json b/src/main/resources/assets/ebwizardry/models/block/earth_runestone_4.json new file mode 100644 index 00000000..e712f365 --- /dev/null +++ b/src/main/resources/assets/ebwizardry/models/block/earth_runestone_4.json @@ -0,0 +1,8 @@ +{ + "parent": "ebwizardry:block/runestone", + "textures": { + "side": "ebwizardry:blocks/runestone_earth_0", + "rune": "ebwizardry:blocks/runestone_earth_4", + "overlay": "ebwizardry:blocks/runestone_earth_4_overlay" + } +} diff --git a/src/main/resources/assets/ebwizardry/models/block/earth_runestone_pedestal.json b/src/main/resources/assets/ebwizardry/models/block/earth_runestone_pedestal.json new file mode 100644 index 00000000..c0c68819 --- /dev/null +++ b/src/main/resources/assets/ebwizardry/models/block/earth_runestone_pedestal.json @@ -0,0 +1,9 @@ +{ + "parent": "ebwizardry:block/runestone_pedestal", + "textures": { + "side": "ebwizardry:blocks/runestone_pedestal_earth", + "top": "ebwizardry:blocks/runestone_earth_0", + "bottom": "ebwizardry:blocks/runestone_earth_0", + "overlay": "ebwizardry:blocks/runestone_pedestal_earth_overlay" + } +} diff --git a/src/main/resources/assets/ebwizardry/models/block/fire_crystal_block.json b/src/main/resources/assets/ebwizardry/models/block/fire_crystal_block.json new file mode 100644 index 00000000..fc76eed1 --- /dev/null +++ b/src/main/resources/assets/ebwizardry/models/block/fire_crystal_block.json @@ -0,0 +1,6 @@ +{ + "parent": "block/cube_all", + "textures": { + "all": "ebwizardry:blocks/crystal_block_fire" + } +} diff --git a/src/main/resources/assets/ebwizardry/models/block/fire_runestone_1.json b/src/main/resources/assets/ebwizardry/models/block/fire_runestone_1.json new file mode 100644 index 00000000..91f6f742 --- /dev/null +++ b/src/main/resources/assets/ebwizardry/models/block/fire_runestone_1.json @@ -0,0 +1,8 @@ +{ + "parent": "ebwizardry:block/runestone", + "textures": { + "side": "ebwizardry:blocks/runestone_fire_0", + "rune": "ebwizardry:blocks/runestone_fire_1", + "overlay": "ebwizardry:blocks/runestone_fire_1_overlay" + } +} diff --git a/src/main/resources/assets/ebwizardry/models/block/fire_runestone_2.json b/src/main/resources/assets/ebwizardry/models/block/fire_runestone_2.json new file mode 100644 index 00000000..4b09137d --- /dev/null +++ b/src/main/resources/assets/ebwizardry/models/block/fire_runestone_2.json @@ -0,0 +1,8 @@ +{ + "parent": "ebwizardry:block/runestone", + "textures": { + "side": "ebwizardry:blocks/runestone_fire_0", + "rune": "ebwizardry:blocks/runestone_fire_2", + "overlay": "ebwizardry:blocks/runestone_fire_2_overlay" + } +} diff --git a/src/main/resources/assets/ebwizardry/models/block/fire_runestone_3.json b/src/main/resources/assets/ebwizardry/models/block/fire_runestone_3.json new file mode 100644 index 00000000..8a29a569 --- /dev/null +++ b/src/main/resources/assets/ebwizardry/models/block/fire_runestone_3.json @@ -0,0 +1,8 @@ +{ + "parent": "ebwizardry:block/runestone", + "textures": { + "side": "ebwizardry:blocks/runestone_fire_0", + "rune": "ebwizardry:blocks/runestone_fire_3", + "overlay": "ebwizardry:blocks/runestone_fire_3_overlay" + } +} diff --git a/src/main/resources/assets/ebwizardry/models/block/fire_runestone_4.json b/src/main/resources/assets/ebwizardry/models/block/fire_runestone_4.json new file mode 100644 index 00000000..b947eff0 --- /dev/null +++ b/src/main/resources/assets/ebwizardry/models/block/fire_runestone_4.json @@ -0,0 +1,8 @@ +{ + "parent": "ebwizardry:block/runestone", + "textures": { + "side": "ebwizardry:blocks/runestone_fire_0", + "rune": "ebwizardry:blocks/runestone_fire_4", + "overlay": "ebwizardry:blocks/runestone_fire_4_overlay" + } +} diff --git a/src/main/resources/assets/ebwizardry/models/block/fire_runestone_pedestal.json b/src/main/resources/assets/ebwizardry/models/block/fire_runestone_pedestal.json new file mode 100644 index 00000000..217052eb --- /dev/null +++ b/src/main/resources/assets/ebwizardry/models/block/fire_runestone_pedestal.json @@ -0,0 +1,9 @@ +{ + "parent": "ebwizardry:block/runestone_pedestal", + "textures": { + "side": "ebwizardry:blocks/runestone_pedestal_fire", + "top": "ebwizardry:blocks/runestone_fire_0", + "bottom": "ebwizardry:blocks/runestone_fire_0", + "overlay": "ebwizardry:blocks/runestone_pedestal_fire_overlay" + } +} diff --git a/src/main/resources/assets/ebwizardry/models/block/healing_crystal_block.json b/src/main/resources/assets/ebwizardry/models/block/healing_crystal_block.json new file mode 100644 index 00000000..8b3b9b59 --- /dev/null +++ b/src/main/resources/assets/ebwizardry/models/block/healing_crystal_block.json @@ -0,0 +1,6 @@ +{ + "parent": "block/cube_all", + "textures": { + "all": "ebwizardry:blocks/crystal_block_healing" + } +} diff --git a/src/main/resources/assets/ebwizardry/models/block/healing_runestone_1.json b/src/main/resources/assets/ebwizardry/models/block/healing_runestone_1.json new file mode 100644 index 00000000..0d22b1c2 --- /dev/null +++ b/src/main/resources/assets/ebwizardry/models/block/healing_runestone_1.json @@ -0,0 +1,8 @@ +{ + "parent": "ebwizardry:block/runestone", + "textures": { + "side": "ebwizardry:blocks/runestone_healing_0", + "rune": "ebwizardry:blocks/runestone_healing_1", + "overlay": "ebwizardry:blocks/runestone_healing_1_overlay" + } +} diff --git a/src/main/resources/assets/ebwizardry/models/block/healing_runestone_2.json b/src/main/resources/assets/ebwizardry/models/block/healing_runestone_2.json new file mode 100644 index 00000000..d53d274d --- /dev/null +++ b/src/main/resources/assets/ebwizardry/models/block/healing_runestone_2.json @@ -0,0 +1,8 @@ +{ + "parent": "ebwizardry:block/runestone", + "textures": { + "side": "ebwizardry:blocks/runestone_healing_0", + "rune": "ebwizardry:blocks/runestone_healing_2", + "overlay": "ebwizardry:blocks/runestone_healing_2_overlay" + } +} diff --git a/src/main/resources/assets/ebwizardry/models/block/healing_runestone_3.json b/src/main/resources/assets/ebwizardry/models/block/healing_runestone_3.json new file mode 100644 index 00000000..072acd5d --- /dev/null +++ b/src/main/resources/assets/ebwizardry/models/block/healing_runestone_3.json @@ -0,0 +1,8 @@ +{ + "parent": "ebwizardry:block/runestone", + "textures": { + "side": "ebwizardry:blocks/runestone_healing_0", + "rune": "ebwizardry:blocks/runestone_healing_3", + "overlay": "ebwizardry:blocks/runestone_healing_3_overlay" + } +} diff --git a/src/main/resources/assets/ebwizardry/models/block/healing_runestone_4.json b/src/main/resources/assets/ebwizardry/models/block/healing_runestone_4.json new file mode 100644 index 00000000..c4c5c93e --- /dev/null +++ b/src/main/resources/assets/ebwizardry/models/block/healing_runestone_4.json @@ -0,0 +1,8 @@ +{ + "parent": "ebwizardry:block/runestone", + "textures": { + "side": "ebwizardry:blocks/runestone_healing_0", + "rune": "ebwizardry:blocks/runestone_healing_4", + "overlay": "ebwizardry:blocks/runestone_healing_4_overlay" + } +} diff --git a/src/main/resources/assets/ebwizardry/models/block/healing_runestone_pedestal.json b/src/main/resources/assets/ebwizardry/models/block/healing_runestone_pedestal.json new file mode 100644 index 00000000..ae6c6622 --- /dev/null +++ b/src/main/resources/assets/ebwizardry/models/block/healing_runestone_pedestal.json @@ -0,0 +1,9 @@ +{ + "parent": "ebwizardry:block/runestone_pedestal", + "textures": { + "side": "ebwizardry:blocks/runestone_pedestal_healing", + "top": "ebwizardry:blocks/runestone_healing_0", + "bottom": "ebwizardry:blocks/runestone_healing_0", + "overlay": "ebwizardry:blocks/runestone_pedestal_healing_overlay" + } +} diff --git a/src/main/resources/assets/ebwizardry/models/block/ice_crystal_block.json b/src/main/resources/assets/ebwizardry/models/block/ice_crystal_block.json new file mode 100644 index 00000000..d9a986c8 --- /dev/null +++ b/src/main/resources/assets/ebwizardry/models/block/ice_crystal_block.json @@ -0,0 +1,6 @@ +{ + "parent": "block/cube_all", + "textures": { + "all": "ebwizardry:blocks/crystal_block_ice" + } +} diff --git a/src/main/resources/assets/ebwizardry/models/block/ice_runestone_1.json b/src/main/resources/assets/ebwizardry/models/block/ice_runestone_1.json new file mode 100644 index 00000000..29ad56da --- /dev/null +++ b/src/main/resources/assets/ebwizardry/models/block/ice_runestone_1.json @@ -0,0 +1,8 @@ +{ + "parent": "ebwizardry:block/runestone", + "textures": { + "side": "ebwizardry:blocks/runestone_ice_0", + "rune": "ebwizardry:blocks/runestone_ice_1", + "overlay": "ebwizardry:blocks/runestone_ice_1_overlay" + } +} diff --git a/src/main/resources/assets/ebwizardry/models/block/ice_runestone_2.json b/src/main/resources/assets/ebwizardry/models/block/ice_runestone_2.json new file mode 100644 index 00000000..238ba14b --- /dev/null +++ b/src/main/resources/assets/ebwizardry/models/block/ice_runestone_2.json @@ -0,0 +1,8 @@ +{ + "parent": "ebwizardry:block/runestone", + "textures": { + "side": "ebwizardry:blocks/runestone_ice_0", + "rune": "ebwizardry:blocks/runestone_ice_2", + "overlay": "ebwizardry:blocks/runestone_ice_2_overlay" + } +} diff --git a/src/main/resources/assets/ebwizardry/models/block/ice_runestone_3.json b/src/main/resources/assets/ebwizardry/models/block/ice_runestone_3.json new file mode 100644 index 00000000..08b19d15 --- /dev/null +++ b/src/main/resources/assets/ebwizardry/models/block/ice_runestone_3.json @@ -0,0 +1,8 @@ +{ + "parent": "ebwizardry:block/runestone", + "textures": { + "side": "ebwizardry:blocks/runestone_ice_0", + "rune": "ebwizardry:blocks/runestone_ice_3", + "overlay": "ebwizardry:blocks/runestone_ice_3_overlay" + } +} diff --git a/src/main/resources/assets/ebwizardry/models/block/ice_runestone_4.json b/src/main/resources/assets/ebwizardry/models/block/ice_runestone_4.json new file mode 100644 index 00000000..657dbaa1 --- /dev/null +++ b/src/main/resources/assets/ebwizardry/models/block/ice_runestone_4.json @@ -0,0 +1,8 @@ +{ + "parent": "ebwizardry:block/runestone", + "textures": { + "side": "ebwizardry:blocks/runestone_ice_0", + "rune": "ebwizardry:blocks/runestone_ice_4", + "overlay": "ebwizardry:blocks/runestone_ice_4_overlay" + } +} diff --git a/src/main/resources/assets/ebwizardry/models/block/ice_runestone_pedestal.json b/src/main/resources/assets/ebwizardry/models/block/ice_runestone_pedestal.json new file mode 100644 index 00000000..b627123b --- /dev/null +++ b/src/main/resources/assets/ebwizardry/models/block/ice_runestone_pedestal.json @@ -0,0 +1,9 @@ +{ + "parent": "ebwizardry:block/runestone_pedestal", + "textures": { + "side": "ebwizardry:blocks/runestone_pedestal_ice", + "top": "ebwizardry:blocks/runestone_ice_0", + "bottom": "ebwizardry:blocks/runestone_ice_0", + "overlay": "ebwizardry:blocks/runestone_pedestal_ice_overlay" + } +} diff --git a/src/main/resources/assets/ebwizardry/models/block/lightning_crystal_block.json b/src/main/resources/assets/ebwizardry/models/block/lightning_crystal_block.json new file mode 100644 index 00000000..b9dd389e --- /dev/null +++ b/src/main/resources/assets/ebwizardry/models/block/lightning_crystal_block.json @@ -0,0 +1,6 @@ +{ + "parent": "block/cube_all", + "textures": { + "all": "ebwizardry:blocks/crystal_block_lightning" + } +} diff --git a/src/main/resources/assets/ebwizardry/models/block/lightning_runestone_1.json b/src/main/resources/assets/ebwizardry/models/block/lightning_runestone_1.json new file mode 100644 index 00000000..3773208b --- /dev/null +++ b/src/main/resources/assets/ebwizardry/models/block/lightning_runestone_1.json @@ -0,0 +1,8 @@ +{ + "parent": "ebwizardry:block/runestone", + "textures": { + "side": "ebwizardry:blocks/runestone_lightning_0", + "rune": "ebwizardry:blocks/runestone_lightning_1", + "overlay": "ebwizardry:blocks/runestone_lightning_1_overlay" + } +} diff --git a/src/main/resources/assets/ebwizardry/models/block/lightning_runestone_2.json b/src/main/resources/assets/ebwizardry/models/block/lightning_runestone_2.json new file mode 100644 index 00000000..2e461a41 --- /dev/null +++ b/src/main/resources/assets/ebwizardry/models/block/lightning_runestone_2.json @@ -0,0 +1,8 @@ +{ + "parent": "ebwizardry:block/runestone", + "textures": { + "side": "ebwizardry:blocks/runestone_lightning_0", + "rune": "ebwizardry:blocks/runestone_lightning_2", + "overlay": "ebwizardry:blocks/runestone_lightning_2_overlay" + } +} diff --git a/src/main/resources/assets/ebwizardry/models/block/lightning_runestone_3.json b/src/main/resources/assets/ebwizardry/models/block/lightning_runestone_3.json new file mode 100644 index 00000000..1db68f01 --- /dev/null +++ b/src/main/resources/assets/ebwizardry/models/block/lightning_runestone_3.json @@ -0,0 +1,8 @@ +{ + "parent": "ebwizardry:block/runestone", + "textures": { + "side": "ebwizardry:blocks/runestone_lightning_0", + "rune": "ebwizardry:blocks/runestone_lightning_3", + "overlay": "ebwizardry:blocks/runestone_lightning_3_overlay" + } +} diff --git a/src/main/resources/assets/ebwizardry/models/block/lightning_runestone_4.json b/src/main/resources/assets/ebwizardry/models/block/lightning_runestone_4.json new file mode 100644 index 00000000..e4cca3cc --- /dev/null +++ b/src/main/resources/assets/ebwizardry/models/block/lightning_runestone_4.json @@ -0,0 +1,8 @@ +{ + "parent": "ebwizardry:block/runestone", + "textures": { + "side": "ebwizardry:blocks/runestone_lightning_0", + "rune": "ebwizardry:blocks/runestone_lightning_4", + "overlay": "ebwizardry:blocks/runestone_lightning_4_overlay" + } +} diff --git a/src/main/resources/assets/ebwizardry/models/block/lightning_runestone_pedestal.json b/src/main/resources/assets/ebwizardry/models/block/lightning_runestone_pedestal.json new file mode 100644 index 00000000..212353ee --- /dev/null +++ b/src/main/resources/assets/ebwizardry/models/block/lightning_runestone_pedestal.json @@ -0,0 +1,9 @@ +{ + "parent": "ebwizardry:block/runestone_pedestal", + "textures": { + "side": "ebwizardry:blocks/runestone_pedestal_lightning", + "top": "ebwizardry:blocks/runestone_lightning_0", + "bottom": "ebwizardry:blocks/runestone_lightning_0", + "overlay": "ebwizardry:blocks/runestone_pedestal_lightning_overlay" + } +} diff --git a/src/main/resources/assets/ebwizardry/models/block/crystal_block.json b/src/main/resources/assets/ebwizardry/models/block/magic_crystal_block.json similarity index 100% rename from src/main/resources/assets/ebwizardry/models/block/crystal_block.json rename to src/main/resources/assets/ebwizardry/models/block/magic_crystal_block.json diff --git a/src/main/resources/assets/ebwizardry/models/block/necromancy_crystal_block.json b/src/main/resources/assets/ebwizardry/models/block/necromancy_crystal_block.json new file mode 100644 index 00000000..52268c00 --- /dev/null +++ b/src/main/resources/assets/ebwizardry/models/block/necromancy_crystal_block.json @@ -0,0 +1,6 @@ +{ + "parent": "block/cube_all", + "textures": { + "all": "ebwizardry:blocks/crystal_block_necromancy" + } +} diff --git a/src/main/resources/assets/ebwizardry/models/block/necromancy_runestone_1.json b/src/main/resources/assets/ebwizardry/models/block/necromancy_runestone_1.json new file mode 100644 index 00000000..9d9bf318 --- /dev/null +++ b/src/main/resources/assets/ebwizardry/models/block/necromancy_runestone_1.json @@ -0,0 +1,8 @@ +{ + "parent": "ebwizardry:block/runestone", + "textures": { + "side": "ebwizardry:blocks/runestone_necromancy_0", + "rune": "ebwizardry:blocks/runestone_necromancy_1", + "overlay": "ebwizardry:blocks/runestone_necromancy_1_overlay" + } +} diff --git a/src/main/resources/assets/ebwizardry/models/block/necromancy_runestone_2.json b/src/main/resources/assets/ebwizardry/models/block/necromancy_runestone_2.json new file mode 100644 index 00000000..8004eac5 --- /dev/null +++ b/src/main/resources/assets/ebwizardry/models/block/necromancy_runestone_2.json @@ -0,0 +1,8 @@ +{ + "parent": "ebwizardry:block/runestone", + "textures": { + "side": "ebwizardry:blocks/runestone_necromancy_0", + "rune": "ebwizardry:blocks/runestone_necromancy_2", + "overlay": "ebwizardry:blocks/runestone_necromancy_2_overlay" + } +} diff --git a/src/main/resources/assets/ebwizardry/models/block/necromancy_runestone_3.json b/src/main/resources/assets/ebwizardry/models/block/necromancy_runestone_3.json new file mode 100644 index 00000000..0eea58e9 --- /dev/null +++ b/src/main/resources/assets/ebwizardry/models/block/necromancy_runestone_3.json @@ -0,0 +1,8 @@ +{ + "parent": "ebwizardry:block/runestone", + "textures": { + "side": "ebwizardry:blocks/runestone_necromancy_0", + "rune": "ebwizardry:blocks/runestone_necromancy_3", + "overlay": "ebwizardry:blocks/runestone_necromancy_3_overlay" + } +} diff --git a/src/main/resources/assets/ebwizardry/models/block/necromancy_runestone_4.json b/src/main/resources/assets/ebwizardry/models/block/necromancy_runestone_4.json new file mode 100644 index 00000000..4a83a330 --- /dev/null +++ b/src/main/resources/assets/ebwizardry/models/block/necromancy_runestone_4.json @@ -0,0 +1,8 @@ +{ + "parent": "ebwizardry:block/runestone", + "textures": { + "side": "ebwizardry:blocks/runestone_necromancy_0", + "rune": "ebwizardry:blocks/runestone_necromancy_4", + "overlay": "ebwizardry:blocks/runestone_necromancy_4_overlay" + } +} diff --git a/src/main/resources/assets/ebwizardry/models/block/necromancy_runestone_pedestal.json b/src/main/resources/assets/ebwizardry/models/block/necromancy_runestone_pedestal.json new file mode 100644 index 00000000..a787cd59 --- /dev/null +++ b/src/main/resources/assets/ebwizardry/models/block/necromancy_runestone_pedestal.json @@ -0,0 +1,9 @@ +{ + "parent": "ebwizardry:block/runestone_pedestal", + "textures": { + "side": "ebwizardry:blocks/runestone_pedestal_necromancy", + "top": "ebwizardry:blocks/runestone_necromancy_0", + "bottom": "ebwizardry:blocks/runestone_necromancy_0", + "overlay": "ebwizardry:blocks/runestone_pedestal_necromancy_overlay" + } +} diff --git a/src/main/resources/assets/ebwizardry/models/block/obsidian_crust_0.json b/src/main/resources/assets/ebwizardry/models/block/obsidian_crust_0.json new file mode 100644 index 00000000..d353e00c --- /dev/null +++ b/src/main/resources/assets/ebwizardry/models/block/obsidian_crust_0.json @@ -0,0 +1,6 @@ +{ + "parent": "block/cube_all", + "textures": { + "all": "ebwizardry:blocks/obsidian_crust_0" + } +} diff --git a/src/main/resources/assets/ebwizardry/models/block/obsidian_crust_1.json b/src/main/resources/assets/ebwizardry/models/block/obsidian_crust_1.json new file mode 100644 index 00000000..a18b3ea2 --- /dev/null +++ b/src/main/resources/assets/ebwizardry/models/block/obsidian_crust_1.json @@ -0,0 +1,6 @@ +{ + "parent": "block/cube_all", + "textures": { + "all": "ebwizardry:blocks/obsidian_crust_1" + } +} diff --git a/src/main/resources/assets/ebwizardry/models/block/obsidian_crust_2.json b/src/main/resources/assets/ebwizardry/models/block/obsidian_crust_2.json new file mode 100644 index 00000000..b29fb73b --- /dev/null +++ b/src/main/resources/assets/ebwizardry/models/block/obsidian_crust_2.json @@ -0,0 +1,6 @@ +{ + "parent": "block/cube_all", + "textures": { + "all": "ebwizardry:blocks/obsidian_crust_2" + } +} diff --git a/src/main/resources/assets/ebwizardry/models/block/obsidian_crust_3.json b/src/main/resources/assets/ebwizardry/models/block/obsidian_crust_3.json new file mode 100644 index 00000000..a25d73bd --- /dev/null +++ b/src/main/resources/assets/ebwizardry/models/block/obsidian_crust_3.json @@ -0,0 +1,6 @@ +{ + "parent": "block/cube_all", + "textures": { + "all": "ebwizardry:blocks/obsidian_crust_3" + } +} diff --git a/src/main/resources/assets/ebwizardry/models/block/runestone.json b/src/main/resources/assets/ebwizardry/models/block/runestone.json new file mode 100644 index 00000000..ed3e9fa6 --- /dev/null +++ b/src/main/resources/assets/ebwizardry/models/block/runestone.json @@ -0,0 +1,27 @@ +{ + "parent": "block/block", + "textures": { + "particle": "#rune" + }, + "elements": [ + { + "from": [ 0, 0, 0 ], + "to": [ 16, 16, 16 ], + "faces": { + "down": { "uv": [ 0, 0, 16, 16 ], "texture": "#side", "cullface": "down" }, + "up": { "uv": [ 0, 0, 16, 16 ], "texture": "#side", "cullface": "up" }, + "north": { "uv": [ 0, 0, 16, 16 ], "texture": "#rune", "cullface": "north" }, + "south": { "uv": [ 0, 0, 16, 16 ], "texture": "#side", "cullface": "south" }, + "west": { "uv": [ 0, 0, 16, 16 ], "texture": "#side", "cullface": "west" }, + "east": { "uv": [ 0, 0, 16, 16 ], "texture": "#side", "cullface": "east" } + } + }, + { + "from": [ 0, 0, 0 ], + "to": [ 16, 16, 16 ], + "faces": { + "north": { "uv": [ 0, 0, 16, 16 ], "texture": "#overlay", "cullface": "north" } + } + } + ] +} diff --git a/src/main/resources/assets/ebwizardry/models/block/runestone_pedestal.json b/src/main/resources/assets/ebwizardry/models/block/runestone_pedestal.json new file mode 100644 index 00000000..63677186 --- /dev/null +++ b/src/main/resources/assets/ebwizardry/models/block/runestone_pedestal.json @@ -0,0 +1,30 @@ +{ + "parent": "block/block", + "textures": { + "particle": "#side" + }, + "elements": [ + { + "from": [ 0, 0, 0 ], + "to": [ 16, 16, 16 ], + "faces": { + "down": { "uv": [ 0, 0, 16, 16 ], "texture": "#bottom", "cullface": "down" }, + "up": { "uv": [ 0, 0, 16, 16 ], "texture": "#top", "cullface": "up" }, + "north": { "uv": [ 0, 0, 16, 16 ], "texture": "#side", "cullface": "north" }, + "south": { "uv": [ 0, 0, 16, 16 ], "texture": "#side", "cullface": "south" }, + "west": { "uv": [ 0, 0, 16, 16 ], "texture": "#side", "cullface": "west" }, + "east": { "uv": [ 0, 0, 16, 16 ], "texture": "#side", "cullface": "east" } + } + }, + { + "from": [ 0, 0, 0 ], + "to": [ 16, 16, 16 ], + "faces": { + "north": { "uv": [ 0, 0, 16, 16 ], "texture": "#overlay", "cullface": "north" }, + "south": { "uv": [ 0, 0, 16, 16 ], "texture": "#overlay", "cullface": "south" }, + "west": { "uv": [ 0, 0, 16, 16 ], "texture": "#overlay", "cullface": "west" }, + "east": { "uv": [ 0, 0, 16, 16 ], "texture": "#overlay", "cullface": "east" } + } + } + ] +} diff --git a/src/main/resources/assets/ebwizardry/models/block/sorcery_crystal_block.json b/src/main/resources/assets/ebwizardry/models/block/sorcery_crystal_block.json new file mode 100644 index 00000000..2c775847 --- /dev/null +++ b/src/main/resources/assets/ebwizardry/models/block/sorcery_crystal_block.json @@ -0,0 +1,6 @@ +{ + "parent": "block/cube_all", + "textures": { + "all": "ebwizardry:blocks/crystal_block_sorcery" + } +} diff --git a/src/main/resources/assets/ebwizardry/models/block/sorcery_runestone_1.json b/src/main/resources/assets/ebwizardry/models/block/sorcery_runestone_1.json new file mode 100644 index 00000000..75c4f206 --- /dev/null +++ b/src/main/resources/assets/ebwizardry/models/block/sorcery_runestone_1.json @@ -0,0 +1,8 @@ +{ + "parent": "ebwizardry:block/runestone", + "textures": { + "side": "ebwizardry:blocks/runestone_sorcery_0", + "rune": "ebwizardry:blocks/runestone_sorcery_1", + "overlay": "ebwizardry:blocks/runestone_sorcery_1_overlay" + } +} diff --git a/src/main/resources/assets/ebwizardry/models/block/sorcery_runestone_2.json b/src/main/resources/assets/ebwizardry/models/block/sorcery_runestone_2.json new file mode 100644 index 00000000..a8d1eb5a --- /dev/null +++ b/src/main/resources/assets/ebwizardry/models/block/sorcery_runestone_2.json @@ -0,0 +1,8 @@ +{ + "parent": "ebwizardry:block/runestone", + "textures": { + "side": "ebwizardry:blocks/runestone_sorcery_0", + "rune": "ebwizardry:blocks/runestone_sorcery_2", + "overlay": "ebwizardry:blocks/runestone_sorcery_2_overlay" + } +} diff --git a/src/main/resources/assets/ebwizardry/models/block/sorcery_runestone_3.json b/src/main/resources/assets/ebwizardry/models/block/sorcery_runestone_3.json new file mode 100644 index 00000000..f280d0e4 --- /dev/null +++ b/src/main/resources/assets/ebwizardry/models/block/sorcery_runestone_3.json @@ -0,0 +1,8 @@ +{ + "parent": "ebwizardry:block/runestone", + "textures": { + "side": "ebwizardry:blocks/runestone_sorcery_0", + "rune": "ebwizardry:blocks/runestone_sorcery_3", + "overlay": "ebwizardry:blocks/runestone_sorcery_3_overlay" + } +} diff --git a/src/main/resources/assets/ebwizardry/models/block/sorcery_runestone_4.json b/src/main/resources/assets/ebwizardry/models/block/sorcery_runestone_4.json new file mode 100644 index 00000000..37cc5471 --- /dev/null +++ b/src/main/resources/assets/ebwizardry/models/block/sorcery_runestone_4.json @@ -0,0 +1,8 @@ +{ + "parent": "ebwizardry:block/runestone", + "textures": { + "side": "ebwizardry:blocks/runestone_sorcery_0", + "rune": "ebwizardry:blocks/runestone_sorcery_4", + "overlay": "ebwizardry:blocks/runestone_sorcery_4_overlay" + } +} diff --git a/src/main/resources/assets/ebwizardry/models/block/sorcery_runestone_pedestal.json b/src/main/resources/assets/ebwizardry/models/block/sorcery_runestone_pedestal.json new file mode 100644 index 00000000..05fa63dc --- /dev/null +++ b/src/main/resources/assets/ebwizardry/models/block/sorcery_runestone_pedestal.json @@ -0,0 +1,9 @@ +{ + "parent": "ebwizardry:block/runestone_pedestal", + "textures": { + "side": "ebwizardry:blocks/runestone_pedestal_sorcery", + "top": "ebwizardry:blocks/runestone_sorcery_0", + "bottom": "ebwizardry:blocks/runestone_sorcery_0", + "overlay": "ebwizardry:blocks/runestone_pedestal_sorcery_overlay" + } +} diff --git a/src/main/resources/assets/ebwizardry/models/block/thorns_lower_0.json b/src/main/resources/assets/ebwizardry/models/block/thorns_lower_0.json new file mode 100644 index 00000000..78a4386f --- /dev/null +++ b/src/main/resources/assets/ebwizardry/models/block/thorns_lower_0.json @@ -0,0 +1,6 @@ +{ + "parent": "block/cross", + "textures": { + "cross": "ebwizardry:blocks/thorns_lower_0" + } +} diff --git a/src/main/resources/assets/ebwizardry/models/block/thorns_lower_1.json b/src/main/resources/assets/ebwizardry/models/block/thorns_lower_1.json new file mode 100644 index 00000000..70929b50 --- /dev/null +++ b/src/main/resources/assets/ebwizardry/models/block/thorns_lower_1.json @@ -0,0 +1,6 @@ +{ + "parent": "block/cross", + "textures": { + "cross": "ebwizardry:blocks/thorns_lower_1" + } +} diff --git a/src/main/resources/assets/ebwizardry/models/block/thorns_lower_2.json b/src/main/resources/assets/ebwizardry/models/block/thorns_lower_2.json new file mode 100644 index 00000000..09671006 --- /dev/null +++ b/src/main/resources/assets/ebwizardry/models/block/thorns_lower_2.json @@ -0,0 +1,6 @@ +{ + "parent": "block/cross", + "textures": { + "cross": "ebwizardry:blocks/thorns_lower_2" + } +} diff --git a/src/main/resources/assets/ebwizardry/models/block/thorns_lower_3.json b/src/main/resources/assets/ebwizardry/models/block/thorns_lower_3.json new file mode 100644 index 00000000..9ad8e92d --- /dev/null +++ b/src/main/resources/assets/ebwizardry/models/block/thorns_lower_3.json @@ -0,0 +1,6 @@ +{ + "parent": "block/cross", + "textures": { + "cross": "ebwizardry:blocks/thorns_lower_3" + } +} diff --git a/src/main/resources/assets/ebwizardry/models/block/thorns_lower_4.json b/src/main/resources/assets/ebwizardry/models/block/thorns_lower_4.json new file mode 100644 index 00000000..00234c0d --- /dev/null +++ b/src/main/resources/assets/ebwizardry/models/block/thorns_lower_4.json @@ -0,0 +1,6 @@ +{ + "parent": "block/cross", + "textures": { + "cross": "ebwizardry:blocks/thorns_lower_4" + } +} diff --git a/src/main/resources/assets/ebwizardry/models/block/thorns_lower_5.json b/src/main/resources/assets/ebwizardry/models/block/thorns_lower_5.json new file mode 100644 index 00000000..3697dbd0 --- /dev/null +++ b/src/main/resources/assets/ebwizardry/models/block/thorns_lower_5.json @@ -0,0 +1,6 @@ +{ + "parent": "block/cross", + "textures": { + "cross": "ebwizardry:blocks/thorns_lower_5" + } +} diff --git a/src/main/resources/assets/ebwizardry/models/block/thorns_lower_6.json b/src/main/resources/assets/ebwizardry/models/block/thorns_lower_6.json new file mode 100644 index 00000000..8bf7cd08 --- /dev/null +++ b/src/main/resources/assets/ebwizardry/models/block/thorns_lower_6.json @@ -0,0 +1,6 @@ +{ + "parent": "block/cross", + "textures": { + "cross": "ebwizardry:blocks/thorns_lower_6" + } +} diff --git a/src/main/resources/assets/ebwizardry/models/block/thorns_lower_7.json b/src/main/resources/assets/ebwizardry/models/block/thorns_lower_7.json new file mode 100644 index 00000000..558dfa08 --- /dev/null +++ b/src/main/resources/assets/ebwizardry/models/block/thorns_lower_7.json @@ -0,0 +1,6 @@ +{ + "parent": "block/cross", + "textures": { + "cross": "ebwizardry:blocks/thorns_lower_7" + } +} diff --git a/src/main/resources/assets/ebwizardry/models/block/thorns_upper_0.json b/src/main/resources/assets/ebwizardry/models/block/thorns_upper_0.json new file mode 100644 index 00000000..8a652816 --- /dev/null +++ b/src/main/resources/assets/ebwizardry/models/block/thorns_upper_0.json @@ -0,0 +1,6 @@ +{ + "parent": "block/cross", + "textures": { + "cross": "ebwizardry:blocks/thorns_upper_0" + } +} diff --git a/src/main/resources/assets/ebwizardry/models/block/thorns_upper_1.json b/src/main/resources/assets/ebwizardry/models/block/thorns_upper_1.json new file mode 100644 index 00000000..b7d8b60f --- /dev/null +++ b/src/main/resources/assets/ebwizardry/models/block/thorns_upper_1.json @@ -0,0 +1,6 @@ +{ + "parent": "block/cross", + "textures": { + "cross": "ebwizardry:blocks/thorns_upper_1" + } +} diff --git a/src/main/resources/assets/ebwizardry/models/block/thorns_upper_2.json b/src/main/resources/assets/ebwizardry/models/block/thorns_upper_2.json new file mode 100644 index 00000000..aef33fc7 --- /dev/null +++ b/src/main/resources/assets/ebwizardry/models/block/thorns_upper_2.json @@ -0,0 +1,6 @@ +{ + "parent": "block/cross", + "textures": { + "cross": "ebwizardry:blocks/thorns_upper_2" + } +} diff --git a/src/main/resources/assets/ebwizardry/models/block/thorns_upper_3.json b/src/main/resources/assets/ebwizardry/models/block/thorns_upper_3.json new file mode 100644 index 00000000..795e030d --- /dev/null +++ b/src/main/resources/assets/ebwizardry/models/block/thorns_upper_3.json @@ -0,0 +1,6 @@ +{ + "parent": "block/cross", + "textures": { + "cross": "ebwizardry:blocks/thorns_upper_3" + } +} diff --git a/src/main/resources/assets/ebwizardry/models/block/thorns_upper_4.json b/src/main/resources/assets/ebwizardry/models/block/thorns_upper_4.json new file mode 100644 index 00000000..47360602 --- /dev/null +++ b/src/main/resources/assets/ebwizardry/models/block/thorns_upper_4.json @@ -0,0 +1,6 @@ +{ + "parent": "block/cross", + "textures": { + "cross": "ebwizardry:blocks/thorns_upper_4" + } +} diff --git a/src/main/resources/assets/ebwizardry/models/block/thorns_upper_5.json b/src/main/resources/assets/ebwizardry/models/block/thorns_upper_5.json new file mode 100644 index 00000000..78b61bd2 --- /dev/null +++ b/src/main/resources/assets/ebwizardry/models/block/thorns_upper_5.json @@ -0,0 +1,6 @@ +{ + "parent": "block/cross", + "textures": { + "cross": "ebwizardry:blocks/thorns_upper_5" + } +} diff --git a/src/main/resources/assets/ebwizardry/models/block/thorns_upper_6.json b/src/main/resources/assets/ebwizardry/models/block/thorns_upper_6.json new file mode 100644 index 00000000..ffc50f97 --- /dev/null +++ b/src/main/resources/assets/ebwizardry/models/block/thorns_upper_6.json @@ -0,0 +1,6 @@ +{ + "parent": "block/cross", + "textures": { + "cross": "ebwizardry:blocks/thorns_upper_6" + } +} diff --git a/src/main/resources/assets/ebwizardry/models/block/thorns_upper_7.json b/src/main/resources/assets/ebwizardry/models/block/thorns_upper_7.json new file mode 100644 index 00000000..c1cf103f --- /dev/null +++ b/src/main/resources/assets/ebwizardry/models/block/thorns_upper_7.json @@ -0,0 +1,6 @@ +{ + "parent": "block/cross", + "textures": { + "cross": "ebwizardry:blocks/thorns_upper_7" + } +} diff --git a/src/main/resources/assets/ebwizardry/models/item/amulet_anchoring.json b/src/main/resources/assets/ebwizardry/models/item/amulet_anchoring.json new file mode 100644 index 00000000..9414c2cb --- /dev/null +++ b/src/main/resources/assets/ebwizardry/models/item/amulet_anchoring.json @@ -0,0 +1,6 @@ +{ + "parent": "item/generated", + "textures": { + "layer0": "ebwizardry:items/amulet_anchoring" + } +} \ No newline at end of file diff --git a/src/main/resources/assets/ebwizardry/models/item/amulet_arcane_defence.json b/src/main/resources/assets/ebwizardry/models/item/amulet_arcane_defence.json new file mode 100644 index 00000000..fd13bda3 --- /dev/null +++ b/src/main/resources/assets/ebwizardry/models/item/amulet_arcane_defence.json @@ -0,0 +1,6 @@ +{ + "parent": "item/generated", + "textures": { + "layer0": "ebwizardry:items/amulet_arcane_defence" + } +} \ No newline at end of file diff --git a/src/main/resources/assets/ebwizardry/models/item/amulet_auto_shield.json b/src/main/resources/assets/ebwizardry/models/item/amulet_auto_shield.json new file mode 100644 index 00000000..e587e072 --- /dev/null +++ b/src/main/resources/assets/ebwizardry/models/item/amulet_auto_shield.json @@ -0,0 +1,6 @@ +{ + "parent": "item/generated", + "textures": { + "layer0": "ebwizardry:items/amulet_auto_shield" + } +} \ No newline at end of file diff --git a/src/main/resources/assets/ebwizardry/models/item/amulet_banishing.json b/src/main/resources/assets/ebwizardry/models/item/amulet_banishing.json new file mode 100644 index 00000000..d79c9040 --- /dev/null +++ b/src/main/resources/assets/ebwizardry/models/item/amulet_banishing.json @@ -0,0 +1,6 @@ +{ + "parent": "item/generated", + "textures": { + "layer0": "ebwizardry:items/amulet_banishing" + } +} \ No newline at end of file diff --git a/src/main/resources/assets/ebwizardry/models/item/amulet_channeling.json b/src/main/resources/assets/ebwizardry/models/item/amulet_channeling.json new file mode 100644 index 00000000..a1e52aa6 --- /dev/null +++ b/src/main/resources/assets/ebwizardry/models/item/amulet_channeling.json @@ -0,0 +1,6 @@ +{ + "parent": "item/generated", + "textures": { + "layer0": "ebwizardry:items/amulet_channeling" + } +} \ No newline at end of file diff --git a/src/main/resources/assets/ebwizardry/models/item/amulet_fire_cloaking.json b/src/main/resources/assets/ebwizardry/models/item/amulet_fire_cloaking.json new file mode 100644 index 00000000..a08ebc3a --- /dev/null +++ b/src/main/resources/assets/ebwizardry/models/item/amulet_fire_cloaking.json @@ -0,0 +1,6 @@ +{ + "parent": "item/generated", + "textures": { + "layer0": "ebwizardry:items/amulet_fire_cloaking" + } +} \ No newline at end of file diff --git a/src/main/resources/assets/ebwizardry/models/item/amulet_fire_protection.json b/src/main/resources/assets/ebwizardry/models/item/amulet_fire_protection.json new file mode 100644 index 00000000..cea2dd3c --- /dev/null +++ b/src/main/resources/assets/ebwizardry/models/item/amulet_fire_protection.json @@ -0,0 +1,6 @@ +{ + "parent": "item/generated", + "textures": { + "layer0": "ebwizardry:items/amulet_fire_protection" + } +} \ No newline at end of file diff --git a/src/main/resources/assets/ebwizardry/models/item/amulet_glide.json b/src/main/resources/assets/ebwizardry/models/item/amulet_glide.json new file mode 100644 index 00000000..7ffa1018 --- /dev/null +++ b/src/main/resources/assets/ebwizardry/models/item/amulet_glide.json @@ -0,0 +1,6 @@ +{ + "parent": "item/generated", + "textures": { + "layer0": "ebwizardry:items/amulet_glide" + } +} \ No newline at end of file diff --git a/src/main/resources/assets/ebwizardry/models/item/amulet_ice_immunity.json b/src/main/resources/assets/ebwizardry/models/item/amulet_ice_immunity.json new file mode 100644 index 00000000..e0794036 --- /dev/null +++ b/src/main/resources/assets/ebwizardry/models/item/amulet_ice_immunity.json @@ -0,0 +1,6 @@ +{ + "parent": "item/generated", + "textures": { + "layer0": "ebwizardry:items/amulet_ice_immunity" + } +} \ No newline at end of file diff --git a/src/main/resources/assets/ebwizardry/models/item/amulet_ice_protection.json b/src/main/resources/assets/ebwizardry/models/item/amulet_ice_protection.json new file mode 100644 index 00000000..d18a09cd --- /dev/null +++ b/src/main/resources/assets/ebwizardry/models/item/amulet_ice_protection.json @@ -0,0 +1,6 @@ +{ + "parent": "item/generated", + "textures": { + "layer0": "ebwizardry:items/amulet_ice_protection" + } +} \ No newline at end of file diff --git a/src/main/resources/assets/ebwizardry/models/item/amulet_lich.json b/src/main/resources/assets/ebwizardry/models/item/amulet_lich.json new file mode 100644 index 00000000..79c28033 --- /dev/null +++ b/src/main/resources/assets/ebwizardry/models/item/amulet_lich.json @@ -0,0 +1,6 @@ +{ + "parent": "item/generated", + "textures": { + "layer0": "ebwizardry:items/amulet_lich" + } +} \ No newline at end of file diff --git a/src/main/resources/assets/ebwizardry/models/item/amulet_potential.json b/src/main/resources/assets/ebwizardry/models/item/amulet_potential.json new file mode 100644 index 00000000..1d0e2976 --- /dev/null +++ b/src/main/resources/assets/ebwizardry/models/item/amulet_potential.json @@ -0,0 +1,6 @@ +{ + "parent": "item/generated", + "textures": { + "layer0": "ebwizardry:items/amulet_potential" + } +} \ No newline at end of file diff --git a/src/main/resources/assets/ebwizardry/models/item/amulet_recovery.json b/src/main/resources/assets/ebwizardry/models/item/amulet_recovery.json new file mode 100644 index 00000000..dd9d0739 --- /dev/null +++ b/src/main/resources/assets/ebwizardry/models/item/amulet_recovery.json @@ -0,0 +1,6 @@ +{ + "parent": "item/generated", + "textures": { + "layer0": "ebwizardry:items/amulet_recovery" + } +} \ No newline at end of file diff --git a/src/main/resources/assets/ebwizardry/models/item/amulet_resurrection.json b/src/main/resources/assets/ebwizardry/models/item/amulet_resurrection.json new file mode 100644 index 00000000..4191270c --- /dev/null +++ b/src/main/resources/assets/ebwizardry/models/item/amulet_resurrection.json @@ -0,0 +1,6 @@ +{ + "parent": "item/generated", + "textures": { + "layer0": "ebwizardry:items/amulet_resurrection" + } +} \ No newline at end of file diff --git a/src/main/resources/assets/ebwizardry/models/item/amulet_transience.json b/src/main/resources/assets/ebwizardry/models/item/amulet_transience.json new file mode 100644 index 00000000..116b66ff --- /dev/null +++ b/src/main/resources/assets/ebwizardry/models/item/amulet_transience.json @@ -0,0 +1,6 @@ +{ + "parent": "item/generated", + "textures": { + "layer0": "ebwizardry:items/amulet_transience" + } +} \ No newline at end of file diff --git a/src/main/resources/assets/ebwizardry/models/item/amulet_warding.json b/src/main/resources/assets/ebwizardry/models/item/amulet_warding.json new file mode 100644 index 00000000..88587ffd --- /dev/null +++ b/src/main/resources/assets/ebwizardry/models/item/amulet_warding.json @@ -0,0 +1,6 @@ +{ + "parent": "item/generated", + "textures": { + "layer0": "ebwizardry:items/amulet_warding" + } +} \ No newline at end of file diff --git a/src/main/resources/assets/ebwizardry/models/item/amulet_wisdom.json b/src/main/resources/assets/ebwizardry/models/item/amulet_wisdom.json new file mode 100644 index 00000000..290e0231 --- /dev/null +++ b/src/main/resources/assets/ebwizardry/models/item/amulet_wisdom.json @@ -0,0 +1,6 @@ +{ + "parent": "item/generated", + "textures": { + "layer0": "ebwizardry:items/amulet_wisdom" + } +} \ No newline at end of file diff --git a/src/main/resources/assets/ebwizardry/models/item/amulet_wither_immunity.json b/src/main/resources/assets/ebwizardry/models/item/amulet_wither_immunity.json new file mode 100644 index 00000000..71c142fa --- /dev/null +++ b/src/main/resources/assets/ebwizardry/models/item/amulet_wither_immunity.json @@ -0,0 +1,6 @@ +{ + "parent": "item/generated", + "textures": { + "layer0": "ebwizardry:items/amulet_wither_immunity" + } +} \ No newline at end of file diff --git a/src/main/resources/assets/ebwizardry/models/item/astral_diamond.json b/src/main/resources/assets/ebwizardry/models/item/astral_diamond.json new file mode 100644 index 00000000..c5f31ce7 --- /dev/null +++ b/src/main/resources/assets/ebwizardry/models/item/astral_diamond.json @@ -0,0 +1,6 @@ +{ + "parent": "item/generated", + "textures": { + "layer0": "ebwizardry:items/astral_diamond" + } +} \ No newline at end of file diff --git a/src/main/resources/assets/ebwizardry/models/item/basic_lightning_wand.json b/src/main/resources/assets/ebwizardry/models/item/basic_lightning_wand.json deleted file mode 100644 index b65b8970..00000000 --- a/src/main/resources/assets/ebwizardry/models/item/basic_lightning_wand.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "parent": "item/handheld", - "textures": { - "layer0": "ebwizardry:items/wand_basic_lightning" - } -} diff --git a/src/main/resources/assets/ebwizardry/models/item/basic_necromancy_wand.json b/src/main/resources/assets/ebwizardry/models/item/basic_necromancy_wand.json deleted file mode 100644 index 6af0d640..00000000 --- a/src/main/resources/assets/ebwizardry/models/item/basic_necromancy_wand.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "parent": "item/handheld", - "textures": { - "layer0": "ebwizardry:items/wand_basic_necromancy" - } -} diff --git a/src/main/resources/assets/ebwizardry/models/item/basic_sorcery_wand.json b/src/main/resources/assets/ebwizardry/models/item/basic_sorcery_wand.json deleted file mode 100644 index c46f8182..00000000 --- a/src/main/resources/assets/ebwizardry/models/item/basic_sorcery_wand.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "parent": "item/handheld", - "textures": { - "layer0": "ebwizardry:items/wand_basic_sorcery" - } -} diff --git a/src/main/resources/assets/ebwizardry/models/item/charm_abseiling.json b/src/main/resources/assets/ebwizardry/models/item/charm_abseiling.json new file mode 100644 index 00000000..d8981e3b --- /dev/null +++ b/src/main/resources/assets/ebwizardry/models/item/charm_abseiling.json @@ -0,0 +1,6 @@ +{ + "parent": "item/generated", + "textures": { + "layer0": "ebwizardry:items/charm_abseiling" + } +} \ No newline at end of file diff --git a/src/main/resources/assets/ebwizardry/models/item/charm_auto_smelt.json b/src/main/resources/assets/ebwizardry/models/item/charm_auto_smelt.json new file mode 100644 index 00000000..e1463ad7 --- /dev/null +++ b/src/main/resources/assets/ebwizardry/models/item/charm_auto_smelt.json @@ -0,0 +1,6 @@ +{ + "parent": "item/generated", + "textures": { + "layer0": "ebwizardry:items/charm_auto_smelt" + } +} \ No newline at end of file diff --git a/src/main/resources/assets/ebwizardry/models/item/charm_experience_tome.json b/src/main/resources/assets/ebwizardry/models/item/charm_experience_tome.json new file mode 100644 index 00000000..c4a13245 --- /dev/null +++ b/src/main/resources/assets/ebwizardry/models/item/charm_experience_tome.json @@ -0,0 +1,6 @@ +{ + "parent": "item/generated", + "textures": { + "layer0": "ebwizardry:items/charm_experience_tome" + } +} \ No newline at end of file diff --git a/src/main/resources/assets/ebwizardry/models/item/charm_feeding.json b/src/main/resources/assets/ebwizardry/models/item/charm_feeding.json new file mode 100644 index 00000000..a44e41bb --- /dev/null +++ b/src/main/resources/assets/ebwizardry/models/item/charm_feeding.json @@ -0,0 +1,6 @@ +{ + "parent": "item/generated", + "textures": { + "layer0": "ebwizardry:items/charm_feeding" + } +} \ No newline at end of file diff --git a/src/main/resources/assets/ebwizardry/models/item/charm_flight.json b/src/main/resources/assets/ebwizardry/models/item/charm_flight.json new file mode 100644 index 00000000..3afe790e --- /dev/null +++ b/src/main/resources/assets/ebwizardry/models/item/charm_flight.json @@ -0,0 +1,6 @@ +{ + "parent": "item/generated", + "textures": { + "layer0": "ebwizardry:items/charm_flight" + } +} \ No newline at end of file diff --git a/src/main/resources/assets/ebwizardry/models/item/charm_growth.json b/src/main/resources/assets/ebwizardry/models/item/charm_growth.json new file mode 100644 index 00000000..8538a441 --- /dev/null +++ b/src/main/resources/assets/ebwizardry/models/item/charm_growth.json @@ -0,0 +1,6 @@ +{ + "parent": "item/generated", + "textures": { + "layer0": "ebwizardry:items/charm_growth" + } +} \ No newline at end of file diff --git a/src/main/resources/assets/ebwizardry/models/item/charm_haggler.json b/src/main/resources/assets/ebwizardry/models/item/charm_haggler.json new file mode 100644 index 00000000..351127fa --- /dev/null +++ b/src/main/resources/assets/ebwizardry/models/item/charm_haggler.json @@ -0,0 +1,6 @@ +{ + "parent": "item/generated", + "textures": { + "layer0": "ebwizardry:items/charm_haggler" + } +} \ No newline at end of file diff --git a/src/main/resources/assets/ebwizardry/models/item/charm_lava_walking.json b/src/main/resources/assets/ebwizardry/models/item/charm_lava_walking.json new file mode 100644 index 00000000..380c928b --- /dev/null +++ b/src/main/resources/assets/ebwizardry/models/item/charm_lava_walking.json @@ -0,0 +1,6 @@ +{ + "parent": "item/generated", + "textures": { + "layer0": "ebwizardry:items/charm_lava_walking" + } +} \ No newline at end of file diff --git a/src/main/resources/assets/ebwizardry/models/item/charm_light.json b/src/main/resources/assets/ebwizardry/models/item/charm_light.json new file mode 100644 index 00000000..a26d6b90 --- /dev/null +++ b/src/main/resources/assets/ebwizardry/models/item/charm_light.json @@ -0,0 +1,6 @@ +{ + "parent": "item/generated", + "textures": { + "layer0": "ebwizardry:items/charm_light" + } +} \ No newline at end of file diff --git a/src/main/resources/assets/ebwizardry/models/item/charm_minion_health.json b/src/main/resources/assets/ebwizardry/models/item/charm_minion_health.json new file mode 100644 index 00000000..ae89ce50 --- /dev/null +++ b/src/main/resources/assets/ebwizardry/models/item/charm_minion_health.json @@ -0,0 +1,6 @@ +{ + "parent": "item/generated", + "textures": { + "layer0": "ebwizardry:items/charm_minion_health" + } +} \ No newline at end of file diff --git a/src/main/resources/assets/ebwizardry/models/item/charm_minion_variants.json b/src/main/resources/assets/ebwizardry/models/item/charm_minion_variants.json new file mode 100644 index 00000000..0ad912bd --- /dev/null +++ b/src/main/resources/assets/ebwizardry/models/item/charm_minion_variants.json @@ -0,0 +1,6 @@ +{ + "parent": "item/generated", + "textures": { + "layer0": "ebwizardry:items/charm_minion_variants" + } +} \ No newline at end of file diff --git a/src/main/resources/assets/ebwizardry/models/item/charm_silk_touch.json b/src/main/resources/assets/ebwizardry/models/item/charm_silk_touch.json new file mode 100644 index 00000000..0461fcb6 --- /dev/null +++ b/src/main/resources/assets/ebwizardry/models/item/charm_silk_touch.json @@ -0,0 +1,6 @@ +{ + "parent": "item/generated", + "textures": { + "layer0": "ebwizardry:items/charm_silk_touch" + } +} \ No newline at end of file diff --git a/src/main/resources/assets/ebwizardry/models/item/charm_stop_time.json b/src/main/resources/assets/ebwizardry/models/item/charm_stop_time.json new file mode 100644 index 00000000..5f518c1d --- /dev/null +++ b/src/main/resources/assets/ebwizardry/models/item/charm_stop_time.json @@ -0,0 +1,6 @@ +{ + "parent": "item/generated", + "textures": { + "layer0": "ebwizardry:items/charm_stop_time" + } +} \ No newline at end of file diff --git a/src/main/resources/assets/ebwizardry/models/item/charm_storm.json b/src/main/resources/assets/ebwizardry/models/item/charm_storm.json new file mode 100644 index 00000000..3132cab8 --- /dev/null +++ b/src/main/resources/assets/ebwizardry/models/item/charm_storm.json @@ -0,0 +1,6 @@ +{ + "parent": "item/generated", + "textures": { + "layer0": "ebwizardry:items/charm_storm" + } +} \ No newline at end of file diff --git a/src/main/resources/assets/ebwizardry/models/item/charm_transportation.json b/src/main/resources/assets/ebwizardry/models/item/charm_transportation.json new file mode 100644 index 00000000..71c0e708 --- /dev/null +++ b/src/main/resources/assets/ebwizardry/models/item/charm_transportation.json @@ -0,0 +1,6 @@ +{ + "parent": "item/generated", + "textures": { + "layer0": "ebwizardry:items/charm_transportation" + } +} \ No newline at end of file diff --git a/src/main/resources/assets/ebwizardry/models/item/crystal_block.json b/src/main/resources/assets/ebwizardry/models/item/crystal_block.json deleted file mode 100644 index 0070e57f..00000000 --- a/src/main/resources/assets/ebwizardry/models/item/crystal_block.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "parent": "ebwizardry:block/crystal_block" -} diff --git a/src/main/resources/assets/ebwizardry/models/item/magic_crystal.json b/src/main/resources/assets/ebwizardry/models/item/crystal_earth.json similarity index 53% rename from src/main/resources/assets/ebwizardry/models/item/magic_crystal.json rename to src/main/resources/assets/ebwizardry/models/item/crystal_earth.json index 9e2e4903..723d42e0 100644 --- a/src/main/resources/assets/ebwizardry/models/item/magic_crystal.json +++ b/src/main/resources/assets/ebwizardry/models/item/crystal_earth.json @@ -1,6 +1,6 @@ { "parent": "item/generated", "textures": { - "layer0": "ebwizardry:items/magic_crystal" + "layer0": "ebwizardry:items/crystal_earth" } } \ No newline at end of file diff --git a/src/main/resources/assets/ebwizardry/models/item/crystal_fire.json b/src/main/resources/assets/ebwizardry/models/item/crystal_fire.json new file mode 100644 index 00000000..573dfe03 --- /dev/null +++ b/src/main/resources/assets/ebwizardry/models/item/crystal_fire.json @@ -0,0 +1,6 @@ +{ + "parent": "item/generated", + "textures": { + "layer0": "ebwizardry:items/crystal_fire" + } +} \ No newline at end of file diff --git a/src/main/resources/assets/ebwizardry/models/item/crystal_healing.json b/src/main/resources/assets/ebwizardry/models/item/crystal_healing.json new file mode 100644 index 00000000..d91d3939 --- /dev/null +++ b/src/main/resources/assets/ebwizardry/models/item/crystal_healing.json @@ -0,0 +1,6 @@ +{ + "parent": "item/generated", + "textures": { + "layer0": "ebwizardry:items/crystal_healing" + } +} \ No newline at end of file diff --git a/src/main/resources/assets/ebwizardry/models/item/crystal_ice.json b/src/main/resources/assets/ebwizardry/models/item/crystal_ice.json new file mode 100644 index 00000000..c879ac46 --- /dev/null +++ b/src/main/resources/assets/ebwizardry/models/item/crystal_ice.json @@ -0,0 +1,6 @@ +{ + "parent": "item/generated", + "textures": { + "layer0": "ebwizardry:items/crystal_ice" + } +} \ No newline at end of file diff --git a/src/main/resources/assets/ebwizardry/models/item/crystal_lightning.json b/src/main/resources/assets/ebwizardry/models/item/crystal_lightning.json new file mode 100644 index 00000000..1c09de74 --- /dev/null +++ b/src/main/resources/assets/ebwizardry/models/item/crystal_lightning.json @@ -0,0 +1,6 @@ +{ + "parent": "item/generated", + "textures": { + "layer0": "ebwizardry:items/crystal_lightning" + } +} \ No newline at end of file diff --git a/src/main/resources/assets/ebwizardry/models/item/crystal_magic.json b/src/main/resources/assets/ebwizardry/models/item/crystal_magic.json new file mode 100644 index 00000000..23f6c4c2 --- /dev/null +++ b/src/main/resources/assets/ebwizardry/models/item/crystal_magic.json @@ -0,0 +1,6 @@ +{ + "parent": "item/generated", + "textures": { + "layer0": "ebwizardry:items/crystal_magic" + } +} \ No newline at end of file diff --git a/src/main/resources/assets/ebwizardry/models/item/crystal_necromancy.json b/src/main/resources/assets/ebwizardry/models/item/crystal_necromancy.json new file mode 100644 index 00000000..bd3310a9 --- /dev/null +++ b/src/main/resources/assets/ebwizardry/models/item/crystal_necromancy.json @@ -0,0 +1,6 @@ +{ + "parent": "item/generated", + "textures": { + "layer0": "ebwizardry:items/crystal_necromancy" + } +} \ No newline at end of file diff --git a/src/main/resources/assets/ebwizardry/models/item/crystal_shard.json b/src/main/resources/assets/ebwizardry/models/item/crystal_shard.json new file mode 100644 index 00000000..b0cd0f4d --- /dev/null +++ b/src/main/resources/assets/ebwizardry/models/item/crystal_shard.json @@ -0,0 +1,6 @@ +{ + "parent": "item/generated", + "textures": { + "layer0": "ebwizardry:items/crystal_shard" + } +} \ No newline at end of file diff --git a/src/main/resources/assets/ebwizardry/models/item/crystal_sorcery.json b/src/main/resources/assets/ebwizardry/models/item/crystal_sorcery.json new file mode 100644 index 00000000..0291367b --- /dev/null +++ b/src/main/resources/assets/ebwizardry/models/item/crystal_sorcery.json @@ -0,0 +1,6 @@ +{ + "parent": "item/generated", + "textures": { + "layer0": "ebwizardry:items/crystal_sorcery" + } +} \ No newline at end of file diff --git a/src/main/resources/assets/ebwizardry/models/item/earth_crystal_block.json b/src/main/resources/assets/ebwizardry/models/item/earth_crystal_block.json new file mode 100644 index 00000000..dcdb4abd --- /dev/null +++ b/src/main/resources/assets/ebwizardry/models/item/earth_crystal_block.json @@ -0,0 +1,3 @@ +{ + "parent": "ebwizardry:block/earth_crystal_block" +} diff --git a/src/main/resources/assets/ebwizardry/models/item/earth_runestone.json b/src/main/resources/assets/ebwizardry/models/item/earth_runestone.json new file mode 100644 index 00000000..cd9da38a --- /dev/null +++ b/src/main/resources/assets/ebwizardry/models/item/earth_runestone.json @@ -0,0 +1,8 @@ +{ + "parent": "ebwizardry:item/runestone_item", + "textures": { + "side": "ebwizardry:blocks/runestone_earth_0", + "rune": "ebwizardry:blocks/runestone_earth_1", + "overlay": "ebwizardry:blocks/runestone_earth_1_overlay" + } +} \ No newline at end of file diff --git a/src/main/resources/assets/ebwizardry/models/item/earth_runestone_pedestal.json b/src/main/resources/assets/ebwizardry/models/item/earth_runestone_pedestal.json new file mode 100644 index 00000000..a63834d2 --- /dev/null +++ b/src/main/resources/assets/ebwizardry/models/item/earth_runestone_pedestal.json @@ -0,0 +1,9 @@ +{ + "parent": "ebwizardry:item/runestone_pedestal_item", + "textures": { + "side": "ebwizardry:blocks/runestone_pedestal_earth", + "top": "ebwizardry:blocks/runestone_earth_0", + "bottom": "ebwizardry:blocks/runestone_earth_0", + "overlay": "ebwizardry:blocks/runestone_pedestal_earth_overlay" + } +} \ No newline at end of file diff --git a/src/main/resources/assets/ebwizardry/models/item/fire_crystal_block.json b/src/main/resources/assets/ebwizardry/models/item/fire_crystal_block.json new file mode 100644 index 00000000..d3b21460 --- /dev/null +++ b/src/main/resources/assets/ebwizardry/models/item/fire_crystal_block.json @@ -0,0 +1,3 @@ +{ + "parent": "ebwizardry:block/fire_crystal_block" +} diff --git a/src/main/resources/assets/ebwizardry/models/item/fire_runestone.json b/src/main/resources/assets/ebwizardry/models/item/fire_runestone.json new file mode 100644 index 00000000..9d526484 --- /dev/null +++ b/src/main/resources/assets/ebwizardry/models/item/fire_runestone.json @@ -0,0 +1,8 @@ +{ + "parent": "ebwizardry:item/runestone_item", + "textures": { + "side": "ebwizardry:blocks/runestone_fire_0", + "rune": "ebwizardry:blocks/runestone_fire_1", + "overlay": "ebwizardry:blocks/runestone_fire_1_overlay" + } +} diff --git a/src/main/resources/assets/ebwizardry/models/item/fire_runestone_pedestal.json b/src/main/resources/assets/ebwizardry/models/item/fire_runestone_pedestal.json new file mode 100644 index 00000000..e82c1691 --- /dev/null +++ b/src/main/resources/assets/ebwizardry/models/item/fire_runestone_pedestal.json @@ -0,0 +1,9 @@ +{ + "parent": "ebwizardry:item/runestone_pedestal_item", + "textures": { + "side": "ebwizardry:blocks/runestone_pedestal_fire", + "top": "ebwizardry:blocks/runestone_fire_0", + "bottom": "ebwizardry:blocks/runestone_fire_0", + "overlay": "ebwizardry:blocks/runestone_pedestal_fire_overlay" + } +} \ No newline at end of file diff --git a/src/main/resources/assets/ebwizardry/models/item/flaming_axe.json b/src/main/resources/assets/ebwizardry/models/item/flaming_axe.json index d2893024..8275b14c 100644 --- a/src/main/resources/assets/ebwizardry/models/item/flaming_axe.json +++ b/src/main/resources/assets/ebwizardry/models/item/flaming_axe.json @@ -2,5 +2,62 @@ "parent": "item/handheld", "textures": { "layer0": "ebwizardry:items/flaming_axe" - } + }, + "overrides": [ + { + "predicate": { + "conjuring": 1 + }, + "model": "ebwizardry:item/flaming_axe_conjuring_0" + }, + { + "predicate": { + "conjuring": 1, + "conjure": 0.125 + }, + "model": "ebwizardry:item/flaming_axe_conjuring_1" + }, + { + "predicate": { + "conjuring": 1, + "conjure": 0.25 + }, + "model": "ebwizardry:item/flaming_axe_conjuring_2" + }, + { + "predicate": { + "conjuring": 1, + "conjure": 0.375 + }, + "model": "ebwizardry:item/flaming_axe_conjuring_3" + }, + { + "predicate": { + "conjuring": 1, + "conjure": 0.5 + }, + "model": "ebwizardry:item/flaming_axe_conjuring_4" + }, + { + "predicate": { + "conjuring": 1, + "conjure": 0.625 + }, + "model": "ebwizardry:item/flaming_axe_conjuring_5" + }, + { + "predicate": { + "conjuring": 1, + "conjure": 0.75 + }, + "model": "ebwizardry:item/flaming_axe_conjuring_6" + }, + { + "predicate": { + "conjuring": 1, + "conjure": 0.875 + }, + "model": "ebwizardry:item/flaming_axe_conjuring_7" + } + ] } diff --git a/src/main/resources/assets/ebwizardry/models/item/flaming_axe_conjuring_0.json b/src/main/resources/assets/ebwizardry/models/item/flaming_axe_conjuring_0.json new file mode 100644 index 00000000..6465ed5b --- /dev/null +++ b/src/main/resources/assets/ebwizardry/models/item/flaming_axe_conjuring_0.json @@ -0,0 +1,6 @@ +{ + "parent": "item/handheld", + "textures": { + "layer0": "ebwizardry:items/flaming_axe_conjuring_0" + } +} diff --git a/src/main/resources/assets/ebwizardry/models/item/flaming_axe_conjuring_1.json b/src/main/resources/assets/ebwizardry/models/item/flaming_axe_conjuring_1.json new file mode 100644 index 00000000..9b42df9a --- /dev/null +++ b/src/main/resources/assets/ebwizardry/models/item/flaming_axe_conjuring_1.json @@ -0,0 +1,6 @@ +{ + "parent": "item/handheld", + "textures": { + "layer0": "ebwizardry:items/flaming_axe_conjuring_1" + } +} diff --git a/src/main/resources/assets/ebwizardry/models/item/flaming_axe_conjuring_2.json b/src/main/resources/assets/ebwizardry/models/item/flaming_axe_conjuring_2.json new file mode 100644 index 00000000..5a5e5692 --- /dev/null +++ b/src/main/resources/assets/ebwizardry/models/item/flaming_axe_conjuring_2.json @@ -0,0 +1,6 @@ +{ + "parent": "item/handheld", + "textures": { + "layer0": "ebwizardry:items/flaming_axe_conjuring_2" + } +} diff --git a/src/main/resources/assets/ebwizardry/models/item/flaming_axe_conjuring_3.json b/src/main/resources/assets/ebwizardry/models/item/flaming_axe_conjuring_3.json new file mode 100644 index 00000000..bec94f1b --- /dev/null +++ b/src/main/resources/assets/ebwizardry/models/item/flaming_axe_conjuring_3.json @@ -0,0 +1,6 @@ +{ + "parent": "item/handheld", + "textures": { + "layer0": "ebwizardry:items/flaming_axe_conjuring_3" + } +} diff --git a/src/main/resources/assets/ebwizardry/models/item/flaming_axe_conjuring_4.json b/src/main/resources/assets/ebwizardry/models/item/flaming_axe_conjuring_4.json new file mode 100644 index 00000000..e0951dad --- /dev/null +++ b/src/main/resources/assets/ebwizardry/models/item/flaming_axe_conjuring_4.json @@ -0,0 +1,6 @@ +{ + "parent": "item/handheld", + "textures": { + "layer0": "ebwizardry:items/flaming_axe_conjuring_4" + } +} diff --git a/src/main/resources/assets/ebwizardry/models/item/flaming_axe_conjuring_5.json b/src/main/resources/assets/ebwizardry/models/item/flaming_axe_conjuring_5.json new file mode 100644 index 00000000..d9c99c9e --- /dev/null +++ b/src/main/resources/assets/ebwizardry/models/item/flaming_axe_conjuring_5.json @@ -0,0 +1,6 @@ +{ + "parent": "item/handheld", + "textures": { + "layer0": "ebwizardry:items/flaming_axe_conjuring_5" + } +} diff --git a/src/main/resources/assets/ebwizardry/models/item/flaming_axe_conjuring_6.json b/src/main/resources/assets/ebwizardry/models/item/flaming_axe_conjuring_6.json new file mode 100644 index 00000000..47959abb --- /dev/null +++ b/src/main/resources/assets/ebwizardry/models/item/flaming_axe_conjuring_6.json @@ -0,0 +1,6 @@ +{ + "parent": "item/handheld", + "textures": { + "layer0": "ebwizardry:items/flaming_axe_conjuring_6" + } +} diff --git a/src/main/resources/assets/ebwizardry/models/item/flaming_axe_conjuring_7.json b/src/main/resources/assets/ebwizardry/models/item/flaming_axe_conjuring_7.json new file mode 100644 index 00000000..76d698cb --- /dev/null +++ b/src/main/resources/assets/ebwizardry/models/item/flaming_axe_conjuring_7.json @@ -0,0 +1,6 @@ +{ + "parent": "item/handheld", + "textures": { + "layer0": "ebwizardry:items/flaming_axe_conjuring_7" + } +} diff --git a/src/main/resources/assets/ebwizardry/models/item/frost_axe.json b/src/main/resources/assets/ebwizardry/models/item/frost_axe.json index 198a09db..57a68827 100644 --- a/src/main/resources/assets/ebwizardry/models/item/frost_axe.json +++ b/src/main/resources/assets/ebwizardry/models/item/frost_axe.json @@ -2,5 +2,62 @@ "parent": "item/handheld", "textures": { "layer0": "ebwizardry:items/frost_axe" - } + }, + "overrides": [ + { + "predicate": { + "conjuring": 1 + }, + "model": "ebwizardry:item/frost_axe_conjuring_0" + }, + { + "predicate": { + "conjuring": 1, + "conjure": 0.125 + }, + "model": "ebwizardry:item/frost_axe_conjuring_1" + }, + { + "predicate": { + "conjuring": 1, + "conjure": 0.25 + }, + "model": "ebwizardry:item/frost_axe_conjuring_2" + }, + { + "predicate": { + "conjuring": 1, + "conjure": 0.375 + }, + "model": "ebwizardry:item/frost_axe_conjuring_3" + }, + { + "predicate": { + "conjuring": 1, + "conjure": 0.5 + }, + "model": "ebwizardry:item/frost_axe_conjuring_4" + }, + { + "predicate": { + "conjuring": 1, + "conjure": 0.625 + }, + "model": "ebwizardry:item/frost_axe_conjuring_5" + }, + { + "predicate": { + "conjuring": 1, + "conjure": 0.75 + }, + "model": "ebwizardry:item/frost_axe_conjuring_6" + }, + { + "predicate": { + "conjuring": 1, + "conjure": 0.875 + }, + "model": "ebwizardry:item/frost_axe_conjuring_7" + } + ] } diff --git a/src/main/resources/assets/ebwizardry/models/item/frost_axe_conjuring_0.json b/src/main/resources/assets/ebwizardry/models/item/frost_axe_conjuring_0.json new file mode 100644 index 00000000..d72f22b9 --- /dev/null +++ b/src/main/resources/assets/ebwizardry/models/item/frost_axe_conjuring_0.json @@ -0,0 +1,6 @@ +{ + "parent": "item/handheld", + "textures": { + "layer0": "ebwizardry:items/frost_axe_conjuring_0" + } +} diff --git a/src/main/resources/assets/ebwizardry/models/item/frost_axe_conjuring_1.json b/src/main/resources/assets/ebwizardry/models/item/frost_axe_conjuring_1.json new file mode 100644 index 00000000..39af7f39 --- /dev/null +++ b/src/main/resources/assets/ebwizardry/models/item/frost_axe_conjuring_1.json @@ -0,0 +1,6 @@ +{ + "parent": "item/handheld", + "textures": { + "layer0": "ebwizardry:items/frost_axe_conjuring_1" + } +} diff --git a/src/main/resources/assets/ebwizardry/models/item/frost_axe_conjuring_2.json b/src/main/resources/assets/ebwizardry/models/item/frost_axe_conjuring_2.json new file mode 100644 index 00000000..bed93962 --- /dev/null +++ b/src/main/resources/assets/ebwizardry/models/item/frost_axe_conjuring_2.json @@ -0,0 +1,6 @@ +{ + "parent": "item/handheld", + "textures": { + "layer0": "ebwizardry:items/frost_axe_conjuring_2" + } +} diff --git a/src/main/resources/assets/ebwizardry/models/item/frost_axe_conjuring_3.json b/src/main/resources/assets/ebwizardry/models/item/frost_axe_conjuring_3.json new file mode 100644 index 00000000..1d1f7838 --- /dev/null +++ b/src/main/resources/assets/ebwizardry/models/item/frost_axe_conjuring_3.json @@ -0,0 +1,6 @@ +{ + "parent": "item/handheld", + "textures": { + "layer0": "ebwizardry:items/frost_axe_conjuring_3" + } +} diff --git a/src/main/resources/assets/ebwizardry/models/item/frost_axe_conjuring_4.json b/src/main/resources/assets/ebwizardry/models/item/frost_axe_conjuring_4.json new file mode 100644 index 00000000..fb7d4fd3 --- /dev/null +++ b/src/main/resources/assets/ebwizardry/models/item/frost_axe_conjuring_4.json @@ -0,0 +1,6 @@ +{ + "parent": "item/handheld", + "textures": { + "layer0": "ebwizardry:items/frost_axe_conjuring_4" + } +} diff --git a/src/main/resources/assets/ebwizardry/models/item/frost_axe_conjuring_5.json b/src/main/resources/assets/ebwizardry/models/item/frost_axe_conjuring_5.json new file mode 100644 index 00000000..6f34b837 --- /dev/null +++ b/src/main/resources/assets/ebwizardry/models/item/frost_axe_conjuring_5.json @@ -0,0 +1,6 @@ +{ + "parent": "item/handheld", + "textures": { + "layer0": "ebwizardry:items/frost_axe_conjuring_5" + } +} diff --git a/src/main/resources/assets/ebwizardry/models/item/frost_axe_conjuring_6.json b/src/main/resources/assets/ebwizardry/models/item/frost_axe_conjuring_6.json new file mode 100644 index 00000000..6eeac463 --- /dev/null +++ b/src/main/resources/assets/ebwizardry/models/item/frost_axe_conjuring_6.json @@ -0,0 +1,6 @@ +{ + "parent": "item/handheld", + "textures": { + "layer0": "ebwizardry:items/frost_axe_conjuring_6" + } +} diff --git a/src/main/resources/assets/ebwizardry/models/item/frost_axe_conjuring_7.json b/src/main/resources/assets/ebwizardry/models/item/frost_axe_conjuring_7.json new file mode 100644 index 00000000..33bc3775 --- /dev/null +++ b/src/main/resources/assets/ebwizardry/models/item/frost_axe_conjuring_7.json @@ -0,0 +1,6 @@ +{ + "parent": "item/handheld", + "textures": { + "layer0": "ebwizardry:items/frost_axe_conjuring_7" + } +} diff --git a/src/main/resources/assets/ebwizardry/models/item/grand_crystal.json b/src/main/resources/assets/ebwizardry/models/item/grand_crystal.json new file mode 100644 index 00000000..c58097d9 --- /dev/null +++ b/src/main/resources/assets/ebwizardry/models/item/grand_crystal.json @@ -0,0 +1,6 @@ +{ + "parent": "item/generated", + "textures": { + "layer0": "ebwizardry:items/crystal_grand" + } +} \ No newline at end of file diff --git a/src/main/resources/assets/ebwizardry/models/item/healing_crystal_block.json b/src/main/resources/assets/ebwizardry/models/item/healing_crystal_block.json new file mode 100644 index 00000000..2932f2ad --- /dev/null +++ b/src/main/resources/assets/ebwizardry/models/item/healing_crystal_block.json @@ -0,0 +1,3 @@ +{ + "parent": "ebwizardry:block/healing_crystal_block" +} diff --git a/src/main/resources/assets/ebwizardry/models/item/healing_runestone.json b/src/main/resources/assets/ebwizardry/models/item/healing_runestone.json new file mode 100644 index 00000000..c583f383 --- /dev/null +++ b/src/main/resources/assets/ebwizardry/models/item/healing_runestone.json @@ -0,0 +1,8 @@ +{ + "parent": "ebwizardry:item/runestone_item", + "textures": { + "side": "ebwizardry:blocks/runestone_healing_0", + "rune": "ebwizardry:blocks/runestone_healing_1", + "overlay": "ebwizardry:blocks/runestone_healing_1_overlay" + } +} diff --git a/src/main/resources/assets/ebwizardry/models/item/healing_runestone_pedestal.json b/src/main/resources/assets/ebwizardry/models/item/healing_runestone_pedestal.json new file mode 100644 index 00000000..7089d574 --- /dev/null +++ b/src/main/resources/assets/ebwizardry/models/item/healing_runestone_pedestal.json @@ -0,0 +1,9 @@ +{ + "parent": "ebwizardry:item/runestone_pedestal_item", + "textures": { + "side": "ebwizardry:blocks/runestone_pedestal_healing", + "top": "ebwizardry:blocks/runestone_healing_0", + "bottom": "ebwizardry:blocks/runestone_healing_0", + "overlay": "ebwizardry:blocks/runestone_pedestal_healing_overlay" + } +} \ No newline at end of file diff --git a/src/main/resources/assets/ebwizardry/models/item/ice_crystal_block.json b/src/main/resources/assets/ebwizardry/models/item/ice_crystal_block.json new file mode 100644 index 00000000..f2bf82fd --- /dev/null +++ b/src/main/resources/assets/ebwizardry/models/item/ice_crystal_block.json @@ -0,0 +1,3 @@ +{ + "parent": "ebwizardry:block/ice_crystal_block" +} diff --git a/src/main/resources/assets/ebwizardry/models/item/ice_runestone.json b/src/main/resources/assets/ebwizardry/models/item/ice_runestone.json new file mode 100644 index 00000000..f3313d51 --- /dev/null +++ b/src/main/resources/assets/ebwizardry/models/item/ice_runestone.json @@ -0,0 +1,8 @@ +{ + "parent": "ebwizardry:item/runestone_item", + "textures": { + "side": "ebwizardry:blocks/runestone_ice_0", + "rune": "ebwizardry:blocks/runestone_ice_1", + "overlay": "ebwizardry:blocks/runestone_ice_1_overlay" + } +} diff --git a/src/main/resources/assets/ebwizardry/models/item/ice_runestone_pedestal.json b/src/main/resources/assets/ebwizardry/models/item/ice_runestone_pedestal.json new file mode 100644 index 00000000..e90ed3eb --- /dev/null +++ b/src/main/resources/assets/ebwizardry/models/item/ice_runestone_pedestal.json @@ -0,0 +1,9 @@ +{ + "parent": "ebwizardry:item/runestone_pedestal_item", + "textures": { + "side": "ebwizardry:blocks/runestone_pedestal_ice", + "top": "ebwizardry:blocks/runestone_ice_0", + "bottom": "ebwizardry:blocks/runestone_ice_0", + "overlay": "ebwizardry:blocks/runestone_pedestal_ice_overlay" + } +} \ No newline at end of file diff --git a/src/main/resources/assets/ebwizardry/models/item/large_mana_flask.json b/src/main/resources/assets/ebwizardry/models/item/large_mana_flask.json new file mode 100644 index 00000000..be926384 --- /dev/null +++ b/src/main/resources/assets/ebwizardry/models/item/large_mana_flask.json @@ -0,0 +1,6 @@ +{ + "parent": "item/generated", + "textures": { + "layer0": "ebwizardry:items/mana_flask_large" + } +} \ No newline at end of file diff --git a/src/main/resources/assets/ebwizardry/models/item/lightning_crystal_block.json b/src/main/resources/assets/ebwizardry/models/item/lightning_crystal_block.json new file mode 100644 index 00000000..5b306ff5 --- /dev/null +++ b/src/main/resources/assets/ebwizardry/models/item/lightning_crystal_block.json @@ -0,0 +1,3 @@ +{ + "parent": "ebwizardry:block/lightning_crystal_block" +} diff --git a/src/main/resources/assets/ebwizardry/models/item/lightning_hammer.json b/src/main/resources/assets/ebwizardry/models/item/lightning_hammer.json new file mode 100644 index 00000000..6019ecf1 --- /dev/null +++ b/src/main/resources/assets/ebwizardry/models/item/lightning_hammer.json @@ -0,0 +1,122 @@ +{ + "credit": "Made with Blockbench", + "textures": { + "0": "ebwizardry:entity/lightning_hammer", + "particle": "ebwizardry:entity/lightning_hammer" + }, + "elements": [ + { + "name": "hammer_head", + "from": [-2, 1, 2], + "to": [18, 13, 14], + "faces": { + "north": {"uv": [3, 3, 8, 6], "texture": "#0"}, + "east": {"uv": [0, 3, 3, 6], "texture": "#0"}, + "south": {"uv": [11, 3, 16, 6], "texture": "#0"}, + "west": {"uv": [8, 3, 11, 6], "texture": "#0"}, + "up": {"uv": [3, 0, 8, 3], "texture": "#0"}, + "down": {"uv": [8, 0, 13, 3], "texture": "#0"} + } + }, + { + "name": "handle", + "from": [6, 13, 6], + "to": [10, 27, 10], + "faces": { + "north": {"uv": [1, 7, 2, 10.5], "texture": "#0"}, + "east": {"uv": [0, 7, 1, 10.5], "texture": "#0"}, + "south": {"uv": [3, 7, 4, 10.5], "texture": "#0"}, + "west": {"uv": [2, 7, 3, 10.5], "texture": "#0"}, + "up": {"uv": [1, 6, 2, 7], "texture": "#0"}, + "down": {"uv": [2, 6, 3, 7], "texture": "#0"} + } + }, + { + "name": "handle_end", + "from": [5.5, 27, 5.5], + "to": [10.5, 32, 10.5], + "faces": { + "north": {"uv": [1.25, 13.5, 2.5, 14.75], "texture": "#0"}, + "east": {"uv": [0, 13.5, 1.25, 14.75], "texture": "#0"}, + "south": {"uv": [3.75, 13.5, 5, 14.75], "texture": "#0"}, + "west": {"uv": [2.5, 13.5, 3.75, 14.75], "texture": "#0"}, + "up": {"uv": [1.25, 12.25, 2.5, 13.5], "texture": "#0"}, + "down": {"uv": [2.5, 12.25, 3.75, 13.5], "texture": "#0"} + } + }, + { + "name": "handle_base", + "from": [5.5, 13, 5.5], + "to": [10.5, 15, 10.5], + "faces": { + "north": {"uv": [1.25, 11.75, 2.5, 12.25], "texture": "#0"}, + "east": {"uv": [0, 11.75, 1.25, 12.25], "texture": "#0"}, + "south": {"uv": [3.75, 11.75, 5, 12.25], "texture": "#0"}, + "west": {"uv": [2.5, 11.75, 3.75, 12.25], "texture": "#0"}, + "up": {"uv": [1.25, 10.5, 2.5, 11.75], "texture": "#0"}, + "down": {"uv": [2.5, 10.5, 3.75, 11.75], "texture": "#0"} + } + }, + { + "name": "ring1", + "from": [0, 0, 1], + "to": [2, 14, 15], + "faces": { + "north": {"uv": [8.5, 9.5, 9, 13], "texture": "#0"}, + "east": {"uv": [5, 9.5, 8.5, 13], "texture": "#0"}, + "south": {"uv": [12.5, 9.5, 13, 13], "texture": "#0"}, + "west": {"uv": [9, 9.5, 12.5, 13], "texture": "#0"}, + "up": {"uv": [8.5, 6, 9, 9.5], "texture": "#0"}, + "down": {"uv": [9, 6, 9.5, 9.5], "texture": "#0"} + } + }, + { + "name": "ring2", + "from": [14, 0, 1], + "to": [16, 14, 15], + "faces": { + "north": {"uv": [8.5, 9.5, 9, 13], "texture": "#0"}, + "east": {"uv": [5, 9.5, 8.5, 13], "texture": "#0"}, + "south": {"uv": [12.5, 9.5, 13, 13], "texture": "#0"}, + "west": {"uv": [9, 9.5, 12.5, 13], "texture": "#0"}, + "up": {"uv": [8.5, 6, 9, 9.5], "texture": "#0"}, + "down": {"uv": [9, 6, 9.5, 9.5], "texture": "#0"} + } + } + ], + "display": { + "thirdperson_righthand": { + "rotation": [90, 90, 90], + "translation": [0, 10, 2], + "scale": [0.75, 0.75, 0.75] + }, + "thirdperson_lefthand": { + "rotation": [90, 90, 90], + "translation": [0.1, 10, 2], + "scale": [0.75, 0.75, 0.75] + }, + "firstperson_righthand": { + "rotation": [90, 90, 90], + "translation": [0.1, 10, 2], + "scale": [0.75, 0.75, 0.75] + }, + "firstperson_lefthand": { + "rotation": [90, 90, 90], + "translation": [0, 10, 2], + "scale": [0.75, 0.75, 0.75] + }, + "ground": { + "scale": [0.75, 0.75, 0.75] + }, + "gui": { + "rotation": [0, -26, 135], + "translation": [1, 1.5, 0], + "scale": [0.45, 0.45, 0.45] + }, + "fixed": { + "rotation": [0, 0, -135], + "translation": [-2, 2, 0], + "scale": [0.6, 0.6, 0.6] + } + } +} \ No newline at end of file diff --git a/src/main/resources/assets/ebwizardry/models/item/lightning_runestone.json b/src/main/resources/assets/ebwizardry/models/item/lightning_runestone.json new file mode 100644 index 00000000..abdb1136 --- /dev/null +++ b/src/main/resources/assets/ebwizardry/models/item/lightning_runestone.json @@ -0,0 +1,8 @@ +{ + "parent": "ebwizardry:item/runestone_item", + "textures": { + "side": "ebwizardry:blocks/runestone_lightning_0", + "rune": "ebwizardry:blocks/runestone_lightning_1", + "overlay": "ebwizardry:blocks/runestone_lightning_1_overlay" + } +} diff --git a/src/main/resources/assets/ebwizardry/models/item/lightning_runestone_pedestal.json b/src/main/resources/assets/ebwizardry/models/item/lightning_runestone_pedestal.json new file mode 100644 index 00000000..bd76dcda --- /dev/null +++ b/src/main/resources/assets/ebwizardry/models/item/lightning_runestone_pedestal.json @@ -0,0 +1,9 @@ +{ + "parent": "ebwizardry:item/runestone_pedestal_item", + "textures": { + "side": "ebwizardry:blocks/runestone_pedestal_lightning", + "top": "ebwizardry:blocks/runestone_lightning_0", + "bottom": "ebwizardry:blocks/runestone_lightning_0", + "overlay": "ebwizardry:blocks/runestone_pedestal_lightning_overlay" + } +} \ No newline at end of file diff --git a/src/main/resources/assets/ebwizardry/models/item/magic_crystal_block.json b/src/main/resources/assets/ebwizardry/models/item/magic_crystal_block.json new file mode 100644 index 00000000..d01cb6d3 --- /dev/null +++ b/src/main/resources/assets/ebwizardry/models/item/magic_crystal_block.json @@ -0,0 +1,3 @@ +{ + "parent": "ebwizardry:block/magic_crystal_block" +} diff --git a/src/main/resources/assets/ebwizardry/models/item/magic_wand.json b/src/main/resources/assets/ebwizardry/models/item/magic_wand.json index 661d9e14..59387cf7 100644 --- a/src/main/resources/assets/ebwizardry/models/item/magic_wand.json +++ b/src/main/resources/assets/ebwizardry/models/item/magic_wand.json @@ -1,6 +1,6 @@ { "parent": "item/handheld", "textures": { - "layer0": "ebwizardry:items/wand_basic" + "layer0": "ebwizardry:items/wand_novice" } } diff --git a/src/main/resources/assets/ebwizardry/models/item/medium_mana_flask.json b/src/main/resources/assets/ebwizardry/models/item/medium_mana_flask.json new file mode 100644 index 00000000..6bda3fba --- /dev/null +++ b/src/main/resources/assets/ebwizardry/models/item/medium_mana_flask.json @@ -0,0 +1,6 @@ +{ + "parent": "item/generated", + "textures": { + "layer0": "ebwizardry:items/mana_flask_medium" + } +} \ No newline at end of file diff --git a/src/main/resources/assets/ebwizardry/models/item/melee_upgrade.json b/src/main/resources/assets/ebwizardry/models/item/melee_upgrade.json new file mode 100644 index 00000000..1aa6fd77 --- /dev/null +++ b/src/main/resources/assets/ebwizardry/models/item/melee_upgrade.json @@ -0,0 +1,6 @@ +{ + "parent": "item/generated", + "textures": { + "layer0": "ebwizardry:items/upgrade_melee" + } +} \ No newline at end of file diff --git a/src/main/resources/assets/ebwizardry/models/item/necromancy_crystal_block.json b/src/main/resources/assets/ebwizardry/models/item/necromancy_crystal_block.json new file mode 100644 index 00000000..b0c03762 --- /dev/null +++ b/src/main/resources/assets/ebwizardry/models/item/necromancy_crystal_block.json @@ -0,0 +1,3 @@ +{ + "parent": "ebwizardry:block/necromancy_crystal_block" +} diff --git a/src/main/resources/assets/ebwizardry/models/item/necromancy_runestone.json b/src/main/resources/assets/ebwizardry/models/item/necromancy_runestone.json new file mode 100644 index 00000000..48e70eb4 --- /dev/null +++ b/src/main/resources/assets/ebwizardry/models/item/necromancy_runestone.json @@ -0,0 +1,8 @@ +{ + "parent": "ebwizardry:item/runestone_item", + "textures": { + "side": "ebwizardry:blocks/runestone_necromancy_0", + "rune": "ebwizardry:blocks/runestone_necromancy_1", + "overlay": "ebwizardry:blocks/runestone_necromancy_1_overlay" + } +} diff --git a/src/main/resources/assets/ebwizardry/models/item/necromancy_runestone_pedestal.json b/src/main/resources/assets/ebwizardry/models/item/necromancy_runestone_pedestal.json new file mode 100644 index 00000000..9c980c83 --- /dev/null +++ b/src/main/resources/assets/ebwizardry/models/item/necromancy_runestone_pedestal.json @@ -0,0 +1,9 @@ +{ + "parent": "ebwizardry:item/runestone_pedestal_item", + "textures": { + "side": "ebwizardry:blocks/runestone_pedestal_necromancy", + "top": "ebwizardry:blocks/runestone_necromancy_0", + "bottom": "ebwizardry:blocks/runestone_necromancy_0", + "overlay": "ebwizardry:blocks/runestone_pedestal_necromancy_overlay" + } +} \ No newline at end of file diff --git a/src/main/resources/assets/ebwizardry/models/item/basic_fire_wand.json b/src/main/resources/assets/ebwizardry/models/item/novice_earth_wand.json similarity index 51% rename from src/main/resources/assets/ebwizardry/models/item/basic_fire_wand.json rename to src/main/resources/assets/ebwizardry/models/item/novice_earth_wand.json index 3a01a02e..7431443b 100644 --- a/src/main/resources/assets/ebwizardry/models/item/basic_fire_wand.json +++ b/src/main/resources/assets/ebwizardry/models/item/novice_earth_wand.json @@ -1,6 +1,6 @@ { "parent": "item/handheld", "textures": { - "layer0": "ebwizardry:items/wand_basic_fire" + "layer0": "ebwizardry:items/wand_novice_earth" } } diff --git a/src/main/resources/assets/ebwizardry/models/item/basic_earth_wand.json b/src/main/resources/assets/ebwizardry/models/item/novice_fire_wand.json similarity index 52% rename from src/main/resources/assets/ebwizardry/models/item/basic_earth_wand.json rename to src/main/resources/assets/ebwizardry/models/item/novice_fire_wand.json index abf377f1..27055741 100644 --- a/src/main/resources/assets/ebwizardry/models/item/basic_earth_wand.json +++ b/src/main/resources/assets/ebwizardry/models/item/novice_fire_wand.json @@ -1,6 +1,6 @@ { "parent": "item/handheld", "textures": { - "layer0": "ebwizardry:items/wand_basic_earth" + "layer0": "ebwizardry:items/wand_novice_fire" } } diff --git a/src/main/resources/assets/ebwizardry/models/item/basic_healing_wand.json b/src/main/resources/assets/ebwizardry/models/item/novice_healing_wand.json similarity index 50% rename from src/main/resources/assets/ebwizardry/models/item/basic_healing_wand.json rename to src/main/resources/assets/ebwizardry/models/item/novice_healing_wand.json index 2dcb118d..e9095bf3 100644 --- a/src/main/resources/assets/ebwizardry/models/item/basic_healing_wand.json +++ b/src/main/resources/assets/ebwizardry/models/item/novice_healing_wand.json @@ -1,6 +1,6 @@ { "parent": "item/handheld", "textures": { - "layer0": "ebwizardry:items/wand_basic_healing" + "layer0": "ebwizardry:items/wand_novice_healing" } } diff --git a/src/main/resources/assets/ebwizardry/models/item/basic_ice_wand.json b/src/main/resources/assets/ebwizardry/models/item/novice_ice_wand.json similarity index 52% rename from src/main/resources/assets/ebwizardry/models/item/basic_ice_wand.json rename to src/main/resources/assets/ebwizardry/models/item/novice_ice_wand.json index 44181bcd..feb24c4c 100644 --- a/src/main/resources/assets/ebwizardry/models/item/basic_ice_wand.json +++ b/src/main/resources/assets/ebwizardry/models/item/novice_ice_wand.json @@ -1,6 +1,6 @@ { "parent": "item/handheld", "textures": { - "layer0": "ebwizardry:items/wand_basic_ice" + "layer0": "ebwizardry:items/wand_novice_ice" } } diff --git a/src/main/resources/assets/ebwizardry/models/item/novice_lightning_wand.json b/src/main/resources/assets/ebwizardry/models/item/novice_lightning_wand.json new file mode 100644 index 00000000..ce044666 --- /dev/null +++ b/src/main/resources/assets/ebwizardry/models/item/novice_lightning_wand.json @@ -0,0 +1,6 @@ +{ + "parent": "item/handheld", + "textures": { + "layer0": "ebwizardry:items/wand_novice_lightning" + } +} diff --git a/src/main/resources/assets/ebwizardry/models/item/novice_necromancy_wand.json b/src/main/resources/assets/ebwizardry/models/item/novice_necromancy_wand.json new file mode 100644 index 00000000..ab64fb68 --- /dev/null +++ b/src/main/resources/assets/ebwizardry/models/item/novice_necromancy_wand.json @@ -0,0 +1,6 @@ +{ + "parent": "item/handheld", + "textures": { + "layer0": "ebwizardry:items/wand_novice_necromancy" + } +} diff --git a/src/main/resources/assets/ebwizardry/models/item/novice_sorcery_wand.json b/src/main/resources/assets/ebwizardry/models/item/novice_sorcery_wand.json new file mode 100644 index 00000000..968ff38e --- /dev/null +++ b/src/main/resources/assets/ebwizardry/models/item/novice_sorcery_wand.json @@ -0,0 +1,6 @@ +{ + "parent": "item/handheld", + "textures": { + "layer0": "ebwizardry:items/wand_novice_sorcery" + } +} diff --git a/src/main/resources/assets/ebwizardry/models/item/purifying_elixir.json b/src/main/resources/assets/ebwizardry/models/item/purifying_elixir.json new file mode 100644 index 00000000..a213668e --- /dev/null +++ b/src/main/resources/assets/ebwizardry/models/item/purifying_elixir.json @@ -0,0 +1,6 @@ +{ + "parent": "item/generated", + "textures": { + "layer0": "ebwizardry:items/purifying_elixir" + } +} \ No newline at end of file diff --git a/src/main/resources/assets/ebwizardry/models/item/ring_arcane_frost.json b/src/main/resources/assets/ebwizardry/models/item/ring_arcane_frost.json new file mode 100644 index 00000000..799e7483 --- /dev/null +++ b/src/main/resources/assets/ebwizardry/models/item/ring_arcane_frost.json @@ -0,0 +1,6 @@ +{ + "parent": "item/generated", + "textures": { + "layer0": "ebwizardry:items/ring_arcane_frost" + } +} \ No newline at end of file diff --git a/src/main/resources/assets/ebwizardry/models/item/ring_battlemage.json b/src/main/resources/assets/ebwizardry/models/item/ring_battlemage.json new file mode 100644 index 00000000..af3c2e35 --- /dev/null +++ b/src/main/resources/assets/ebwizardry/models/item/ring_battlemage.json @@ -0,0 +1,6 @@ +{ + "parent": "item/generated", + "textures": { + "layer0": "ebwizardry:items/ring_battlemage" + } +} \ No newline at end of file diff --git a/src/main/resources/assets/ebwizardry/models/item/ring_blockwrangler.json b/src/main/resources/assets/ebwizardry/models/item/ring_blockwrangler.json new file mode 100644 index 00000000..654f22b7 --- /dev/null +++ b/src/main/resources/assets/ebwizardry/models/item/ring_blockwrangler.json @@ -0,0 +1,6 @@ +{ + "parent": "item/generated", + "textures": { + "layer0": "ebwizardry:items/ring_blockwrangler" + } +} \ No newline at end of file diff --git a/src/main/resources/assets/ebwizardry/models/item/ring_combustion.json b/src/main/resources/assets/ebwizardry/models/item/ring_combustion.json new file mode 100644 index 00000000..55f914e3 --- /dev/null +++ b/src/main/resources/assets/ebwizardry/models/item/ring_combustion.json @@ -0,0 +1,6 @@ +{ + "parent": "item/generated", + "textures": { + "layer0": "ebwizardry:items/ring_combustion" + } +} \ No newline at end of file diff --git a/src/main/resources/assets/ebwizardry/models/item/ring_condensing.json b/src/main/resources/assets/ebwizardry/models/item/ring_condensing.json new file mode 100644 index 00000000..442f589d --- /dev/null +++ b/src/main/resources/assets/ebwizardry/models/item/ring_condensing.json @@ -0,0 +1,6 @@ +{ + "parent": "item/generated", + "textures": { + "layer0": "ebwizardry:items/ring_condensing" + } +} \ No newline at end of file diff --git a/src/main/resources/assets/ebwizardry/models/item/ring_conjurer.json b/src/main/resources/assets/ebwizardry/models/item/ring_conjurer.json new file mode 100644 index 00000000..8c8a26f5 --- /dev/null +++ b/src/main/resources/assets/ebwizardry/models/item/ring_conjurer.json @@ -0,0 +1,6 @@ +{ + "parent": "item/generated", + "textures": { + "layer0": "ebwizardry:items/ring_conjurer" + } +} \ No newline at end of file diff --git a/src/main/resources/assets/ebwizardry/models/item/ring_defender.json b/src/main/resources/assets/ebwizardry/models/item/ring_defender.json new file mode 100644 index 00000000..3b5ad34d --- /dev/null +++ b/src/main/resources/assets/ebwizardry/models/item/ring_defender.json @@ -0,0 +1,6 @@ +{ + "parent": "item/generated", + "textures": { + "layer0": "ebwizardry:items/ring_defender" + } +} \ No newline at end of file diff --git a/src/main/resources/assets/ebwizardry/models/item/ring_disintegration.json b/src/main/resources/assets/ebwizardry/models/item/ring_disintegration.json new file mode 100644 index 00000000..e8e3a131 --- /dev/null +++ b/src/main/resources/assets/ebwizardry/models/item/ring_disintegration.json @@ -0,0 +1,6 @@ +{ + "parent": "item/generated", + "textures": { + "layer0": "ebwizardry:items/ring_disintegration" + } +} \ No newline at end of file diff --git a/src/main/resources/assets/ebwizardry/models/item/ring_earth_biome.json b/src/main/resources/assets/ebwizardry/models/item/ring_earth_biome.json new file mode 100644 index 00000000..7f5c46c9 --- /dev/null +++ b/src/main/resources/assets/ebwizardry/models/item/ring_earth_biome.json @@ -0,0 +1,6 @@ +{ + "parent": "item/generated", + "textures": { + "layer0": "ebwizardry:items/ring_earth_biome" + } +} \ No newline at end of file diff --git a/src/main/resources/assets/ebwizardry/models/item/ring_earth_melee.json b/src/main/resources/assets/ebwizardry/models/item/ring_earth_melee.json new file mode 100644 index 00000000..19213d66 --- /dev/null +++ b/src/main/resources/assets/ebwizardry/models/item/ring_earth_melee.json @@ -0,0 +1,6 @@ +{ + "parent": "item/generated", + "textures": { + "layer0": "ebwizardry:items/ring_earth_melee" + } +} \ No newline at end of file diff --git a/src/main/resources/assets/ebwizardry/models/item/ring_extraction.json b/src/main/resources/assets/ebwizardry/models/item/ring_extraction.json new file mode 100644 index 00000000..49c344f2 --- /dev/null +++ b/src/main/resources/assets/ebwizardry/models/item/ring_extraction.json @@ -0,0 +1,6 @@ +{ + "parent": "item/generated", + "textures": { + "layer0": "ebwizardry:items/ring_extraction" + } +} \ No newline at end of file diff --git a/src/main/resources/assets/ebwizardry/models/item/ring_fire_biome.json b/src/main/resources/assets/ebwizardry/models/item/ring_fire_biome.json new file mode 100644 index 00000000..fa30a48d --- /dev/null +++ b/src/main/resources/assets/ebwizardry/models/item/ring_fire_biome.json @@ -0,0 +1,6 @@ +{ + "parent": "item/generated", + "textures": { + "layer0": "ebwizardry:items/ring_fire_biome" + } +} \ No newline at end of file diff --git a/src/main/resources/assets/ebwizardry/models/item/ring_fire_melee.json b/src/main/resources/assets/ebwizardry/models/item/ring_fire_melee.json new file mode 100644 index 00000000..4e89c680 --- /dev/null +++ b/src/main/resources/assets/ebwizardry/models/item/ring_fire_melee.json @@ -0,0 +1,6 @@ +{ + "parent": "item/generated", + "textures": { + "layer0": "ebwizardry:items/ring_fire_melee" + } +} \ No newline at end of file diff --git a/src/main/resources/assets/ebwizardry/models/item/ring_full_moon.json b/src/main/resources/assets/ebwizardry/models/item/ring_full_moon.json new file mode 100644 index 00000000..565a90c0 --- /dev/null +++ b/src/main/resources/assets/ebwizardry/models/item/ring_full_moon.json @@ -0,0 +1,6 @@ +{ + "parent": "item/generated", + "textures": { + "layer0": "ebwizardry:items/ring_full_moon" + } +} \ No newline at end of file diff --git a/src/main/resources/assets/ebwizardry/models/item/ring_hammer.json b/src/main/resources/assets/ebwizardry/models/item/ring_hammer.json new file mode 100644 index 00000000..ca3a1586 --- /dev/null +++ b/src/main/resources/assets/ebwizardry/models/item/ring_hammer.json @@ -0,0 +1,6 @@ +{ + "parent": "item/generated", + "textures": { + "layer0": "ebwizardry:items/ring_hammer" + } +} \ No newline at end of file diff --git a/src/main/resources/assets/ebwizardry/models/item/ring_ice_biome.json b/src/main/resources/assets/ebwizardry/models/item/ring_ice_biome.json new file mode 100644 index 00000000..821fa0b7 --- /dev/null +++ b/src/main/resources/assets/ebwizardry/models/item/ring_ice_biome.json @@ -0,0 +1,6 @@ +{ + "parent": "item/generated", + "textures": { + "layer0": "ebwizardry:items/ring_ice_biome" + } +} \ No newline at end of file diff --git a/src/main/resources/assets/ebwizardry/models/item/ring_ice_melee.json b/src/main/resources/assets/ebwizardry/models/item/ring_ice_melee.json new file mode 100644 index 00000000..00951549 --- /dev/null +++ b/src/main/resources/assets/ebwizardry/models/item/ring_ice_melee.json @@ -0,0 +1,6 @@ +{ + "parent": "item/generated", + "textures": { + "layer0": "ebwizardry:items/ring_ice_melee" + } +} \ No newline at end of file diff --git a/src/main/resources/assets/ebwizardry/models/item/ring_interdiction.json b/src/main/resources/assets/ebwizardry/models/item/ring_interdiction.json new file mode 100644 index 00000000..d956a49a --- /dev/null +++ b/src/main/resources/assets/ebwizardry/models/item/ring_interdiction.json @@ -0,0 +1,6 @@ +{ + "parent": "item/generated", + "textures": { + "layer0": "ebwizardry:items/ring_interdiction" + } +} \ No newline at end of file diff --git a/src/main/resources/assets/ebwizardry/models/item/ring_leeching.json b/src/main/resources/assets/ebwizardry/models/item/ring_leeching.json new file mode 100644 index 00000000..add07d6e --- /dev/null +++ b/src/main/resources/assets/ebwizardry/models/item/ring_leeching.json @@ -0,0 +1,6 @@ +{ + "parent": "item/generated", + "textures": { + "layer0": "ebwizardry:items/ring_leeching" + } +} \ No newline at end of file diff --git a/src/main/resources/assets/ebwizardry/models/item/ring_lightning_melee.json b/src/main/resources/assets/ebwizardry/models/item/ring_lightning_melee.json new file mode 100644 index 00000000..44b4ba59 --- /dev/null +++ b/src/main/resources/assets/ebwizardry/models/item/ring_lightning_melee.json @@ -0,0 +1,6 @@ +{ + "parent": "item/generated", + "textures": { + "layer0": "ebwizardry:items/ring_lightning_melee" + } +} \ No newline at end of file diff --git a/src/main/resources/assets/ebwizardry/models/item/ring_mana_return.json b/src/main/resources/assets/ebwizardry/models/item/ring_mana_return.json new file mode 100644 index 00000000..07e9de7b --- /dev/null +++ b/src/main/resources/assets/ebwizardry/models/item/ring_mana_return.json @@ -0,0 +1,6 @@ +{ + "parent": "item/generated", + "textures": { + "layer0": "ebwizardry:items/ring_mana_return" + } +} \ No newline at end of file diff --git a/src/main/resources/assets/ebwizardry/models/item/ring_mind_control.json b/src/main/resources/assets/ebwizardry/models/item/ring_mind_control.json new file mode 100644 index 00000000..d9657f06 --- /dev/null +++ b/src/main/resources/assets/ebwizardry/models/item/ring_mind_control.json @@ -0,0 +1,6 @@ +{ + "parent": "item/generated", + "textures": { + "layer0": "ebwizardry:items/ring_mind_control" + } +} \ No newline at end of file diff --git a/src/main/resources/assets/ebwizardry/models/item/ring_necromancy_melee.json b/src/main/resources/assets/ebwizardry/models/item/ring_necromancy_melee.json new file mode 100644 index 00000000..14c32043 --- /dev/null +++ b/src/main/resources/assets/ebwizardry/models/item/ring_necromancy_melee.json @@ -0,0 +1,6 @@ +{ + "parent": "item/generated", + "textures": { + "layer0": "ebwizardry:items/ring_necromancy_melee" + } +} \ No newline at end of file diff --git a/src/main/resources/assets/ebwizardry/models/item/ring_paladin.json b/src/main/resources/assets/ebwizardry/models/item/ring_paladin.json new file mode 100644 index 00000000..b41dc94a --- /dev/null +++ b/src/main/resources/assets/ebwizardry/models/item/ring_paladin.json @@ -0,0 +1,6 @@ +{ + "parent": "item/generated", + "textures": { + "layer0": "ebwizardry:items/ring_paladin" + } +} \ No newline at end of file diff --git a/src/main/resources/assets/ebwizardry/models/item/ring_poison.json b/src/main/resources/assets/ebwizardry/models/item/ring_poison.json new file mode 100644 index 00000000..0273aad5 --- /dev/null +++ b/src/main/resources/assets/ebwizardry/models/item/ring_poison.json @@ -0,0 +1,6 @@ +{ + "parent": "item/generated", + "textures": { + "layer0": "ebwizardry:items/ring_poison" + } +} \ No newline at end of file diff --git a/src/main/resources/assets/ebwizardry/models/item/ring_seeking.json b/src/main/resources/assets/ebwizardry/models/item/ring_seeking.json new file mode 100644 index 00000000..bb5759dc --- /dev/null +++ b/src/main/resources/assets/ebwizardry/models/item/ring_seeking.json @@ -0,0 +1,6 @@ +{ + "parent": "item/generated", + "textures": { + "layer0": "ebwizardry:items/ring_seeking" + } +} \ No newline at end of file diff --git a/src/main/resources/assets/ebwizardry/models/item/ring_shattering.json b/src/main/resources/assets/ebwizardry/models/item/ring_shattering.json new file mode 100644 index 00000000..509900bc --- /dev/null +++ b/src/main/resources/assets/ebwizardry/models/item/ring_shattering.json @@ -0,0 +1,6 @@ +{ + "parent": "item/generated", + "textures": { + "layer0": "ebwizardry:items/ring_shattering" + } +} \ No newline at end of file diff --git a/src/main/resources/assets/ebwizardry/models/item/ring_siphoning.json b/src/main/resources/assets/ebwizardry/models/item/ring_siphoning.json new file mode 100644 index 00000000..d94758d9 --- /dev/null +++ b/src/main/resources/assets/ebwizardry/models/item/ring_siphoning.json @@ -0,0 +1,6 @@ +{ + "parent": "item/generated", + "textures": { + "layer0": "ebwizardry:items/ring_siphoning" + } +} \ No newline at end of file diff --git a/src/main/resources/assets/ebwizardry/models/item/ring_soulbinding.json b/src/main/resources/assets/ebwizardry/models/item/ring_soulbinding.json new file mode 100644 index 00000000..23e710f4 --- /dev/null +++ b/src/main/resources/assets/ebwizardry/models/item/ring_soulbinding.json @@ -0,0 +1,6 @@ +{ + "parent": "item/generated", + "textures": { + "layer0": "ebwizardry:items/ring_soulbinding" + } +} \ No newline at end of file diff --git a/src/main/resources/assets/ebwizardry/models/item/ring_spirit_animal.json b/src/main/resources/assets/ebwizardry/models/item/ring_spirit_animal.json new file mode 100644 index 00000000..838291be --- /dev/null +++ b/src/main/resources/assets/ebwizardry/models/item/ring_spirit_animal.json @@ -0,0 +1,6 @@ +{ + "parent": "item/generated", + "textures": { + "layer0": "ebwizardry:items/ring_spirit_animal" + } +} \ No newline at end of file diff --git a/src/main/resources/assets/ebwizardry/models/item/ring_storm.json b/src/main/resources/assets/ebwizardry/models/item/ring_storm.json new file mode 100644 index 00000000..1227579e --- /dev/null +++ b/src/main/resources/assets/ebwizardry/models/item/ring_storm.json @@ -0,0 +1,6 @@ +{ + "parent": "item/generated", + "textures": { + "layer0": "ebwizardry:items/ring_storm" + } +} \ No newline at end of file diff --git a/src/main/resources/assets/ebwizardry/models/item/runestone_item.json b/src/main/resources/assets/ebwizardry/models/item/runestone_item.json new file mode 100644 index 00000000..77b8d431 --- /dev/null +++ b/src/main/resources/assets/ebwizardry/models/item/runestone_item.json @@ -0,0 +1,28 @@ +{ + "parent": "block/block", + "textures": { + "particle": "#rune" + }, + "elements": [ + { + "from": [ 0, 0, 0 ], + "to": [ 16, 16, 16 ], + "faces": { + "down": { "uv": [ 0, 0, 16, 16 ], "texture": "#side", "cullface": "down" }, + "up": { "uv": [ 0, 0, 16, 16 ], "texture": "#side", "cullface": "up" }, + "north": { "uv": [ 0, 0, 16, 16 ], "texture": "#rune", "cullface": "north" }, + "south": { "uv": [ 0, 0, 16, 16 ], "texture": "#side", "cullface": "south" }, + "west": { "uv": [ 0, 0, 16, 16 ], "texture": "#side", "cullface": "west" }, + "east": { "uv": [ 0, 0, 16, 16 ], "texture": "#side", "cullface": "east" } + } + }, + { + "from": [ 0, 0, 0 ], + "to": [ 16, 16, 16 ], + "shade": false, + "faces": { + "north": { "uv": [ 0, 0, 16, 16 ], "texture": "#overlay", "cullface": "north" } + } + } + ] +} diff --git a/src/main/resources/assets/ebwizardry/models/item/runestone_pedestal_item.json b/src/main/resources/assets/ebwizardry/models/item/runestone_pedestal_item.json new file mode 100644 index 00000000..66455ce8 --- /dev/null +++ b/src/main/resources/assets/ebwizardry/models/item/runestone_pedestal_item.json @@ -0,0 +1,31 @@ +{ + "parent": "block/block", + "textures": { + "particle": "#side" + }, + "elements": [ + { + "from": [ 0, 0, 0 ], + "to": [ 16, 16, 16 ], + "faces": { + "down": { "uv": [ 0, 0, 16, 16 ], "texture": "#bottom", "cullface": "down" }, + "up": { "uv": [ 0, 0, 16, 16 ], "texture": "#top", "cullface": "up" }, + "north": { "uv": [ 0, 0, 16, 16 ], "texture": "#side", "cullface": "north" }, + "south": { "uv": [ 0, 0, 16, 16 ], "texture": "#side", "cullface": "south" }, + "west": { "uv": [ 0, 0, 16, 16 ], "texture": "#side", "cullface": "west" }, + "east": { "uv": [ 0, 0, 16, 16 ], "texture": "#side", "cullface": "east" } + } + }, + { + "from": [ 0, 0, 0 ], + "to": [ 16, 16, 16 ], + "shade": false, + "faces": { + "north": { "uv": [ 0, 0, 16, 16 ], "texture": "#overlay", "cullface": "north" }, + "south": { "uv": [ 0, 0, 16, 16 ], "texture": "#overlay", "cullface": "south" }, + "west": { "uv": [ 0, 0, 16, 16 ], "texture": "#overlay", "cullface": "west" }, + "east": { "uv": [ 0, 0, 16, 16 ], "texture": "#overlay", "cullface": "east" } + } + } + ] +} diff --git a/src/main/resources/assets/ebwizardry/models/item/small_mana_flask.json b/src/main/resources/assets/ebwizardry/models/item/small_mana_flask.json new file mode 100644 index 00000000..8bbca59b --- /dev/null +++ b/src/main/resources/assets/ebwizardry/models/item/small_mana_flask.json @@ -0,0 +1,6 @@ +{ + "parent": "item/generated", + "textures": { + "layer0": "ebwizardry:items/mana_flask_small" + } +} \ No newline at end of file diff --git a/src/main/resources/assets/ebwizardry/models/item/sorcery_crystal_block.json b/src/main/resources/assets/ebwizardry/models/item/sorcery_crystal_block.json new file mode 100644 index 00000000..ecc2f3df --- /dev/null +++ b/src/main/resources/assets/ebwizardry/models/item/sorcery_crystal_block.json @@ -0,0 +1,3 @@ +{ + "parent": "ebwizardry:block/sorcery_crystal_block" +} diff --git a/src/main/resources/assets/ebwizardry/models/item/sorcery_runestone.json b/src/main/resources/assets/ebwizardry/models/item/sorcery_runestone.json new file mode 100644 index 00000000..fb9805f3 --- /dev/null +++ b/src/main/resources/assets/ebwizardry/models/item/sorcery_runestone.json @@ -0,0 +1,8 @@ +{ + "parent": "ebwizardry:item/runestone_item", + "textures": { + "side": "ebwizardry:blocks/runestone_sorcery_0", + "rune": "ebwizardry:blocks/runestone_sorcery_1", + "overlay": "ebwizardry:blocks/runestone_sorcery_1_overlay" + } +} diff --git a/src/main/resources/assets/ebwizardry/models/item/sorcery_runestone_pedestal.json b/src/main/resources/assets/ebwizardry/models/item/sorcery_runestone_pedestal.json new file mode 100644 index 00000000..7b87f885 --- /dev/null +++ b/src/main/resources/assets/ebwizardry/models/item/sorcery_runestone_pedestal.json @@ -0,0 +1,9 @@ +{ + "parent": "ebwizardry:item/runestone_pedestal_item", + "textures": { + "side": "ebwizardry:blocks/runestone_pedestal_sorcery", + "top": "ebwizardry:blocks/runestone_sorcery_0", + "bottom": "ebwizardry:blocks/runestone_sorcery_0", + "overlay": "ebwizardry:blocks/runestone_pedestal_sorcery_overlay" + } +} \ No newline at end of file diff --git a/src/main/resources/assets/ebwizardry/models/item/mana_flask.json b/src/main/resources/assets/ebwizardry/models/item/spark_bomb.json similarity index 55% rename from src/main/resources/assets/ebwizardry/models/item/mana_flask.json rename to src/main/resources/assets/ebwizardry/models/item/spark_bomb.json index 278c497e..5e7423fa 100644 --- a/src/main/resources/assets/ebwizardry/models/item/mana_flask.json +++ b/src/main/resources/assets/ebwizardry/models/item/spark_bomb.json @@ -1,6 +1,6 @@ { "parent": "item/generated", "textures": { - "layer0": "ebwizardry:items/mana_flask" + "layer0": "ebwizardry:items/spark_bomb" } } \ No newline at end of file diff --git a/src/main/resources/assets/ebwizardry/models/item/spectral_bow.json b/src/main/resources/assets/ebwizardry/models/item/spectral_bow.json index e6e97ae8..befb8c49 100644 --- a/src/main/resources/assets/ebwizardry/models/item/spectral_bow.json +++ b/src/main/resources/assets/ebwizardry/models/item/spectral_bow.json @@ -45,6 +45,61 @@ "pull": 0.9 }, "model": "ebwizardry:item/spectral_bow_pulling_2" + }, + { + "predicate": { + "conjuring": 1 + }, + "model": "ebwizardry:item/spectral_bow_conjuring_0" + }, + { + "predicate": { + "conjuring": 1, + "conjure": 0.125 + }, + "model": "ebwizardry:item/spectral_bow_conjuring_1" + }, + { + "predicate": { + "conjuring": 1, + "conjure": 0.25 + }, + "model": "ebwizardry:item/spectral_bow_conjuring_2" + }, + { + "predicate": { + "conjuring": 1, + "conjure": 0.375 + }, + "model": "ebwizardry:item/spectral_bow_conjuring_3" + }, + { + "predicate": { + "conjuring": 1, + "conjure": 0.5 + }, + "model": "ebwizardry:item/spectral_bow_conjuring_4" + }, + { + "predicate": { + "conjuring": 1, + "conjure": 0.625 + }, + "model": "ebwizardry:item/spectral_bow_conjuring_5" + }, + { + "predicate": { + "conjuring": 1, + "conjure": 0.75 + }, + "model": "ebwizardry:item/spectral_bow_conjuring_6" + }, + { + "predicate": { + "conjuring": 1, + "conjure": 0.875 + }, + "model": "ebwizardry:item/spectral_bow_conjuring_7" } ] } diff --git a/src/main/resources/assets/ebwizardry/models/item/spectral_bow_conjuring_0.json b/src/main/resources/assets/ebwizardry/models/item/spectral_bow_conjuring_0.json new file mode 100644 index 00000000..96be3a05 --- /dev/null +++ b/src/main/resources/assets/ebwizardry/models/item/spectral_bow_conjuring_0.json @@ -0,0 +1,6 @@ +{ + "parent": "item/bow", + "textures": { + "layer0": "ebwizardry:items/spectral_bow_conjuring_0" + } +} diff --git a/src/main/resources/assets/ebwizardry/models/item/spectral_bow_conjuring_1.json b/src/main/resources/assets/ebwizardry/models/item/spectral_bow_conjuring_1.json new file mode 100644 index 00000000..1d515028 --- /dev/null +++ b/src/main/resources/assets/ebwizardry/models/item/spectral_bow_conjuring_1.json @@ -0,0 +1,6 @@ +{ + "parent": "item/bow", + "textures": { + "layer0": "ebwizardry:items/spectral_bow_conjuring_1" + } +} diff --git a/src/main/resources/assets/ebwizardry/models/item/spectral_bow_conjuring_2.json b/src/main/resources/assets/ebwizardry/models/item/spectral_bow_conjuring_2.json new file mode 100644 index 00000000..811e8bcb --- /dev/null +++ b/src/main/resources/assets/ebwizardry/models/item/spectral_bow_conjuring_2.json @@ -0,0 +1,6 @@ +{ + "parent": "item/bow", + "textures": { + "layer0": "ebwizardry:items/spectral_bow_conjuring_2" + } +} diff --git a/src/main/resources/assets/ebwizardry/models/item/spectral_bow_conjuring_3.json b/src/main/resources/assets/ebwizardry/models/item/spectral_bow_conjuring_3.json new file mode 100644 index 00000000..82a1134f --- /dev/null +++ b/src/main/resources/assets/ebwizardry/models/item/spectral_bow_conjuring_3.json @@ -0,0 +1,6 @@ +{ + "parent": "item/bow", + "textures": { + "layer0": "ebwizardry:items/spectral_bow_conjuring_3" + } +} diff --git a/src/main/resources/assets/ebwizardry/models/item/spectral_bow_conjuring_4.json b/src/main/resources/assets/ebwizardry/models/item/spectral_bow_conjuring_4.json new file mode 100644 index 00000000..53925e92 --- /dev/null +++ b/src/main/resources/assets/ebwizardry/models/item/spectral_bow_conjuring_4.json @@ -0,0 +1,6 @@ +{ + "parent": "item/bow", + "textures": { + "layer0": "ebwizardry:items/spectral_bow_conjuring_4" + } +} diff --git a/src/main/resources/assets/ebwizardry/models/item/spectral_bow_conjuring_5.json b/src/main/resources/assets/ebwizardry/models/item/spectral_bow_conjuring_5.json new file mode 100644 index 00000000..119c0e08 --- /dev/null +++ b/src/main/resources/assets/ebwizardry/models/item/spectral_bow_conjuring_5.json @@ -0,0 +1,6 @@ +{ + "parent": "item/bow", + "textures": { + "layer0": "ebwizardry:items/spectral_bow_conjuring_5" + } +} diff --git a/src/main/resources/assets/ebwizardry/models/item/spectral_bow_conjuring_6.json b/src/main/resources/assets/ebwizardry/models/item/spectral_bow_conjuring_6.json new file mode 100644 index 00000000..5db23b8c --- /dev/null +++ b/src/main/resources/assets/ebwizardry/models/item/spectral_bow_conjuring_6.json @@ -0,0 +1,6 @@ +{ + "parent": "item/bow", + "textures": { + "layer0": "ebwizardry:items/spectral_bow_conjuring_6" + } +} diff --git a/src/main/resources/assets/ebwizardry/models/item/spectral_bow_conjuring_7.json b/src/main/resources/assets/ebwizardry/models/item/spectral_bow_conjuring_7.json new file mode 100644 index 00000000..d4424975 --- /dev/null +++ b/src/main/resources/assets/ebwizardry/models/item/spectral_bow_conjuring_7.json @@ -0,0 +1,6 @@ +{ + "parent": "item/bow", + "textures": { + "layer0": "ebwizardry:items/spectral_bow_conjuring_7" + } +} diff --git a/src/main/resources/assets/ebwizardry/models/item/spectral_pickaxe.json b/src/main/resources/assets/ebwizardry/models/item/spectral_pickaxe.json index 3f4b3eb2..84f23972 100644 --- a/src/main/resources/assets/ebwizardry/models/item/spectral_pickaxe.json +++ b/src/main/resources/assets/ebwizardry/models/item/spectral_pickaxe.json @@ -2,5 +2,62 @@ "parent": "item/handheld", "textures": { "layer0": "ebwizardry:items/spectral_pickaxe" - } + }, + "overrides": [ + { + "predicate": { + "conjuring": 1 + }, + "model": "ebwizardry:item/spectral_pickaxe_conjuring_0" + }, + { + "predicate": { + "conjuring": 1, + "conjure": 0.125 + }, + "model": "ebwizardry:item/spectral_pickaxe_conjuring_1" + }, + { + "predicate": { + "conjuring": 1, + "conjure": 0.25 + }, + "model": "ebwizardry:item/spectral_pickaxe_conjuring_2" + }, + { + "predicate": { + "conjuring": 1, + "conjure": 0.375 + }, + "model": "ebwizardry:item/spectral_pickaxe_conjuring_3" + }, + { + "predicate": { + "conjuring": 1, + "conjure": 0.5 + }, + "model": "ebwizardry:item/spectral_pickaxe_conjuring_4" + }, + { + "predicate": { + "conjuring": 1, + "conjure": 0.625 + }, + "model": "ebwizardry:item/spectral_pickaxe_conjuring_5" + }, + { + "predicate": { + "conjuring": 1, + "conjure": 0.75 + }, + "model": "ebwizardry:item/spectral_pickaxe_conjuring_6" + }, + { + "predicate": { + "conjuring": 1, + "conjure": 0.875 + }, + "model": "ebwizardry:item/spectral_pickaxe_conjuring_7" + } + ] } diff --git a/src/main/resources/assets/ebwizardry/models/item/spectral_pickaxe_conjuring_0.json b/src/main/resources/assets/ebwizardry/models/item/spectral_pickaxe_conjuring_0.json new file mode 100644 index 00000000..08b5ec38 --- /dev/null +++ b/src/main/resources/assets/ebwizardry/models/item/spectral_pickaxe_conjuring_0.json @@ -0,0 +1,6 @@ +{ + "parent": "item/handheld", + "textures": { + "layer0": "ebwizardry:items/spectral_pickaxe_conjuring_0" + } +} diff --git a/src/main/resources/assets/ebwizardry/models/item/spectral_pickaxe_conjuring_1.json b/src/main/resources/assets/ebwizardry/models/item/spectral_pickaxe_conjuring_1.json new file mode 100644 index 00000000..e619f89f --- /dev/null +++ b/src/main/resources/assets/ebwizardry/models/item/spectral_pickaxe_conjuring_1.json @@ -0,0 +1,6 @@ +{ + "parent": "item/handheld", + "textures": { + "layer0": "ebwizardry:items/spectral_pickaxe_conjuring_1" + } +} diff --git a/src/main/resources/assets/ebwizardry/models/item/spectral_pickaxe_conjuring_2.json b/src/main/resources/assets/ebwizardry/models/item/spectral_pickaxe_conjuring_2.json new file mode 100644 index 00000000..664b43c8 --- /dev/null +++ b/src/main/resources/assets/ebwizardry/models/item/spectral_pickaxe_conjuring_2.json @@ -0,0 +1,6 @@ +{ + "parent": "item/handheld", + "textures": { + "layer0": "ebwizardry:items/spectral_pickaxe_conjuring_2" + } +} diff --git a/src/main/resources/assets/ebwizardry/models/item/spectral_pickaxe_conjuring_3.json b/src/main/resources/assets/ebwizardry/models/item/spectral_pickaxe_conjuring_3.json new file mode 100644 index 00000000..5f35d953 --- /dev/null +++ b/src/main/resources/assets/ebwizardry/models/item/spectral_pickaxe_conjuring_3.json @@ -0,0 +1,6 @@ +{ + "parent": "item/handheld", + "textures": { + "layer0": "ebwizardry:items/spectral_pickaxe_conjuring_3" + } +} diff --git a/src/main/resources/assets/ebwizardry/models/item/spectral_pickaxe_conjuring_4.json b/src/main/resources/assets/ebwizardry/models/item/spectral_pickaxe_conjuring_4.json new file mode 100644 index 00000000..c9466a44 --- /dev/null +++ b/src/main/resources/assets/ebwizardry/models/item/spectral_pickaxe_conjuring_4.json @@ -0,0 +1,6 @@ +{ + "parent": "item/handheld", + "textures": { + "layer0": "ebwizardry:items/spectral_pickaxe_conjuring_4" + } +} diff --git a/src/main/resources/assets/ebwizardry/models/item/spectral_pickaxe_conjuring_5.json b/src/main/resources/assets/ebwizardry/models/item/spectral_pickaxe_conjuring_5.json new file mode 100644 index 00000000..e848aef6 --- /dev/null +++ b/src/main/resources/assets/ebwizardry/models/item/spectral_pickaxe_conjuring_5.json @@ -0,0 +1,6 @@ +{ + "parent": "item/handheld", + "textures": { + "layer0": "ebwizardry:items/spectral_pickaxe_conjuring_5" + } +} diff --git a/src/main/resources/assets/ebwizardry/models/item/spectral_pickaxe_conjuring_6.json b/src/main/resources/assets/ebwizardry/models/item/spectral_pickaxe_conjuring_6.json new file mode 100644 index 00000000..4b100b8a --- /dev/null +++ b/src/main/resources/assets/ebwizardry/models/item/spectral_pickaxe_conjuring_6.json @@ -0,0 +1,6 @@ +{ + "parent": "item/handheld", + "textures": { + "layer0": "ebwizardry:items/spectral_pickaxe_conjuring_6" + } +} diff --git a/src/main/resources/assets/ebwizardry/models/item/spectral_pickaxe_conjuring_7.json b/src/main/resources/assets/ebwizardry/models/item/spectral_pickaxe_conjuring_7.json new file mode 100644 index 00000000..18b6c06c --- /dev/null +++ b/src/main/resources/assets/ebwizardry/models/item/spectral_pickaxe_conjuring_7.json @@ -0,0 +1,6 @@ +{ + "parent": "item/handheld", + "textures": { + "layer0": "ebwizardry:items/spectral_pickaxe_conjuring_7" + } +} diff --git a/src/main/resources/assets/ebwizardry/models/item/spectral_sword.json b/src/main/resources/assets/ebwizardry/models/item/spectral_sword.json index c217987b..e812a899 100644 --- a/src/main/resources/assets/ebwizardry/models/item/spectral_sword.json +++ b/src/main/resources/assets/ebwizardry/models/item/spectral_sword.json @@ -2,5 +2,62 @@ "parent": "item/handheld", "textures": { "layer0": "ebwizardry:items/spectral_sword" - } + }, + "overrides": [ + { + "predicate": { + "conjuring": 1 + }, + "model": "ebwizardry:item/spectral_sword_conjuring_0" + }, + { + "predicate": { + "conjuring": 1, + "conjure": 0.125 + }, + "model": "ebwizardry:item/spectral_sword_conjuring_1" + }, + { + "predicate": { + "conjuring": 1, + "conjure": 0.25 + }, + "model": "ebwizardry:item/spectral_sword_conjuring_2" + }, + { + "predicate": { + "conjuring": 1, + "conjure": 0.375 + }, + "model": "ebwizardry:item/spectral_sword_conjuring_3" + }, + { + "predicate": { + "conjuring": 1, + "conjure": 0.5 + }, + "model": "ebwizardry:item/spectral_sword_conjuring_4" + }, + { + "predicate": { + "conjuring": 1, + "conjure": 0.625 + }, + "model": "ebwizardry:item/spectral_sword_conjuring_5" + }, + { + "predicate": { + "conjuring": 1, + "conjure": 0.75 + }, + "model": "ebwizardry:item/spectral_sword_conjuring_6" + }, + { + "predicate": { + "conjuring": 1, + "conjure": 0.875 + }, + "model": "ebwizardry:item/spectral_sword_conjuring_7" + } + ] } diff --git a/src/main/resources/assets/ebwizardry/models/item/spectral_sword_conjuring_0.json b/src/main/resources/assets/ebwizardry/models/item/spectral_sword_conjuring_0.json new file mode 100644 index 00000000..89cae15a --- /dev/null +++ b/src/main/resources/assets/ebwizardry/models/item/spectral_sword_conjuring_0.json @@ -0,0 +1,6 @@ +{ + "parent": "item/handheld", + "textures": { + "layer0": "ebwizardry:items/spectral_sword_conjuring_0" + } +} diff --git a/src/main/resources/assets/ebwizardry/models/item/spectral_sword_conjuring_1.json b/src/main/resources/assets/ebwizardry/models/item/spectral_sword_conjuring_1.json new file mode 100644 index 00000000..5cf533e0 --- /dev/null +++ b/src/main/resources/assets/ebwizardry/models/item/spectral_sword_conjuring_1.json @@ -0,0 +1,6 @@ +{ + "parent": "item/handheld", + "textures": { + "layer0": "ebwizardry:items/spectral_sword_conjuring_1" + } +} diff --git a/src/main/resources/assets/ebwizardry/models/item/spectral_sword_conjuring_2.json b/src/main/resources/assets/ebwizardry/models/item/spectral_sword_conjuring_2.json new file mode 100644 index 00000000..47d254b9 --- /dev/null +++ b/src/main/resources/assets/ebwizardry/models/item/spectral_sword_conjuring_2.json @@ -0,0 +1,6 @@ +{ + "parent": "item/handheld", + "textures": { + "layer0": "ebwizardry:items/spectral_sword_conjuring_2" + } +} diff --git a/src/main/resources/assets/ebwizardry/models/item/spectral_sword_conjuring_3.json b/src/main/resources/assets/ebwizardry/models/item/spectral_sword_conjuring_3.json new file mode 100644 index 00000000..e4e22c97 --- /dev/null +++ b/src/main/resources/assets/ebwizardry/models/item/spectral_sword_conjuring_3.json @@ -0,0 +1,6 @@ +{ + "parent": "item/handheld", + "textures": { + "layer0": "ebwizardry:items/spectral_sword_conjuring_3" + } +} diff --git a/src/main/resources/assets/ebwizardry/models/item/spectral_sword_conjuring_4.json b/src/main/resources/assets/ebwizardry/models/item/spectral_sword_conjuring_4.json new file mode 100644 index 00000000..c4a0a651 --- /dev/null +++ b/src/main/resources/assets/ebwizardry/models/item/spectral_sword_conjuring_4.json @@ -0,0 +1,6 @@ +{ + "parent": "item/handheld", + "textures": { + "layer0": "ebwizardry:items/spectral_sword_conjuring_4" + } +} diff --git a/src/main/resources/assets/ebwizardry/models/item/spectral_sword_conjuring_5.json b/src/main/resources/assets/ebwizardry/models/item/spectral_sword_conjuring_5.json new file mode 100644 index 00000000..5d84cb34 --- /dev/null +++ b/src/main/resources/assets/ebwizardry/models/item/spectral_sword_conjuring_5.json @@ -0,0 +1,6 @@ +{ + "parent": "item/handheld", + "textures": { + "layer0": "ebwizardry:items/spectral_sword_conjuring_5" + } +} diff --git a/src/main/resources/assets/ebwizardry/models/item/spectral_sword_conjuring_6.json b/src/main/resources/assets/ebwizardry/models/item/spectral_sword_conjuring_6.json new file mode 100644 index 00000000..78b6502e --- /dev/null +++ b/src/main/resources/assets/ebwizardry/models/item/spectral_sword_conjuring_6.json @@ -0,0 +1,6 @@ +{ + "parent": "item/handheld", + "textures": { + "layer0": "ebwizardry:items/spectral_sword_conjuring_6" + } +} diff --git a/src/main/resources/assets/ebwizardry/models/item/spectral_sword_conjuring_7.json b/src/main/resources/assets/ebwizardry/models/item/spectral_sword_conjuring_7.json new file mode 100644 index 00000000..9ec91330 --- /dev/null +++ b/src/main/resources/assets/ebwizardry/models/item/spectral_sword_conjuring_7.json @@ -0,0 +1,6 @@ +{ + "parent": "item/handheld", + "textures": { + "layer0": "ebwizardry:items/spectral_sword_conjuring_7" + } +} diff --git a/src/main/resources/assets/ebwizardry/models/item/thorns.json b/src/main/resources/assets/ebwizardry/models/item/thorns.json new file mode 100644 index 00000000..4255e8bb --- /dev/null +++ b/src/main/resources/assets/ebwizardry/models/item/thorns.json @@ -0,0 +1,6 @@ +{ + "parent": "item/generated", + "textures": { + "layer0": "ebwizardry:blocks/thorns_upper_7" + } +} diff --git a/src/main/resources/assets/ebwizardry/recipes/arcane_workbench.json b/src/main/resources/assets/ebwizardry/recipes/arcane_workbench.json index 6727cb0c..735cacc0 100644 --- a/src/main/resources/assets/ebwizardry/recipes/arcane_workbench.json +++ b/src/main/resources/assets/ebwizardry/recipes/arcane_workbench.json @@ -14,9 +14,40 @@ "item": "minecraft:carpet", "data": 10 }, - "x": { - "item": "ebwizardry:magic_crystal" - }, + "x": [ + { + "item": "ebwizardry:magic_crystal", + "data": 0 + }, + { + "item": "ebwizardry:magic_crystal", + "data": 1 + }, + { + "item": "ebwizardry:magic_crystal", + "data": 2 + }, + { + "item": "ebwizardry:magic_crystal", + "data": 3 + }, + { + "item": "ebwizardry:magic_crystal", + "data": 4 + }, + { + "item": "ebwizardry:magic_crystal", + "data": 5 + }, + { + "item": "ebwizardry:magic_crystal", + "data": 6 + }, + { + "item": "ebwizardry:magic_crystal", + "data": 7 + } + ], "y": { "type": "forge:ore_dict", "ore": "blockLapis" diff --git a/src/main/resources/assets/ebwizardry/recipes/crystal_block.json b/src/main/resources/assets/ebwizardry/recipes/crystal_block.json index e70bb53c..2bf0ef30 100644 --- a/src/main/resources/assets/ebwizardry/recipes/crystal_block.json +++ b/src/main/resources/assets/ebwizardry/recipes/crystal_block.json @@ -7,10 +7,12 @@ ], "key": { "z": { - "item": "ebwizardry:magic_crystal" + "item": "ebwizardry:magic_crystal", + "data": 0 } }, "result": { - "item": "ebwizardry:crystal_block" + "item": "ebwizardry:crystal_block", + "data": 0 } } \ No newline at end of file diff --git a/src/main/resources/assets/ebwizardry/recipes/crystal_block_earth.json b/src/main/resources/assets/ebwizardry/recipes/crystal_block_earth.json new file mode 100644 index 00000000..c24d9441 --- /dev/null +++ b/src/main/resources/assets/ebwizardry/recipes/crystal_block_earth.json @@ -0,0 +1,18 @@ +{ + "type": "minecraft:crafting_shaped", + "pattern": [ + "zzz", + "zzz", + "zzz" + ], + "key": { + "z": { + "item": "ebwizardry:magic_crystal", + "data": 5 + } + }, + "result": { + "item": "ebwizardry:crystal_block", + "data": 5 + } +} \ No newline at end of file diff --git a/src/main/resources/assets/ebwizardry/recipes/crystal_block_fire.json b/src/main/resources/assets/ebwizardry/recipes/crystal_block_fire.json new file mode 100644 index 00000000..fbb0b15a --- /dev/null +++ b/src/main/resources/assets/ebwizardry/recipes/crystal_block_fire.json @@ -0,0 +1,18 @@ +{ + "type": "minecraft:crafting_shaped", + "pattern": [ + "zzz", + "zzz", + "zzz" + ], + "key": { + "z": { + "item": "ebwizardry:magic_crystal", + "data": 1 + } + }, + "result": { + "item": "ebwizardry:crystal_block", + "data": 1 + } +} \ No newline at end of file diff --git a/src/main/resources/assets/ebwizardry/recipes/crystal_block_healing.json b/src/main/resources/assets/ebwizardry/recipes/crystal_block_healing.json new file mode 100644 index 00000000..2cf4e092 --- /dev/null +++ b/src/main/resources/assets/ebwizardry/recipes/crystal_block_healing.json @@ -0,0 +1,18 @@ +{ + "type": "minecraft:crafting_shaped", + "pattern": [ + "zzz", + "zzz", + "zzz" + ], + "key": { + "z": { + "item": "ebwizardry:magic_crystal", + "data": 7 + } + }, + "result": { + "item": "ebwizardry:crystal_block", + "data": 7 + } +} \ No newline at end of file diff --git a/src/main/resources/assets/ebwizardry/recipes/crystal_block_ice.json b/src/main/resources/assets/ebwizardry/recipes/crystal_block_ice.json new file mode 100644 index 00000000..3e172395 --- /dev/null +++ b/src/main/resources/assets/ebwizardry/recipes/crystal_block_ice.json @@ -0,0 +1,18 @@ +{ + "type": "minecraft:crafting_shaped", + "pattern": [ + "zzz", + "zzz", + "zzz" + ], + "key": { + "z": { + "item": "ebwizardry:magic_crystal", + "data": 2 + } + }, + "result": { + "item": "ebwizardry:crystal_block", + "data": 2 + } +} \ No newline at end of file diff --git a/src/main/resources/assets/ebwizardry/recipes/crystal_block_lightning.json b/src/main/resources/assets/ebwizardry/recipes/crystal_block_lightning.json new file mode 100644 index 00000000..8f7417fc --- /dev/null +++ b/src/main/resources/assets/ebwizardry/recipes/crystal_block_lightning.json @@ -0,0 +1,18 @@ +{ + "type": "minecraft:crafting_shaped", + "pattern": [ + "zzz", + "zzz", + "zzz" + ], + "key": { + "z": { + "item": "ebwizardry:magic_crystal", + "data": 3 + } + }, + "result": { + "item": "ebwizardry:crystal_block", + "data": 3 + } +} \ No newline at end of file diff --git a/src/main/resources/assets/ebwizardry/recipes/crystal_block_necromancy.json b/src/main/resources/assets/ebwizardry/recipes/crystal_block_necromancy.json new file mode 100644 index 00000000..4d76abdc --- /dev/null +++ b/src/main/resources/assets/ebwizardry/recipes/crystal_block_necromancy.json @@ -0,0 +1,18 @@ +{ + "type": "minecraft:crafting_shaped", + "pattern": [ + "zzz", + "zzz", + "zzz" + ], + "key": { + "z": { + "item": "ebwizardry:magic_crystal", + "data": 4 + } + }, + "result": { + "item": "ebwizardry:crystal_block", + "data": 4 + } +} \ No newline at end of file diff --git a/src/main/resources/assets/ebwizardry/recipes/crystal_block_sorcery.json b/src/main/resources/assets/ebwizardry/recipes/crystal_block_sorcery.json new file mode 100644 index 00000000..079793ad --- /dev/null +++ b/src/main/resources/assets/ebwizardry/recipes/crystal_block_sorcery.json @@ -0,0 +1,18 @@ +{ + "type": "minecraft:crafting_shaped", + "pattern": [ + "zzz", + "zzz", + "zzz" + ], + "key": { + "z": { + "item": "ebwizardry:magic_crystal", + "data": 6 + } + }, + "result": { + "item": "ebwizardry:crystal_block", + "data": 6 + } +} \ No newline at end of file diff --git a/src/main/resources/assets/ebwizardry/recipes/crystal_block_to_crystals.json b/src/main/resources/assets/ebwizardry/recipes/crystal_block_to_crystals.json index 488efbac..d2cb4435 100644 --- a/src/main/resources/assets/ebwizardry/recipes/crystal_block_to_crystals.json +++ b/src/main/resources/assets/ebwizardry/recipes/crystal_block_to_crystals.json @@ -3,11 +3,13 @@ "group": "magic_crystal", "ingredients": [ { - "item": "ebwizardry:crystal_block" + "item": "ebwizardry:crystal_block", + "data": 0 } ], "result": { "item": "ebwizardry:magic_crystal", + "data": 0, "count": 9 } } \ No newline at end of file diff --git a/src/main/resources/assets/ebwizardry/recipes/crystal_block_to_crystals_earth.json b/src/main/resources/assets/ebwizardry/recipes/crystal_block_to_crystals_earth.json new file mode 100644 index 00000000..81d77ff9 --- /dev/null +++ b/src/main/resources/assets/ebwizardry/recipes/crystal_block_to_crystals_earth.json @@ -0,0 +1,15 @@ +{ + "type": "minecraft:crafting_shapeless", + "group": "magic_crystal", + "ingredients": [ + { + "item": "ebwizardry:crystal_block", + "data": 5 + } + ], + "result": { + "item": "ebwizardry:magic_crystal", + "data": 5, + "count": 9 + } +} \ No newline at end of file diff --git a/src/main/resources/assets/ebwizardry/recipes/crystal_block_to_crystals_fire.json b/src/main/resources/assets/ebwizardry/recipes/crystal_block_to_crystals_fire.json new file mode 100644 index 00000000..2760c161 --- /dev/null +++ b/src/main/resources/assets/ebwizardry/recipes/crystal_block_to_crystals_fire.json @@ -0,0 +1,15 @@ +{ + "type": "minecraft:crafting_shapeless", + "group": "magic_crystal", + "ingredients": [ + { + "item": "ebwizardry:crystal_block", + "data": 1 + } + ], + "result": { + "item": "ebwizardry:magic_crystal", + "data": 1, + "count": 9 + } +} \ No newline at end of file diff --git a/src/main/resources/assets/ebwizardry/recipes/crystal_block_to_crystals_healing.json b/src/main/resources/assets/ebwizardry/recipes/crystal_block_to_crystals_healing.json new file mode 100644 index 00000000..46f180de --- /dev/null +++ b/src/main/resources/assets/ebwizardry/recipes/crystal_block_to_crystals_healing.json @@ -0,0 +1,15 @@ +{ + "type": "minecraft:crafting_shapeless", + "group": "magic_crystal", + "ingredients": [ + { + "item": "ebwizardry:crystal_block", + "data": 7 + } + ], + "result": { + "item": "ebwizardry:magic_crystal", + "data": 7, + "count": 9 + } +} \ No newline at end of file diff --git a/src/main/resources/assets/ebwizardry/recipes/crystal_block_to_crystals_ice.json b/src/main/resources/assets/ebwizardry/recipes/crystal_block_to_crystals_ice.json new file mode 100644 index 00000000..bc34ba01 --- /dev/null +++ b/src/main/resources/assets/ebwizardry/recipes/crystal_block_to_crystals_ice.json @@ -0,0 +1,15 @@ +{ + "type": "minecraft:crafting_shapeless", + "group": "magic_crystal", + "ingredients": [ + { + "item": "ebwizardry:crystal_block", + "data": 2 + } + ], + "result": { + "item": "ebwizardry:magic_crystal", + "data": 2, + "count": 9 + } +} \ No newline at end of file diff --git a/src/main/resources/assets/ebwizardry/recipes/crystal_block_to_crystals_lightning.json b/src/main/resources/assets/ebwizardry/recipes/crystal_block_to_crystals_lightning.json new file mode 100644 index 00000000..3bf151c0 --- /dev/null +++ b/src/main/resources/assets/ebwizardry/recipes/crystal_block_to_crystals_lightning.json @@ -0,0 +1,15 @@ +{ + "type": "minecraft:crafting_shapeless", + "group": "magic_crystal", + "ingredients": [ + { + "item": "ebwizardry:crystal_block", + "data": 3 + } + ], + "result": { + "item": "ebwizardry:magic_crystal", + "data": 3, + "count": 9 + } +} \ No newline at end of file diff --git a/src/main/resources/assets/ebwizardry/recipes/crystal_block_to_crystals_necromancy.json b/src/main/resources/assets/ebwizardry/recipes/crystal_block_to_crystals_necromancy.json new file mode 100644 index 00000000..0de3b757 --- /dev/null +++ b/src/main/resources/assets/ebwizardry/recipes/crystal_block_to_crystals_necromancy.json @@ -0,0 +1,15 @@ +{ + "type": "minecraft:crafting_shapeless", + "group": "magic_crystal", + "ingredients": [ + { + "item": "ebwizardry:crystal_block", + "data": 4 + } + ], + "result": { + "item": "ebwizardry:magic_crystal", + "data": 4, + "count": 9 + } +} \ No newline at end of file diff --git a/src/main/resources/assets/ebwizardry/recipes/crystal_block_to_crystals_sorcery.json b/src/main/resources/assets/ebwizardry/recipes/crystal_block_to_crystals_sorcery.json new file mode 100644 index 00000000..cde5784c --- /dev/null +++ b/src/main/resources/assets/ebwizardry/recipes/crystal_block_to_crystals_sorcery.json @@ -0,0 +1,15 @@ +{ + "type": "minecraft:crafting_shapeless", + "group": "magic_crystal", + "ingredients": [ + { + "item": "ebwizardry:crystal_block", + "data": 6 + } + ], + "result": { + "item": "ebwizardry:magic_crystal", + "data": 6, + "count": 9 + } +} \ No newline at end of file diff --git a/src/main/resources/assets/ebwizardry/recipes/crystal_flower_to_crystals.json b/src/main/resources/assets/ebwizardry/recipes/crystal_flower_to_crystals.json index 2ba98699..4a86c790 100644 --- a/src/main/resources/assets/ebwizardry/recipes/crystal_flower_to_crystals.json +++ b/src/main/resources/assets/ebwizardry/recipes/crystal_flower_to_crystals.json @@ -8,6 +8,7 @@ ], "result": { "item": "ebwizardry:magic_crystal", + "data": 0, "count": 2 } } \ No newline at end of file diff --git a/src/main/resources/assets/ebwizardry/recipes/crystal_shard.json b/src/main/resources/assets/ebwizardry/recipes/crystal_shard.json new file mode 100644 index 00000000..8055c3cf --- /dev/null +++ b/src/main/resources/assets/ebwizardry/recipes/crystal_shard.json @@ -0,0 +1,13 @@ +{ + "type": "minecraft:crafting_shapeless", + "ingredients": [ + { + "item": "ebwizardry:magic_crystal", + "data": 0 + } + ], + "result": { + "item": "ebwizardry:crystal_shard", + "count": 9 + } +} \ No newline at end of file diff --git a/src/main/resources/assets/ebwizardry/recipes/large_mana_flask.json b/src/main/resources/assets/ebwizardry/recipes/large_mana_flask.json new file mode 100644 index 00000000..ddd76bc0 --- /dev/null +++ b/src/main/resources/assets/ebwizardry/recipes/large_mana_flask.json @@ -0,0 +1,19 @@ +{ + "type": "minecraft:crafting_shaped", + "pattern": [ + " y ", + "yxy", + " y " + ], + "key": { + "x": { + "item": "minecraft:glass_bottle" + }, + "y": { + "item": "ebwizardry:grand_crystal" + } + }, + "result": { + "item": "ebwizardry:large_mana_flask" + } +} \ No newline at end of file diff --git a/src/main/resources/assets/ebwizardry/recipes/magic_missile_spell_book.json b/src/main/resources/assets/ebwizardry/recipes/magic_missile_spell_book.json index b366af36..f182d17b 100644 --- a/src/main/resources/assets/ebwizardry/recipes/magic_missile_spell_book.json +++ b/src/main/resources/assets/ebwizardry/recipes/magic_missile_spell_book.json @@ -7,7 +7,8 @@ ], "key": { "x": { - "item": "ebwizardry:magic_crystal" + "item": "ebwizardry:magic_crystal", + "data": 0 }, "y": { "item": "minecraft:book" diff --git a/src/main/resources/assets/ebwizardry/recipes/magic_silk.json b/src/main/resources/assets/ebwizardry/recipes/magic_silk.json index 7f2cad0c..033a85e4 100644 --- a/src/main/resources/assets/ebwizardry/recipes/magic_silk.json +++ b/src/main/resources/assets/ebwizardry/recipes/magic_silk.json @@ -9,9 +9,40 @@ "x": { "item": "minecraft:string" }, - "y": { - "item": "ebwizardry:magic_crystal" - } + "y": [ + { + "item": "ebwizardry:magic_crystal", + "data": 0 + }, + { + "item": "ebwizardry:magic_crystal", + "data": 1 + }, + { + "item": "ebwizardry:magic_crystal", + "data": 2 + }, + { + "item": "ebwizardry:magic_crystal", + "data": 3 + }, + { + "item": "ebwizardry:magic_crystal", + "data": 4 + }, + { + "item": "ebwizardry:magic_crystal", + "data": 5 + }, + { + "item": "ebwizardry:magic_crystal", + "data": 6 + }, + { + "item": "ebwizardry:magic_crystal", + "data": 7 + } + ] }, "result": { "item": "ebwizardry:magic_silk", diff --git a/src/main/resources/assets/ebwizardry/recipes/magic_wand.json b/src/main/resources/assets/ebwizardry/recipes/magic_wand.json index ab8988a1..0326f1d3 100644 --- a/src/main/resources/assets/ebwizardry/recipes/magic_wand.json +++ b/src/main/resources/assets/ebwizardry/recipes/magic_wand.json @@ -15,7 +15,8 @@ "ore": "stickWood" }, "z": { - "item": "ebwizardry:magic_crystal" + "item": "ebwizardry:magic_crystal", + "data": 0 } }, "result": { diff --git a/src/main/resources/assets/ebwizardry/recipes/medium_mana_flask.json b/src/main/resources/assets/ebwizardry/recipes/medium_mana_flask.json new file mode 100644 index 00000000..05d32520 --- /dev/null +++ b/src/main/resources/assets/ebwizardry/recipes/medium_mana_flask.json @@ -0,0 +1,50 @@ +{ + "type": "minecraft:crafting_shaped", + "pattern": [ + "yyy", + "yxy", + "yyy" + ], + "key": { + "x": { + "item": "minecraft:glass_bottle" + }, + "y": [ + { + "item": "ebwizardry:magic_crystal", + "data": 0 + }, + { + "item": "ebwizardry:magic_crystal", + "data": 1 + }, + { + "item": "ebwizardry:magic_crystal", + "data": 2 + }, + { + "item": "ebwizardry:magic_crystal", + "data": 3 + }, + { + "item": "ebwizardry:magic_crystal", + "data": 4 + }, + { + "item": "ebwizardry:magic_crystal", + "data": 5 + }, + { + "item": "ebwizardry:magic_crystal", + "data": 6 + }, + { + "item": "ebwizardry:magic_crystal", + "data": 7 + } + ] + }, + "result": { + "item": "ebwizardry:medium_mana_flask" + } +} \ No newline at end of file diff --git a/src/main/resources/assets/ebwizardry/recipes/runestone_earth.json b/src/main/resources/assets/ebwizardry/recipes/runestone_earth.json new file mode 100644 index 00000000..e9c6525d --- /dev/null +++ b/src/main/resources/assets/ebwizardry/recipes/runestone_earth.json @@ -0,0 +1,23 @@ +{ + "type": "minecraft:crafting_shaped", + "pattern": [ + "zzz", + "zyz", + "zzz" + ], + "key": { + "y": { + "item": "ebwizardry:magic_crystal", + "data": 5 + }, + "z": { + "type": "forge:ore_dict", + "ore": "stone" + } + }, + "result": { + "item": "ebwizardry:runestone", + "data": 5, + "count": 8 + } +} \ No newline at end of file diff --git a/src/main/resources/assets/ebwizardry/recipes/runestone_fire.json b/src/main/resources/assets/ebwizardry/recipes/runestone_fire.json new file mode 100644 index 00000000..bbad7ccb --- /dev/null +++ b/src/main/resources/assets/ebwizardry/recipes/runestone_fire.json @@ -0,0 +1,23 @@ +{ + "type": "minecraft:crafting_shaped", + "pattern": [ + "zzz", + "zyz", + "zzz" + ], + "key": { + "y": { + "item": "ebwizardry:magic_crystal", + "data": 1 + }, + "z": { + "type": "forge:ore_dict", + "ore": "stone" + } + }, + "result": { + "item": "ebwizardry:runestone", + "data": 1, + "count": 8 + } +} \ No newline at end of file diff --git a/src/main/resources/assets/ebwizardry/recipes/runestone_healing.json b/src/main/resources/assets/ebwizardry/recipes/runestone_healing.json new file mode 100644 index 00000000..91a51a69 --- /dev/null +++ b/src/main/resources/assets/ebwizardry/recipes/runestone_healing.json @@ -0,0 +1,23 @@ +{ + "type": "minecraft:crafting_shaped", + "pattern": [ + "zzz", + "zyz", + "zzz" + ], + "key": { + "y": { + "item": "ebwizardry:magic_crystal", + "data": 7 + }, + "z": { + "type": "forge:ore_dict", + "ore": "stone" + } + }, + "result": { + "item": "ebwizardry:runestone", + "data": 7, + "count": 8 + } +} \ No newline at end of file diff --git a/src/main/resources/assets/ebwizardry/recipes/runestone_ice.json b/src/main/resources/assets/ebwizardry/recipes/runestone_ice.json new file mode 100644 index 00000000..cce3b6de --- /dev/null +++ b/src/main/resources/assets/ebwizardry/recipes/runestone_ice.json @@ -0,0 +1,23 @@ +{ + "type": "minecraft:crafting_shaped", + "pattern": [ + "zzz", + "zyz", + "zzz" + ], + "key": { + "y": { + "item": "ebwizardry:magic_crystal", + "data": 2 + }, + "z": { + "type": "forge:ore_dict", + "ore": "stone" + } + }, + "result": { + "item": "ebwizardry:runestone", + "data": 2, + "count": 8 + } +} \ No newline at end of file diff --git a/src/main/resources/assets/ebwizardry/recipes/runestone_lightning.json b/src/main/resources/assets/ebwizardry/recipes/runestone_lightning.json new file mode 100644 index 00000000..d18ed59c --- /dev/null +++ b/src/main/resources/assets/ebwizardry/recipes/runestone_lightning.json @@ -0,0 +1,23 @@ +{ + "type": "minecraft:crafting_shaped", + "pattern": [ + "zzz", + "zyz", + "zzz" + ], + "key": { + "y": { + "item": "ebwizardry:magic_crystal", + "data": 3 + }, + "z": { + "type": "forge:ore_dict", + "ore": "stone" + } + }, + "result": { + "item": "ebwizardry:runestone", + "data": 3, + "count": 8 + } +} \ No newline at end of file diff --git a/src/main/resources/assets/ebwizardry/recipes/runestone_necromancy.json b/src/main/resources/assets/ebwizardry/recipes/runestone_necromancy.json new file mode 100644 index 00000000..2c90d6e1 --- /dev/null +++ b/src/main/resources/assets/ebwizardry/recipes/runestone_necromancy.json @@ -0,0 +1,23 @@ +{ + "type": "minecraft:crafting_shaped", + "pattern": [ + "zzz", + "zyz", + "zzz" + ], + "key": { + "y": { + "item": "ebwizardry:magic_crystal", + "data": 4 + }, + "z": { + "type": "forge:ore_dict", + "ore": "stone" + } + }, + "result": { + "item": "ebwizardry:runestone", + "data": 4, + "count": 8 + } +} \ No newline at end of file diff --git a/src/main/resources/assets/ebwizardry/recipes/runestone_pedestal_earth.json b/src/main/resources/assets/ebwizardry/recipes/runestone_pedestal_earth.json new file mode 100644 index 00000000..740650c9 --- /dev/null +++ b/src/main/resources/assets/ebwizardry/recipes/runestone_pedestal_earth.json @@ -0,0 +1,23 @@ +{ + "type": "minecraft:crafting_shaped", + "pattern": [ + "zzz", + "yyy", + "zyz" + ], + "key": { + "y": { + "item": "ebwizardry:magic_crystal", + "data": 5 + }, + "z": { + "type": "forge:ore_dict", + "ore": "stone" + } + }, + "result": { + "item": "ebwizardry:runestone_pedestal", + "data": 5, + "count": 2 + } +} \ No newline at end of file diff --git a/src/main/resources/assets/ebwizardry/recipes/runestone_pedestal_fire.json b/src/main/resources/assets/ebwizardry/recipes/runestone_pedestal_fire.json new file mode 100644 index 00000000..966acb1f --- /dev/null +++ b/src/main/resources/assets/ebwizardry/recipes/runestone_pedestal_fire.json @@ -0,0 +1,23 @@ +{ + "type": "minecraft:crafting_shaped", + "pattern": [ + "zzz", + "yyy", + "zyz" + ], + "key": { + "y": { + "item": "ebwizardry:magic_crystal", + "data": 1 + }, + "z": { + "type": "forge:ore_dict", + "ore": "stone" + } + }, + "result": { + "item": "ebwizardry:runestone_pedestal", + "data": 1, + "count": 2 + } +} \ No newline at end of file diff --git a/src/main/resources/assets/ebwizardry/recipes/runestone_pedestal_healing.json b/src/main/resources/assets/ebwizardry/recipes/runestone_pedestal_healing.json new file mode 100644 index 00000000..d61a20a3 --- /dev/null +++ b/src/main/resources/assets/ebwizardry/recipes/runestone_pedestal_healing.json @@ -0,0 +1,23 @@ +{ + "type": "minecraft:crafting_shaped", + "pattern": [ + "zzz", + "yyy", + "zyz" + ], + "key": { + "y": { + "item": "ebwizardry:magic_crystal", + "data": 7 + }, + "z": { + "type": "forge:ore_dict", + "ore": "stone" + } + }, + "result": { + "item": "ebwizardry:runestone_pedestal", + "data": 7, + "count": 2 + } +} \ No newline at end of file diff --git a/src/main/resources/assets/ebwizardry/recipes/runestone_pedestal_ice.json b/src/main/resources/assets/ebwizardry/recipes/runestone_pedestal_ice.json new file mode 100644 index 00000000..c9bb2a29 --- /dev/null +++ b/src/main/resources/assets/ebwizardry/recipes/runestone_pedestal_ice.json @@ -0,0 +1,23 @@ +{ + "type": "minecraft:crafting_shaped", + "pattern": [ + "zzz", + "yyy", + "zyz" + ], + "key": { + "y": { + "item": "ebwizardry:magic_crystal", + "data": 2 + }, + "z": { + "type": "forge:ore_dict", + "ore": "stone" + } + }, + "result": { + "item": "ebwizardry:runestone_pedestal", + "data": 2, + "count": 2 + } +} \ No newline at end of file diff --git a/src/main/resources/assets/ebwizardry/recipes/runestone_pedestal_lightning.json b/src/main/resources/assets/ebwizardry/recipes/runestone_pedestal_lightning.json new file mode 100644 index 00000000..f04d08ae --- /dev/null +++ b/src/main/resources/assets/ebwizardry/recipes/runestone_pedestal_lightning.json @@ -0,0 +1,23 @@ +{ + "type": "minecraft:crafting_shaped", + "pattern": [ + "zzz", + "yyy", + "zyz" + ], + "key": { + "y": { + "item": "ebwizardry:magic_crystal", + "data": 3 + }, + "z": { + "type": "forge:ore_dict", + "ore": "stone" + } + }, + "result": { + "item": "ebwizardry:runestone_pedestal", + "data": 3, + "count": 2 + } +} \ No newline at end of file diff --git a/src/main/resources/assets/ebwizardry/recipes/runestone_pedestal_necromancy.json b/src/main/resources/assets/ebwizardry/recipes/runestone_pedestal_necromancy.json new file mode 100644 index 00000000..5b55f0cb --- /dev/null +++ b/src/main/resources/assets/ebwizardry/recipes/runestone_pedestal_necromancy.json @@ -0,0 +1,23 @@ +{ + "type": "minecraft:crafting_shaped", + "pattern": [ + "zzz", + "yyy", + "zyz" + ], + "key": { + "y": { + "item": "ebwizardry:magic_crystal", + "data": 4 + }, + "z": { + "type": "forge:ore_dict", + "ore": "stone" + } + }, + "result": { + "item": "ebwizardry:runestone_pedestal", + "data": 4, + "count": 2 + } +} \ No newline at end of file diff --git a/src/main/resources/assets/ebwizardry/recipes/runestone_pedestal_sorcery.json b/src/main/resources/assets/ebwizardry/recipes/runestone_pedestal_sorcery.json new file mode 100644 index 00000000..3de61998 --- /dev/null +++ b/src/main/resources/assets/ebwizardry/recipes/runestone_pedestal_sorcery.json @@ -0,0 +1,23 @@ +{ + "type": "minecraft:crafting_shaped", + "pattern": [ + "zzz", + "yyy", + "zyz" + ], + "key": { + "y": { + "item": "ebwizardry:magic_crystal", + "data": 6 + }, + "z": { + "type": "forge:ore_dict", + "ore": "stone" + } + }, + "result": { + "item": "ebwizardry:runestone_pedestal", + "data": 6, + "count": 2 + } +} \ No newline at end of file diff --git a/src/main/resources/assets/ebwizardry/recipes/runestone_sorcery.json b/src/main/resources/assets/ebwizardry/recipes/runestone_sorcery.json new file mode 100644 index 00000000..b32ec980 --- /dev/null +++ b/src/main/resources/assets/ebwizardry/recipes/runestone_sorcery.json @@ -0,0 +1,23 @@ +{ + "type": "minecraft:crafting_shaped", + "pattern": [ + "zzz", + "zyz", + "zzz" + ], + "key": { + "y": { + "item": "ebwizardry:magic_crystal", + "data": 6 + }, + "z": { + "type": "forge:ore_dict", + "ore": "stone" + } + }, + "result": { + "item": "ebwizardry:runestone", + "data": 6, + "count": 8 + } +} \ No newline at end of file diff --git a/src/main/resources/assets/ebwizardry/recipes/mana_flask.json b/src/main/resources/assets/ebwizardry/recipes/small_mana_flask.json similarity index 71% rename from src/main/resources/assets/ebwizardry/recipes/mana_flask.json rename to src/main/resources/assets/ebwizardry/recipes/small_mana_flask.json index af183c45..50bd84d3 100644 --- a/src/main/resources/assets/ebwizardry/recipes/mana_flask.json +++ b/src/main/resources/assets/ebwizardry/recipes/small_mana_flask.json @@ -10,10 +10,10 @@ "item": "minecraft:glass_bottle" }, "y": { - "item": "ebwizardry:magic_crystal" - } + "item": "ebwizardry:crystal_shard" + } }, "result": { - "item": "ebwizardry:mana_flask" + "item": "ebwizardry:small_mana_flask" } } \ No newline at end of file diff --git a/src/main/resources/assets/ebwizardry/recipes/spark_bomb.json b/src/main/resources/assets/ebwizardry/recipes/spark_bomb.json new file mode 100644 index 00000000..84ce4135 --- /dev/null +++ b/src/main/resources/assets/ebwizardry/recipes/spark_bomb.json @@ -0,0 +1,23 @@ +{ + "type": "minecraft:crafting_shapeless", + "ingredients": [ + { + "item": "ebwizardry:magic_crystal", + "data": 3 + }, + { + "item": "ebwizardry:magic_crystal", + "data": 3 + }, + { + "item": "minecraft:glass_bottle" + }, + { + "item": "minecraft:gunpowder" + } + ], + "result": { + "item": "ebwizardry:spark_bomb", + "count": 3 + } +} \ No newline at end of file diff --git a/src/main/resources/assets/ebwizardry/recipes/transportation_stone.json b/src/main/resources/assets/ebwizardry/recipes/transportation_stone.json index f28c629b..f8f8bb27 100644 --- a/src/main/resources/assets/ebwizardry/recipes/transportation_stone.json +++ b/src/main/resources/assets/ebwizardry/recipes/transportation_stone.json @@ -10,9 +10,40 @@ "type": "forge:ore_dict", "ore": "stone" }, - "y": { - "item": "ebwizardry:magic_crystal" - } + "y": [ + { + "item": "ebwizardry:magic_crystal", + "data": 0 + }, + { + "item": "ebwizardry:magic_crystal", + "data": 1 + }, + { + "item": "ebwizardry:magic_crystal", + "data": 2 + }, + { + "item": "ebwizardry:magic_crystal", + "data": 3 + }, + { + "item": "ebwizardry:magic_crystal", + "data": 4 + }, + { + "item": "ebwizardry:magic_crystal", + "data": 5 + }, + { + "item": "ebwizardry:magic_crystal", + "data": 6 + }, + { + "item": "ebwizardry:magic_crystal", + "data": 7 + } + ] }, "result": { "item": "ebwizardry:transportation_stone", diff --git a/src/main/resources/assets/ebwizardry/recipes/wand_earth.json b/src/main/resources/assets/ebwizardry/recipes/wand_earth.json new file mode 100644 index 00000000..efd14864 --- /dev/null +++ b/src/main/resources/assets/ebwizardry/recipes/wand_earth.json @@ -0,0 +1,25 @@ +{ + "type": "forge:ore_shaped", + "pattern": [ + " z", + " y ", + "x " + ], + "key": { + "x": { + "type": "forge:ore_dict", + "ore": "nuggetGold" + }, + "y": { + "type": "forge:ore_dict", + "ore": "stickWood" + }, + "z": { + "item": "ebwizardry:magic_crystal", + "data": 5 + } + }, + "result": { + "item": "ebwizardry:novice_earth_wand" + } +} \ No newline at end of file diff --git a/src/main/resources/assets/ebwizardry/recipes/wand_fire.json b/src/main/resources/assets/ebwizardry/recipes/wand_fire.json new file mode 100644 index 00000000..fab82814 --- /dev/null +++ b/src/main/resources/assets/ebwizardry/recipes/wand_fire.json @@ -0,0 +1,25 @@ +{ + "type": "forge:ore_shaped", + "pattern": [ + " z", + " y ", + "x " + ], + "key": { + "x": { + "type": "forge:ore_dict", + "ore": "nuggetGold" + }, + "y": { + "type": "forge:ore_dict", + "ore": "stickWood" + }, + "z": { + "item": "ebwizardry:magic_crystal", + "data": 1 + } + }, + "result": { + "item": "ebwizardry:novice_fire_wand" + } +} \ No newline at end of file diff --git a/src/main/resources/assets/ebwizardry/recipes/wand_healing.json b/src/main/resources/assets/ebwizardry/recipes/wand_healing.json new file mode 100644 index 00000000..4e5ec1e3 --- /dev/null +++ b/src/main/resources/assets/ebwizardry/recipes/wand_healing.json @@ -0,0 +1,25 @@ +{ + "type": "forge:ore_shaped", + "pattern": [ + " z", + " y ", + "x " + ], + "key": { + "x": { + "type": "forge:ore_dict", + "ore": "nuggetGold" + }, + "y": { + "type": "forge:ore_dict", + "ore": "stickWood" + }, + "z": { + "item": "ebwizardry:magic_crystal", + "data": 7 + } + }, + "result": { + "item": "ebwizardry:novice_healing_wand" + } +} \ No newline at end of file diff --git a/src/main/resources/assets/ebwizardry/recipes/wand_ice.json b/src/main/resources/assets/ebwizardry/recipes/wand_ice.json new file mode 100644 index 00000000..c7a8db84 --- /dev/null +++ b/src/main/resources/assets/ebwizardry/recipes/wand_ice.json @@ -0,0 +1,25 @@ +{ + "type": "forge:ore_shaped", + "pattern": [ + " z", + " y ", + "x " + ], + "key": { + "x": { + "type": "forge:ore_dict", + "ore": "nuggetGold" + }, + "y": { + "type": "forge:ore_dict", + "ore": "stickWood" + }, + "z": { + "item": "ebwizardry:magic_crystal", + "data": 2 + } + }, + "result": { + "item": "ebwizardry:novice_ice_wand" + } +} \ No newline at end of file diff --git a/src/main/resources/assets/ebwizardry/recipes/wand_lightning.json b/src/main/resources/assets/ebwizardry/recipes/wand_lightning.json new file mode 100644 index 00000000..fd88205e --- /dev/null +++ b/src/main/resources/assets/ebwizardry/recipes/wand_lightning.json @@ -0,0 +1,25 @@ +{ + "type": "forge:ore_shaped", + "pattern": [ + " z", + " y ", + "x " + ], + "key": { + "x": { + "type": "forge:ore_dict", + "ore": "nuggetGold" + }, + "y": { + "type": "forge:ore_dict", + "ore": "stickWood" + }, + "z": { + "item": "ebwizardry:magic_crystal", + "data": 3 + } + }, + "result": { + "item": "ebwizardry:novice_lightning_wand" + } +} \ No newline at end of file diff --git a/src/main/resources/assets/ebwizardry/recipes/wand_necromancy.json b/src/main/resources/assets/ebwizardry/recipes/wand_necromancy.json new file mode 100644 index 00000000..8173afa3 --- /dev/null +++ b/src/main/resources/assets/ebwizardry/recipes/wand_necromancy.json @@ -0,0 +1,25 @@ +{ + "type": "forge:ore_shaped", + "pattern": [ + " z", + " y ", + "x " + ], + "key": { + "x": { + "type": "forge:ore_dict", + "ore": "nuggetGold" + }, + "y": { + "type": "forge:ore_dict", + "ore": "stickWood" + }, + "z": { + "item": "ebwizardry:magic_crystal", + "data": 4 + } + }, + "result": { + "item": "ebwizardry:novice_necromancy_wand" + } +} \ No newline at end of file diff --git a/src/main/resources/assets/ebwizardry/recipes/wand_sorcery.json b/src/main/resources/assets/ebwizardry/recipes/wand_sorcery.json new file mode 100644 index 00000000..d8cc12a3 --- /dev/null +++ b/src/main/resources/assets/ebwizardry/recipes/wand_sorcery.json @@ -0,0 +1,25 @@ +{ + "type": "forge:ore_shaped", + "pattern": [ + " z", + " y ", + "x " + ], + "key": { + "x": { + "type": "forge:ore_dict", + "ore": "nuggetGold" + }, + "y": { + "type": "forge:ore_dict", + "ore": "stickWood" + }, + "z": { + "item": "ebwizardry:magic_crystal", + "data": 6 + } + }, + "result": { + "item": "ebwizardry:novice_sorcery_wand" + } +} \ No newline at end of file diff --git a/src/main/resources/assets/ebwizardry/recipes/wizard_handbook.json b/src/main/resources/assets/ebwizardry/recipes/wizard_handbook.json index f9bee5da..fa51a004 100644 --- a/src/main/resources/assets/ebwizardry/recipes/wizard_handbook.json +++ b/src/main/resources/assets/ebwizardry/recipes/wizard_handbook.json @@ -4,9 +4,40 @@ { "item": "minecraft:book" }, - { - "item": "ebwizardry:magic_crystal" - } + [ + { + "item": "ebwizardry:magic_crystal", + "data": 0 + }, + { + "item": "ebwizardry:magic_crystal", + "data": 1 + }, + { + "item": "ebwizardry:magic_crystal", + "data": 2 + }, + { + "item": "ebwizardry:magic_crystal", + "data": 3 + }, + { + "item": "ebwizardry:magic_crystal", + "data": 4 + }, + { + "item": "ebwizardry:magic_crystal", + "data": 5 + }, + { + "item": "ebwizardry:magic_crystal", + "data": 6 + }, + { + "item": "ebwizardry:magic_crystal", + "data": 7 + } + ] ], "result": { "item": "ebwizardry:wizard_handbook" diff --git a/src/main/resources/assets/ebwizardry/shaders/post/possession.json b/src/main/resources/assets/ebwizardry/shaders/post/possession.json new file mode 100644 index 00000000..04c52685 --- /dev/null +++ b/src/main/resources/assets/ebwizardry/shaders/post/possession.json @@ -0,0 +1,73 @@ +{ + "targets": [ + "swap", + "previous", + "a", + "b", + "c" + ], + "passes": [ + { + "name": "color_convolve", + "intarget": "minecraft:main", + "outtarget": "a", + "uniforms": [ + { + "name": "Saturation", + "values": [ 0.2 ] + } + ] + }, + { + "name": "color_convolve", + "intarget": "a", + "outtarget": "b", + "uniforms": [ + { + "name": "RedMatrix", + "values": [ 0.2, 0.2, 0.1 ] + }, + { + "name": "GreenMatrix", + "values": [ 0.1, 0.1, 0.1 ] + }, + { + "name": "BlueMatrix", + "values": [ 0.2, 0.2, 0.3 ] + } + ] + }, + { + "name": "deconverge", + "intarget": "a", + "outtarget": "c" + }, + { + "name": "phosphor", + "intarget": "c", + "outtarget": "swap", + "auxtargets": [ + { + "name": "PrevSampler", + "id": "previous" + } + ], + "uniforms": [ + { + "name": "Phosphor", + "values": [ 0.8, 0.8, 0.8 ] + } + ] + }, + { + "name": "blit", + "intarget": "swap", + "outtarget": "previous" + }, + { + "name": "blit", + "intarget": "swap", + "outtarget": "minecraft:main" + } + ] +} diff --git a/src/main/resources/assets/ebwizardry/shaders/post/sixth_sense.json b/src/main/resources/assets/ebwizardry/shaders/post/sixth_sense.json new file mode 100644 index 00000000..0c66b6ae --- /dev/null +++ b/src/main/resources/assets/ebwizardry/shaders/post/sixth_sense.json @@ -0,0 +1,67 @@ +{ + "targets": [ + "swap", + "previous", + "a", + "b" + ], + "passes": [ + { + "name": "color_convolve", + "intarget": "minecraft:main", + "outtarget": "a", + "uniforms": [ + { + "name": "Saturation", + "values": [ 0.3 ] + } + ] + }, + { + "name": "color_convolve", + "intarget": "a", + "outtarget": "b", + "uniforms": [ + { + "name": "RedMatrix", + "values": [ 0.3, 0, 0 ] + }, + { + "name": "GreenMatrix", + "values": [ 0.3, 0.6, 0.3 ] + }, + { + "name": "BlueMatrix", + "values": [ 0.2, 0.2, 0.5 ] + } + ] + }, + { + "name": "phosphor", + "intarget": "b", + "outtarget": "swap", + "auxtargets": [ + { + "name": "PrevSampler", + "id": "previous" + } + ], + "uniforms": [ + { + "name": "Phosphor", + "values": [ 0.8, 0.8, 0.8 ] + } + ] + }, + { + "name": "blit", + "intarget": "swap", + "outtarget": "previous" + }, + { + "name": "blit", + "intarget": "swap", + "outtarget": "minecraft:main" + } + ] +} diff --git a/src/main/resources/assets/ebwizardry/shaders/post/slow_time.json b/src/main/resources/assets/ebwizardry/shaders/post/slow_time.json new file mode 100644 index 00000000..09f32ab1 --- /dev/null +++ b/src/main/resources/assets/ebwizardry/shaders/post/slow_time.json @@ -0,0 +1,37 @@ +{ + "targets": [ + "a" + ], + "passes": [ + { + "name": "color_convolve", + "intarget": "minecraft:main", + "outtarget": "a", + "uniforms": [ + { + "name": "Saturation", + "values": [ 0.2 ] + } + ] + }, + { + "name": "color_convolve", + "intarget": "a", + "outtarget": "minecraft:main", + "uniforms": [ + { + "name": "RedMatrix", + "values": [ 0.6, 0, 0 ] + }, + { + "name": "GreenMatrix", + "values": [ 0, 0.7, 0 ] + }, + { + "name": "BlueMatrix", + "values": [ 0.1, 0.1, 1 ] + } + ] + } + ] +} diff --git a/src/main/resources/assets/ebwizardry/shaders/post/transience.json b/src/main/resources/assets/ebwizardry/shaders/post/transience.json new file mode 100644 index 00000000..9b30fe4f --- /dev/null +++ b/src/main/resources/assets/ebwizardry/shaders/post/transience.json @@ -0,0 +1,67 @@ +{ + "targets": [ + "swap", + "previous", + "a", + "b" + ], + "passes": [ + { + "name": "color_convolve", + "intarget": "minecraft:main", + "outtarget": "a", + "uniforms": [ + { + "name": "Saturation", + "values": [ 0.8 ] + } + ] + }, + { + "name": "color_convolve", + "intarget": "a", + "outtarget": "b", + "uniforms": [ + { + "name": "RedMatrix", + "values": [ 0.9, 0.9, 0.7 ] + }, + { + "name": "GreenMatrix", + "values": [ 0.9, 0.9, 0.7 ] + }, + { + "name": "BlueMatrix", + "values": [ 0.8, 0.8, 0.7 ] + } + ] + }, + { + "name": "phosphor", + "intarget": "b", + "outtarget": "swap", + "auxtargets": [ + { + "name": "PrevSampler", + "id": "previous" + } + ], + "uniforms": [ + { + "name": "Phosphor", + "values": [ 0.8, 0.8, 0.8 ] + } + ] + }, + { + "name": "blit", + "intarget": "swap", + "outtarget": "previous" + }, + { + "name": "blit", + "intarget": "swap", + "outtarget": "minecraft:main" + } + ] +} diff --git a/src/main/resources/assets/ebwizardry/sounds.json b/src/main/resources/assets/ebwizardry/sounds.json index 42258e4b..9ed093b0 100644 --- a/src/main/resources/assets/ebwizardry/sounds.json +++ b/src/main/resources/assets/ebwizardry/sounds.json @@ -1,41 +1,361 @@ { - "arc": {"category": "player","sounds": [ - {"name": "ebwizardry:arc1","stream": false}, - {"name": "ebwizardry:arc1","stream": false}, - {"name": "ebwizardry:arc3","stream": false} - ]}, - - "aura": {"category": "player","sounds": [{"name": "ebwizardry:aura","stream": false}]}, - "boom": {"category": "player","sounds": [{"name": "ebwizardry:boom","stream": false}]}, - "crackle": {"category": "player","sounds": [{"name": "ebwizardry:crackle","stream": false}]}, + "block.arcane_workbench.bind_spell": {"category": "blocks", "sounds": ["ebwizardry:spellbind"]}, + "block.pedestal.activate": {"category": "blocks", "sounds": ["mob/evocation_illager/prepare_summon"]}, + "block.pedestal.conquer": {"category": "blocks", "sounds": ["ui/toast/challenge_complete"]}, + + "item.wand.switch_spell": {"category": "player", "sounds": ["ebwizardry:select"]}, + "item.wand.levelup": {"category": "player", "sounds": ["random/levelup"]}, + "item.wand.melee": {"category": "player", "sounds": ["ebwizardry:effect1", "ebwizardry:effect2"]}, + "item.armour.equip_silk": {"category": "player", "sounds": ["item/armor/equip_leather1", "item/armor/equip_leather2", "item/armor/equip_leather3", "item/armor/equip_leather4", "item/armor/equip_leather5", "item/armor/equip_leather6"]}, + "item.purifying_elixir.drink": {"category": "player", "sounds": ["ebwizardry:spellbind"]}, - "darkaura": {"category": "player","sounds": [ - {"name": "ebwizardry:darkaura1","stream": false}, - {"name": "ebwizardry:darkaura2","stream": false} - ]}, - - "effect": {"category": "player","sounds": [ - {"name": "ebwizardry:effect1","stream": false}, - {"name": "ebwizardry:effect2","stream": false} - ]}, - - "electricitya": {"category": "player","sounds": [{"name": "ebwizardry:electricitya","stream": false}]}, - "electricityb": {"category": "player","sounds": [{"name": "ebwizardry:electricityb","stream": false}]}, + "entity.black_hole.ambient": {"category": "spells", "sounds": ["portal/portal"]}, + "entity.black_hole.vanish": {"category": "spells", "sounds": ["portal/trigger"]}, + "entity.bubble.pop": {"category": "spells", "sounds": ["random/pop"]}, + "entity.blizzard.ambient": {"category": "spells", "sounds": ["ebwizardry:wind"]}, + "entity.decay.ambient": {"category": "spells", "sounds": ["liquid/lava"]}, + "entity.entrapment.ambient": {"category": "spells", "sounds": ["portal/portal"]}, + "entity.entrapment.vanish": {"category": "spells", "sounds": ["portal/trigger"]}, + "entity.fire_ring.ambient": {"category": "spells", "sounds": ["fire/fire"]}, + "entity.fire_sigil.trigger": {"category": "spells", "sounds": ["mob/ghast/fireball4"]}, + "entity.forcefield.deflect": {"category": "spells", "sounds": ["ebwizardry:effect1", "ebwizardry:effect2"]}, + "entity.frost_sigil.trigger": {"category": "spells", "sounds": ["ebwizardry:freeze"]}, + "entity.hammer.attack": {"category": "spells", "sounds": ["ebwizardry:arc1", "ebwizardry:arc2", "ebwizardry:arc3"]}, + "entity.hammer.explode": {"category": "spells", "sounds": ["random/explode1", "random/explode2", "random/explode3", "random/explode4"]}, + "entity.hammer.throw": {"category": "spells", "sounds": ["random/bow"]}, + "entity.hammer.land": {"category": "spells", "sounds": ["random/anvil_land"]}, + "entity.heal_aura.ambient": {"category": "spells", "sounds": ["ebwizardry:sparkle"]}, + "entity.ice_spike.extend": {"category": "spells", "sounds": ["ebwizardry:ice"]}, + "entity.lightning_sigil.trigger": {"category": "spells", "sounds": ["ebwizardry:arc1", "ebwizardry:arc2", "ebwizardry:arc3"]}, + "entity.meteor.falling": {"category": "spells", "sounds": ["ebwizardry:flames_loop"]}, + "entity.shield.deflect": {"category": "spells", "sounds": ["ebwizardry:effect1", "ebwizardry:effect2"]}, + "entity.tornado.ambient": {"category": "spells", "sounds": ["ebwizardry:wind"]}, - "flameray": {"category": "player","sounds": [{"name": "ebwizardry:flameray2","stream": false}]}, - "force": {"category": "player","sounds": [{"name": "ebwizardry:force","stream": false}]}, - - "freeze": {"category": "player","sounds": [{"name": "ebwizardry:freeze","stream": false}]}, - "frostray": {"category": "player","sounds": [{"name": "ebwizardry:frostray","stream": false}]}, - "heal": {"category": "player","sounds": [{"name": "ebwizardry:heal","stream": false}]}, - "ice": {"category": "player","sounds": [{"name": "ebwizardry:ice","stream": false}]}, - "largeaura": {"category": "player","sounds": [{"name": "ebwizardry:largeaura","stream": false}]}, + "entity.evil_wizard.ambient": {"category": "hostile", "sounds": ["mob/evocation_illager/idle1", "mob/evocation_illager/idle2", "mob/evocation_illager/idle3", "mob/evocation_illager/idle4"]}, + "entity.evil_wizard.hurt": {"category": "hostile", "sounds": ["mob/evocation_illager/hurt1", "mob/evocation_illager/hurt2"]}, + "entity.evil_wizard.death": {"category": "hostile", "sounds": ["mob/evocation_illager/death1", "mob/evocation_illager/death2"]}, + "entity.ice_giant.attack": {"category": "hostile", "sounds": ["mob/irongolem/throw"]}, + "entity.ice_giant.despawn": {"category": "hostile", "sounds": ["ebwizardry:freeze"]}, + "entity.ice_wraith.ambient": {"category": "hostile", "sounds": ["ebwizardry:wind"]}, + "entity.magic_slime.attack": {"category": "hostile", "sounds": ["mob/slime/attack1", "mob/slime/attack2"]}, + "entity.magic_slime.explode": {"category": "hostile", "sounds": ["fireworks/blast_far1"]}, + "entity.magic_slime.splat": {"category": "hostile", "sounds": ["mob/slime/attack1", "mob/slime/attack2"]}, + "entity.phoenix.ambient": {"category": "hostile", "sounds": ["mob/blaze/breathe1", "mob/blaze/breathe2", "mob/blaze/breathe3", "mob/blaze/breathe4"]}, + "entity.phoenix.burn": {"category": "hostile", "sounds": ["fire/fire"]}, + "entity.phoenix.flap": {"category": "hostile", "sounds": ["mob/enderdragon/wings1", "mob/enderdragon/wings2", "mob/enderdragon/wings3", "mob/enderdragon/wings4", "mob/enderdragon/wings5", "mob/enderdragon/wings6"]}, + "entity.phoenix.hurt": {"category": "hostile", "sounds": ["mob/blaze/hit1", "mob/blaze/hit2", "mob/blaze/hit3", "mob/blaze/hit4"]}, + "entity.phoenix.death": {"category": "hostile", "sounds": ["mob/blaze/death"]}, + "entity.shadow_wraith.ambient": {"category": "hostile", "sounds": ["mob/blaze/breathe1", "mob/blaze/breathe2", "mob/blaze/breathe3", "mob/blaze/breathe4"]}, + "entity.shadow_wraith.noise": {"category": "hostile", "sounds": ["portal/portal"]}, + "entity.shadow_wraith.hurt": {"category": "hostile", "sounds": ["mob/blaze/hit1", "mob/blaze/hit2", "mob/blaze/hit3", "mob/blaze/hit4"]}, + "entity.shadow_wraith.death": {"category": "hostile", "sounds": ["mob/blaze/death"]}, + "entity.spirit_horse.vanish": {"category": "neutral", "sounds": ["ebwizardry:conjure_large"]}, + "entity.spirit_wolf.vanish": {"category": "neutral", "sounds": ["ebwizardry:conjure_large"]}, + "entity.storm_elemental.ambient": {"category": "hostile", "sounds": ["mob/blaze/breathe1", "mob/blaze/breathe2", "mob/blaze/breathe3", "mob/blaze/breathe4"]}, + "entity.storm_elemental.burn": {"category": "hostile", "sounds": ["fire/fire"]}, + "entity.storm_elemental.wind": {"category": "hostile", "sounds": ["ebwizardry:wind"]}, + "entity.storm_elemental.hurt": {"category": "hostile", "sounds": ["mob/blaze/hit1", "mob/blaze/hit2", "mob/blaze/hit3", "mob/blaze/hit4"]}, + "entity.storm_elemental.death": {"category": "hostile", "sounds": ["mob/blaze/death"]}, + "entity.wizard.ambient": {"category": "neutral", "sounds": ["mob/villager/idle1", "mob/villager/idle2", "mob/villager/idle3"]}, + "entity.wizard.trading": {"category": "neutral", "sounds": ["mob/villager/haggle1", "mob/villager/haggle2", "mob/villager/haggle3"]}, + "entity.wizard.yes": {"category": "neutral", "sounds": ["mob/villager/yes1", "mob/villager/yes2", "mob/villager/yes3"]}, + "entity.wizard.no": {"category": "neutral", "sounds": ["mob/villager/no1", "mob/villager/no2", "mob/villager/no3"]}, + "entity.wizard.hurt": {"category": "neutral", "sounds": ["mob/villager/hit1", "mob/villager/hit2", "mob/villager/hit3", "mob/villager/hit4"]}, + "entity.wizard.death": {"category": "neutral", "sounds": ["mob/villager/death"]}, - "magic": {"category": "player","sounds": [{"name": "ebwizardry:magic1","stream": false}]}, - - "sparkle": {"category": "player","sounds": [{"name": "ebwizardry:sparkle","stream": false}]}, - "wind": {"category": "player","sounds": [{"name": "ebwizardry:wind","stream": false}]}, - "rumble": {"category": "player","sounds": [{"name": "ebwizardry:rumble","stream": false}]}, + "entity.darkness_orb.hit": {"category": "spells", "sounds": ["mob/wither/hurt1", "mob/wither/hurt2", "mob/wither/hurt3", "mob/wither/hurt4"]}, + "entity.dart.hit": {"category": "spells", "sounds": ["damage/hit1", "damage/hit2", "damage/hit3"]}, + "entity.dart.hit_block": {"category": "spells", "sounds": ["random/bowhit1", "random/bowhit2", "random/bowhit3"]}, + "entity.firebolt.hit": {"category": "spells", "sounds": ["liquid/lavapop"]}, + "entity.firebomb.throw": {"category": "spells", "sounds": ["random/bow"]}, + "entity.firebomb.smash": {"category": "spells", "sounds": ["random/glass1", "random/glass2", "random/glass3"]}, + "entity.firebomb.fire": {"category": "spells", "sounds": ["mob/ghast/fireball4"]}, + "entity.force_arrow.hit": {"category": "spells", "sounds": ["fireworks/blast1"]}, + "entity.force_orb.hit": {"category": "spells", "sounds": ["damage/hit1", "damage/hit2", "damage/hit3"]}, + "entity.force_orb.hit_block": {"category": "spells", "sounds": ["fireworks/blast1"]}, + "entity.iceball.hit": {"category": "spells", "sounds": ["damage/hit1", "damage/hit2", "damage/hit3"]}, + "entity.ice_charge.smash": {"category": "spells", "sounds": ["random/glass1", "random/glass2", "random/glass3"]}, + "entity.ice_charge.ice": {"category": "spells", "sounds": ["ebwizardry:ice"]}, + "entity.ice_lance.smash": {"category": "spells", "sounds": ["random/glass1", "random/glass2", "random/glass3"]}, + "entity.ice_lance.hit": {"category": "spells", "sounds": ["damage/hit1", "damage/hit2", "damage/hit3"]}, + "entity.ice_shard.smash": {"category": "spells", "sounds": ["random/glass1", "random/glass2", "random/glass3"]}, + "entity.ice_shard.hit": {"category": "spells", "sounds": ["damage/hit1", "damage/hit2", "damage/hit3"]}, + "entity.lightning_arrow.hit": {"category": "spells", "sounds": ["ebwizardry:arc1", "ebwizardry:arc2", "ebwizardry:arc3"]}, + "entity.lightning_disc.hit": {"category": "spells", "sounds": ["ebwizardry:arc1", "ebwizardry:arc2", "ebwizardry:arc3"]}, + "entity.magic_missile.hit": {"category": "spells", "sounds": ["damage/hit1", "damage/hit2", "damage/hit3"]}, + "entity.poison_bomb.throw": {"category": "spells", "sounds": ["random/bow"]}, + "entity.poison_bomb.smash": {"category": "spells", "sounds": ["random/glass1", "random/glass2", "random/glass3"]}, + "entity.poison_bomb.poison": {"category": "spells", "sounds": ["random/fizz"]}, + "entity.smoke_bomb.throw": {"category": "spells", "sounds": ["random/bow"]}, + "entity.smoke_bomb.smash": {"category": "spells", "sounds": ["random/glass1", "random/glass2", "random/glass3"]}, + "entity.smoke_bomb.smoke": {"category": "spells", "sounds": ["random/fizz"]}, + "entity.homing_spark.hit": {"category": "spells", "sounds": ["ebwizardry:arc1", "ebwizardry:arc2", "ebwizardry:arc3"]}, + "entity.spark_bomb.throw": {"category": "spells", "sounds": ["random/bow"]}, + "entity.spark_bomb.hit": {"category": "spells", "sounds": ["damage/hit1", "damage/hit2", "damage/hit3"]}, + "entity.spark_bomb.hit_block": {"category": "spells", "sounds": ["fireworks/blast_far1"]}, + "entity.spark_bomb.chain": {"category": "spells", "sounds": ["ebwizardry:arc1", "ebwizardry:arc2", "ebwizardry:arc3"]}, + "entity.thunderbolt.hit": {"category": "spells", "sounds": ["fireworks/largeblast1"]}, - "select": {"category": "player","sounds": [{"name": "ebwizardry:select","stream": false}]} + "misc.discover_spell": {"category": "player", "sounds": ["random/levelup"]}, + "misc.page_turn": {"category": "player", "sounds": ["ebwizardry:page1", "ebwizardry:page2", "ebwizardry:page3"]}, + "misc.book_open": {"category": "player", "sounds": ["ebwizardry:book"]}, + + "misc.freeze": {"category": "spells", "sounds": ["ebwizardry:freeze"]}, + + "spell.agility": {"category": "spells", "sounds": ["ebwizardry:heal"]}, + "spell.arc": {"category": "spells", "sounds": ["ebwizardry:arc1", "ebwizardry:arc2", "ebwizardry:arc3"]}, + "spell.arcane_jammer": {"category": "spells", "sounds": ["ebwizardry:effect1", "ebwizardry:effect2"]}, + "spell.arcane_lock": {"category": "spells", "sounds": ["entity/endereye/dead1", "entity/endereye/dead2"]}, + "spell.arrow_rain": {"category": "spells", "sounds": ["mob/illusion_illager/prepare_blind"]}, + "spell.banish": {"category": "spells", "sounds": ["mob/endermen/portal", "mob/endermen/portal2"]}, + "spell.black_hole": {"category": "spells", "sounds": ["mob/evocation_illager/prepare_attack1", "mob/evocation_illager/prepare_attack2"]}, + "spell.blink": {"category": "spells", "sounds": ["mob/endermen/portal", "mob/endermen/portal2"]}, + "spell.blizzard": {"category": "spells", "sounds": ["ebwizardry:ice"]}, + "spell.bubble.shoot": {"category": "spells", "sounds": ["ebwizardry:ice"]}, + "spell.bubble.splash": {"category": "spells", "sounds": ["liquid/swim1", "liquid/swim2", "liquid/swim3", "liquid/swim4"], "volume": 2}, + "spell.chain_lightning": {"category": "spells", "sounds": ["ebwizardry:arc1", "ebwizardry:arc2", "ebwizardry:arc3"]}, + "spell.charge": {"category": "spells", "sounds": ["ebwizardry:shockwave"]}, + "spell.clairvoyance": {"category": "spells", "sounds": ["ebwizardry:conjure"]}, + "spell.cobwebs": {"category": "spells", "sounds": ["random/fizz"]}, + "spell.combustion_rune": {"category": "spells", "sounds": ["fire/ignite"]}, + "spell.containment": {"category": "spells", "sounds": ["mob/guardian/curse"]}, + "spell.conjure_armour": {"category": "spells", "sounds": ["ebwizardry:conjure"]}, + "spell.conjure_block": {"category": "spells", "sounds": ["ebwizardry:conjure"]}, + "spell.conjure_bow": {"category": "spells", "sounds": ["ebwizardry:conjure"]}, + "spell.conjure_pickaxe": {"category": "spells", "sounds": ["ebwizardry:conjure"]}, + "spell.conjure_sword": {"category": "spells", "sounds": ["ebwizardry:conjure"]}, + "spell.cure_effects": {"category": "spells", "sounds": ["ebwizardry:heal"]}, + "spell.curse_of_enfeeblement": {"category": "spells", "sounds": ["mob/wither/spawn"]}, + "spell.curse_of_soulbinding": {"category": "spells", "sounds": ["mob/guardian/curse"]}, + "spell.curse_of_soulbinding.retaliate": {"category": "spells", "sounds": ["mob/wither/hurt1", "mob/wither/hurt2", "mob/wither/hurt3", "mob/wither/hurt4"]}, + "spell.curse_of_undeath": {"category": "spells", "sounds": ["mob/guardian/curse"]}, + "spell.darkness_orb": {"category": "spells", "sounds": ["mob/wither/shoot"]}, + "spell.darkvision": {"category": "spells", "sounds": ["ebwizardry:heal"]}, + "spell.dart": {"category": "spells", "sounds": ["random/bow"]}, + "spell.decay": {"category": "spells", "sounds": ["mob/wither/shoot"]}, + "spell.decoy": {"category": "spells", "sounds": ["mob/illusion_illager/mirror_move1", "mob/illusion_illager/mirror_move2"]}, + "spell.detonate": {"category": "spells", "sounds": ["random/explode1", "random/explode2", "random/explode3", "random/explode4"]}, + "spell.diamondflesh": {"category": "spells", "sounds": ["ebwizardry:buff"]}, + "spell.disintegration": {"category": "spells", "sounds": ["ebwizardry:firebolt"]}, + "spell.divination": {"category": "spells", "sounds": ["ebwizardry:conjure"]}, + "spell.dragon_fireball": {"category": "spells", "sounds": ["mob/ghast/fireball4"]}, + "spell.earthquake": {"category": "spells", "sounds": ["ebwizardry:rumble"]}, + "spell.empowering_presence": {"category": "spells", "sounds": ["ebwizardry:buff"]}, + "spell.entrapment": {"category": "spells", "sounds": ["mob/evocation_illager/prepare_attack1", "mob/evocation_illager/prepare_attack2"]}, + "spell.evade": {"category": "spells", "sounds": ["random/bow"]}, + "spell.fireball": {"category": "spells", "sounds": ["mob/ghast/fireball4"]}, + "spell.firebolt": {"category": "spells", "sounds": ["mob/ghast/fireball4"]}, + "spell.firebomb": {"category": "spells", "sounds": ["random/bow"]}, + "spell.fire_resistance": {"category": "spells", "sounds": ["ebwizardry:buff"]}, + "spell.fire_sigil": {"category": "spells", "sounds": ["fire/ignite"]}, + "spell.fireskin": {"category": "spells", "sounds": ["ebwizardry:buff"]}, + "spell.fire_breath.start": {"category": "spells", "sounds": ["ebwizardry:flames_start"]}, + "spell.fire_breath.loop": {"category": "spells", "sounds": ["ebwizardry:flames_loop"]}, + "spell.fire_breath.end": {"category": "spells", "sounds": ["ebwizardry:flames_end"]}, + "spell.flame_ray.start": {"category": "spells", "sounds": ["ebwizardry:flames_start"]}, + "spell.flame_ray.loop": {"category": "spells", "sounds": ["ebwizardry:flames_loop"]}, + "spell.flame_ray.end": {"category": "spells", "sounds": ["ebwizardry:flames_end"]}, + "spell.flaming_axe": {"category": "spells", "sounds": ["ebwizardry:buff"]}, + "spell.flaming_weapon": {"category": "spells", "sounds": ["ebwizardry:buff"]}, + "spell.flight": {"category": "spells", "sounds": ["mob/enderdragon/wings1", "mob/enderdragon/wings2", "mob/enderdragon/wings3", "mob/enderdragon/wings4", "mob/enderdragon/wings5", "mob/enderdragon/wings6"]}, + "spell.font_of_mana": {"category": "spells", "sounds": ["ebwizardry:spellbind"]}, + "spell.font_of_vitality": {"category": "spells", "sounds": ["ebwizardry:spellbind"]}, + "spell.force_arrow": {"category": "spells", "sounds": ["ebwizardry:force"]}, + "spell.forcefield": {"category": "spells", "sounds": ["ebwizardry:conjure_large"]}, + "spell.force_orb": {"category": "spells", "sounds": ["random/bow"]}, + "spell.forests_curse": {"category": "spells", "sounds": ["mob/wither/spawn"]}, + "spell.forest_of_thorns": {"category": "spells", "sounds": ["ebwizardry:grow"]}, + "spell.freeze": {"category": "spells", "sounds": ["ebwizardry:ice"]}, + "spell.freezing_weapon": {"category": "spells", "sounds": ["ebwizardry:buff"]}, + "spell.frost_axe": {"category": "spells", "sounds": ["ebwizardry:buff"]}, + "spell.frost_ray.start": {"category": "spells", "sounds": ["ebwizardry:frostray"]}, + "spell.frost_ray.loop": {"category": "spells", "sounds": ["ebwizardry:frostray"]}, + "spell.frost_ray.end": {"category": "spells", "sounds": ["ebwizardry:frostray"]}, + "spell.frost_sigil": {"category": "spells", "sounds": ["ebwizardry:ice"]}, + "spell.frost_step": {"category": "spells", "sounds": ["ebwizardry:buff"]}, + "spell.glide": {"category": "spells", "sounds": [{"name": "item/elytra/elytra_loop", "volume": 0.6}]}, + "spell.grapple.shoot": {"category": "spells", "sounds": ["random/bow"]}, + "spell.grapple.attach": {"category": "spells", "sounds": ["dig/grass1", "dig/grass2", "dig/grass3", "dig/grass4"]}, + "spell.grapple.pull": {"category": "spells", "sounds": ["ebwizardry:pull1", "ebwizardry:pull2"]}, + "spell.grapple.release": {"category": "spells", "sounds": ["random/bowhit1", "random/bowhit2", "random/bowhit3"]}, + "spell.greater_fireball": {"category": "spells", "sounds": ["mob/ghast/fireball4"]}, + "spell.greater_heal": {"category": "spells", "sounds": ["ebwizardry:spellbind"]}, + "spell.greater_telekinesis.start": {"category": "spells", "sounds": ["ebwizardry:aura_start"]}, + "spell.greater_telekinesis.loop": {"category": "spells", "sounds": ["ebwizardry:aura_loop"]}, + "spell.greater_telekinesis.end": {"category": "spells", "sounds": ["ebwizardry:aura_end"]}, + "spell.greater_ward": {"category": "spells", "sounds": ["ebwizardry:spellbind"]}, + "spell.group_heal": {"category": "spells", "sounds": ["ebwizardry:heal"]}, + "spell.growth_aura": {"category": "spells", "sounds": ["ebwizardry:conjure_large"]}, + "spell.hailstorm": {"category": "spells", "sounds": ["mob/illusion_illager/prepare_blind"]}, + "spell.heal": {"category": "spells", "sounds": ["ebwizardry:heal"]}, + "spell.heal_ally": {"category": "spells", "sounds": ["ebwizardry:heal"]}, + "spell.healing_aura": {"category": "spells", "sounds": ["ebwizardry:conjure_large"]}, + "spell.homing_spark": {"category": "spells", "sounds": ["ebwizardry:conjure"]}, + "spell.iceball": {"category": "spells", "sounds": ["ebwizardry:ice"]}, + "spell.ice_age": {"category": "spells", "sounds": ["ebwizardry:ice"]}, + "spell.ice_charge": {"category": "spells", "sounds": ["ebwizardry:ice"]}, + "spell.ice_lance": {"category": "spells", "sounds": ["ebwizardry:ice"]}, + "spell.ice_shard": {"category": "spells", "sounds": ["ebwizardry:ice"]}, + "spell.ice_shroud": {"category": "spells", "sounds": ["ebwizardry:buff"]}, + "spell.ice_spikes": {"category": "spells", "sounds": ["ebwizardry:ice"]}, + "spell.ice_statue.shoot": {"category": "spells", "sounds": ["ebwizardry:ice"]}, + "spell.ice_statue.freeze": {"category": "spells", "sounds": ["ebwizardry:freeze"]}, + "spell.ignite": {"category": "spells", "sounds": ["fire/ignite"]}, + "spell.imbue_weapon": {"category": "spells", "sounds": ["ebwizardry:buff"]}, + "spell.intimidate": {"category": "spells", "sounds": ["mob/enderdragon/growl1", "mob/enderdragon/growl2", "mob/enderdragon/growl3", "mob/enderdragon/growl4"]}, + "spell.invigorating_presence": {"category": "spells", "sounds": ["ebwizardry:buff"]}, + "spell.invisibility": {"category": "spells", "sounds": ["ebwizardry:buff"]}, + "spell.invoke_weather": {"category": "spells", "sounds": ["ambient/weather/thunder1", "ambient/weather/thunder2", "ambient/weather/thunder3"]}, + "spell.ironflesh": {"category": "spells", "sounds": ["ebwizardry:buff"]}, + "spell.leap": {"category": "spells", "sounds": ["mob/enderdragon/wings1", "mob/enderdragon/wings2", "mob/enderdragon/wings3", "mob/enderdragon/wings4", "mob/enderdragon/wings5", "mob/enderdragon/wings6"]}, + "spell.levitation.start": {"category": "spells", "sounds": ["ebwizardry:aura_start"]}, + "spell.levitation.loop": {"category": "spells", "sounds": ["ebwizardry:aura_loop"]}, + "spell.levitation.end": {"category": "spells", "sounds": ["ebwizardry:aura_end"]}, + "spell.life_drain.start": {"category": "spells", "sounds": ["ebwizardry:dark_aura_start"]}, + "spell.life_drain.loop": {"category": "spells", "sounds": ["ebwizardry:dark_aura_loop"]}, + "spell.life_drain.end": {"category": "spells", "sounds": ["ebwizardry:dark_aura_end"]}, + "spell.light": {"category": "spells", "sounds": ["ebwizardry:conjure"]}, + "spell.lightning_arrow": {"category": "spells", "sounds": ["mob/evocation_illager/cast1", "mob/evocation_illager/cast2"]}, + "spell.lightning_bolt": {"category": "spells", "sounds": []}, + "spell.lightning_disc": {"category": "spells", "sounds": ["ebwizardry:lightning_ray_start"]}, + "spell.lightning_hammer": {"category": "spells", "sounds": ["mob/illusion_illager/prepare_blind"]}, + "spell.lightning_pulse.spark": {"category": "spells", "sounds": ["ebwizardry:lightning_ray_start"]}, + "spell.lightning_pulse.explosion": {"category": "spells", "sounds": ["ebwizardry:shockwave"]}, + "spell.lightning_ray.start": {"category": "spells", "sounds": ["ebwizardry:lightning_ray_start"]}, + "spell.lightning_ray.loop": {"category": "spells", "sounds": ["ebwizardry:lightning_ray_loop"]}, + "spell.lightning_ray.end": {"category": "spells", "sounds": ["ebwizardry:lightning_ray_end"]}, + "spell.lightning_sigil": {"category": "spells", "sounds": ["ebwizardry:conjure"]}, + "spell.lightning_web.start": {"category": "spells", "sounds": ["ebwizardry:lightning_ray_start"]}, + "spell.lightning_web.loop": {"category": "spells", "sounds": ["ebwizardry:lightning_ray_loop"]}, + "spell.lightning_web.end": {"category": "spells", "sounds": ["ebwizardry:lightning_ray_end"]}, + "spell.magic_missile": {"category": "spells", "sounds": ["ebwizardry:magic1"]}, + "spell.metamorphosis": {"category": "spells", "sounds": ["mob/illusion_illager/prepare_mirror"]}, + "spell.meteor": {"category": "spells", "sounds": ["mob/illusion_illager/prepare_blind"]}, + "spell.mind_control": {"category": "spells", "sounds": ["mob/guardian/elder_death"]}, + "spell.mind_trick": {"category": "spells", "sounds": ["ebwizardry:effect1", "ebwizardry:effect2"]}, + "spell.mine": {"category": "spells", "sounds": []}, + "spell.muffle": {"category": "spells", "sounds": ["ebwizardry:buff"]}, + "spell.none": {"category": "spells", "sounds": []}, + "spell.oakflesh": {"category": "spells", "sounds": ["ebwizardry:buff"]}, + "spell.paralysis": {"category": "spells", "sounds": ["ebwizardry:shockwave"]}, + "spell.petrify": {"category": "spells", "sounds": ["mob/wither/spawn"]}, + "spell.phase_step": {"category": "spells", "sounds": ["mob/endermen/portal", "mob/endermen/portal2"]}, + "spell.plague_of_darkness": {"category": "spells", "sounds": ["mob/wither/death"]}, + "spell.pocket_furnace": {"category": "spells", "sounds": ["block/furnace/fire_crackle1", "block/furnace/fire_crackle2", "block/furnace/fire_crackle3", "block/furnace/fire_crackle4", "block/furnace/fire_crackle5"]}, + "spell.pocket_workbench": {"category": "spells", "sounds": ["ebwizardry:conjure"]}, + "spell.poison": {"category": "spells", "sounds": ["ebwizardry:ice"]}, + "spell.poison_bomb": {"category": "spells", "sounds": ["random/bow"]}, + "spell.possession.possess": {"category": "spells", "sounds": ["mob/evocation_illager/prepare_attack1", "mob/evocation_illager/prepare_attack2"]}, + "spell.possession.end": {"category": "spells", "sounds": ["mob/guardian/elder_idle1", "mob/guardian/elder_idle2", "mob/guardian/elder_idle3", "mob/guardian/elder_idle4"]}, + "spell.ray_of_purification.start": {"category": "spells", "sounds": ["ebwizardry:aura_start"]}, + "spell.ray_of_purification.loop": {"category": "spells", "sounds": ["ebwizardry:aura_loop"]}, + "spell.ray_of_purification.end": {"category": "spells", "sounds": ["ebwizardry:aura_end"]}, + "spell.remove_curse": {"category": "spells", "sounds": ["ebwizardry:spellbind"]}, + "spell.replenish_hunger": {"category": "spells", "sounds": ["ebwizardry:heal"]}, + "spell.resurrection": {"category": "spells", "sounds": ["ebwizardry:spellbind"]}, + "spell.reversal": {"category": "spells", "sounds": ["mob/wither/hurt1", "mob/wither/hurt2", "mob/wither/hurt3", "mob/wither/hurt4"]}, + "spell.ring_of_fire": {"category": "spells", "sounds": ["mob/ghast/fireball4"]}, + "spell.satiety": {"category": "spells", "sounds": ["ebwizardry:spellbind"]}, + "spell.shadow_ward.start": {"category": "spells", "sounds": ["ebwizardry:dark_aura_start"]}, + "spell.shadow_ward.loop": {"category": "spells", "sounds": ["ebwizardry:dark_aura_loop"]}, + "spell.shadow_ward.end": {"category": "spells", "sounds": ["ebwizardry:dark_aura_end"]}, + "spell.shield.start": {"category": "spells", "sounds": ["ebwizardry:small_aura_start"]}, + "spell.shield.loop": {"category": "spells", "sounds": ["ebwizardry:small_aura_loop"]}, + "spell.shield.end": {"category": "spells", "sounds": ["ebwizardry:small_aura_end"]}, + "spell.shulker_bullet": {"category": "spells", "sounds": ["entity/shulker/shoot1", "entity/shulker/shoot2", "entity/shulker/shoot3", "entity/shulker/shoot4"]}, + "spell.shockwave": {"category": "spells", "sounds": ["ebwizardry:shockwave"]}, + "spell.silverfish_swarm": {"category": "spells", "sounds": ["random/fizz"]}, + "spell.sixth_sense": {"category": "spells", "sounds": ["mob/wither/shoot"]}, + "spell.slime": {"category": "spells", "sounds": ["ebwizardry:ice"]}, + "spell.slime.squelch": {"category": "spells", "sounds": ["mob/slime/attack1", "mob/slime/attack2"], "pitch": 0.5}, + "spell.slow_time": {"category": "spells", "sounds": ["portal/travel"]}, + "spell.smoke_bomb": {"category": "spells", "sounds": ["random/bow"]}, + "spell.snare": {"category": "spells", "sounds": ["dig/grass1", "dig/grass2", "dig/grass3", "dig/grass4"]}, + "spell.snowball": {"category": "spells", "sounds": ["random/bow"]}, + "spell.spark_bomb": {"category": "spells", "sounds": ["random/bow"]}, + "spell.spectral_pathway": {"category": "spells", "sounds": ["ebwizardry:conjure_large"]}, + "spell.speed_time.start": {"category": "spells", "sounds": ["ebwizardry:aura_start"]}, + "spell.speed_time.loop": {"category": "spells", "sounds": ["ebwizardry:aura_loop"]}, + "spell.speed_time.end": {"category": "spells", "sounds": ["ebwizardry:aura_end"]}, + "spell.spider_swarm": {"category": "spells", "sounds": ["random/fizz"]}, + "spell.static_aura": {"category": "spells", "sounds": ["ebwizardry:buff"]}, + "spell.static_aura.retaliate": {"category": "spells", "sounds": ["ebwizardry:arc1", "ebwizardry:arc2", "ebwizardry:arc3"]}, + "spell.summon_blaze": {"category": "spells", "sounds": ["mob/wither/idle1", "mob/wither/idle2", "mob/wither/idle3", "mob/wither/idle4"]}, + "spell.summon_ice_giant": {"category": "spells", "sounds": ["mob/evocation_illager/prepare_summon"]}, + "spell.summon_ice_wraith": {"category": "spells", "sounds": ["mob/wither/idle1", "mob/wither/idle2", "mob/wither/idle3", "mob/wither/idle4"]}, + "spell.summon_iron_golem": {"category": "spells", "sounds": ["mob/wither/spawn"]}, + "spell.summon_lightning_wraith": {"category": "spells", "sounds": ["mob/wither/idle1", "mob/wither/idle2", "mob/wither/idle3", "mob/wither/idle4"]}, + "spell.summon_phoenix": {"category": "spells", "sounds": ["mob/wither/idle1", "mob/wither/idle2", "mob/wither/idle3", "mob/wither/idle4"]}, + "spell.summon_shadow_wraith": {"category": "spells", "sounds": ["mob/wither/idle1", "mob/wither/idle2", "mob/wither/idle3", "mob/wither/idle4"]}, + "spell.summon_skeleton": {"category": "spells", "sounds": ["ebwizardry:summon1", "ebwizardry:summon2"]}, + "spell.summon_skeleton_legion": {"category": "spells", "sounds": ["mob/evocation_illager/prepare_summon"]}, + "spell.summon_snow_golem": {"category": "spells", "sounds": ["ebwizardry:ice"]}, + "spell.summon_spirit_horse": {"category": "spells", "sounds": ["ebwizardry:conjure_large"]}, + "spell.summon_spirit_wolf": {"category": "spells", "sounds": ["ebwizardry:conjure_large"]}, + "spell.summon_storm_elemental": {"category": "spells", "sounds": ["mob/wither/idle1", "mob/wither/idle2", "mob/wither/idle3", "mob/wither/idle4"]}, + "spell.summon_wither_skeleton": {"category": "spells", "sounds": ["ebwizardry:summon1", "ebwizardry:summon2"]}, + "spell.summon_zombie": {"category": "spells", "sounds": ["ebwizardry:summon1", "ebwizardry:summon2"]}, + "spell.telekinesis": {"category": "spells", "sounds": ["ebwizardry:conjure"]}, + "spell.thunderbolt": {"category": "spells", "sounds": ["mob/evocation_illager/cast1", "mob/evocation_illager/cast2"]}, + "spell.thunderstorm": {"category": "spells", "sounds": ["ebwizardry:arc1", "ebwizardry:arc2", "ebwizardry:arc3"]}, + "spell.tornado": {"category": "spells", "sounds": ["ebwizardry:ice"]}, + "spell.transience": {"category": "spells", "sounds": ["ebwizardry:buff"]}, + "spell.transportation": {"category": "spells", "sounds": ["portal/trigger"]}, + "spell.transportation.travel": {"category": "spells", "sounds": ["portal/travel"]}, + "spell.vanishing_box": {"category": "spells", "sounds": ["block/enderchest/open"]}, + "spell.vex_swarm": {"category": "spells", "sounds": ["mob/evocation_illager/prepare_summon"]}, + "spell.wall_of_frost.start": {"category": "spells", "sounds": ["ebwizardry:frostray"]}, + "spell.wall_of_frost.loop": {"category": "spells", "sounds": ["ebwizardry:frostray"]}, + "spell.wall_of_frost.end": {"category": "spells", "sounds": ["ebwizardry:frostray"]}, + "spell.ward": {"category": "spells", "sounds": ["ebwizardry:buff"]}, + "spell.water_breathing": {"category": "spells", "sounds": ["ebwizardry:buff"]}, + "spell.whirlwind": {"category": "spells", "sounds": ["ebwizardry:ice"]}, + "spell.wither": {"category": "spells", "sounds": ["mob/wither/hurt1", "mob/wither/hurt2", "mob/wither/hurt3", "mob/wither/hurt4"]}, + "spell.wither_skull": {"category": "spells", "sounds": ["mob/wither/shoot"]}, + + "forfeit.burn_self": {"category": "spells", "sounds": ["fire/ignite"]}, + "forfeit.fireball": {"category": "spells", "sounds": ["mob/ghast/fireball4"]}, + "forfeit.firebomb": {"category": "spells", "sounds": ["mob/ghast/fireball4"]}, + "forfeit.explode": {"category": "spells", "sounds": ["random/explode1", "random/explode2", "random/explode3", "random/explode4"]}, + "forfeit.blazes": {"category": "spells", "sounds": ["mob/wither/idle1", "mob/wither/idle2", "mob/wither/idle3", "mob/wither/idle4"]}, + "forfeit.burn_surroundings": {"category": "spells", "sounds": ["mob/evocation_illager/prepare_attack1", "mob/evocation_illager/prepare_attack2"]}, + "forfeit.meteors": {"category": "spells", "sounds": ["mob/illusion_illager/prepare_blind"]}, + "forfeit.freeze_self": {"category": "spells", "sounds": ["ebwizardry:freeze"]}, + "forfeit.freeze_self_2": {"category": "spells", "sounds": ["ebwizardry:freeze"]}, + "forfeit.ice_spikes": {"category": "spells", "sounds": []}, + "forfeit.blizzard": {"category": "spells", "sounds": ["ebwizardry:ice"]}, + "forfeit.ice_wraiths": {"category": "spells", "sounds": ["mob/wither/idle1", "mob/wither/idle2", "mob/wither/idle3", "mob/wither/idle4"]}, + "forfeit.hailstorm": {"category": "spells", "sounds": ["mob/illusion_illager/prepare_blind"]}, + "forfeit.ice_giant": {"category": "spells", "sounds": ["mob/evocation_illager/prepare_summon"]}, + "forfeit.thunder": {"category": "spells", "sounds": ["fireworks/largeblast1"]}, + "forfeit.storm": {"category": "spells", "sounds": ["ambient/weather/thunder1", "ambient/weather/thunder2", "ambient/weather/thunder3"]}, + "forfeit.lightning_sigils": {"category": "spells", "sounds": ["ebwizardry:conjure"]}, + "forfeit.lightning": {"category": "spells", "sounds": []}, + "forfeit.paralyse_self": {"category": "spells", "sounds": ["ebwizardry:shockwave"]}, + "forfeit.lightning_wraiths": {"category": "spells", "sounds": ["mob/wither/idle1", "mob/wither/idle2", "mob/wither/idle3", "mob/wither/idle4"]}, + "forfeit.storm_elementals": {"category": "spells", "sounds": ["mob/wither/idle1", "mob/wither/idle2", "mob/wither/idle3", "mob/wither/idle4"]}, + "forfeit.nausea": {"category": "spells", "sounds": ["ebwizardry:effect1", "ebwizardry:effect2"]}, + "forfeit.zombie_horde": {"category": "spells", "sounds": ["mob/evocation_illager/prepare_summon"]}, + "forfeit.wither_self": {"category": "spells", "sounds": ["mob/wither/hurt1", "mob/wither/hurt2", "mob/wither/hurt3", "mob/wither/hurt4"]}, + "forfeit.cripple_self": {"category": "spells", "sounds": ["mob/wither/death"]}, + "forfeit.shadow_wraiths": {"category": "spells", "sounds": ["mob/wither/idle1", "mob/wither/idle2", "mob/wither/idle3", "mob/wither/idle4"]}, + "forfeit.snares": {"category": "spells", "sounds": ["dig/grass1", "dig/grass2", "dig/grass3", "dig/grass4"]}, + "forfeit.squid": {"category": "spells", "sounds": ["liquid/swim1", "liquid/swim2", "liquid/swim3", "liquid/swim4"], "volume": 2}, + "forfeit.uproot_plants": {"category": "spells", "sounds": []}, + "forfeit.poison_self": {"category": "spells", "sounds": ["ebwizardry:ice"]}, + "forfeit.flood": {"category": "spells", "sounds": ["item/bucket/empty1", "item/bucket/empty2", "item/bucket/empty3"]}, + "forfeit.bury_self": {"category": "spells", "sounds": ["ebwizardry:rumble"]}, + "forfeit.spill_inventory": {"category": "spells", "sounds": ["ebwizardry:effect1", "ebwizardry:effect2"]}, + "forfeit.teleport_self": {"category": "spells", "sounds": ["mob/endermen/portal", "mob/endermen/portal2"]}, + "forfeit.levitate_self": {"category": "spells", "sounds": ["ebwizardry:effect1", "ebwizardry:effect2"]}, + "forfeit.vex_horde": {"category": "spells", "sounds": ["mob/evocation_illager/prepare_summon"]}, + "forfeit.black_hole": {"category": "spells", "sounds": ["mob/evocation_illager/prepare_attack1", "mob/evocation_illager/prepare_attack2"]}, + "forfeit.arrow_rain": {"category": "spells", "sounds": ["mob/illusion_illager/prepare_blind"]}, + "forfeit.damage_self": {"category": "spells", "sounds": ["damage/hit1", "damage/hit2", "damage/hit3"]}, + "forfeit.spill_armour": {"category": "spells", "sounds": ["ebwizardry:effect1", "ebwizardry:effect2"]}, + "forfeit.hunger": {"category": "spells", "sounds": ["mob/guardian/curse"]}, + "forfeit.blind_self": {"category": "spells", "sounds": ["mob/guardian/curse"]}, + "forfeit.weaken_self": {"category": "spells", "sounds": ["mob/guardian/curse"]}, + "forfeit.jam_self": {"category": "spells", "sounds": ["ebwizardry:effect1", "ebwizardry:effect2"]}, + "forfeit.curse_self": {"category": "spells", "sounds": ["mob/guardian/curse"]} } \ No newline at end of file diff --git a/src/main/resources/assets/ebwizardry/sounds/aura_end.ogg b/src/main/resources/assets/ebwizardry/sounds/aura_end.ogg new file mode 100644 index 0000000000000000000000000000000000000000..89170073a3d36083545f4ad16811a5342b6b750b GIT binary patch literal 51608 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∈6Bs*8B|w$x@u$k3AK4Z*89ugHJO9HGu7yqV3A~(WY5z+SYEI7hZnk z{Q4XJ?!IuhZg-no`t$DnPmks6%3mZ2TIJTPI(f8xudA%tmL$EuX~O?rEPp4(^{kE6 zZnmY*x%n@RPa5ZRWmfHKoGj=XSDRYY@MdmkdEoxt&(=;(vtriEsjaDLxL5uyX!^4W z%+5{Sy!jK4b2k3`bTjFDD&PGzt4^OZx$gIu^|4lP%H>MuNmJLg{NBxPfAsfL`FC<( zw7&~1t8R;%$-8pL%f`>l`k~Iv=byd3b;a?!CFg$gx4CcMrV6DMuAdVhi^i-nBJ=Q8i}I6u(ewL$*&Qy1I-E3QQB$ zNY~!eyO+A=@h{VfpHvc9l8@cH&L5~EpjF{_#$!)~^B#7F8=no+UT3e3T;X+c%4r6M zJ9cM-6Q{4Y_!1}1a6rE3x7q60b=S9grtGk}m3IH;>DlrBZg+32314>FT}=Pa$Db$j z_iJ=F{1jTXT5jI#xy}VUPVTN}EcB3ZTK)5!f};Ailiyw}G*_Q|>)M8|YDay%eCrtf zx8GcP@a4P{Ec+T6+6pIW%3j)7FKc!%?bpd$X=M{X?)OvO#ck%fa20#oyBsBtXE!6a z&+)Qa|8HjIth-M(s~F~d{WSZWT-srt1>y{bnj0^~9Ns=z{<^GmLQKWJ@LdmmpT1nQ z@XM7YRpnuKoYm?-Ir@Gt2ocR*_2k=jg9NuX>$N|pfA4WJvbpdhA!g#ru5Wg_#TjC= z?5@V%Z##1?+E#z^<43b1-&}pZ>xH&;aVhWXYq38fORrp;J6l@WZ)MKZfYh%ZR@pKh zwMzvub5HNv|L*&(4Gl*fSZ^lmWnySxVL#RPr%cE$E$8>IgTg*evTX**^S{Tst>|=F zpzLm%xr%iIqh7w-*|hNbahs9sYcV{vspW5exA5gIL_`x{=d9Q z39BMR>@@$Z{Pq37jMX=GKWw*~khLj&MRr8s+o$vP{ZXCPR?yyCe<(A_BQ3uu?(p5O z$_qZutLjU-$?mxT~UY?!Hc_l5cOlH}vm{skMR#k0~da-Bo8S!^f%d;+9 zZ=Ut$iIOz)6;oH0St>8*<@mD+Td%j?TySFM9p<;Il024OcTGYYd_OZysd$b(iEeczyPKJn)D;~EpM_q$1NH4E7^#V447 zfg$0+q!9m~oBJ!Yw!D6rYZGbpo;}RzXbBYl8*d_hoI;ef;tE3g=r^`{ovP zs_J{yJkb{N^6`0+UM*i$WK;FvRv)6-_pIim-#bspAC**6%fgK+1u`I!ll;OAzid$PUp?vMy4g%>Nq&ykvmE~H7d|n$ zdDE(yMUz#Yr@f8`k0r3qxrrD{;A3E5uw0n^k~#N(!}WXC+nKJ)KRKi${c_i?%~rzq zCLegW*YfPbldBW{uH@DVJZEca%J5cou7jHMtR{9ohIr${y;ZNjwYNTrU3>q1Sl+e6 z;vzP`Wcb@!zySke7Ot1It+r51Ar!$}R&UyW+y_UMuN9_6Kodx;w_HkyrBP$-C zoBCdmIVEL-{r`P=du^v)K6C#6^Z17kAAT;W{P*zRmWX>kN8hXsI(N1He}3M+_&Uoo zH}7jts}2{7cxO5P{r~jdcjw>#fBa&f*Jb9*kAG;K4gK>weqDOZ-2eaT=TEGzn!oVV zzd3g&Pc62)fBt5!q)zi<3!|>)0Ja66-WYE^`|0=^!)mz`rxq0{g8fo7#e51X-dj8#%x05GqJt<=2e&*`AXFGQ>+1c6I$&^@{ADG&H|NsAZ o#vPieQ@-B2JL@*n-@s`Ha#YP0OT3-b!`Pt~wJTfQfnhNN0E#=C-T(jq literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/ebwizardry/sounds/aura_loop.ogg b/src/main/resources/assets/ebwizardry/sounds/aura_loop.ogg new file mode 100644 index 0000000000000000000000000000000000000000..616ed77c19821ed9ec11d24d5e405627b4865e56 GIT binary patch literal 216380 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 literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/ebwizardry/sounds/aura_start.ogg b/src/main/resources/assets/ebwizardry/sounds/aura_start.ogg new file mode 100644 index 0000000000000000000000000000000000000000..1736c3bb0b4868f59eaad9ee0325284a7bcb3b7c GIT binary patch literal 18824 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 z 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 literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/ebwizardry/sounds/aura.ogg b/src/main/resources/assets/ebwizardry/sounds/conjure.ogg similarity index 100% rename from src/main/resources/assets/ebwizardry/sounds/aura.ogg rename to src/main/resources/assets/ebwizardry/sounds/conjure.ogg diff --git a/src/main/resources/assets/ebwizardry/sounds/largeaura.ogg b/src/main/resources/assets/ebwizardry/sounds/conjure_large.ogg similarity index 100% rename from src/main/resources/assets/ebwizardry/sounds/largeaura.ogg rename to src/main/resources/assets/ebwizardry/sounds/conjure_large.ogg diff --git a/src/main/resources/assets/ebwizardry/sounds/dark_aura_end.ogg b/src/main/resources/assets/ebwizardry/sounds/dark_aura_end.ogg new file mode 100644 index 0000000000000000000000000000000000000000..3e3093c18261d2ad9ae9c91a41e19f40df2c99d6 GIT binary patch literal 63140 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 ZSlI5)#}8r+&vt3VGM;mtc5vcERsaX*K(+t? literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/ebwizardry/sounds/dark_aura_start.ogg b/src/main/resources/assets/ebwizardry/sounds/dark_aura_start.ogg new file mode 100644 index 0000000000000000000000000000000000000000..04fd8be5f0cbc971a49d7e4ff9e38c502cca7b69 GIT binary patch literal 30358 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%0Du6cEK1;<3(Z-Hb_*k5-`? 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 Q?$MdVoBNFR|4$b`7cW!Ye`i_Gruo*J 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

    7msS5s-n8cW zZRL-}F>&|bABs)gq4RH!-nsAhU){PL_@vtX-|Le{r%jXfe*5hH36AHlTOTI=uK6*s z@Z)Q4hB;2c%ni&@tGAj8+-ci$(>lN6b4A7do^`7)Xr8F9ORN99eRgDUt?lRFqM47F zKUsaW$X#~*?E4pw4eN#FeV-(Jj-Pn@zJGLWmQSwUlZyQK*6oky3(cSZZ}l&`pFWH= zPM!=6TxDfe5-U`?vf~@>>@yGi+@89`9+iu_gS+}#N-tgNzeY5@f_216SoS$fS zd->xx2hZK-ZdFa5!JOk1+;S+GRqJ2c#`5+n4s9>@{9JZ)xAEqQm#_3Pq(q!vdzojt zP4E0C@8AEK{V`km(&aMk_5Rm)cU%26k&f*Dyqj%(en)vsZuoiJRxO zt*-p${Q0lW-?T`a|NF|_f|_S1cltJA+_iKiXG`V&#&@6m_5G{NMDP6lP@4aI?(xrOzdU^R=Yq_7`_suTcR$|v z6P7#y zKQ6`j-`>l4y%T(?fB)07_w&AgP&EAc+x+&;PqWv)zJB4BJl{XjqhT}U7^YZ7GjQ-_ zY`k`qVdX5ZKSw^tFR%Z8Nov;}83_-A@A1J^-xuC{@#*a5(@7tt{{FA< zkIK)Vp3S@$*KxGOe(rnzT{S2F%(k5v{;ht-8Fm|M|Bl#bu5t>lC}_ph=Ui zbRO-V>&L4Ru;V%RgtC?041Rak79300mpGEGy}S0YyXVh0Q})Nn*wxROU;qAZWqsYx zy3JqB=jcV9Jo@{!=uG8bj}JdNcmMC-Icv=K|MzPC{_t)5k>maS&x`+jHtgKR(qk2V zbPJPJ#azF~4kto(d}4i}R2sNp|Kx=JDCuMOB4@AI5%blf#t`Tj?1{&v5;B3|)N<^2Bpx`kg}|Ge;iWwB5_Lk^d+ z;es`0c_Ma`r!sPj=%4%l>)HOgMVY&FUZt_f&i#1w{_@i&r2T$9RQ&lZ};VnHXv^s@VZA9ekGdi1{Q$My5iTYlMe ze)^RDQ`bK~Y&;Ur^Z(ndxb*+I#X9fy?@+t^=j`c5<$7bi|G%H!jh}n}x%)jAzJFhp zd4DQ*Z(Yb*;sTeQSkTjI1dd%~A;GqKE$gNq;TR&-7cedo=)F`%r|~2?^pZ!arXSO$@k>`*&W$aQ)74id-?y*HQPNu zrrDLO4ZiU8ar@g%x%u~{|LH8N`qXsCdP07?!?`~lRw;T*O}QLu4rpvLY6xZez*Mr< z<;1a`+xM3oe(^4sVcV~TUp4tX(kil}zpvPDu>WY<`z<~{|2{1&o4IdoT-_Vt_4;d{ z%iF%cFT8*IpPINCwfh$RiaWjc>AmWG{}?aqKeNg3@AQi6N4$>cg?s8MSUoV7l)TvV z=)f1I63e#=(GmNZ7gz3PN4M-)oXq$H;!&uHAk3eE$5hv(B^bi=ThCefi;I z;Wqd6JDViVPtUo(Z_iD!iXC<9|K%T_%^9DQ&bq8$T9ifezR#ZDc?>;9xhxE^0^^y`}@=^hJR&h;5mhaQ+cUFIATAk3-wBPjm{$HQU9E;}P`G4%;fzRn> z|6V+Q|9kV{--oRqP4^2vb9MWV>u*v{pMSlV<^NHo3hz(sj!ZF13mFfUsKz?Jykw=I zbD)XcL1&$Yf=v#)-@45UXL{cD&srBgvG|1WOQpFiFXF0|5-KD*zi^mF!~uYYsi z+t=PLE?hTrkMaJcd%gy3yu0g%N{!M^R*SF=OWIbRUDZ$+t+_UbzajUW#=;t@2a{HR zz4g_dFLm+WPj}n@zOJ4()4y`n&z~_i`+szQe0a}3opDzGeSgPNf5n&8yHm>e-{vbm zT*=PvV-(2Vvpy`qeEKyeO=dG2hHaM4FLv)wY_%<)COu2tywEFK@Ak(3&;N*A_pY0_ z_kH!Rx-Xk&y5v7^_di!Y>F(t6=|9_F@IO1@_-Iw@1W$=2cGXNyEemG&r%gD}%C!%i zWP`ud`5QdtA29tpD@xmq_JZ zyWP9r{Ft-*S>pR7KKqXg^52PjY? zzh;xo3NCutkGVIj%i(*sj@f5R_|9M3Lrk8^AAS1e;n~^k^X32jtl59;bNI2-MgR9j z%{$(I^7Zw9Rlj#lpDq6H-JdzipWiiS@1Otw_y4^5I?K%4-zBd6+VnTu?BARpTNxPE zxJffJFlMbTW?XQPY2y#3C+l>y4n?zQYLE%>dEb^6^XWcwkzeyuQ0px$cO)WzW@6(_kH@Y{oDBFO8#m5%wJ>w;C|dTt-O|c z9Y$#h#uhE+4@}IW;y!wSdfBJqVTK`>f5AyJn#AY_&aY8zdiis zQA_*xlr!i0qRyH}Ww*>)UZJia)AIW5O#Qo`UkJRuA^P;xw+nmT%)hnr>B|-G3i5xw zORD;}Y3;6p&CXJ%HnnC}|Ib}M_3h2HAIo>AUwQZR>_wY6^Y(p)adBjon!o80I`b z*ucWTpwH8gXkimDeXczNgNeXdYwk0lZ{{C)#Pa8p`o)-KU;gXs&Uq2DOp2kwjMd4Q zVM%8f3j>40F4hEz&$Y~Zs<#U=e2MlKWITon^4V=W6XBowfngS zy|qs|i+6>d+5Eo9f9JiO%ih2Je!KL@-|XxE0<)godwyHIdalh~>HC|bpZ?LAzVWUU zv+mXgwj8NSwdFxGKeR=yE}6)naKMgX(OL;6`DZT^-nEPF+gID~_5aLM&Tn6zZNGU- zdVkgF<8>BO?|)tSCuVc_v*VF*zpX_=`u)x9L(C$?Y`)Hl_F^oN5@w1y;n(Y%U1DZs zAw8$Fnz87tE5r6wru&~?-#T@byZHN&k6-UbZ@+!}+m{c27PX!BKYmlbZpW>S|84fv zuiyCp{qw)C>*mQH-Rx4Rr4n_%NNt|;&wq{2_h5}pO*h^{QvOD#ixqr+ID#TV6V5>w{!KnU&nvFoUi}k9^-=D z@;Cl5x0uc5FcN4upJL>2!sk!Qh03Hy^}pt>^ZxeX#T{?fRf+o##;*EY>cMn!(&jmO zvu0f|mp^MyoYoEg2}kF6bK2J2aJW&o`SA28 z`;%8s+kdtA`YF5AsxGHK^zx5q7XQD*ozD1Qb??W9+OmpWJ%769?EU?Fefmzd&v)JT zS56K~__13&PQ-FwL8T~<>z+MA+kPo*!46n_4&5K7QK!pOL%b{GZ>n{j%Xs{N4HY z=PI-d?VB%u`uXN5TQ+Fls*b$AKf6B8p!l)T1EGBkkhKmBvk@Z|paHuamFhieDH(Zb z=~*d>nW@>i>DhT9!ReV)q=6^^cD~|Murk@*<0)@sD0d%#)vW z{k*^Y(^pePJ_r5#W3jLH@9wq#L~cJ^cK+w@I?Gim`!>kd$=3ai`lNjS`^p;=I->uS zem=51hrx%dmuaE-REsJ8D$^Afvt;Nyyqlvks~}u>%IDiFAD`Y>u})6Q^536byZ`*y zTV>huKj!n(i?iEL*Uas^-v6bhs-oiahMB8hvtPer<9Vw8;qsTWxj!m@y7sj_{Zre8 zpmohRpSAmNJPWaaNnPqv9V=ig`Cb9VjKxsy^3?Axa^zjI?y z{ruC<#eP;y*<<)+-?Kl|r>;`<;1git;=|y*D^5ile)_e$eM#T>e*NcfoBzJ=*Gzl;Ny-c<--NiPgesgco7mPkA$Zx%&$mvBzm8pg zdZnkzhRgduiOzf4ZoaE#Z}j8b^6&H8n^*t-^K!e*96PgbO*?;|P5bC@wCvxGrvdX% zo&TyUeDP2H-hzEqZhD7Hz9(eWSG;y=m}=$niNlbC)AGu(J}vFVo*Y^l`VQi;-l8ww zb6%@2JurLowApVLUf(VK-zv}Y&&^D~?O#7!YkOQ)_}TaOU)i_9duxt|oqPIuO5K~v zMt=Vsq5<~tvMmb@?f^y^3A#QG_(AMLEK-7B~JU&WmxUq6`L zn^(Dc=JTi5x4D*9-%~mJr~dEn4S&0q5gJQep}*8cxqKR*7ReeR95#t*lB^nCmI!|A0juRnhD^V9QOo!9 z*Y1eCWBj3U&oT4c?8&=o-t<>Jw|=}`Uhn_=Oyj+0k3T=R*Z=LA>;EG}dvE3(v@d=9 zp}M*Le-~pzQ-eK&$u|jhG06j(#c2+zqHb?lUpUQ~dST~v$B)fNPsc4@vB{xq^ZlH@ zlYch+e)zU3Hazb1;lmrgR-ZgC{U>IAyPb^Q{pq!J@hgSvjdfNh6;}NJSy;K}0K5JE zr3c>^i`FRBPAJls-|!;;m&O5R<{Tkiwx$!Z8p;x-X=eh9QWq@w##j^=vGASq^n&;0 zyZ4&!j26Cly`StOveQ!_4zkgRZr`oRO&xsrH{U0y> zyQj3>?{QW9yzf6WpUdxG|GW6Z>zN*Qa%M^IDjjZmGL(oZvxFUGa+@q@YItVq?!aos zBah|;3cR=85Geli&hBp)V-{`C*VA|#AL)Nj>F>;`;!-pJEPWR}@BH>}#?`N%-P#)) z-^DAh_vvRr{?v{BN*%lhJ(*&JRFgL=9%3>K6)R+M_ntIGxVB-+Y(t+9HV(Clm+I`k z96Gt~+&;NiHEE|`@|X8J{(tuW^~LY3J6<2EnYV6c-wc~lqx2oGV~(p9{P+{vV8X2$ z@WF;jarw1I2OX_eFNUz?%;#l^%qYs@dZ`|0S(->^Be{`|bXuiIx?-udl*`u4vb$=Zv5PMr7{em;CU zcUS#kPA3H)F5avILEJ~hxHL1`jkv_+7o1<)dCKd>op+3n->=A@e&h6P{^E?clWXqI z{q}U1t^BmdWZ{D|$h%>lb zvD5za_1H5UWgp(3`19h;XUz!*I6kq>QL<)cV3_WHxO0Vr)2aOoD_^9!&3K-7p!IFj z>HOCn;g=5Q*X^t|t}W+H-gSLO?EKBI;}6E)zjgog!o;WL@%Gg-QYU?^|Nre|R_U)7 z(SjlW{$)qo9gM8`e`3+2OBK_z-^cOAGS>*DAK>%#SCC4Z>HfMwA#Bl=NPUOvt9)4A zpP%_5eZ|TDYZsopc(nccJLQZ2J_f7S{kvUOyZQ5)XYY>p&JTI-+;{x*)A#Of^>6P@ zfBH8^P229@-qsD>*I&1uk8%qC;J#AcZg2EYlMm7iC3@Cuei@={_f(B8E@uiKi=fAmTC{P>z;%dk&AUSIDg1{KRKGuQL+jIpc9 zczgc4%<(rXZtUOv@HKl-iDlpU^Uov8ud?kHhhx2O%YcG zH{_Z%vxfx5{_33aj@84}J@wM=(_50nKe|o%;n;U-_1~|v&w6fN|M=+Z{6{8#|Nfct z$M)p+y|3hJem|_Ux;y{ZpEtjLma6=}a%^|}h97HVQhrzNtl3i+5oc#9Rc|0KowNUA z`*o@B%R4J<#j99i%v4z-XR*!DYM#WHY8>%_>4~4nglItN)>Jd3JI|?HvB={@iUxKfld9zq2Uf{vN-1 z^`9!kzw%DLKmVTn%+qVb#l)_Ebf0y7zI42kbR6qX4Tg#D*}7&)x5x!w35}fG^X~Bk z;RiiD9j)RE);^7C`JVo|V6SA{jc4+f{VBix=>FWX$HxBN*X#dvZWl?fwy!^bzvkuV z>whQl{ja`f^nBg^2bZnqi`@SA-r>IC;nVRy?IpI_(0xBGf$rT#kn`Rv1ab}Fae ze&(;W^{t!v=Ww>) zUw-|6?~MPohWUrP*^DxlG%zMHF@G_eZfLdOZUfI=d4>c1=kL$^UupB|_xb0N{C4;H zU*Gy0qG9tev*+Tr+}h-pi z{OkI?>-)Lt-v3Mc=Vt3U|Ifde;_v^T%(S{1{8YQ!?5;{JSNY4Jr-_H}sr4j zzjGdlg#YI~ePzw&vmdf=FmIDRz;Naa&(Wzr-<@AyWA|mrnIy#@rmw5c{(P?sr<1=f8lEED2S^tOXNa z=$>HVzaz%Xz#zh3SZnOdKlzZ&|EKyI4P~qA{$9>*6l3~z^G^-~14E1)v$1)z&Vdr9 zsh0u|MTAu_p7ILhic4+~eQTStEa_~=o*(AMKQ^cTD4zBFbIRW*y7tvSO1f$-88V;XIPk(yc&oZFyA8usEmqeDRpPQ+^sDxDFM4dc zvHE2A_a}Om^^4ZXP$cYt0(_O&g`#C`}+F-OSg=c8$GEjjTn8T8kwhZ zt5{xQoa=r1j)z~vH-;t8g!B&b$2Ww({QRG{XU?~xKPB%{l^#j2+iNcWH|baO*Dp_& zm-~Ix-4veof8na<<*EE13^O0GHqWSyeIOYkwbSL4N|WRBONjyT`IBmL*Zck7xx4DmMgF5X6Th#2|0SI-cK5TI6CdU4W~`5Isz3i{`NJKm zCI_Y z}ULY+L=kcR$R}oteEmXNGn?!<_W*xuF!dVVvsqR}OzkYf9 z@8A6Le@-x8y!QTXwe`EB51;49`JX<0_pCv@zP#EqY4tzP+9&^gUn^cxxAu-sK%F@= zL;QZmCvQz|IS9lm2sx`YdNt{^rtA@4a5~VkW!>Yv^%bjMwT0UT&J2F}ZGQ4olMhwj zFT_lLdfoZ#<-Nz+eiOjh8)o<4-_IjZ z|KMG?J=23vR~Z`iGqi~5F5-IXY@+#-zg&c|`|PRisp1Q=9~Ehp?7n8jEn;Um!H}x)psRrNDK4XC9ZHbY!_!~ z`GVJr?pBH1-?r-4g|oHt@9gF4#izTTF_-^TU3+*}^QJrde=7d(>z}7z9~Tz?>i zAN_cLegE|5l|Sd^*QQUc*gLb|FYMia{lhYspH8;N?Hi17)i?hB>SX`$dfjuu z-{LxaOYhBKWW6ERxn#oC#UZ@d40>%47#%J-r_ zne}>)f4;ZhH}jA4dGG%=|Nh?j{`~y(dDG)3?zfY*JF+tB^ZUOCxBdQbyS*sgen#)x zQoqZt_dmW@+xh(A>)FTt8Lk!&x3zNlq{H1PL=wz^!K*EzFpBSUAm(2cBTcpGH_hl?@3vch2`?CGR_kZWtw;ligtm^gS%OCgW-L%>L%U}NYzhwF4 zoGqD^pC-@wS7R9}KXXR1TKe^Tp;ys!r&qkxvD@}z!rP~p@83`LDJwD-{{8Uv^H-lO zuU{&xZZ)%PUpewE96-1~Og|H1vett}Zh-dl$*e-#}nqi{0& z{pZV}`Ns3NmnS^@#&val z-*V2EyjEYH7Wc~JC(DoQPw921uK61NDUUtrclLk%ujQ`;dVc@uI9rqU{^diNtb27` zY0uddUVobN+2nuu|M$>~6-`^P_|uQ~f40~C zvs~lAy!ZQU=C|cJ|8~p&sq>fP4gcQAd`ds0>=MJwgeaf?ZthI)ze^6eva2MSq4p&Vnzmm zH_=8eubLQm3>NG+v0__dspfZ!IU!n#=?-7Q_T6Xse%|_acvZOm`54Xp`~S_oK4<5T z*w4;-rBkl&s-DZ9b^VO~^JV`&8>d&;1$@{NEPams!HfUN3_fDAO5V=gmqcbCRAF*% zQR$FZc&%y57H`R@w67@PqvzJBr&r(HJpRA$&3kuwHT^*OG~R9Jf9(DG`Pq{@6)rZ^h-T+{xfVy7h?Gv z=FjNz&w{~g>5^c%Muw?^IqMxlKkhlX`{aI|-h!-F#>|5CH~&2Pv2bqXKb;@@_p9DM zuDq@2$NW>-_R^d4qn=$ZGpv8Sf5GHs&q7$*?HdI4^G5tk+G)%n^GQK5Ty3qQz$VU~ zh-=p`@JPGyJE&`&G`LlMxr^KG59?{$m9w5-y}SR1X)LGh-@Lw+>htA)<^D@~to8qa z&%xWJuYP4EG5`Dat(En4wi)BUl8q&Sj3S>DnC5iw^i1_wd}U^;%gn`l7<`uoIUd~E zIn{D)$<5V!{m-vo@YQs)!C8L3+xf*Rb(O!b7fvz#%y#Aa|1-;de@jnY^Gj2pH1EiM z;U@MEjc;U5F@O1)!Q2x+@k<7emZ$G@9Tgjf)Z#wQeB%ShF3o>&+51?&^PZ4zfueUm zR+n}JS3j!{p4|WHm3q4FvdQ)Pz7{;Xo6{%h8YAd*IK{tDp7B)g7M8l-Of0Wlm=$z+ zxXPz6nP;=O{9t`?z@_Zk_&%!o}ZEWyZVNlg@kDQ~#empMUdP`9YO3RhAjk z!hbNhaB(s{^jXaGvD==nK`XNH=O3Tn+xeg0eX*<1RPp`4O}C=Hw|n06+5K3$Xe=ehRrb^8tOeg9MW(ae1R{+hq`f4&;%{P>@L zM`qVv**~ujyyn|fznn3I33R{M)MFluR}1Xy9K6$`Gv2O!ulzi$@bx1Xe6U-|E2f92m5_Hpt5&K9cG|9O$eS@-u-_UkXQ z^(*fM%-^57FkY*|{jcbe`qyt3vxj^WVqjoscVy!ca*(TFEV>u5pjdptp2o!TeOs63 zZQ);=^ZT3pk@K@(e=DE;Bci_i|Ff!^J>TkX?wR`~^8cgbiuvsE>UDC{(m#EE?^0Ly z{oCc5Umw)|c$a-;-`^G=?|3rv-JOaPaw_lCE?T@>IZe{yj-+q*#oJP`|GqGlcu(HZ z8aIh=_3mH3FSZ-5|D9It5&!$!d3nC&{jYxMTK?6nT|BW~x$aNJ+M9JAdhrjh_jg~P z9RDrxoW1oCd%4u#8BOJ) zD;;icT5?l-!Rw&gPUW#|b2fhInOmAJDPA8L_wxF*_|1FfFX#UpX#Uk|Lfzl98$Y)H ztopyZUtWIMrx%Z&pV6m(r=DNu|MTxbtyx{|w}+p9 zFJW{MTFk+9iJ3WC>EeQvu#=2;gx}w(8&3vHx{b{#ja_pS;$(eZlL`o;B2kuFrm^egE%2*M5uR zzccrpc%56XZ*l0K+=a*^i=Hm;WqQNd`J$6eYD0{WHJbn*r@TUL>?@%v`OVC^FU{kA zE3aRuZ~y(z*PF-pf2pb8ZxLHRch3Cx`uV@MN}Yb~obvHw?TOQ;lJ{5FzO8)acHheK z?;35t^&by2KZ_AvyNTz$*gl=hPfG3K9^>mvv08S<8MOPG>hY=Umxgy{`uwMh0R~5zd3(@{`uRFpK2BU(tPxM-}_&`zR28u z-kttu;lC;Iw{7L?;u4DLul!zR@VCV6B>NM)e6hN7tWtm5^u-vz9d{RC(0Mi|fq_Bk z(6d4XrYA~@>*N<~72AAa&wYgliQW17KMvi}`?J34&zIYuyOp%R*7*ONsek+X)5p$> zer`DX`0MsVpWo-U)>Q1BnfFue+poSycT?8XR9I*U$e*=^K#m~$P z43j#HC7etRSOf$t*TgYcFzk_MIPhlC)bAhP?T^;4tKw^a_Nl2UIZ?XOI!#+BQkpl{ zV68~5z?)suCrnK5k$wHjV)}N&_-k*D|DJt6lk?}AsuwP+f8D=+x!&7mNBv&2-+z;u zw=7-%_uI_wxQ}7`O>2JdF}Jxh-7oz2?}PFAFE78eD1W(p-oJ={a@%s3?N)x?dgrMf zo9rIL^CIh3o-O$I)A-N4weM5X84@^mt=zfn+rNMbyQ|vPSe?|rZZiMpCHu{*%kl#6 zPJU{aAJRU5`jT?{|7;JMcYikUWv>5k|1kqkX43^%U*|8wa>_p!i+j|0h2~e6;B6wQL-TwQG7A8~*q@F|;hu{mjV0V8f;QkVEUCV6Ki8&zc@a8-~6G zQ-taka$oq-^I8AlO1&cMU!BLVhW#mikpAlY)0*>h-W2!$NqcwZWY4;Hhf~+h{4?kD zL+_g&OE(9{Gi0;#>u_0Sy|@~nDp1o|GNX)9#lM2VrFf~qD}L=eDa$_2llm2D9C>-Z z<Hg_?lmA`%{Cm&yJMH(*c78km>;J>n{nB&K*8aHpdG5{g zFKZh+0#}z_Wm{a^r^mqO!o3&+{7EkW3DY6GxCn(7+w_DkB`(FCCNg_feKc84U zym$YOao+U*_48M&tKGRS_T_!vw)LNjWy{_@eByg%cUe~LN!@K(^mVeLx=4thJ|4F|h-tMU9+V*>D zzhvLlJzrl|-wM849%tO-#s0xJzvF>9D|9g8Bw{dvlYxODU^jcdT3U8$=Ks(B{{8`h zsd>dEIe8fwX*pRbc?DSkURgOsIR!b{S^2pkY~n7?8J3NIb>uhd9^ zR+D))=fl~M=*X`HAMg9^`}63_v#%emzJ7i$r+@QW&9B%q;TNyRoL~O^yKZVsT-U!> z>vvT2e}8}d%zE=EZ$B+3Kbd~{%l}KW|Gmv`DPhw2XSDXGf_Ue38=;L!EfdSrlDb}V zD|FpdW0a4}SrHRs>Et)>`sEo@^WQDc|M&Uq{NGQXKb^>bJbgO-xG}ajz5DeeXS=JP@}JA!_5XbM`19rY zYL=*ZAx!KnO&&sr zo)lMhSVaoO9%*{VdZ8ozdQ3;bZ<_;pOZL5LJt)sx|MjK0)blOf|9-v`xxDuD=|ata zKaMx;jQbw;*xKe}l-+L=)t`Pgdv@5@Z+xEOuP?vhX?*qO{r~T$U$g)4Jx%oN6h8h* z8ZwM*91IoH_ugdeVBl%62i>msHLU;B5sBBg%ogR&;9DHkyNXNepQPyWj%{bN!qW$c&gZ2bDU&|b&>+4|%ib??0_e$KPm`}Xh7@2BlQ z9pXOGHkto-rDeX{K_$JT3pr)2W0;6L?~e%avyZ<|zIlJr_IL4j=jT6KYksBwn)}k~@8jKb z{~R=q|6g>szW!_Sxi4S-guG|0v7N2_?ESyh`@X%~)_j}s+)2v`JcR}So_gprXeyr% zO8Dejpm5zanPEZozc7g(@3-Io$I0A~ayh0Z_g~JN#oQ~dvBvc_3N`7gH8S0?TH^Im z>vzh}CeC@YcyHWVFVb4lGK2TS=feto8v5d$Po&E>23>DpwPKZvv7z=*-#W0dpDuOjv-USRr5#h&L)H6on;%iKOe8&{B3#F`?CKV zY-Oay-+cYP(s=p%yifCw{Nw%W`17Rw@A?f5Pi~qdx2$-y#8gJ-TN8@_7iafgtxZ9a zFWkMqFcxI3Q(#1m&dOvtC$eFU^P#!lqRterxmTrKlF0qE@O$PL^|Ax^ivHcV zj;)cOc>h|>{})x;>)7N!|9-r0nT+JVNEP+}(d!(a*ZeixJa1~B`}OzCztjJoDrVe} zIoYP!u*UM4o6JLg4xMka*p@K3bY!bo32OLPd%Whpusq{xVfK#yMveOA%bTaZTEQ=u z{v$stZjIiZwfS<>et(<%>h+^XpNdZZ`&OA$diwnKe_w6Rgq7F*dVT(RokiW8`M%dr zv#&ejBlYFQvk%?(|2#U)o-bSf>CP7R{gOU>%ugaG9$d@Z_eXMp($8rPpP5P~wq-2* znfa;V+;?NS&?`~AJNM7LKc{TH{Bq}?te<^-YybQx-2La@pAt6v^ZD}Ae-|X&`uFEi z=JU(vHvgPsb2LUe``_OB-%nNdZ2iL~5F?)diF-c3!F&0+^XuldelOk1z`|tcurev# z@%r=6iYdi!bS57ZUl6tJlvDZ41N)%OlEy(ja2dd(M^>i?p}M_;GbowBsQ|M%PVf62EK`*e1+?Wz2j{99nM z{LejmKe*MNZ_nRvw>G~1$g}6${~qVG`M1lVBV|s&g&)QeJ_ZUL@(W(Obh}p6ui0=; z>7ugVoHg$Mt^eG;?^nP2^5e&(%L) zR{ZyoGx_iNN~`SY`Q1}~bmo2Ga!7jT|9``dyAHMU^g~^AT-cadC-C|SsI~GkFeKPH zWM`(jR_uL!AoJI``5Bu7qEDXQEB=4p>)pS0A6@u-`SqeZdS7qvpYYR4cSXPZ(jDpb zwfl~>-8(10XZrom??3lH`?*2BlG}_|ypFRVC8EeUBKQyqPTq}kdyIUCDP zoEA`!jF|I(|F!V+?rFP2p0rHbzCLD7(Y~9$(?82smA{^T^zieKQAggKx4-fK-?^#T z*W!--QQTFvtFrdzh424vUrw^BtN!xXG;-hb5XqCD*;d7CiQn5BJ~R1egWt?uj5eRN z6hs*m{M}U?rm##=+|QtUB;-lU9^MO&Z*SatQ~gWN>(^WCKRm<^8Ygrw!z%?VOh{emgD7Ps;S=c8_?8+`XrNFvlp~s}pFOcI{h@BO_}D ztH?hC_6=H!adPF%FRpD`=VP;v;qEM`>T!o$a5^ufNVL zuCFn8bZYbax~KmX-^`Bxe|x*-nWQ?8?bFTw{@E_!CqMCOajm@GlmAU;>+9zIuU|Z= zPF=G(e*tGjPYQ#JTr+cI#PS&)u@4Fym_D**>?|%k^m>kTT~Nh=gz19IckcU8xX1?@B5xiw{LHshr1Wa|NHvzr`4q+r?2J>Jhwk{{^{|{-_Jk&d(Xc9?H&~- z?TH&04kTS<6$r5KXtZ~jzFfx1{5;F`brxr&O|P!<{`Twl2cM1ij8_lzG^KktMY>R0CH?yD(xo9wr_-uZLH{nLS}_WHh`e{L-N zS-#)Fm|5nR&?z^?E0NDnB(N!%@ISC&&?{EdsCp+WyDu(x(ZB1_Z9D&DKG*kqJ>UH7 z`uX*9&lbe|6H0ya%Rv3y_n5PFyPvN*eDHiQ#FAo;f!hjf9f3kmW{XOUY_lx`L=ESTE=0Dud{`t$=mua>e z-wJYZADH_-fB%bLOMWce#by80#^s$AmkOi9jfE4l9fZVr;u_X1bzIbvH&6V7^U6+_ zDrTY2W}j>Kgr1N8Y`Cv3V$O_Z`G2hJzw6$wKRo-a$nm#N!;km#%TJ$t{O5`JbAH~O z{r|%LAA3K3zTfxo|0n;nWtU%P)Y`ir&_9@TP+~5(%fC(SUvk{1J@B-jez=vvkx%)? z@2B?vzwf@XH6xMx@4eG&9Nz!GSGTrLetqxLUZ3Spe%}AL>F=+b`~Us?y|cdd^HZV! zasQ6J=jPc~Y-|7HYuSwWsrUc9Z{4tE|8w=K?|Tm1eEIKTa_z;R>(8GrIM{!$cL#&c zFByiW0|q>k59&3zsAyC$?(%!H>caB~beOP_ItexLJ=WP1@>}{Rb zZH{~v=eK{c_kW~sd`#QZ_j<;2>rU)n8@WFHOXa;Y(x0xI|J(fU$-iaGlS7~E|GQJ5 z^6gu{ZS~*Wmz%4%Z2!pLYq{wh^QlR@*#3MB$hje^EL344*31&*sC1&9aaYPwrBD~O zFB8rueE3#+q&HQjNdcoePM^mqLf7$qc+U@7x%log_{CL^TKP&jBMto9m-2c*=KXo_LKY!e@ z`R;~4ZszC3IYRIMDtz{)=y%QY&i<3%N{s$DJ@5UyrcFip=O5L;zj6xGnRWOUpKB1B z=UDMaP~YH=W5+wz7n^d0>m=OU=gpQa`WP$vJN($;i7(S1KCGxRu6;k^YgHT zMm8TYU6!kQy%rz0NK9ei@H=!Bl=waQ7Wx;bx1QfV=h^H7p}Mbbd_7y!xnJk;rpmp0 zqrdK+y|ex8@z-W5^_x3VAGg-Z)l2@ldG`Bf_saKHu|CbGX8%!&KN`6p_oa3N%m4fF zb;87apDH$j_EDHP6S;?p+tgQ1zb?pbC-*J>kr(ox3npL`RM<%`>TH_ z`aj*m8h4PL;lujvyniBoJN`~TxBh-JD;s1O;=m)sFa#F^1B26($ZD0az>Jh+f8U^x zkieX@z^v??qP)<6%n8 zsX&V>js=lc%m)4Z)eL7|x-5Fw(kLihA6B%TgZtnY#*mkDl)pT#)=&8NJa7HYtc>&P z_o~LfdvSVy|Du0SzyCOYGx|~a^>?qLUf!%{Tlif2LI3N0F@hX=7pu7%nEHgdbl$CD zisWVvIUrP-G41xnC5dN#W_;TI{#V>A4Yvt>ZNDFVN|*D$|MF2q@sG$4x9h)g+kfBl zXP*50=UjhM&wu!EU3GuNnHYQjr_*=dH@Tep?|Kp6{?_`F=^vQBK9+X*u{2iJPJJI+ z!c2CPcMNRPYSlG*tz1(SRwoqv`>}riZ_bT+rCKd(ZtXw(I{$lVX8FYD|L^&I{kJDa zU*7fJ&i|<%{Wb3&Z?(&LcKvo{-RA=)x_y}Z6U;@ForKX(7ATtC0|>$}gE`BL-m#xJi@*k9!TvHM7>{e(J34>L#C zN8%EbC7wJD$Y9WOka4WFI??DYdEjID)ceQ0yAMw?I`m+b@Zno?+-sM-x%dBd`Q-nf zHZQ(Af00}NxqIK=>7TQ#tkPTepa0AHlW$iaoH&Vv(ZpBa2Q$wzi?+-sz}q zIB=OcVA~XlwT0aKR?aZp^xW^}Pu1*yJC9!5&sXz?eSf9jMQEoDdlJey;G|IcS<)#sak=C{oJ zYcKh<-2Tsuxi`+QJ^S1<>x%S+`Nz)l*F?9No$^*c1g>{3edee3?B(hE`s?T2e{S!7DqdJNWd48FIoUsJ zi|(w|JIAf?;j#WYafS=JcQ_dum_m*=&b#W-w?+Or zdUJZr|NV*n+W+*|uTL)?R>bnT`{n=n@z>=0!pQv{f9~n)q~DwW>7(ak_1>qNdq0Zn zZH%`6o*``!-yogG39J0Hf)o;eQ>YKoCh68 z@8-XoRuS=V&zhPU+ub$iSKjLT9*}=__T9s_;q}F}ovL;DzrP)vx#Hb*;~Ia}xlNCz z-*a22f4-jK(yzP*WesDQe=@u+9->*R0wXjH1UT+JViZ{G@%RP@qk%ua#@o!w4ZpcI zPRSI$lX&;hd;isG#rh|A?n|>iAO7%gsnpTSSO4z*_Dp5}`DgMnbG}zG{8+Y7`p;jb z)OLe&3HyXK=a_6_W;*wmsl+mO?;a2K=LcCBKHa~!ah~?opC7t}S3Ozyu3Y}(v7WQ? ze)n@8Rpso@vy(ctdC#$@hcchtJTp6SXH4CVxQ^fZxQpWdKRj)}`S%anp@YsbqXojGSaKdarn{qWx(o7%tc z>V6yAzpMTm*4=$Kb#nX*_5P{yr}y2>cl`Hy`o6j)eZQ>2zn;H;`_})+zJ?!L>lJmG zKK#l1dNc9CXI=*LnGy^(--H5Vq;|CiRQ?H7Xbo&xx^W+aZg-wy$#&+P*Gm>3{B&FG zxk=H#)C)&V|L(YH*LC^)?sM1A|9|&r!prri_SO8kXYakNZTG(OdvyMlnSPo5!}g2* z6t;x@`Ri@A?CR%csHuN#rqAH=r)r;G4ztQHtqU7wwEBE8yunxyCTd;OAfIq|j;};~ z*oJpU;%jwRJS%-2(PjVq{`vLy+nv|`TYSGZwEoQ%bNOleZ05cCSM=xgqb-{yKYgv) zdFSWP=MR7U`T5xY+xK4+Ctmq{`tkYa_Vp1rUX{Jt{_OB`Q-@&lbLW2g9n(%7~=&gItg9&TaVU6G)=wDaf)qvP?EdNybaHj;vKLDKKX%uCYX0)x z*Z<$YDUU@yE6$Jon|VI%fAx2@yn~h>W*@e%U-{s#GE2k0x(8pR0vJq$lv&)=Z#>rh zrNpJzfBoSU`2}lKLO702XR-hPp^M)q^k&Zd@6Y#7oH+ls+V9t!eEB|Z{v98D_xJVX zv)|g7em)xThhOdcduBz+hbF0y%@_(~UKyQIVo6BK{9?+~@?XPJ^ZD!lpJvzWn0nUA z&`7*$HSgh@`S-5ej@tkCL(|pm->;sR$-n;j{gcf$$CmGyXJ-G=K)(O_pFeZXaQ%M! z(nQ~0y3EeydDWK82ge^c>5H_~?$H!rcv8wx5y>E<)_cHcl_o>4b$6-a+Q5*mA50~t z=^os@)@En;Cp?|`+J-Z1eg6%exZ|^b{V4pHc<Tzg4UMtM=`k^1Qg_ z&E*XpPme!d`TwuEp#FL8!#C&e{{HzlYm1%U{|~vJ-k-idMgC;{|FWkn5ey9X+Uji2 z-~Jq9_T(dvfl>fZ%F+qX1u~;%EfsL*`^H@2+jFd?D!=$}`SkfwVc!?A+?`VQeZS2Q zqrFq-{p&w+^7GvGmp>+-3w|-%d(xj-^7FI)*ROtgDO z`5(AHxXUr>0cSYZi+z2JRu*d-7=0Kr{ICFZ2H>6vrNwTXur$~(6QraG~8qHsm%RMV`k)TlQt8V@awbpZvVV%e(k#3 z^|wANF4dNsWA}5()HmN22&Ttc#4GpJpV<1SS?`^>`2EQ8`ETR*=V@iDeSYbCZ|?8v z>Eg@HbAA};r%ihsJtxxk?D>EB$1`sC3;ir#KVS2+WZbvwe|Pv7pVypmGe3Ru`wual z3p3YkWn20D&CR!KVv3(G%l^L3$euU&`JHgJ(hn)$9`es|U4CQsY~JHNbuoQ24;-^Q zv-A7Bwt2I97yrvo+qPJ%=-2K4aEx?L%fHVlJ}W$bZu!;cd*ZA9G=BlSoJ{yzQh?<%W8S}>{l`uD-InF)VV33Mby>gWbA-M?Rm?ZC-kg_eL@2d3yrXfZgjKe*Y) z5L9!_r=f=HfSRSpHFj=hhP*XR^W&K={Q1Kuz#z-AkAWdf-Nc4<2Ezx{TW+8kzB&em zf?wUNbr@pHlgMvg4A}|LxMh_ht6xI^#dHQ;hS)x?g7|d98OY zKi+wI%fZLGJKxxR_Kov1U0!BvKVSV*|2^Y5&*m5V{riR%i7HaxhzQSJWr7nP^?p83oE#rV9O-JZbn!I%EneVKpf&W5el zE7z`hf7{kRc=F!2GdF$|{&d3rtL^-6F>_PPO8+O%Uwd=WxwVa#PabA#SoOO9+qtY) z>DT$^znXQ=_^d-eS(Yv=U;Usis=X{p|-O;wxy z72B@0>zf$=Sik!9f9Dt#2kVRRoeRR>R9)2)sQbGxO(l<8UNL&NqWST^ulWlkS~CAK zHnS(@{zxj3HkhQlo;z>fGWOI}`Jw_`8Bc8l1gzK?_z%c2{1lzQ6x(xf&jB`N#{PrH z8~E!B8ARSqdcb*FLc&R?R+NFEfj^)tkjqs$pFd{*nc1ghcAW~lvOm2{bGz;Is1NIx z&6uCcKlQhNT=nnw{n=&r?YDokvs?YXX-_-LgC(w>|5_Qp{9V8r%p}FuC?<7+;Q;f6 zoxwa_6*ttwfAlMVxO4qh-mgD@|J}U*_+oJE^6lN7U%ncx|9S3@O?vmU!xi;+cKOY# zFDslhW8p#jIa7JsgYIQ;_cgHS^1L$ImUxzFf#D2^32I%B@891S`8RXM%P`ASC-1V# z&4JUW_v?LGKl}cvwbyUH*kS$e_FVIrr2jQ@e=q;@?`F)lsef+nT=`LF_62pfT8mF# zKeK)~>bC9v#+eoF>lsx3p4UtNzwI3N0S&Vlrt~SR0#C>i;(tQWs-QM>ugYg_yM_46;< zmClc>d&z%tb^OMIHunE_{p;qQC;Vxf|EKTVHFhuVJbi7no%au;Y!b_Z2W-D4oj)<} zOib4!))QwJ89jV{o+WrG_urH8D^C4>KHIMA?t8uY`oJF9T%SwsbF-NT2$LC2uosZ@VU#XtZM0rBf;=y=VOV_wB`zhfm)WpNm_2 z<5sk6*5db#^7r>$%l|sN)$CNRd**TH`+KKHzcb30sS2GQx5f8W!~OTZmw)IqA2-*D zPyf1I^0k0lg|NmY&Syb`;@!vqd+V8h!|NIp2etqfnSvMag9xk7xcKPnzt9PsC zzxWw!dUZ$n{;l(iZ%l~%echh-`xzDY*l$;+pL+X7=*{lw@BiGK6Z>A}%Tr~GJo(?# z{xfi~1@q?Dy=*Ez<-7m$C+qWEbMME0y?kblR9)eMUwQK*J<5tS8mcy(e7OAAmz-}o zRr40jo||73Qf-~sAkAa^<^KdzhM8CQ{CuCY>^1wUw#~C`8TMLAGrZVQZv5H)%Vg`~ z|8iA_?@6EgnHiVx|IPoO;(N}{-N?mtHu9agS;_O1@X23N&c$WzpL};egNgO>dG-0$ z&foY{tS_f97JTD>^GoD%z~24^KKw_ExB1(;F)(#B^wgbm`QKn~X4M|g!Jx1?;^Cuz ztQ(mUm>C%2ncnj;HT+2IZf1C}{opc2mTMCXR_K}^Tr*Q_R(qowCxeIqg9F3wt=_CJ z9`G_ST#MsnfUdA$_>UOc;AUW8Pz<~KUpXu!BqT5~JL~`bpzxr`@a)|G$NpbP&CJfu z4)x2(%FRp9$@}t=VPe5ug`@Jzs=r+H0h*Wb0OJ@Q`STcq3P^%Ks;)K9ume?INZ_g^3H zJ!jrm{r-`t+V9uiTrE!Os{`(VO zeU{QJz5nIz%>&mYbyN=I*7m5a>%VN%E@Qv?@mSFY zu9rIw{j~otRKNG_lXX1CY)b-n$y)35UsAi6zq9{&VeaYv509U`obUGHkNop_{|^1! zZTnJlZwP<;qr=aqb8KDq#K}_M{@#4$pP$~VEY+wN{qa?wky+-G4wp<ck{`b|={{H{@Uz~pwUXL#y43NewYfp}x8=I{ z#&*pPQROVTd*l7RweOa1m}|VRX1C_I+-0BH&*fFr@9|x?|Hk+B`)5DrmL<-;{O)aS zWA(J(RxaN&%RPU;dzZKChRo&1{{52<|5)k&uVb~o#lbiE^67jNcPjog-RR5y`)}Rq zU1d3b|NfXqE`IWG=gxA`|Nq|U%b140bAI-<^?q&s`Iq_|E46;6ocsED_0Ku+U*GeF zntCm-UXg1d-u*b_@|(LK|2W&nEI0mXY#(B@``mwqoPRl!p4r~NTs-5|=k$47)sxMB zPV?V(`pbpq_wzsQ&T{^5+LKmU{N(Yk;&WI2x4nx!uy?<7m4k8k)0=zG|MLqE|8+&L z?EiVY|8g(vFK7FUUyfkd`ty0l)YPLt-@Zy&`RZh1qjR)h{Di4f-^>lMcHii8ZI0!C z<2U!t+FAacXY<)7OxdiS-ylY0&;0Kz58o7VxOTYlzhB@N10EIe(xadL&76Pn-PetW z;#nCI&b3?jKKy=0qlt&{+oOhmhh(G}{+UR4O}0HR|K~V!{A~AlMg{{Tj^3S?zu9>v zF6CacpQq~;PgmEZdw-AZpBMW_{&fPw0r7@8964u}url%-Fi+K-!;ru)qw`IMAtK_y zL;d7BA@Ro+dUg&|Bo}8qd)xB(PvM)c6M<`OU)5HWK7aW9iA>y|AM@-?{_Z(*`=7Bn z_uu(iWp#Eh?y%38yMKY&#xMD-No+zl4zS;Q^4GvPz*8t~n%kmO8*kx)j|?q4xio$m zJ#Xvgm$>)f-{D!i&BNcHpJRM~a(;2e&d1lkZG0QsKO_IzmwW!jg0oNg-;Glgu6z8? zO=KS1hWNOaw^x_WX86mm!zaruz@)IkphNWRNke9V{|pu(23_y+gn!(=zvpl2sq-QK zn|_D)?wjv?cKxmy#`cx*&+Yx^pWS12Ui4z@>=)I)6>l8=|NjQV8Amd}3XHnDvjafa{qHnF@c_{ufz)EBas2?I{x&bv+))Gdy{#vSD)Pl(j9( z81Md6U=X@iwDOh3zxMm*>NnprPc7C^Z7I!{KX&x%x%Qi1KmXZT_btq^KKg(4eEZnw zz2Sew3@X2Ie~&BQ_*q;b7hPP42w3$WrE38dw16%)5YuW=(;WWqBKOCpWZ|61p@cS6U$%p(hzhunsOfz7usJp|< zwIfAm?myNSb3)a*Z2R9t$QE5ZP`&NRzM#qa|HZy5AKS9&=k@;;Ud12(XyyND-Y1*) z*lDfY1M(=w+?FjGU^*_tMZmfOztMPc?g>UC9i!|S-%uT$n{b_AN!Tl%p zyOj(d>Hk`PY;o$Ivjwdur$<))IC}Bj-Y<#E?ntKdwl}@2xcgmt&#mf*!PB$r}aD9{W-gz zt#r}1duP^vusgS-%I1E^oxdv=Zn61M5Fh;WubHv*?R>SmI=0^_<@R>FZLRXv-~T+5 z@%&4`kNauT%>TA-{=Hjr(&s1J`Rt#cHLfoj!{6`u8>}3iztcbgL_GgKF+20AF zD&_SFlaKD-kuE;d!S3K*S?ifB4{|->(fDyjR{9OJO07 zOAFZF{Qm8wjZ3`M+?$_YZsz^{<;%qf&(Gb``FcKRu4k29@wfMPZ{{jJ&42&@#<%m5 zqSqzcS`@RtKPkPOw`%1Y%TmKxtDLyX#U7tF{$eM8$@ao;fyZp;ey4oY58dQn*M3*^ zaQm4inY?B8XKQ8_-`%_4ck=HuH_zS)`D{6Vb7Q5JHsgvv<*9T3ZeBP^=Ntd?3+d-9 zLaNWo*S>xl*zw<(^X^uMb0WXfo!@R=czuoVZreTb6ONkS4!AOZ=X%TN!<#DW=1%0E zz*x`4@FdKHfhA7w!|GM8{Xe_R7$jQl83h)|GZ=8K$P(1JAE70}bD-3s0((z)p6gQ7q zUznauvs(J%>pQVO-#_bqw=0wjT+T25?8E)J_qA%K2kw0C`l4cQiShFF{zlf*=f|Ia zdis1t@a1D3&(D1peU<<2=ijID(!z@me~V62S@`GR;(uZLR9UaQl`vs2XfU1IF6iKS zF-(Ndl8GPp5`p=8!%iGQQy5F#N-}B?&;?KuhvecY=BQhs+=|+}!QmG3j zXia2#aNb?Rz|{0ai}(W5z-gTKZcng1VlVYCYlY9Y^XvFezBK2rueqo`lfPErTfM%$ zU7Yu?Dm%M{gkk^g_E9qcrE*R>zqH8 zI=j}%^WE3KRCDg@-``(OIJdvP{pGNUZSb!zKjpRMo;+r~=QDfzdSN&1CG)2*)d@KJ z=;yBZ2_N=uj+0z_;?SG799cGPU)#KIWd?|6K4>#ou!mviX4#e*z zeR;h7pC{|j&!4|{@0V{Mw^V*xvHa(g=(=5VQl3@V*wp%5{o}rWzvb+>eLt6^t-&z5o2G{Gc8$F4N9p^KTcE*Rn>BOAM`hC0Tp_OnB7sld<5&q^9TJ zwQnrH613jS;Vxh8A+H~+JCTYg@Z7N~!CZ%+QF-F91NzglHGBRb%Y z^zZcUW9p0!d<-&Nt5ebqyA^La#j&;=W)k?q)M0j1qUNjK3j@W3!^7k=wrl%FEx?pH7`0|9flXyMJF6E`R)YpJS}qfI_5J^jB^4)mp7{4#`LRzWG{_4BSeto_x|NqnX)2I8-9~S$1 zZ~xwp)!%;}zO>)y{QLLsAI|*u`{Muq_FrpW*Qp0r?R!73UhZDa|7rbVc9VLnmFB(a zD)ir{!ld#`Xj;+3jf@XJl})?E;nA=`e8K8BSDfU}y?n6fyldS5l6~8E-z}PWe~;(1 z%O4DFXI*ZN|MPY8mwz|cPoI6~$-l3EADG`ieERco`=rWi-{seBlw9;Vvv0!17x$*y z)iDGbikLI}QTSGVdHt7v54JJdyi;SiW9U zzeVic@O=NZP?6j5LBGvQ}|QE*Qz(mwH{0FzWd4kzP|YLzsEP$?yabsl86j@;dHX1^3zFKQ`~*|CK9$O>zBMd6CixhCg46Cdx7}<`nO8$W~Ek z_{#cX*Onl^9o`MGI~QD(I=pSw`|~f;DsBJ%JbY)h-{qJ4?2qXC)xVqnKJMO^sh79x zt@&KFdu89xuV32wKUV+OJomxa{^|Sm(s_*+%s(GtO*p)MJNG|Rjd~Uh&K+TlCjZnJ znp`eqckWxrm@d7eWiP|p(#XO~XZ@MW{+yUPZ=pKRX8Av@?OeMryRR>?uC4hew(-x8 zz<<@Uie5tYuj`N7eX+AI*mLCl*Nb=Sil>w;`n~La?atj(w(ISBaIazh^GDxTC@-wA zlZdv`|MF>;J7gJ#gCrxUj%6^BWMJT7U|=|M>*o%IqTIayhrEOQ0@5?{Qv5yr(^AvY zg9B6ZbMpQl`G4a7`8$lN=3WQ2*j2bz$8j*a98HO9m=-px?LyW1=EHRYQt6H*p*j23 z<_nPsX_V$0$vrn@{ z?f+L}AG7U+@wVm@iH(KoRGGZ_m4bZ&&WD{P*UMue}x9yZo&WKX00U((1r`Q+Eb=rOo;3(wFwT-}oPEU+$&* zf?-oyvK9ja&tuA*Bv}GubN?n+1~e!hyFh1w*RnBqvdUTfyc7-r|-{v|NqbP|4Nb#m!E83dusm6 z`e4h*m+O+=aP=MMzp4;&=ECJC<#o>)mY=KM=JD|M#*yIwGI%rq{EtGB_a5 zSpR#%?$=t}Y)uT&Cco3gC6dpz|5?irz_5UM)*;Zon1qIZ+i%|IpYT6>dO@tkZ3c$; z(+mlJj2Reewr}L|(d}{YUSJaMsG8Ma!r)N{T5(cD;oqun~L_l+`U=6{M?N>T3okg&Qkw#{>nG|dw0{%@BgtZ zE6e`=(&w|@?EW@y&V%{Cuk^2Y7ySRs^~TSF@dtR?g&3ZE-ND3RTG2dfyR*dsr-l!V zZzjofeJgK#8&-CxF4^Z@TD|S}eI7aLHYw-6mp`3n^*?^*mpL|be_I|cOZb%U;x~6z zeV)(XuihEb;tc=n_V76{s(b?7u~Te)qJfF^C-ai9Wg=(4Titjpbh&;)Q|LYOIHP^~ zMsLr=*yl*Ue)8w%=KrRp|BBzaV=j8oAcKP$Hs@>!6ojduv{ok26^Y5I! z|9is3+CRVE|L>R2Ry$BXHT!AUHSNpcsSjALeAM~Qus}iV+bosdhckE-`fUGy{qX+3 zt(b0mM3=!%ztf@Xmp^6x`s|&*xx3!w^wYV^emz#^`ug+r+sbE~{bKIVx$^t>=9%%& zj^BTA-qL37yN5bbg>Bc5*T+v|W-ze-|NDK40S`+O1Is&~#*no|2RVE9_cC45XgqQE z|L@7~@6Vt8@`%Sw&X=>ZuRdF9AII1KwEWxB`2C^$pFdh%oo!zCe&0WR`|p3R+uG0h zwd?ou)9sgkf7|o){q)P4zkYpOd?~4(C!SGLMC-%?$vKz z&ghU@Qr(A9LdNI-6%;fo0zdxJnPxe>( z?6+t6@>VL>#o(k<4qJIIli%bgB5LvrI;V=soY59IbY*fpSC)QeXa9Ul{a4o?F0HAl z`&vD7{q*^tKmD|~mkeHRKjV0J{QIT#zR&F5{wt09midf#PKEN~tNE4N|JZDtd-&Vq zFNxkUtbg8$sLoB;^q{-ky0bwgg^B51@$!E~^9?ORg^~lV#rY=N|LHqF&*skr`#&dt zmG1R?XMVYc^TGA+#`jyQ_^)nVKl7*TxAQq0KF?hk{JL-XrY|pfxKxB06w9spm^`~v zTaup^eq744O|`XY<-Ocx>v!(bs^9(m)}NnwCX4s{{5b#S-p_ydrFF*`~Hg<`t7c;31V9$6AIQ?XH70atVJ-<9BQ=2xYXanlgX8 znf>{l^WQ}Ldl`N5UFiJBZB{P-b;|P2zPC|Nl(*xpN!|Q>?VYN25s`0A%uQ?)E}70h z&(zTHko!Vsq9N;db-o_yo!Ki6Ygga;{rK+s{_8()nlJxZwa0#%-H|);>Xq-_^Ut@P z9~<^8(O5Ta?e22-ns2weW0L;QD&FU=KU;r4V*~q-vejQV{CU7|XrIC+MwxGOSRyU` zPR7LhOBwL89jj)Hl5$;i;O*P2qu%~@J`X%E-*y*^3|3%uFye4X)W z2Sd_f-#4W^G7R5XUxf9t6bY2y&3byWY3cI|c4x)DbXL4R|9P|TryK7=y6YvMd`+&k z%)g`m`|0)bmu@Hi-uX8Bx4HPIrRquF+dnH`ej=|S_;K5Rw-nI}hbCV354t-$u6q>& z&nK%ujcXc;Z{Afg1_rRYp7_C3@-iplgJr39-HYot=f!8tT70=SHqO4FI{)6T{?xkp z^Zf4HcK`hO@{61L$A{ln|9@Wn=;uZE|M#LaAAFZ9%9<+iw@!<_PQ9+4?@@%n=XAUO zw#AGLPu|L0>oL+xR}Vf>e8h=?@fQ0EO}_S~pU&EAieFe28Ft^6`~S~- z-&@^x{#?CaYFXY#*YkG8Mb&xxo;x#bo3HkQZQpL$hJQ*QH*+wsd}5k@r6@Twa`tIM zz7`)x7I_7oAPu(d<;ks?k*5E1=L;TA`rlW$BAI=pFU%n(ise8>qsxD$Eq9hK`B<~e zX*0tCz4gXh%wJjuZ~ql|a{GSUlCN)PKV2Tu|L?ldBAo%8mGd;gCLsRtVWb}#*J zb3(11{b>@r=`XV@tJ==-E;#aAxlD86OJ0Wi{0s|jJ=fk>vAy=+QGe}OH-Ap-eJmJl zoxRp{(M2s+L&e2wg#>)$FU8)myM1fVn|-<8uIuLgJO1pf^y>0|c0Yf=uK#!c-kbm7 zdK%S_Ha`0<{pj-fH&075y`LX1v#>c8x&8j0(q}KvKKklbeXd&a=%(OrH^1e+xBh(L z&%3{`pRdVJi~3`=yxQ;Gnx5Auv&;Pc<}EY%7`DskmYp$s+nrLW3D4!f=Wm;rGVgQx zF$R)^p1~p`Eu)U~cnAdSTNseJd!>Pv~UK#k5F;wImx$WE0vGnJh5{vsW z$4lxOlhb`o+!l*1TdV1NI&F$pbNV}}wHwctz5n~eplW{R?dgA?YMAVq-?IAbLi_mc z-uS3z$%_}gO%D6{ag+Z3#|82KY99ZLE`NJ`XMN0l|1`1PE8@`e3R z9*6%wA#0@6^tSxJ&Be?IR+H~PwEmoZ?%|&4SsnZS$Nwo2pR@A+^Y6RuWxDRpIVJc0 zILD7)&%0}_-Qttgeit#eb)5e9`ThBQC!Xz8)D*A^xjOCk|J&cset&M^Ic2}ioygGV z&)v@#TTNcY^hwYwm|d@GQv7^LuA*=M_HVBLYyY3qAkFs2zd!HtzE;+qJO9)2)$-r& zQ&~fN`L|7eRs6p3);;6uZTEjZ4+y>Y+updi*Zz83T--nF-&gkA_w$zjfBRW={Tj9x zdB@JL`#r}n`*hzgU4~t|cQgE0=(%ccj@{<;^FPGpjS}zQVc4;K2P1Qg&Q_gMBqWu}t3>+7DbU?@M9FV;qR1!F$BAK~?W6z&D#xBMe z+vdqLBpz$~lr7Q5q;q@i)$O67cg4PM-^|dU+L+A3Pksg{xvttY#%80+q|i;3|b?v`rc%|`)!WkuWG$qvli8QUYb1TO?}Ve^~Dy`N=u;SA(T*{F(RppV@vt^^<;| zzC1s@Feux9_xJN3{?$~?n<+Te`Ru<(ci$*A*8V$r-tV>kjrMu%(f^VrygBpl>dMd! z=YMnWxbYzAIae~z-jj9?{+HitwylppATi_D=4*KeHFrJx{Zjqe>tFKM#dqo6irm}C zvg0A|Bo@a6?_8^Hjba|ZSIP~B<_sIk(pUoO5(F0T8#pmA6uqyPW)NuDCnNMgj^R;) zh+Z1QEoKKxiCxJo3XfUW=p0b6IUT!SZ$JNcZhQOF(~cfJzP$6ye#1l8esV8VJTHIp z0J8`5%8Uj}#Bc&H0|SHdl#1n2|1bW({(sZ|ga7aOd;5X*a9j=w%+AcoP5m$TBU-WP zR3h_^-h+1&eFD$0eYiX8*^$fh3uoNt%v$=q)Vy_8a^hL-tn6Gy&vHANK?_PfYZn-zVwUH11*5BXD z?27kIuKeb;&)xUm8I#AK3*VkwR>-Kc@$!LkBkRAPUT>)0_5H9N^Ot|m_S==l&8_#{ zB>!raT%F!5DZj!h=E?Rm{+*w5^ZAeX>EHdOZj=;;SXVr)`T6_z{H^+J#=Ci++BszxU5fH?Mvd=HRCrxgCx4lDfA#8w^Cs#Flc;a)!Ej! zz;CG&;{?MT^+WQ0pQ5)#H8AX}xb4Nj$Z%lEhlvb3{Md|s$aTfex3xQBbgg3J67f9q z^wv)&)pxz~EwaB=6~Fm{)@;sIS}(4B-&dd475{UW@BQS2#Z~pR8CGzV3 zOa4*^>|>pMb!MvBow;nXQt7MR{M%FH1&g<7)Kz|%Kbt>i7u&B-!J8l2TtBnm`J3bQ z^M7s>_EXXOY0D`7H~@-5*!y zC4BpGnCHODThgnh&uKa{dGpVgjZ(if^9`?_{AV}oZqBTkd&?K?+!-hFDgN)1`lTn+ z_wQf+{a*EM`_GRBe$RNbuRXiQs(h34c*Q52|_swCN9W7J6C}B$M0X;B&--14*X^g5}ROkgW*tpop&Dd|EcX4T6EeO zD;6%~`{%G{nt+7!RTGJV77g{LmX4`G1`EVyxjHwCgw!~N2KaIXJT%LW7kZ+~!Vu?S zv!U$~gVvVzBX>O_3Yi^#Gc(-S{_ePV+un2MH?QwbT3le07khhKuFJKKEEY=*CMOZj zgjeqx_I_7ieZo&U@UT?4c>eb7Pf!1{xBK}tAl4=AMdP={=Oq8^dD!nOW%vK5O>7_c z%9o|>`7OVX&v>3W>9=o9Px6Gq8=qY7?0NQP^WQUu#hYHAS(av@VOf7}@qf+os)y5G z^t=3Ic{R&_p56X7=d=GS>%K=HknEHD_dRk``hz#V3s>4+^(lL9yY;hsHLlVbGAbIuIjj=y2*zXS3BIldA5Ajo3CaP2fmaV&k+m# zyk66&B5meZ>*rM!iSFN~ch>VRvfp<9*U#fyCtIrUzPHQSb%br!NpA!3hhQrO)LYu9db<$_xw+v79mD$4{_HbFX0&_@Xk)Hr-xH*J1bmyQeQLms@;rhBWhE zcK^dN3=9VIKmATV%rHY=BH3-(!EmMv-$V`>@QAuMIWN}ANMe}hVH4BRA?uvA<|kig zd*_A6X-q%vJ^B0dea*$+8Rp6BpTD)ba{tEXvXa~_y;&|-r`!#A$z*906V`R`_&v6@ zc7ES^Pp8~JA6&5Ih371zf0xhsKi~Z0<;|M^AOCz_|NG&tiXU&iHXY#C@87)d&UyXv zH~Oa^^3SZ_Ec^RbL&)B5k4*k{i(NG_-u=Af+p5qZD*-9-_GKUR@*UYzti zG57iYjmJMfu{+qNH{)Pz_p>*5if7FG{4>ru-hThG&rd?Wy|i+3)VZg_r{BOUQfjet zq1sNVN3*)7oc!}EFFrkd)~daQ@7JwsE5EV-v&wGy>oN6nZ`Qh2{+PM$34iR(n`cdf zXU7(ay5Yv3Cbjvl>;GHQ zWx3q04(y91m>E8JKP!q7+t(-*5I9XhxOa(zG_!`vpSH~@8~!xAPOrW?y(c6=CF;O0 zubMaW(*EZp`ffSDF284~;E4y*KD_S_GU9SLk)v=azuD0@cXi) z1%7?IHy^*d@2)aWa%j;q^WEp?>OWuh@$ri7&%S+$x@>5>_xHcc28X{F?|N`{_Wt{a z`+r}S&VRS5d7b&}fB*KX^xyA&dL{UIymS6aMZTkNE^C?@{rQxAyZW*6r(}C*PhQbwsk(%X>QtnYyYdF zc}efrS31wL*LTg^_}y&!zccfabL9WU+imOV-}rLX+VgjE?7pR~51;#5?(ey#JNs4J z`Yq(@Yrjmhe?Cia&#d~t!OHi|k3PA_nRD(-efqQOO@2spMtb?mXu>*S59hm%{VDY&Q1Oes3J}jtl=z>^yM0F6RT=iaX|u z%Kl&Y@#9(9=UeW7KOdaCe`SwKoJESm`Ss#;j+{|oq=J^lBs5sdiN!Ky7O<*UaPS7 z`;%rc#ivbHVTg$M_1@{}S|>RNeLW_P4MpEsb5=A=FlQ)vt6-9_;KRo2#eHE3xv7!y z4DF)F9=!L{&YASO-sSFE!?!>A_eP%kvPQ0M)wAbHpF^j-`CtG2_3AGMCwYFCU;h8_ zL;EF5#r3Cl5OVV_fuk2Zjv^@(j_QS_k)u3e-KBoqBeIum1mYw|ADm zd-H3q{h9Tfv*+8$7a6O+xA~nee%avu|JI-H9~WI?TO-Kb$zIHzz;NfQP+&{QrpJe) z&TDMsH09j%f#Jq9p61;>d`#hcKD<9QS-bt; zer;=iE#v!Zp4AF@9jjA*#J^XQ=gQw5OB8u^JiZs&aW}dao%q7~;+d5D{?9BP<{yf( z*+fHL`8TV4eR%k(NY&qpC9lpduH02^fArs{Pv4b3{*1U{C$jPP_xI1$zi*8-&aeM_ zcdES6KPhe3WtDZJdei)$e7^rxkoOrs7vq$VHd8JdKI@+NuIdPbW9%u_tV4SklGNKW zN~SZ1yw8@s%gVi7Q1-{>eUW_o58r?I^XJ#ubvN?%-Cwb1pHGZk+_J}qx6fH-`Tpg0 z>;1b6{OwNt{~v5$ySx9`@$HXu?Tv1|$o^8r(l2IufZO?-{+f>xSquUT_I~7GVDfY_ z(Lb=uYxBi&>zztzH3?Qcos-hWe`JkR|9bEnKdJIk->g*~rpb3e`S zJ30Fi^G=Z(+wae3mtI|XdCPCZZ4CNWGLIi~EA;VCzwZ5z>1X60YhHbsO=3P1n4Q@t z%-Y>{S&EU1;R7?nkHc^O+NcEP>uZ)9y7-xQVA`@ZQ&pbpo##8W z-0*nbrsu|Mt^Z4H{eN@veb3uZGTxu8$keNmzI*8Y!uQ{&|Ie7_z3Zv7eA$t*-S1QP zuK&9=XMTP6ggmj09qkK0cUDHOpDp!mrP|8#W@nz8@Xr7J=k{~=o8LKvZx%jz{e0W? znC|ZIt4YqakH36wegD@%P9bkb%=fy7b8CwCzbwBlzbfHbx}AN^s~V%<&%YF%d%5(N zjM46MCx8Bwuj36>OHW%?UA=2x+Pz~T#~)|Tdv<;H!I|&lEY8ZsoSQJ|jqb#H_Mf+z zqSThLa{PFg9-n^w{S)p2jjny?BpD{GUSMx>iRHtmXufF5ox&5zd z|EzkJ_nUivo$b=1FF#Bs?>-lQ=KZaiyU#uOKWF~Q_uKwU#q~llq}uYQe@m@wZT9>- zeLcr+&&%iXGtHO3th-_LeBUzje3iKE=Pl>gPLsbW@7(?Wm*OLnAOGa;|2ulE_yJRc zE61IeZO1j1TuBJn=FD&+fqBmH`hRzK8!yhh8{~h2N4RtC@n@!|pI`p;xL0nLT#9}b>Z(bu6}wl{r4v(`~P$8t~kX-JzHkKU+MRE`@gKeE^ZC1oB7#@ zfxYhYsoU!rD&${PO3(SaBz)pYH^%L2k8_?_vQ@(A7gLFDyY82{(?vyQ*Nf)<3Qnvu ze*SoGb;akLiqraEqCZR5*VX@8_HKJ!q)q+a_!)<$m zo8NnN|NH^oUDs+~9~AqOzcoHtg<;KnwmBae*d|S2OS=4AS!Tr*=0pGX)cpOp`?id7 z>57o1*RL*DSMpoc+W37uyK>#}{(GOlSNGR>{_Cv&^t1T>{`$7~`45C^?f(1UtN;I1 z?6Y9|_WC*X`~Ll_=l%TBM123ciDw?Z=s!7=VbV8m2L>4ig}jJfmdEA{cjOryc7Ht_ zyD>Wc+x~SKzg|>N{PvA`lNby;|NiUvoq4`=&Gz`mANJR7yVk+xmA~-K z8e{uS#(v99*(I_c)Jy*@-@miw)c(7+H6J$fpD%l}{OR^)`ENffQZ1*>-=aM|GJ|DP={Z1unP zykpKAe}BI88};ARC%06+IQ;4V&UY&%7tFYO#&bb@n^Y)U^Z%IG|KJr8j0~ZOAq_qT z1_rB?A2uo%)3Y+t60>u%{R0C1e3SBWv-5&{ys~m~b22mkANhaQJtaN!^XJlJK2Ja6 zzlGN<|342mPG|VW?DPJe@1@13tfdS5)&Iy_%=`M-&@s}<$`@8ht`Mh%` z`_sOaKVI$rILGeI>pz=Wr1%W>3(qU|_~P~d+-`I0_EjQ}PM4efeA+kR=O=G{`TM^c zn3=vuKG;_=KWX3p$J5hZ9pHG;;Ba+)avwwIqdx-ECOORgsmiGBWcE*8f~QRM%CZE{ z#T#p%ymohDXlj;Z;C=Kwx6*K19K$KrhK;{}8#Nte-)AK1$vEXd;~RO659|gE5e=Ij z|KZ|e*z1lseb^k;5y8riW7EKEH8@Bm=$KhvRe!cVcai1J)Uof%4R>5bp%zc~a zg#5ks97Teg7~Xu8Vp*qn@ZLiigVdl?Hzw5WVbJxBK6RnyyXcmCrC-H!Gp63wv z+v*P=zx=YUYVlv^qM8+)+%oJ(o_28XG#^ph|51c#liK7nn)(jcQ#Y#Ix}S8kid}X= zWznX^-F9*N9{%|HO>zGE?(M0!zLlHDtpED_^w;^O|J~;6>)k)GF;k;1{?pgc)Zn}O zUv=^^T>ob7nf3E`qb~dG`S+h|85lgf$-L%ck3wJ~lef*5pEAk34rdC^2mh=2`1oDb z>6tS`XO%sj`(<6w-(NRRMa#?m3HY__{ps_Ma=*zN%YS;jcGlxLc5zvs&f4#P8Xi~k z``wcn(n(!EKgNIh#J$bt--Ca4LF-v3*rzpI=d%9uQ;f?&DB)h2Aj1WQk9$7;*?-GmwDd)`Ro){R(q@Fx48I`JvnlG-@ja(vFrIcyC3`Cub=FF$o*Hm`oGwz z-@YsI1@E^k5PARoVExIL^JQEz8t&$QFFSAZlso9*_x96j@%R2_?2DTtckj&cm;d4{_g21md%fs?Mc;~g^QnLSS+}qo}t3>L-x0-*yzrQaQw&G@4mCrckCkrEkih=1zuS|vw z2fp_)#G2o3Q7`Z7i>}MITl2E)(&BBOrDJQV!?(?TEb`Jn`j6dj{W)QFdv^S+2%i^U zw){`_jd%O&N%a&B34c8h$n8^^3Cea z59AB^%9$+rI%S29DHq3&SBxSlD;va*ulJj8JI8cxuBIf{uHF9^-qV+_TV#LbfBN5Z zrXT+L&zry2I5Mx#;^KY%$jQ5xzn5Qrel~-|kMoX?Jbq}O+|RJ(trAy{hsTVG#|}?; zu`u-JgOd8o*Xw@9^5y7>y4A;j{Ip45a=(gx_1yWvHCg{6-~BILVf?b%U+lT@v8#4< z;^+7OHLkJC6`1g?pE1U5J_o~^uT6}d8NB&c-M3vE9h}q@dg~Z&Pf;qc-YzN}d$Dl+ z-#zWyf4*PeuYCA^gtb-VEYl(H&2xWkF_r8V#~ErbDZHD(8BKE zv!B}ja$WqK^VP3+ zpH*JdlFy@7$8hJXTADLc^NP8TT{(;b1mYS@taUCrKWo#yx~h;jGivUR`Onjj?_U4> zUrJ1zz8=50?f36C*Kf=#o|qK1=V!qq3)^Dxz5Dmqi%t6d-TC|Xj<;72ePgbDe}C7R zYvI-V`yAP{xmw=3q_t}^`7C+;yJ9t;hZ;-2))(fIlNA;drL?}dHWiec&#SyVA@Q5{ z&v|dJmp#A#`Sael^Xn4}zn<O-+eyOrL`sow*s@>;be)_#QUaur4UjE@? zhQDkNzURBzZ%DMBG%>%M`AczK3Bw%DrN;}pg#NiSeX0p%cJiEbko!XEBJCEtH_WF* zrq43@d3DY`;oztLmVen%Y5VWj%`KKzF?M-n`XAGF&hbAz`Dgs$qHFAj|2>}ds$%Mw z=I39w)X6%W;&}42^0(^zA3N)88EP1eH@&sr&;0jjy!@P(JWCa3u=Hlk)qla-DahBd zmtk&((CiO&IR+Cy9MyI*F%LiL+Q0Y5hR?A+%loG%$J-v1x3fF*{n!8ZcbC8Y^ws=( zG1K$Uv%fyqx! zjrRZR{^>C{uFFR~d$L?26)N zZu=W5?2y`+IqM^9hUM)!AEy51_z`en;(sv{)h)I%_jUZ@=j%T{yLD?>T>tr?nE!uk zZaz_0s^4kd8}s||sp;z9Y@Qv}H;SKbfB(6StZ7^A@~uDT=%y&lf8PFf(dWi!vEqO` zUln|Fro9a=$&EeFxnN>wg7-3Ug}0{yTc-0L&=k(N;;@f(mic|1K4$CXPxI}UeLkyN z_jlF(s%Q1)`*TWCe!R8$pEoUO-}dzX_qgNg-WCgeo3sAQExZ3LKMWZTh}hRnUnEm+ zzyDNbwBUV{OEq5?JhNn0XMR;Pp;MQ!wP6oK>~u3jRonZ_<@~)yGwfOJb?PZ-F{+HJ?e|i4??3a%#cAY-I{?Vhe zTlO(9%rBjEd#^DgL;X{wWiKCR3-tVCU}$38xBIAYXX8Q1i7z;-8F%e*(>e6~3}^bi zU3)s#^p^dv`1ASVxfq-3h&>-?=pFz3_lERiC)u#`Svtq(-+p}NPnGf3UD+j@|Nr0= z$UiFfuHO9gk{{EjJZlzZdGOgaU#mWXAwl~Xqdm9snx7fWEHhP3`rb}tm}4M0{WH^+ z&>Jm3xg@&Uc1)XVzw+nLpX>jcoUgCDyl3m(vR}VGZvOFG`_aeb{~N#DuC>hh@cH}w zpWm&!D*N8EM%vd+K7akslK)mmq+9muGSvMzd-(fu9){oSf&v1JS3WKrM6KJK;<2+x-7iF(p&@@XLL5(cJf} z-oJ6#Q`pD-`1$#Lot8V*zt{bA7jb|wMb-j{#`F%x(1M!X;QEoa6 z&7T<#{CCS~ax7pz@SmBX;^&8b+w=EVt*)0APk&zczD~togXvoCwqlnp*RrODc{#H# zWhqHIQ(FI`uJ*wCTy?(P;c57<=3NgJh{c}}y7wUK1j{W^~`tqGGKP%OJ zE7O>`gH$v&qr-x+$MtCgQ^JY0U` zf#02TtADA_ej_Oqw{55Xzwe@-zZ;tsJ$rn-Zl`{^(9O%%^6kH$m#up_ulQ(x<+>cd zcg9QqueAF8+<1@lyX|$F1~<~BmZW_D&$|2T$K&VUmlr)y3HRT0bMMc@EUtZ#vHJ5> zu9mVr_^@`Car%q1_tcBis=Vv9@3BcA`B4A+{CeKq+2>9_G*OTLrp{O(T4P!8?21A{ z!y~4Bvuhum|16yMr!KT{_NMyf4F6KDPF5(M-f}tbLLujc3G9nM7-sT5cow6gJD2I? z_r(qko0c%VWMN?WP~5ml(V;<;;Rf5|#LwybukbB&tVv+Fk`pMnD!#N-kRg?QVPl#T z!_)8rrn0ac2c|m=AGQm+H#6>LW_|acox$MWow}d9E$Yp?+IwoR#oOOm7gH!X@teV# zw^8x&+3wOl(o0tzR8jc$n`|sVCpW2V7zkk7cHM&uyZRf|gi`Gv!-(8{`sToO<~3VKd;xW4tl=n+`qH@IltbXT=Kn1P^a#${qGHu zRVF9x($CpNzMuK5B-84()`Pc=?<~J0JbUx%yTM+6anth#g=zWr+vo596fE{}+y58; zjZNNsUU}a9d-?f$tUNpyCb#aB{`4e-i6MBtapcVl%oh7MthNlVtl_XzG}@nD zZ{o`D*m8FX%c|8WJqw)n&ktgllX>REBbFmS7cp~6e7IF3#;knef!yu$e^1N#zI)Ua z$RlI^_C}J-!zuIn{%(2ycDa9T_kHpFvj3a4_di`Xr#9{Xhi&UCW}j|Oe!Nv!harVg zFnhoGu1Fch{a-iV*bynv@%8-n|3CiLUY@NM8=SUa(%$I&++F+jeOo-~*SpsFpVB`& z-~YG%cW?am$bYue&Odqj{n&lI$IZvLb1R(g-}i6oI_>rUf0~^M_%r`2vpu`OKf5=V zm~8%PJi93|EAqkiml9lS_O*A5FAxqEo_gW3u=dxhyPs|P=^w+fpGSUKqS^X*_37@V zy0r<#zQ1~l=fD5lJy|Y3{@#_XO`YBQzy6G^Jp28P?eF#SMc-{6Ou7GO+sDcEPxu?m zSee-a&BdpD|7TVf6Is^xe@+Mf{k-*si{YUc-=9nIwokhJa=Ex%?A`kR zmrLhOzj-=y=Z_B;?$>F(`}%n8`S;5o*Sz}ouf+87@wcUA>)-INo&RTo&6^WnpJ&{j zP*h`k>TjmQkH`NTR9-THM;RCxiV&j={0s~Xe}x+7D|w}5r04uU_5aBK<9>d=K4}^0 zfj$8l*}2*OkNWw9czJqd`g~-`QLbSAux&F>$N~kK{T5H9zrP8Y>8QCO?$Y+8bGxhG z1wWkK-?`nY-){M@;Q3Yc7S{XY>;G4q8>okV<}qEiZTIaal|O8SstjjX)j4;~J+Wl- z^{=}YT{K-;8({N-HNt$lfJFK8177jlw#y2IWSjGUK4^c};NAS6Py6drBcEOWoV{=F z&8ny8{l1=EoP1ViUH$j%cPeYc=KW{po1HHI?a%k{et*rL^VPMKfIa8rCSv z*5Ukb{!4|kVXR_H#237d(#lf!bEo*g2Lb1Mam8~(MGx=UD=q)Z?peRw^!!Q-y+?_L zwVVG;OZ_{|{Z9V#_2O3k*DdPq9yBf%ZjYb6vp(-@b=`KAo*ka2-amd)|L}{s83Pw% z&&vfIYpx2-)IE1Svq&?yZB~K4gZiW!Aurm64el=c`nDltwLw1n|96w@uY6hmynmC0 z-S-EtUr){W|LgzZ|MO38Hvc*Mw9Wt0CH%E3pYE^wrd|Kq<7vEeajuPvZj#Vr*$?J% zR#*OB=E?b}(fDP}LiT5d@z+eQG$=jV#}KO?R(R<7ZP6IPN3(wJ<;t7*`)zysYxl^U zcaI-0{+Bju`}*ITZq&TB%Uw3RfA;w&KbN}~$ky*){%w8xb?H0(O?&e8UY)-({q*M# zr}iH4PcZ+#^JD{)&Vzi1Y%8~(5QaAy3NyF$MszdmV0`eKk>StB&rd(^Kl!l!Ti*6} zd+dwD{&-xxc(_;1H2!|nim1@llY+ch8L$1A@ObgJwaNamnYPR4&oX;zd+qR_r$4OA zbZ3<>|NrM*b!^;+JGJWdzdtUv`uXTtY3c_+U6we=#UfBvlay+eIsWyFsC-~JxA z$-n*l`JZLp*Q>=3s~_Kg^5mcJx&CplX1`=zwrkft+w!-TTT9O03$+SVb**M!|M-gk zeEAQ5cK&{~%J%)A~g)zUKle_U+{Q^}BXje7fCK+fYv9-MiKq@7+J4Bq(@xe0}A29>za6 z<lur1Ddst3^SD9u#1-)?3$p(`J&}P_^IwP>6g+| zY7=`uw9EQUYsf15ApL^l`?L*imnAPQsE-vmp~&sBk-^SAXOiP%)&~6v6@?OF<_uf% z?;PLv>k&Wy`R^H<*ta?z{3}?et9i1yvHXT%X*raku>$y)n(m$bnNhLMS1go&+=@eVzzvLe){{<&o}=6 z%RB0Cw`McHV0~a z*Nz`wT=`68@BXWMS^wC~skGX?>(zz*v#g4{mOTtO;M)Drds6J~3EJ89@9unbtzBkc zYPVm#zU8&kv@f$==l9wF%}hz(cv5En*3TdB9KH8jBKrUNPoW&|R-R9r|0>w2^Og72 zb8|m`o88lJ{F}JhhJT;_#`^@he)mbM`!#3p=B^%=gl&fRYBwwtkeOh>>riL3^0&9& zq?4AcT9*@7tkMejw~E)7i%<-^9s3e zY;9Sc^hE`g3O+mD2FDHOpKoH(nNXjT!Tewii<)gsodMI~kM-RxPbEKl*Rs{olXeJgh$P_i%{q?pF(o=if5t ze3p9r=AXMo_Lf)A&wDp#Z~cR{?Vq20{d1K6!ui=NQ#Q?h81vzbE5F0{^~EE(vxBvMQ7z`MWiGM!h$+Ccvfp=dXqXHwt>@Qo_Pwd~X zkuXDkE<;4w|3=?GTPG|Gi~b;bC1k;Bv0VxbED^7cPd?82VwJf0j}()5Gj#vDzSV|Q;BTsE(dtTze0QfvPE`P$l$ z`OdY=+~)i>PUru1(rWiV`^viS;ciFYRLy*Qexh)6t#F%?WZ-(no{u~%8E!?sx7Kkv zNNi3>YGOaI)Ivq%OgVSLuP=@@q249oR;SAsRoz?lr{tXfvVS=rSEt+k*ke&DUbW)q zcl+PI{;?IOH{U#F(s=!fh(OI(9W#c2fJYT!LR-B$W=ZlpXclWQ?%14oV2hLal}{lh z5AW>N-k$pZS^4uh_ut&V{%_`Td#gy9&*ooc_bLuS z@8&N~dcJGz>TSP&|F0KKH(0%gx9KhOlE0fWmTdUB;bQD(NfwRU*7hm(4%08^u|7G? zAo}o5=5F3l(N9mOmrw6}d_GG4(XI93+%FU3?rmBLM2i45mDr(V3 z@cq4edN*61Ep~o+^YGic?^BO{TFiXpK=|?fOblo1wx}}n{N=fJ;@XUhOgW(z*H1gJ zCoNyn@|R(+tN&^)4T;Z^d)&J3{k`z^QC-TRxjtGKp8U}Jwl;uy{7g(G{5xS=U-$9r=6FAw%2$@l zU;X7TpU64=KhNj2DQ_4aa5HDfKWkuI^HGV3LFkP{f8vK*f)Xw42j-j*WxR7we#0BL z=GSF`pTk;9rfyodd4uSDckid>v(`uIEwfpEqx@CfpZ!0~Z?gWLdh(e*Gs9QL#g_jV z?!0AVbM^P~?+TXDS9WM%c**QCRg{VUF877Md$sSn=O-`PuYXtn!_Mg6;YZ4jeHV*< zb20wU?Rg7#emZWj|C?@&!Sj+onGTPb7$NPpz)J6FMjU z{hT}dy!{;AU3X$!COrAB-J1U+lt0%#`p80Y{;%81_nO!5i#+r2zldGE{QJdwW@e|^ z{a1|q@@dJH58LiP{g-d%_v!p|@n^-wMPI`GcE$+@hI1zIt!Fs$lZ{uXQ(5)%ISE^q(zd;R*2wf`#q zef{*ad{cbfx98RC+b`Gr|2XgG;mmc}U1|TjKAf*)UG`mU|9j~p{rl}5x}3wgmVCW% z;7nI-Qc`N>b4IC#hLRslPxLMYwS2vKD{)&$d`+!-Tcud$o{9PM?keox{`1%G$0e&S z|7dSN+gvl<-s{;>>Bgwazl-kM|6F|T@M*JuUw?1STYk^4d1J+r)2)wO>rS7~>^t{7 zr$PEdC_^f9&Rd48c19PM)=hH83ED{lE1dKXl%I z{=awf{nqn&x(@dbIUI6lHFC>g0CnNpd1pH;$W;Hz@SdGv!>#lCfB!jO9RIJNZrkSf zchA@6ZZ6xhDr-vXN|l-&Dh}q)f0pb%Ju%wt7S3|4h4DF8=jz-HyKd@yq@^k$!f&+}`s1rmw+&uN^6v zdGGtVgE_zDCd!xF=Is4jeYgIMnUQHQ&;Dd5ySTo+7P8wX$35@lOz*n>qcm@Rzt-29 zb^Qf%m(8&F_lE1$;Z5m6j?Zq+k~016tUi^8se*T$-|Ihc>ScY8s zd;Z@Y`|?MdeC7N0+r5)GI(_j4i3FAn+T{nYUcP)`_xa}=tc$*F|clf-Ur~ld4 zoV$0{?)s7(Nx_L9XGPoozPNt#pNE%EvQ1KKtUY)9>C z0`ETmTUh>Xr|-W%KQ}QP*x6=W%%A2PxgbB`+kg9ib8hUPzij2(dP|ms#9H$Prhou$ zheaP&b1}T`;rrj*A9G6DfFba-9777r{s$)}eSa)?;Ms=WvX|Nn3^_0FxnGWWoXe2V zr~f;$&RMSSprJukX)-fI$gPO>63_Sx46O`vKB_QJdebE06K~zrq)@f!{8DxYk+TL& z`z2&G{`dUW`)9r4rupmg`6nlR{$2NYe%YMmut;hrC^?{Nv`C58PItr+f08 za+Lo6fMv}`8P~RiRm~>XU-Ojkm#PKIF%nO>yBXJfHDdO>GGU2fRB9yS=fI zeg5o!y#77^z97wgoQx(Ce>X6O{FN|fD)?}#CYEVo#)YQO3?k;q3^ux@GjyK_ZjH;H zcYclkDy{4N6Yn417rNJepUCa_eQ)m8SIs*AeR7Pm-OjG&|A!aaU-V#TW?AyLh-sCE zgYV~cKX<75sWaSRKd?}O?LloqYUX19`?Ja`_}{FIzxgxs+4u7|1>aY`TWEiIj{bc9 zmw)DR{QM*GMYU?#cf~8Uxq-}67^gBv=7olxuX%0hw#lL41H%-fc83R+Yd?5}2gMp6 z(B9U0|Mu^OFaNZnxjz01o@@F1&zbxmC;#N0{quc(y?FV!MJ#{r{-6I}&A*>-VqbUePtEfC zD*ODhyI!ARului~7B~Oa^WU#dz20+m{?Erp*W0~d|3B%^+pYiY8RI{F?`LqX{Sl`y z54u^yVJc$GL4bjQVd~qDQ$#Zo{;&AI;{T5SEB~+gzvchh{|o-__+RqVfO*m>-giI0 z%~siP#pBs2@ddNj8ZUfqT$*ss`dHci^61$W)wkuJ{QOez)9RD?+U`Vc{#|R|&#V7( z{Mn<|*Dd>n>$k^?3(i0P`Hg>V`QNnv|9;l^&18zJJ;MJ){7~Ar`_o;g*v3gQ-}!6C z#h_JDzF)X2Df88zBl{TE3eRA#;_^E`zx_WfU|q9*PS551r<3CAs!IN;d@8(I zA7A%3FSuyujlw6TU$WQjoxgPI@+x9T z$nfD@huYB#96UaI zEME86>i5s5zczgN{CD2>&uMe3*4-2R{_d=8$;$UDSOH~$PU`hX+DExW1n$*kq)l4dkb&H$$ zn1omE@@Sm%-u;$m!kzR*8K-y|*#6EoV`5yxIM3XsrSa|`hJxR1+tnEB7s)6B#7eJe-9tdK3+B{^I+4?GW%aDAAf$VdAV2Ke)CHEx+@+3e#-sZ z9GG66_W5DZ)9s({DSw{oHp3$ASKab;_kV7_S=y16yqn?Atkc)5e}DP1v%XCI@Bf_| zx58B?|Ms50YG>E;YdOzi;u#(pySS>ow@fd-@`C3J|KD%x4!>Wm5 zO$&}qTl<>n-mi~)qt$oSTRpv5S~kD---O`n6H+cqoXgv{tFF#!`S>5?9U5k-%Ix!59|GN4(0vBRF?l^FaM7Z`aD7k@~w(4OL-fV z);#$?)$}~$%R^31JG4(QEq);W>ussX8iw7L5BeQz%$N?adDJm)a`?AGt4M`m#XQ!A zoG;JPRs2L5f*IzytvSH(l2!D_tB$KnKJlGc$nd`Tt3g$b;jhFsFLtusf8Snyc1>p5 z;n0Gd2RvIBZ|jYU&|QBu#M1A9-C`c6goY{aZtt|x{j==wcgxddPxfxFxAvQ{(<=7j z%yO~6_xFd}Ph`_w{N>3zn}^TesK}S(w*FvfVLgBA_O+9L+w<4m{+D*`@ym-P_HpMw znWuMq?@M917j4OE{d-P%c8phy`v2Y8|I4q>v#ZOD>-xL?{-0BJ-)AMQb+4X(zvffT z&8k~hllIx?@cEdloif~ef7M=dTW7z@E#G&lf0tRd<)`1H;=fPdN89tyFq`ntY`J;t zsk4SwN7)x>-RG!yxBtPHWiRfOzB|Q#^y|Z!m3F_cc>ETz`B(q-Kl|BhPp{vVpL3K9ukaUty6idM=hf~1HWU8a{C)T%Z`*^MW0O@rybgB~JJ*=m(07_^OY!o! z&pgj^Sq?ljHrUVocl)#4L+`d1pJ>{8vVAcFLxuE@nTHo@cjrXw+rO_eW4O#VDc^*LKb zx$cv$uex@|DK%pUkC4OC>APZQ%`v={c>jCg-0J$ZH8;=3Slh_YfA`(1WYcOPxAeci zN~>mW`15?}Ip+-)woy~gg+G7%`FYBz$ITXg`S!ol=bv0xecXj}e*V`j^>tt0Ro+X# zmGWuwPUF`hX>b31k6HYEk>%z8X7zSo|36%^%JTAVNnY`z88_1F%l-d<-+8BgbNX{5 z`}ekaCblnM?^aaL7yW!U-TwV%yY<_q_sjqL^zix4SXXhE3-5j`dHH_cv%_CD?9I`C z8=Px?Stk6?OG|@D&trc+hoq%`4Vmwm_IK`i!_(V~ErPEvY+P6O$0vW%+&MwDSJJfm=1lbpAEZTsb>;WYTF^^LMWNs-F#Y);Yhw z6`j!C_I_EzdWHX=zUm)%!f|8jbKBiF?JGC!{Ie&r<6FGesc?2iFM%emkXh0Ubq9dXPjM&@TBCqP)N=Rm6P z=2i96t18cH_8&fXM&w7?qQ2<|151h`SZnl&zHY!`>%hZ zzUbGMBK1Gzp`qryo;UB$EcTmxe&*IwdP08Yk@lvWk2+ksTVpiYXO%@toZ#VYzGfd^ zUobd*XLD2h>+0YTpJ(f=Y?r^ge)obs@0Gv)$V z#THYuCgH%gxs7i1%+Z<*JWO94JL(uUE>1isEf5heea3A{zA{6~z7Ny4cz)cas(69n znAsV21`}4@^yQ*+ni1wc#&Cs+;a`|d!$~Hls*2nrkybArF>*%l<3B6$ z@pyY}+4sLkCmq^n{r`}`FQaqcwl2=Sy^VKuR_sc>U=@b^8QObZd!4haKNnD3@czdU z9rNEGf7#d97Qg*xVw zzuy*#m+pVFXS3a!AM=bqpW$y$nRjyMnt6vy{`1e-^Vrz-@wxMs;?=*NoUgh2dF}i) zbDvpV{c34>|8zlpT^WD+F1gj4D!&=eRh`xLe!1nO^Ea=uTl%UyX;+C+ zd0=GZpY=gk|72&K_;|(P>k{k4`tLWlrl0w;D>viD=lg%{=NlW(?kz4d3*Nn{?dN%( zwRb1Hb%Vj-?}IlI>B}X*9=>p8W`3yI?70qRu?#;I46giq zD4{CZCLny-QBpV{JJaZEzUGw14Ih%Fj;!C8(evc8UET;c>r(*upMojzkta$nQyPv~0>jlrBH~(_!zV!Dte|{flvH$T% zqL9aq@AzAz%a#9U&U}}+j`#9eQN4fl<%OG!rLUM5+`F=W)~WZUuXnFCmcAPL(#HPx zlXCH`?Y`HJ?PMHnBQ{MD%Jc?p8tET=KsIm|6b+9iu66a3a@spe`P!S<#vs8 z3~UK(TH4(&_iPTiEd3&rA@KV2W&hG&WS*F{Xa4*5{PXYqwBP+cyVmZ*ne%r4lfFIn zy|(SdvV*f9ZYp46FgSPBZuhSXb=OM7N)Og4?3b>4kiamPf3aiKq4hPHGcQhlvEA~> z<^ySqQY)YS3_JKsk&#=yL{iO1$3^!RVn7F)+Q@GPk-`vOp?wYkX$m&+JH{ z+z^?Dvl)9?xftZa_jrr3GacyGp6BWGk@3LyG|Tw!^*cU&xO%iw*mLWB-?vs`Tmcfv zxwkL6nVy-lgh%X*O2C@ZwI70{@BDYR-f4T|+zPvOu{!G`=lji?cJtTI#ZOLpmFU}_ z-Bd61dF7YSv$rcfGY{5Xc22kKhS+iEzb8vpO%bnI&A0rqki2XDf4hI@{(erK_4Dt$ zMHTgj*uU9S)*nmSm6v*X?R3pLyWiq}1FskUwPRO(Gw<-1>Z-K&bDx~Ezj?VjO@7|P zGrVWd`uoqfGYPR}elaOx+b+NN^1pVu#6P$de%E1g%ynyDe$%6W-q>0`p6MS~^lzem zP2R-=A%(x%{nOPhn6%sOSGWIZJe_UH%sbU}n~ml5Ui>LJpYrU(mpNyYPTs7}->3dN zMJ((3{+F9QJzUQ``M2BDk%@CxcSA#hfkHz3&p9V+&)<$T{lvb2 z?}y0-zGmCm3-A3~UT*(3hjGQ!KMITs{=H=g@%_&^bG{8LTfog9Yk#~qV_14>-~M<3 z28M=zVmzj;KWiB5>!$;@mIvu6_5+_UYG60c7k zS3~*bmz%xrK5*Rs=&O#Ih{WQ}i*v2pu0|F2I2#!YSiQb^y{PuxelPa*p~0JDKR?NP zzhv8vS@y*>8F5lZB@^E^eOG^|{WHDi$LXS%TW{?7dHCh`)2EB{cGlGW`uyQ@{`uQw z=VN3(ZK&+}+b#S1-{;3O?r$!>vGl#>tKYVFeqR?&xpw8s%J=6pmK({hdKO~K{@}X( z^T+SK>;3DBYTxNL6+L_U-QbJQdwJF?^WN-Tc>n5sr?dY|C$!IcTJ~;I!T;Ge^zZK3 z|L>1U=-2ta!l`fLPZm3#-8Y*pt?Tf@@AYl3?0(y;ue@w9XVvGkH-#pg`DJ_7&UXG? z--$OuYt&}mGLY{&d((C%?{D^14R3f08eXM;+V8VZ{J>9N#vLzb_V4{~YP;twL+sW4 z&nNuVzOlSzh1PJ_5ZSCxhnMz@|XD^ zh_N$NXm*MzMIxKHhD;1N>0 zw>IEJ`>Gj6qVgY$K74TB;J5!*)a?rat5<3*)nYu*etgIO&t@C<+xhM&G|Q~tzJdE` z*@v>Hj}}zvFYKDueEmtjt8MOyw;3Pp<;&#$mmEv`V=I4umi_Xw86`=xUO#^N=h?jM z`IfWqPCf8G{`{BqvCoRw@7o?RY@7GuZN-ck>)+h9_ARUZVX?4ty3f4xg6IEw+Dw1_ zXIE2Ol-$d6(SO`xYb1So?cyy?icEMjF-QOQwde!crSI=gPOsn1=X>Y<%B|&d>#d*a zhhMna180Gmi8{Z-+xGzhPtJF|to=0Ma?QKF;B^;_4to(} zAc71G44=#vy%1UZf7}15{}=q9@_*6)Y5y1g-~4~)|MTZ&&ADg4`MkO2s#$6Eo>jpY z=hz=L`FVDpPx`k1^55lyZ#Vz{@V}PzXVkM-Hy-@@dwYq>yMDH4c__pc*E-UOSKhRFs1Fg7WH-F zmFz9Kk*bUg3)=txzjpBd=Ff_!zj&vc{JSc2*x=9#4adux-9$RF>&e|UZEVw)$=9(>;6oBt!Ad)^GQ z+K-?3cAmNWxoq8^^IPZK*#2y8Rs1IPpZ@dh{_goZ-$s7L%){k;>E}Msp*?1t@vjzXdv4};KKZNc+<`ADrAF1y?*3)IUh(4m!Wnmrt9w`9wEyFN;931_ z@%n%FU(Vr;H9r~mIY*7r=J<_Yr27%{$ zkJtRvHDHiB$5yxImyF`ayA1}%7TkWtoWX2A$N#P2@dyTk50V`X`JwfzrzUck%3rvk z%B4Gt!Om^YO8-}<>mG{;7 z+y5Rv{c(L%;Gg^VpPE-h2Mp^BvpXFF*b~ zc9z|oRav~n-z8-me9N@#WrwoJ1mHGQ@85sWXDTp)l zGlDJ_W=N?u-nK*KP1k(=2Rt78-1ZnxTgRle;h5li*Ch!I5%*tg-hASIid^zh*5l93 z3o5&>upZt%H}`PX)g@VH6g5sTIJE!$^mW%aiwWOl4}brWRU~5Ta0i6;%~^Y{dbX>4H;sK3|NimK@ArPp`Sz{&M=9UZ|8wt$95lH3X0>_vS(fT! z_g~JNw8!}QTwkN#*=6r??5*Ro_-=->zgY5Y8T+znV!p;ZFI>HA!trvUI&kUy!_|X``~KUPgfJ0|L#mPHg#4Fp88(z;a=gZ zeh>EF`fY4K`Rm!Ancw(dp8Rt&P;%+#;O9K)Ezg%T`mdi+`cUCV`5o5s+xKO+{kZ!f zZCSO%E`PQAHs1z>+S{Dbo`I}db8%_?i~r=YvNa|bbfzw z|HtkBf1bWyDsPy#Nw0k0zNtaWzwKQqwBaNF@|6=<&op^@DVVkQ|Kz&lFz;3f+Xbl) zHVlr63$j=RmhwLcW@;$^xu8X+?#n`s<{u{#m;)OA`6%nn4RGUXXk=hzxaT^j(X*Jf zVP)@*UOUlKDNL8ozC8Vmg0Da z*Du9>pZ)N@pWAI@chy(j+#kEI#(w6FE$8=Zx8L>5{}WbU9ro$9b=!3NoAvLHzx_RL z{{3>ppP%oZ^q=bU{ci5F=qvuY&%Vsbj?WccKBx50=1Y;iCu-}p?oNH8_E|f<%-sF{ zzPI-$8|<7K?fK^8nE;-@YmIkaF1q*kpP55===*Wc*&VPAgf7kl? zn|oeYjnj`m-<~BO@Z68#|KG)83F&5Ma@Hk2e{r_lYx3rQ;qo8qYvGPN4bD)yBx85>3)3=A_k_iR``&r&I^onNrvp~%Ve2BxX~f3taJ ztk>Ntp(rq+z-&K5XYUO`LGQrzQ#V!Bm^wXJb!9Rm!;7YkybKY~S*2F8?0co)oK$(A zu_51z!OqQQg~tI2hHUANI(n?k2lmOH-);Bz!^4)~Pnicx8=t$Elx#~|+vnyTsk=l) zfx&^}zW?gobKjQyzkUAcb@P07_AtNyYqQz&%>84&gvN%g&b#r?%>3P3|JnJvs%NJ^ zzNBi-zw}PX|DT%s?B8FNIj1@0>et;T{{4CUl*2~8NyYBldG+rB#=k$D44HqTs->&vfX5Q;3t7opbeY?iOxbDpLcMqF;6aP5RKlW!G^I6Nxx=FRWW>{VR zyV{@mZcdlHU9n%H^IqN`jtf+a>m2ipH}tQ+CtVj-otql0o3`%OW%JE*Wae32J`=s; z`@_R8lLKqoil42YA77ndQT_ha-1ak{Z}M&y{qRq^{PFK>`{GzVhNk-rzUKaO_h~Rp zI=Na)c-@-W=QY2b7qqwE`+H7&X;$04`-h*+;mvY8_$(WTj)iWyCFlcya{Fw5X+dy8@JHcTSqw~(E^|tB8zp@y7ib6GJvN1NS zc-d}mf1feuLvA9&m9XBT-{0#a85!ysCI|^I{ByP0;JJXoV5^|MDVu0O!%Jy~2QMS8 zwpZ<1@$pKZtyJ#f&`?d~Eg}pI5w^1%_{-PV*tc!n+ctA*@45Ny$C6fW`&oUbdgJa4 z=A^E+Ir|I0IR12=7wsH;{5M;Z<%#0iJAZHPzcc5)>2=+& z`K40qq4#gi&fS-%JHEJg@5CHlOV3?J_x{}cdhPeJ#}eE&bGQHebmQN#moFy$jJon9 z&>%$q#mzrSx8JV+oqf)~?)QhEpZ|QBdF%Q5FVBD5SK67L|2p^K3-(XzXZh~BtthUS z&|NQD`^I*}-)bhuo^Tg((-wGe%@4B>UC^F?Btybm)F<+{Q2d7 z_uH4h?*B_Pdv5ciwts8+JDc+Izi${{&v<=LZ9|>8Z$Yc-+>a~*OiT<%>g^|U3w=oD zQR=@hv~|P8!r2@yC6jnghpVyIZ(8cTx$;Iv%LIA54@>JC4-{r zgVCdFvvtgM#1g7@l*C?Budvy4^5*HMjBe%A*E6}wGxFSjcv~$kHzYJvS%RU#E~75; z`Ua!g+UbAle;9oFJahYfFUg(1gGFBb>Hht`an<_Dn>}HC!qXPs*=QuE8|EjTd%ReF z=Z4yU!TLWxZF)L;Pw2^)R_T4eqrc9ydjH+;;I)@0_SR2~DVo3TUqMC9r(BCXzxRJH z2b+e^eg3|7zHWVqQFNL3Wc#USrplBpo%Ha`J!`F^`_(L8zU|(A!XoGJht0*`jMptJ z4!^u=g=fX5#x=3GtF2dS27K>7zpyy?OWDWTn@@Is_j~n)|MxDVmHA!q7aa1kX7dL> z^t*g|#+-i}81J9|A3xpxbLWd?>h(U=*Zx1c6H~iyUDbl`{J(i7yfOX~J^Nnd)-!A~ zc+cnA@q0Rc?U+7i-?>W5sm_l6O?T3ZpU*t^cg zEwAbp-R|oNg11BtO8uD2bkEghqsK!AgDHaBPcGqP6ut7(cXHgWiktiM*Wcd#W!^n! z@#@)I4!2)jl)F}NDi4Fgf3x*+f26)WXb)fH^84_wEobIR{BwVP*8K5>`IqDWWEbr+ zSS4p&vv=Q@-hF?|*3@kGIJ14ft?s*DhfNQEJfB`{^1Wv9?*A2EiiPUx>*t@@{W`w= z{JrOE^W@LonOnVY=l`?+R@7}j7xnZ@XXYw%T_f!#|L5oaB~E7k!hh?I`gcu>kgi?x zwcF3^%XY66w+x+G{Qq9v(eo*GMSKSZPi8LN|2!$HV4`%}vH53K-Lsqg^Z0SQ^D^zv z=3ZG=eE#AymhbPmH6pIJ#?;JtpP;g3lhs3RnPvN1<=p)9HNOY?+uD}CTeyDzvIiB< z&Bbd2=bjYbwA!k6{-5hF&)e;_|25<3-0~m)9i~1vu+BD`6m0qK&;6tO_ig>D`96>9 z+l14XKc`Zv?Ml)llef^=LeOg2jlu)ohq#?32xENyls}1Y;w(O zH5)5K!^?%{r@z#_|6g6TQ)u(dAGv<7%fD{YkF4LCvu$IZ{@%3be|E%Pyq~+PVs=gP z`7_7eFPHbHC4b&sZ@llbW}oq8o3CFC&e!DKosnKwo98KaE@0}~n&0vH{}kKqom>0S zQEpQ2_u0$ScW2%By7qqB4|U$lr54gfF3Xl!zOV70dB$f&V_2QqZnc-$b+YGbET{fI zR}$uHxqJER<$mG!XYTi#AN=>MUg5slb$6!v1jc?VB^$|gPz{&FT~fBwJpz5cUa8JoU$R{uQv*YvdXxi3F*7pA_N#sBi>yL+~_ zZxY>}Ienabf9~JP8~Wp8^=hhSmCwqqzQ6O^`TG0a`}cpc zpMUtHWvux8%wGmi{%xMAwadKn`yazkzh^z{%31!v`FxYd4AEnk*f#W59Q@5NmE%BI zZNvUG4Ogn(Okc+GidiGCf&a&cqmP0Q**%~3J?BR+|K%p$=j**I9Yk0~MIIz{+CF^6 zRP;$?r_KQe*1A-ih2F}H4O)*5x^N{k&$!ny;rzw;zMFB@GVgzVwO?PM-Ben(9%UV6&^+ew=f)8;>XxT*fk`&{)O zUvti_73RJ7f9JV}*7lYu^MAeX+xO?p%=0JZbM9OCPjbFrYjyJb!+GZA>dR*Yi|<^{ z_w@z)z1`iNJ1p+sn!Nkxy!#h+|6Ez)IVpDCKi_|+diOtn686lp^v3^evu$Zk$Ne_k ztBKn8d;h!qv-ZNPY-)8+Jvx3x9Xu+*n(_!SDj~$cz%Xs$(jtM?|L1|nBxe7g`afKh zk#Y0>ueQsJ`RBc_{ANEta{t%E_b%H#S1(uNv8|p`|E;{sr|{N-|2bXqRhu@gUj3T2 zD>#@l^0&dxlHD47XVP-R?9(ErZ?>)u51jc^W*zUT(whA3-%mc%TA^}(vP!`J;T(h+_9y?3DSnyF->M|bUS~3u1mI8c&HX5L&JrF-1?0bcdA#nElazvH*c1>nSRdyoaNj0OMlnh z@4bJ{{T-X@KRm6TzF*z%v-$qh^WXk3DcqygeY4{-^JKdtVe94ngD;4r?+AT$hjKx#!i+wtsn6?nurY_qZ9; zz3<(dSZ`>zV!e5mrE_uk+&A{TlWRVCMZCT;^HG7{{55se&-ZT>;09#pLOqF zk-Ney{mEc5zv-NHJAciYd6R#}KS|^Ki)DZ9LIdLK*^}q|UA}vnh39033v-{S{0#dy zXO-o0J_eK7{&i((Ore|Qf5q}_KH2#2er##@U*p|-zr~0NO9^tZ9p$b+a7@O*W7iF7 z772lWhHMrQr@|S90`{?mnkgJO)0VZ!kW)d(;ha_H7q*5Cd@<9dr)BSA_?Hrs;iJyz z^TA}!9v=_(hKp~1b}VQA{qFYfv#SgC9lQ9xL^k*Kwq;Vcw3ZsNFfx46S-u>RC zxqr@d_g+5wS848#eLMchm*oC^^zi74hwmOQ{cyGFmv?^cw->JWp8WZ^UgI>kYku81 zyZ`t1KYIB6-^yaHZ#ln$cMJcxu|4J6^ZWL3OtU7Je?PhFOug0q`MWJ6FCV`Ba>a=V zv#G^)>UUSY{$1a8PR?-p=kNb6=9taiRrmkb+^cub?ymk+e(g-&gFUtP4tq{|;(z|; zYmxL{Zy(zK$*%wY@@1yUici1a2YvJjy8b5$Ore0Q#U zF56x5@9e+7D|siY^UwKHD;pX%Zy|Txw@e118|>%4$G`aFz56>uz-CsR`md&cPhWp{ zY2GJRmKo3A|NLnB`24qD@BiPe|K@P^=G3kG=ZpS#&Hwei@#M0$~`0bT6C&z=Z#KD401NV&%a+^o+)?l`CX~= zhSzQwi?3%=Uy*-1>~`4I=!g|6j0`EoTHkint$Dk(`}@;|zwMWQ$<6ou6<2gtFlq1J z;OhNzG@spGE5GNz-=m*rL$-A3$CdN$oc~_*`g!YjHoyOc|Gl;RqsGg&lj|yGzTo7a zdj9<1uXhe?GnSA3dYbpioU@4<`>ub zz3o=oCnqu-|NZfBZ|T1#`<}&F?+&*uk=*s=bI{DMIpwkmeXrW>k2ZdvuzbNjlljFb zc<vxGCb$S@EMm9J4vPV`F_sS^>%nTD!;^n_f3Kjdjefc%D>Ydr! zYv-l6pZ=Yl{r+T8)z$C9zhCmDWr^4C{_QSbGfTVaX-#eL?fK&TamVxbtpD`j`^N<} zM~l1qbkrAF|K6LXdU4*{#hmsN`McfsJG&$o?VWsUy4j_4t(nE!EKQf6dr|IN`}6)v|G4nD@F~Av zon3eD*_>VeGWYLyS@Kj|{%w58e(LTc7fhZ@7q>k&er|BKjPdK^Juic=28;Y?x7@Jv z?fzr^zvf?M=Xrlm(=Ps*%=3lD+-3Whwg0j#_;#{#Qp{058>wH-%oX{0&(inIHcV$Y z@yKfT!Wl=!KNJSqXBViyUt^iRjN9VK?Y)PuCa3Q&`&$0mV)Oj7YV93snPvX{klXa8 z>A&|sp#*6Irhoi$avOU1+ur0$SFHcst#aWZhrW__gzuH~iKdZRuTxPIR{iaP%dHm0>uTxz1aNl>f*ws!GkndO;JZ?>EIpG$ux_9o@z zwKLlv?<|k~TW_{?Z~g!H4~ajgwx=v|e`i}+|E_l3BE8`F%l5AF(vM&N@i#60ws6(w z=eytbGUfky`t`}-#LXw~?cIOj^4FLvVa2}$&z#x!Hs#I52RnXz&)ycEAJ6jdzvXPJ zz2cWvCPjV!yR(kv=1<12S45`9%>1yHF+(c->+k&6`fK+al&?u(G`S^mbmrt*-a0#p z^5|l|4U%nE<&5G^@jjV1`XvuIDDC>Sm|+r!3imtpcE4Fgp}q|!{~jI?W9yNhAS9r0 zN}tpj!Z^HTp<9Irmin3H(=N9ne5PIga&hMl>&>9?;bty&di1iF6g=bhu% zlmG9SzBmFAjQnI_Un<+hIQ>Z1#WP5$vC+G;m_GoO6-%=ss;PhXoTX)EB~;q&uPb@~?TMGPy>R0q$0ueSPc#MGrL zU--q}_YF>oHJ#({_`c0^Svi0Da1fhf}-(3A&D;`;y{!}vb z+Jm&oD?k5A3-O%xl4Wn~ZpIaBQnGwvXLK_x(_z2X@ZUBf;#kl*R>p)yvDu9)mM%TO hqSJk0HphYn;RJ?tr+>VU+&_f@bR-!l2*H?-4**v$42C`mM;k6o2xVXpU|>j4(d3()=Bc@K%0i9G8B;t!tfK~O!l*S zxngmj)hmrH7o50tw_Nh_F}xaut3>z+GEW{N>Ym+SuSF3X)J=g98(T!|_6yZ|Htr=ZC#U$F z{o=z9R>Hspj&=qH2Sb^og)%2Es`v-#UM?~XFSfm2?0da5HXIZp_;DjRy|6GaD9%lr zmes&vJRuPrETDjvSjgeb1F?yPfuUpJ6NOn9W_>WPV)I2zGIS!bBfPpUYf?ChPKv2%*g z{Y;tj?kp!r3_bZcFfgzr-jFypw@IP4k1a_=ahc*|xsraq$qNimXfBcK?Q`>5*&Glg zslK$N3G8zP28I>^a4Loo;G_&m#Y-l2X`Ry8e8%Xs4v1KD_?*@24TlAsc?`E)^3pNA z8kXF<_1V1Qb(S94OSfK&(q1|x$V+o6IQ&2vL?LB@Bby{RleEn!I;FXMK@%4wI3W@D zLFK%l>_sGW{-aEwkZPci>O~{nU}M|RkkIh5+{o#rx3{;(-YC6)z4rd~-gxmg^n?Y^ zISfu5iY?$gIVGvb@c5i&KPOH|1jBMpp~&%xGAAdhcyChiy`*#YlZpRllZ(QxfhNAe zqOli6OD~J12AjoRHch=8ntHV?_2#zJ=MU*W29(zn; z0cQ(v&RL+*_sF78*>jRg>@>qicCb*Yl1(jm~MA zowHW$T$FQa-RoTh5j^L(7pb@xfpU&(kqT1IIbbN`9Her5laB9ah#ze)8rz1JxQZi3 z00YB;2|V85awITF_iB*o)gax_5L^5?CNwnks)_Gqlg0}ZrZO-{GB7+@vg}F~pHR{S z%TC7(4$mVpM`NsB&RHDO(>_7j&GW5d@EHM?turoowu)SN6qO}g9MavpHpRnHciXWb z#iuLSot(os7#2!0@EvEA@nx3rW(F533=E!^8GJ<;&kBQT3kC*;0~bvkgl!#!U7^wx zQ8K>FCV?y_fsg`>0c6p|5XOrpP`ez2T@M($I+%n~WC>I=7P|sX8U2y$axn3A2=Rp~ zAEib^fR-V^$iTqJ$H2fS=Cn{zo2kKqk)i#u!z2aI4<-%CksoX-qwm8Jpb9| za*IaSqD-bh6JJIK23An8n`L$ z_jzI0%O<{|rLosp7iG*^wsO_F*Sj3R3a^&Nig$p-R_$8%nhB&RH1_(`)P~Get5)q= zr^6f)3g$~LShecau65d{8LpSc-kh2m$@T!m+oZ$5@ZbO=gTet0tCK4>aY*~__`o0{ zwMmJggNcEmC(+ArDNnMH6W78-A14pRl%OCj&81vUTB=in96gpU2{Q81T{Dd_Jex&+Fuj;&YbjOHd;r6uPqpD&pb^2e&B0fd`=Iny22iEYow+vdVetvzBFMOHWfR}aA)%qIp!V*nRj&_i1BL(f(!|@VR)IqLKxypt(p1SE zpz2$Pn}NZ=f>S`hsgTC#3LWv|^D#vpO7mDwS(rPp|k%3RStHgTykP(j`}-aty`JTe2@)G9{`@bK4`!=S!AciRv*t z78S#-xO7TXx9&EH**S_!rUYdh9*asg_S!lns@w3GM7ECC&M86J8;?q4_quA#jt0qQ zuQkVV=F%ykma34K=F%xaL0+1z0!|Q#rAwv+aVfS4 zfF-;*L0%w>g1lCOgdi3z zoe~7rp$W3cOLHky9jI>{qA)&W6cd#K^}1oM%rk zFbJ@3+;S~ybx+YLPtUc^Zc@({EV<#yuDCVAJ5|B)l&9C+CJs%um90HmOJ_`;=5%^S z5Koe}VM&jnyXDgmr{fX~3=B;S49tQ?!W<$Fjg34E77iX0m>9UYd1Mc}IymSlEAwi<>L7jAg$ z-qE1P9CP7lEV~njlR#61i~}R5g~h`*^?M&$q~|OM4teDOt~%rx9xyT}++@$-^{?k!2xzG1A`)1KX}vw)UN&Wr{{{fy}PHkyNA1nx2?B_*MA;+3u{j=ZwFf& zduuyyKTjVo4-YSIPaj_&e=koj9}hP#4^L0O|DtwxvQ{!O2>bmH^X6rkQSgiXO0c@h ziIXQ!o)i>F4p}2nS}(GH-^#z5-`jr`fBgOI<>qhgS(bly{wV%f^ZCo!9EK~?rm{R0 zil4auM%HPsrlQXN6Y+2C9GoW1k>PV#$&lQ%NoRhm_u8YYI@|VA$I#7~q0R7;%R4!8 z+S6NIivl;S3Ude)`TEapzWJ-Wzn3l8-lP!0@_$u_l9cPjOA(w`x@-koCgoYgti2)Z zsPVGx@LmRK$(;&Jz6|aWQ}hpPh}pVqMJDS7twkAY8AS!RC?$nnSRtnUA@AN><==W2 zS044&o|<*>h8x44S*5Z^T=Ok%#+}{8_h^y%oHup{-2C(yGp0H?btLYbvM_9GhKOrm zu5Q;2w~HNXqgX<-dy_6kh)(>h{oU_>2 z*dJhFO_XQ|YS?*BT!lxRNo$Sk;swDDBGIC}VXpgR`CVN_)^^u=Zt1vjsivy6PvWGX zegY@MmU*7cxBu16b>RFFc78*1VtqZ&l!oujJu+h63}WVuOS5JzyzsD)WqnBZq70L+ zgwU&5+N-jj?A!YL_rJP_=e{k<+WJcOj%~Da^Axrt^AZb$`|spdZaq3Hv4Fe&!Mf?! z|1+LAaYB=6!BQRtO*I`B%cN}&^X6dhaZwe-uE%;M^Z;^HOWAHQeV)Ay3^jT;wN z*_3M=FErlua6H)eirJ*GrG<5YiowAhhSLP(*yl!dM`&lw(uy!oTD_{znMigtP$*QoxHC-pTp6ps1)t+^*Lw8Z=kp~WCBJ-b>xUw!;$8%=h{qIU|l68AF zKVRR={d=8MoBVW_bIlp{2N>>~GaPv1S6yA!9^xkx)M;t4 zr09@{cT`uW;baDe1!*ealBEHb%YS3F}f;R6QXs_SDNUNNRfWVpG$c zO^!M~!5a^7B_&2kv@OkyV)s6>XJ@Xaon`mW3F}RxLvux%#a26U*_28+S%1mWIb%OL zNiddc>K8w`dDRXqj4US8^iKJ2TB5sn-L{`ctXehR+t?LNHM_t6O?tn_TmR?PVgk_u zya}r}>)y(LY_LVJL3wTg+a$TU+UMuz&J*2qViG&U-1T>+sp&7*wheiEbiZ;Dvx_%Z z3&V?VavpK7^5w*8eyYyQJRSAwN4Hze3H{!OU-ebmH5jhcmEPQvmVBdJziexKtl8R| z5^B4}ck?TBJd|J#Fm7z7W!-lxt3J zSYE8XVCcmzt&WH-U8^!oyCVuxS{oOxE@v;;s@1ra=>gM~dAFZUjrsJlAb#ufZIw%R zJiT0SUq0a|FGI#e#ve&7=`Om0Yu#4g@NzX=q_t{^=vud_j$WxtSFAMPU=F^QBEr5< zXHQG_L~(sFrX%z0zcoysmE2`p|EAGmRpKuO?R5eSx~UBNSmqzz#1k1K9vL}#r|nAn z_qlg{_Dny1ddl%fRVR9Xq@9q@dp`er3IF;2S^uuRb)TQWaAe-rtGd@`@?RF-b7S+i zT~Bv?ZWKCTEpWgfFvx&GS15s{GRAS5fw`+zORtFQqyy_#_1few={1niPR+3G6y;-B zlJ>W6MGjY}snT-V zkTCI(#_gCm#+F6QOQx;#5c_>YGI84#Bhiyd^47@~w?@Ixkj z**Z=6k9SqW?=F%NOL8<3FnSbOn9g)&-phrLy?y5_zPl!JhHj0r4zv4ieg%V0L58y) z3cf+tJDvtDVhvn6ZO#%AwGPLFi$s%Mv>z}fx6b_aT=eZd_A^aiW2en2fBW!D`oUj% zhbyPc`u&gCK96VOiA2L=3>DeC1D#tNbu`pIe(~L3k-Ij-;EA~D?@bTq3!i27F)MdT zKCCt0(e{DTT+-DJen?$JIY{zh00$D`SD! z%rz@kDQX9XIPUG%zq@U>RK%JL(`Q=O<|GD$$$TU>tC5Q(d{OmN4&v-CD(dP&Xqa*YGPEASD1M6gaMN&!!&h|3YiU7 zp&?hpLPM{v3cKoIz9>V4VdIv(#mf{l@2)uKnmatUnH}7`l<*_SP*tJ;`)ZKE(lpfNWfz*zfOmqamKnde@vD0cYMt@l^w zRhK{Re)!?`|JsI$?FLK>T-hGX?nvno4k*-$`s;P@su$zR4AWH&cc$&099^s4I!j0) z>ZoR($mu(t=TaEA%$mq{sriSZZ28q5vjq90)3^L)5avnbap>l%so10#aq82>4$80UIXqpALQPM}HBSG%t55(ifWns7y}&0;xImC5>w^I&TF-YraDTOJh2 zFX)ZY=5XLum{Xa^r_Hr$Yv{%dAHj_wYcy9xxj0^2$%a8B87HerAoV0Um z&eSe9?Igo9O^r`xxz+Eu-pk7Dr@46lj_ZFJIyr^78^jo6gr5s0@-eP5U9dSI&XGeSPEZg_`PN$aE z)^_nNQO!s`{ji0o!pFf8I^SBPee&Af7a@f2R` z0uO-)7HXX?(#l?wQMx9ypgU@<#`f*o|Gj%> z75Om9_s4GTu(ggF`IF)}uFSi6L2})*Y3J(W-_GQn`Y>zWmw(^m8(f?u#27E|I9M3e z7)&?dnRadMtOd8WMqTCj{?n~zk$1bBV&0Q`TuhGlMYgo^1+MC9SgU)c%`;_tqB0k2 z!DKcw`t2J|6MPsua&BsT(@EO@~dfTLYTI`c#T5mK=cw5T3r*CJgikyvs!m4ySg;J@XtzuUEXVeUMdcdsye(w%@iK;kVgmEHJQSTflo@%LEfU z{)0>nT3vp^&MkGQ%n-WEs+EK22C-iN(~a*rY+LAk##h}x@4GemJHWM13SpvbMaD#^A>D=JVl zG(R%YpwU%2>cSQ_QQa`U*Q-OgL|>igm3eV=f8d%X+s#bRHwG9?SefvC%>hF(sT2RM zT@e%PT#&$|$5^mTSZ6_S>(py=w$^ulk=pXe`<>v$h0Hw*UTsk-Ub|8C;35SMmy8JA z%74r)lm5y+nJvbZmyTh$Stg9j8U`yCVuT@G>tf$rQ&%N+Ygr|u? zNB=$L^Y|)tgh0V8Z7#(M~s{AtlO)QAyZ$El+Ec;IxB$IXg>j zmng5Q@LZm7a8Vblv*+|%=CTbF8dw5$)>yjV>)Frl=r^Y=>a^8E79J*!n-xye5>DRL z$eii!sj^ntxIe|GTp^T+fx(bNtL386aV4(Q$YVuM-fRm$DRIxo$e-iEgG~pjq*`xk z7+1dhmmI}#r?0U2_G*o->YH}UPG-9lIwk6Zj~#4eE_vyuGU@!ze+q_BhCKRrE|fq}sVF&+ULw@BJ>Xt9ZlmA#dni@&#*y-$#< zm94eE_kaHXvd;d#|K;p#Ty4BPJ^a1AUEF;=ef)eqZ2UZZ0^I%Y%)6_2dBsofg+fKs ztIOJb1Yhd+dOf($E?_bzi9t&8L0ab{n|XcH*X_BX9I4G-CBog|;H1o6m=Kb=(JgI{ z*1hxk=8S9lYvMC z)qFHl;OoEt%^Pg3C0WkQO8jt1EKt!+$vC_1pmzJ!Xb!Hw2yjIZ;rD+aI6Ur`ru=)RKzityVOZUeQ%4_vB61VYor+${c^{VO8fwJvu zmIpEHG(5)eBt2(>k-tme!CxNJ?@Mnwqr@r9S9`tcleA8{#+!MumsZD|*1z#?UhcKs zF-zh%)H0~>bZRp6@+8D~1x&d3s$lV}Ac+>KCmFHd=G*J<@M_l4?kTb~7r)Uh#c*WS z%agq2v&E)&n{scq|1|Ydx!-$64#pi~%ol>#G~%zSX71cHNk!LjgNCD{0?(wZrTJ?O z`3_&O8 zlGkgA;6UkOpDn+FRxg;hJxglKf>n3!zYklXo8g#k&=uj_6ynew*!hM*dl|!)q`!TA z`wSP&snfpp{)K?F@~M~g4ZaZ#GL2deMGYAmda0I6S1l0Txa!8DZ~<167cK#=AtsAl zH?ppFK3Vcnblvn;=A%imAydWe7+U;l8JDCk(Yf-`YvnzTGipI%uYP>bQuP-yiDt@U z(3;HC6?}Ek*0A0yBIi8{C%Zac(9()JsMVFUCS&95NyT<2rcD!IUsj+a$1ZfIYh&@I z$`4CSC$0_aanYVVSzRVa-l3sKCYd3N;d+XqP!2i#nP1<&edhUjbKWzP9N97z>tp0lvB;j%k}~ZPdJkqHgOu9I-SUI z{lT-k>24vSdsnPGsucCr=X-kmlk-wXJ7Q0JNpNjWXjb|-JD1^3mu+C%QW=Y|brJHZ z5vLlHWjP$$439CGC?DKbbg1y)!yCV2Y-+teZ@;_m$K-#l_y4Ya+g<;;_G3Nso>{it zeKqfdUq1Y~f0k``=T94vL@Ykw4$b|g;hSN+qT z&3|>))rc<)N80`hZrGp{_bT*_e?zO_#~^m53En z4_BIoeSC3YQRtMw5-p8YqRgxK+8ehjRfR?e9u4mlyd1^qx|}KLiXkFdtQC7uH2h3&C7G)7pbZ)A}mICOLCVHArn+yx7O}@v4l_D_a#M+_?@rxP_&}PVV5F^{i=ws9{nr7mGsT zafw3=PA6|PEnrU+Sp9R$!~=i)RtDYG^WYa`b`VtZVcN7ow57#$hK-<`l89eoC+CzW zAAbsjG*5NP7GZ9D%b=jrYB%pr`{WavW(k5i0TZs>{w^Xg<>U>a1&yqa^<5_|_RDrS z^sw}Bq0)B;+jGBdH(j}_6<;L7%cc84`102SH>bDT>d*j2N0H>Up*f*F9c-d3EF4bCk0P{m=a=2wJyTL_snY4mmYH&s3=&qmnOKR0 zh>A4GvN#58Ydy&4%VS|;q~V}+XvHeWD^5LPjRBhkR-G~mQP3=4xfFFZX+!SfP-g>= z1zj>4hqv9ZRI{Q z@Aac3yJ<>ARhyqzM7&rg@&0LTLvIF;LpM)={**7KF$P&vukZR)RC_PDyl{I^l!(^a z2SFyOOD`%~@KnR=Hfv5LvUz?IK6VqKgZi1t&%v7G0C2+tsux)bYWW{rP8CMFsNy zXWYbnEt&I~eFNjV-3gZ06#g?yJou%V{rcLg~mbG?tE4Po2cbxu(l8Dfjjg{q!`}=|PogYj8l(>VKD(sn zg2qQ7Sf+cjpX!<~ zqUXV@HkmI*&|W9}cl6rM4h1*80EUw8sO*5PVJvIU75E5ngzCn=V0CHNG3#3JDnv1_ z<#&y9vvXmF2+N{ZW(wU5(tEQ03OW2>UtWDy%!6T}{G4yBE0o$ND_;;;z?1nXMt^>y zp^tV}RK)dH22$M`3LJYDaA|~@u9+kou+QoG;?Q|4ZiNZ=TNjsBvQ3$n$dsAA|HJR) z>2n-z-qQbbk3WHvk&)*BFQZgg(y}JWX^T%S%5aS^SrrkfDdD=BC&_j7#jw!M*Wa#* zw$5!~oV-b?IqBn5rZ@BWoxi_L|C9EAYxO;y`YrOGw*UC|n_1@}3)=#f1HLS6JZX+1 zy~|c`Ke?8*H7a!Ls<4o&nX6ZYt=44b_q@w6)@^=%6Y3=X~6(Z+Mg!6HUi>@L?dmnB*{ zQKf<=N2b0A(`T8nHFExK+by#SQ}@jM)4WpPPndDel4-#;X2FU-^bfe{^)O~kZur>N zvU82$^D`zrn*v^UNnF%YTD3@+b)ojIkd30D7rIW&TXL!RfRfI)=+Xj~HM2~)B`h73 za!tF%I+n`J_{;7wVe;gOj0Me%HJ3RG^-l*a(&$Q9yDiBjP$cuaUH+5&=e>Vw?})4| z*IM#bd*AOp6Swib=~}7P6na*5;^*F_Ai?p`Ztd0zI*m5YaY7vuE^QuDLPyAoz9nLvgG1pus{=Mb8Pcr8} zJ67N258zH@aX874l)C+)SkT_+S8GChSFJd@D$6yboli+KXZ71>o!eGzO>#}DymT-s zRMk;u!eRpr#eFPix(eBBo=K-wi#GFo(YINp`#EkNU$c;y&B0Spa7hNsV_+r+awKBpj<6+{OHe10LX8&4FA8TVh&c3tP z{^2Hhg=qp}3<)z?zWRKKI8?}(y;7@5uUE#Jhq*h$#Wlom)lsX1*Sa>EYOQ)CbFI&} zdA-UTjo=j=iVS<^&E9zF-C22=ob}JMbgcJ%mi}hvpxVX5R7d+acKc3v$j}hpy~G1bE_7Gh8#_@GIaRI_c5oaP18jHN*~XwCj7Ku{KHY?5?_A#xt`fE=ZpKi^F_( zq_L3C88`WdX}=jJ$s~g+u?Z<>gS{+WtXDO0O?<-8dcPtrX1n0>iuIop4<5TyHJRba zq@|0NOy1L-oL;Re%>Bf*ZpZQeOj}%-!WbG@8S7$t-t(RmC=F1ITz!;7JN2rWWavSS zrE#Hx+*ViKEi3D2(3&;Dd6(iMcI`vmb*>W3Z@L_f6C>Sj$o*R<5hiMudgG>@gVIES zD@+qa9XNz``AEuys(UTe>R6?<;A3r2dDP0Ii-hL#xvG18kJ`m=+9|}clB3JD`v5z` znR&sS`%1$v&(T_f@^5X4cog<-|VsUs}x~)GVkgk?xNodcTcp5$Uk56)YbL(N#jZE z&)IJzv>Gy)HuSElusL0{b5#~suiIjc(wE8eS8-(>-4eRCOQS0xbam9W>IEiMu~L?1 zLi;CgIeWqAOx;DEW6Mo9Dx7{Z{Zv9ll(XYBaRtYD6POsLFzBd0YEhOJ*D5yADOdp;N7qJ{@P>sYs!}1YqRf)ow-1FdUX_y8UgVm*xFf7(zxAoARU26+#A@F?ZwZ>p z7nptLR_o3CeUT!IBX70d+|STCak6xS21DvrCmDknohv324cB};wP?ll-If8aVkXzL zx&&7rpY;CDpX4<~%NZ^#kYHpuGw(3N#}}>ZYv0`TRgi00So+qk;V=_JLs@#mbS?>X zp7xJhgW9fL%UZ;@W`ncS!UhLM?-Qq@vQ=G!7BsNl6c(zxA1;1+6GKazpeFCzv^u%v z-Mcl#rfk{T{kJuEcRNG(L78bj3=PLQ52UkPS#$a6yXO(7o@Tc?9bA=lyKCQ$iML#I zHU#RV?7yPABY;Id=HAu+Iw!wn8SJSlmE53M7=3Nu*VWz*c@lS;GXFAkPCP8Ywjk`m zi{3>%hYc@i1Zj%8`u486vFO*Q`CHgT16*CTR~7uN|L{n7wRWbdgQ4O#={J3q#_ZN* z26x|-AK&wGaqO&vMVtRKY!xzKP-R$Lv4CN<#J(iQ)sCT8oFZ1w2e%NbbuL&G*^tF*m( zTYOxHY4@uHiyQR~slJ@d6Id-CFbOF}{4n8aU6sY|n!JUnD{PI<0@mI|0g3A9dm8cWKzViFUCoWNlz&yrCkQuiGH>u;lkjQc z>|F6CaB5dt=Vhn0(TlrWZ6n`3o)#XuVP82MXvg)ca+AXZunmn3=cBlhbwAJ$JIb#{pFP6jJcEaE za#W*vP@pJlVCcmTG1oOw%B!@F{=K@=O?jKBfLD)em{!A93zZeRe=|R(#@I4EnWw&d z^15&Cll03fc0Ly?eX`DeQtZbAzZtX{l^JGDbda9Ld1*seWNC)~?M<55t5>PSu8&H|hRQhm)!EBy^y+Xr=J6EILp6XZ>V%n7u8oP4Us#UAb&z?Pd_7oQp*NYibX1na( zzdzsmXZgwu6RF-s9n37{iRO-8mv5NG6^NI~E-~rNeSCM*JS8Iu%bg5!La(sfygTR%ViBc#`KR(7QS&V}bqd zrOFSo_+)bQ4@_&&Y;?HBQf+;tgs{D+^cPh{wg+kTT_&%Dh{nP=_KyiGgr`!Q?!*Xx_NS2HGQ^BmxHYueGYHc|DAlS81Zf2;q=-O4QI@}gN33y>D z&hxbULJBfGB5tx=bod_`D3)%JhX=xFh6V>*&|bX9+k&bH>eZ^G7GQxH3LgRe|p zLFmboD3(PGm#t?ca)|ec9$lq0%iv5vM3ruroa5%8fDPTBF2wFSrP*n>Doee|)us8< zO35c(iJ`vL(`LE}Wv-J5oB1s#+vZk%L+>0PrT}395h0F~LB||87iPJJYAssPwPM98 z5x3)BM>L`~uCNLbEYywu*?qm_zrLcGz<;hQ)3!#oua$}7{IhnJt?&lvom=MpwPjHC zU^~uGlf+>ED~gG+RVUf$wqS(zf(4 zSUYJi^NF<}79Y!o1_nu)1~bMVk#Qa$I{&Y`By-F8!3l|E%l_sD2ZN~Qq@0O+CNA8x zMuK5U*HN}rwSRVOwioRdP5J#}(r3}PlSyvcGs!uo*y^xZWLRt}$qf{N|4*?NK=?AcUOm4 z=vG;+gsogV0~w}V^Y&2JxOVH44a1UYEA^D+moB}r_imQtORYU8FTKl^Pw*CzWH4vh zG5_QQ#ji5@(Y%3cyx(pLYmZueqe<+dmRQV+DA(0jGhA61S1&T|$)$DM9)HE+oqG7-J7x~Q2nVJMYC<7X^ezY=lb`RUy);zzSJm>|-m6SH zU1C$NWc7$TF+JjZbFRpHo!F5^$72UiIWz2;l*sTmP%q|9`bnLJUux`JLZAhNUJMN0 zY!dkmMHVh;JJSSvHBQNPtrG5CkabaU)e3v})eD(*pS%xPDA~jpyO!52Nmbxcg^q&q zlX{Q=+d^=!ZWgeIv=$h=~e8ES6?VJUN$*NWQj;bmLG%sC$xMAYl#ad$P zk0>#$nU~6}<5{zL>%36rjZ-^~Z?k)t8}S_A?Pr_Yb#zVIsFdNU`&VAPTzs40nR&ktyXd?*bT<3^>!XEcMW@m}GMZ_# z94MOjVD^T<#dSA}{yl$PdvWXZr`7vE87Fm}I{Mpv{`u1y;cK=Do%&WFH|^q)i(6hq z?iRHu(OqTqXcy<1X{kxI`!6c*Ui%~ctkLFO_kT>jUY1kMXqISX#E`|v<5T4Dx9K2P zO23&;sbFt_hSWxlut1X)%-2?yu3Xi9VhhLNf7`Wxt&OkJOtrl->**`s!<)91H+yyD zY)&iMv2k{k`HGe!-x$pn8L%yAWr+6{=HTo%4}5WL#idn2fg!G<*H@)2U2%#jA~G}N zXveDST6T2`OM?PK7%w?$Y}#)vE`Dd;?I(wFe)zszSXk}1+52eFf3~+*>>Car;%IPV zGZ5{XZMxW|aO18^(>w%N-WrtXCxuOKa`Dqj48g^oFTa}OiQY4 zIgdEsDX3c>o6q!7fdAZkW{$QEtc(H7Z>BH2<9EL4>MN0u=|%gay4(UoMOr=7j#!C? ztkDole6b<^?6j7*855m2Di>W02|U7Zrs$%IMz*BIjkMhvLQ7mFEpFH`R4OU@usL`x z$eU%rR5L9xbgA3owtxHV_tiYlV$Hs=GS2CemYcd*X7Ixhh3Kq}v)=D}!oH=eb%pZ! zrwUOQc55x0b0Fq)aaHm*6;tzZ7mJ6t<_z0nGmBa@CQ9xnb-aNpir zOkJ|JFaFz4euv&{R)!5RO;7SSr*+Iv;$5o{;kGt{%hjb(O@)JH^(xoJJCXtmLfmr% z1a3RHW^edCS1D2Ecmv~;d54dl@7i|wZtc0<`)p_LK7Z=-k=wBlF&> z_3T;FczWBs!)J1>mbRYW!yvZ7kfFPug@0z;@%-S-gy@>Nhr(o9;$(!|_`xpsR~ucG%^z`t_cylLYG8MK&B_-7+ux>9)IN zO>vvLZQDIt+vhIuE|X6%mSlUtW^^F?@N=c+kHx2wPR3{k>vx3}YOiuzEwOQtR#b0T zAxFom3~^=l!rK#>*BE_H&3m_*^~o&9vR<9%&6EGGl}x#=G41cclmD2nBnTa2n8Fe^ zDQbee1E+EqpU$c<*O1pj>}wqyZ!L1(%Jv~@tJrF(*{PLf8U?2sy&UV_Mp-gmnRb)q z*5=xeb^6nL(&J8VuK8H^p4sO@ib%s#CIeBk9F53uc6GPNwUL=Ip`wp(&ARw>l~?us z<4MsQ+Z?Oy^bXm1P@40}C`ZMlrgjDNai{vT9$1Aj6q? zk&`A$duwnQXHN@EFl!4C_{HdTfhmPyiyPC+)+q^lqx3Fj^u&p;THU4Fb>m=@=!)P} z$85pSvkem*wl#5bUb!USGHp-L)-CzG(7}d!#9#v(0|UdCTb$k|p8j4QUS7U_-oEZ0 zpv@EirT*(%`TKf=dU*u-_;}cR`TO{IJ9s%;+c}1K2lxkg`FPsRDcZ~V#Mi1|?km99vKiTRHX+$@uR#@K28 z@xd>9huI4hBpJ@K#Hk$VXkWk*<+>&+eukRlQK2;*YqO$6qeZqXzVRz;Wl)%)F4u`- zBaOJuA8&U5VOTS-wB2*wUx(>$!p=WR+j`@Tm=$P0gRl_ug=LIaWHi{Bbsr07Z&hs# z5?yjlBcVHJt=7vuGuLulTh$S<+Vr(2ml9{@(zm()tr_?9ZS{PxeP_@H^^N_a-Og_L z#Y+?Xlm0U*E%fD3*pR|t+?L$QAkPvin5&qTP^z&o)TKK~Cu~c`mAglK+-7tAyRvf8 zM!`F}Gv^v6I51wBcROX_@=ZDG@8A0T!YXYx-}?LS*>C8mGUyr|5V-xjbZ6bFuTOWm zO_s@$-Krwhx^xj=nD(kH!I`3gFGO88L^e4{h@32xXftH$|By9-;YgdUq{=$+mFc@~ zY}n3p`m54cpYM!9Pnw=Yu}E>AxTGt<+J1QDD}gmpS66QJo9osq{qx_yfBW~pkDe&Z zC6>MRTi=w3^;w~z*_&-xucX<^oar^#@^JOhSCSKd2{}vOuPys)Bp|G!K1uPxafNHQ z_6T)##fb*4)eQ|~4b@~l`?gGJm0PHe<^5-K)~{KuDH^7pS#~We#AVH^0Kw4Y zzd5~KJGQZ=eQXKZvP+DaY0bQ&jBoVp3aVG9FKpiOx$*RG25!bgPS7Mk)zYIJ^HqE7 zL}V8Qt%wpVy`Z-6^e9)@H=AdsoE#8(Za{`WYQT0Mg{>d4#|m}*2}MM zN|Fehty#VCpx@fEK>pRe5@nvn1c%|<64fe zj*g8Q$(c&Gzo~9rs(r;gsa$oyfs(;AH1Ku??<_f;o2HyLZ|z)h}S5>RITP za>Ysc`lIQ^mRGmfo_N9;*x#k#u+-7yO-{m65zBXx5Z);f3Hc2diDLv zGq!H}PmV0Vs`Yx(Vdiu5m}@Le7+J+^`l|a+*&kqxUw`Ax-oUyB=6(4L4R=|l?`sYG zxNdUJGB4NNBC8G09yz1Jz_3V#GiZ}b;o+Iz%+~e4nOwN6*SDrgT0UQ*j5Dl8ZGjQr zr3D+7$UHHB zEyz`ls*c`l%g5l|z&zpL2}Z@m3HRUa6%uol@@8X?zE;#Q4X+>rZE0LTpA+z7wrf(0`Wl%B@ zI+kS;adD#i&CC;64b)@jw;VURrx3G5VO!M2wO3bWdAnSEA-ZvEkH$2EBa#9vF58^V zFP%Mm);H>;wRYx27KST%wY(e`9$IaW&SziMd207;@ddu#ZhZ}06VCNS^a~um)zd0^ zImB7_s#O;kpZ&2!r*7W&%k?YgO=xA{>5pZ5X3F#O zL-TRHiP!eEo$WlldupbaVsA_Y7lVL4bJVhR47;|hViOI#5~8yrbc<(s_}+VxQ3=zo z#quSwyXE{Sc(GgAje+6HyzA|6-bUR!W>US+=H=eG+YkLsZQr0xSXZDGRP-2KmY2YuJW8k*n;>telR~`FSX}Bs@ zEDfETY}(^1z#@1yU4W&j@b%m#2d@YJ4^8F!GU?*cCGlqrHow;mUj6j5TKmkuYq#HX zI@Bqs%J7ayO!-Dt^x{?BO&3@eigcM8tSONQwBC7EAgQ&ku)NOAfs_x~hR@3`krcRod(D?r3GApBM3Qmb7d;i6ow>-m{dL-nP4g|@A__kGXr zc}v(tT+LeLOTY2|_7ppow-=@uc|CYzcOb05h+z@K!ls^J`HB?RU8^oH z?C?9p*ITNkkrcfCP?(Eo$&C&{-C2_kI4!Pe72{G~xBLtDo;F+ABd%(nZyj&@$_!@I zGaOVEI>eB|>U8H2SJ0^sEWI6zeodbeBFZ>-6&q)0j$pV$;E@RRMI7xNV$z1S%+_L? ze$QbzGpp43xL#IJ^@O`Qk=K3CESh$!`HdaJ&J8CG7}hfC_`2*p*KnFks=LFd^PW7f z(xEN0GzG(0+(cM@3cPYY&T^-zRc*2K#zo(5+;4iRB_O?V%kh6}qVqjZxTv1sJ+LcQ zP<-PCmnRAwt4cXut(Yx;bx}ve>!Xt!9jD&dhtdWOABE zP-n($+s!wR=tKv3h2Lhs;S|7hL5h=$?IkV0};q)SBdQrkldPH`!VaWWlgySVWEsm?9pmEHx@{Q>0C?Ia=X|O5v#LGLRZQ)gmq(}X~O;9=-?s^#SXCv%@QiP414B% zWIW>k_1WCzUwQl#>Ry>w&*KjWJtWa^^dv*I$Bbt}dJnt8wnThgGvh49~YKg46A3j2jPwwAkczU)ygZ5DahP4wPsHc5yDt)xh za+lrqOV6vG)V(V@b30sJ*3NE{#<#ui?PaX)vuC}TvA)8Aah;YPr^uCgmtU&IKT6&= z$9DPUgKr)^Gb^@Z*tUqH!BzQS=F*uHZc3dxChNMlZ{oQl&Rd?GdA5~PY3g0yg|2n;Fe+N1lKY!` z_v*Xs0s;XNTn*P){uD1Sb~&wTb)nDW^Y1loE{All#xa`tMK}iOUCm=lYPVq6QpO$5 zsmxy(q)>*P7y3TwQ!LbQirf*kXC!C3~en%*C)XmC6ifCVgc-a#JrRUN_R-Vb0}4Uuzq5 zmnbltW#YLz_w{4pX^XCAh|XQHNJHx40>hOZd?sSiYYd~5x%lQz(h1d>vWQoPVYNy9 z?EA~zHz+Kr5?q$^=@~oUws8HlGkxtA99DnC6IitsI1X5IZg{lL`Xl!yojbcC6jNkf zw(^xEgmRi__^k;wEt5Frc;n%H(FpBD3Mbnm4{+5ktyhX-ST)TDE<&8cTs&d3T} zFL|)RzQMF8g82ip@qxLquWRGhyWdOoIvaKN^xaKy?w+<`J+HeKDohJA%IryS4XrE> z^eZyon2@U4(k**5iI<1r%)I65rC)XVkKO$IWl^wx+02)$E7lYubNK})5(Q2&MtD5%v(;B%SQEEZL&|kcSWRHSRfBD^?F;R? z#mv9fef(DKe(UUpUXhH_Rq0*m#w@^O(bgBS8yDTsSP{me+ZExe%(wI?U!chPH5`8W<+UH}P0C85w7JY~iyoP@ zlIw_?tc8D$Z z&hZ$H>Cn1Iz*cliYd_v=_ z6zu)HeS`i>JK8#UdHZ|%gm?$|`S^PUg!p;-db)ahg`TN8s| zxnkFqwI?E;&!6=*UFmhucAsaZ|Kt;%a7H*XZ1Or$u<*6BrH-k#tElTmt0``Qp`xp$ zPV1W=_wDmDQR>pT618H^PNi!J&i6KNZDPGM%X70t`R+a4vFm1+fz5pG)|-B_J`wQqV3?M{Jm363ZI#G_Q|3@Z~wR5h`uuK?T4k8e!j`? zyl18BE@oW~G1;-GICth&i|Jvjq?S(D|DA`c$-!lnlrL{= zuEwM(7lqW0N{4P_+Vnd$+w;->i3tq5<2O!G`DZO;@*sGzTx9;;S&MW|pUDbLiCr}7 zM8}rYd*M26!JUHMU72ZVX=;oNVYfxncPrISImkABUbn}z6ycqd_S`n&UfcOpLOU#w zH>C8Uqh?p0;Vc(HsUuvc5_l8+JFHeKO;I#DCXlEsc0sp8W0y2Xj3O69`wLywRSgRl zwHTgo)UiCo!r{{7_~_)3_RYI*JzFNqsp)d)P@$`FmSE^brUfgy3>A`P3>G?x9Bp;n zrXzA{p;scqG{IF70vD4u-f*eOENm@PVwM-b@GE9%G^d15w?b#Emmfnw>D;N`@-y4E zuly!n;J}#2a5DAS-=x;S4-zx|M~E9MvotQ4&{v3&Uy$5xOiV*#>7yfRoip* z@9If0&;P_!NgjTz?Xf0!exX;|2^qcqL*Ul=mTN3R zVrMj_-nji!B3kN5QZ4g=8}`NfBG%+H9K2;;d@p%@wDyt~v1AK|ozmGyXB;@f*DL3u ztaQTHmGyPY^0)SH?5u2+^Up_dyD`1#YkeUcH0l4Tnj7D{UP^Fje$>y9|0drcBbLnL z(93e1t`Kh zd9%v?0?&VD9|6AO99u*WXm2j~+0>HSyLDyM#i%V!dxb(>muI{enxC;niu+WTd&6`- z=55FJzg_;Hp|X2Whvzbsiv zSIrgK*R(c7Enc=ri*Na&t5e?Vl}%q`V6-6mZ0Z)Tho7FkKIF@=W*RH^CD}(}BH^c- zSf6qha&^fs&{AY@Uy#eWXGbq*b5R?GAf&p|(`(^sB!%EPiE@fQ@Q=yckP$k*B^e$-Eu27s3P`%{obSd_WU-LZhvpJE%*P_n=b0*sd7Jz z6ZSEGnU%}%^8N?$jQ#JguQ6KxY5O16Tkm(5z7`SG;O1~<+_7tFf{%`dc6O-u!s{v{vm43T18Ht3}`R2|iDn;gh-NuBh_CM1@EC&Bu3sz0%vUM9OlfScCYd&4PI zhrYd};kZD9V?$Hs)hf2j9gD&PzDCY5Z{6ayYv)AM4XduMdi7{3!=9{Cj)q(EP4hDE zz7kZ}`B(A5P5ucA;wtAEbUX^?q_UJ~Jbe{qvT8?H-zw9L3o$$I-7PJ;`^rCdsdkg- z+C!z;`>a{ToL6p~b#c`~h9!NiT%QiVXSV$~wXan4%I&{L3-<8`Xs={_;K^JO-rB-9 zT~TqX=~BM%UMUyC?Yqg4|Q^m=@&0?XVQ_~ral(jOH zES9&(&zWA<&|CMQV*9*VO3Ep{JZj1l+~+L0ma+6gYoANIZr3g`C#SWWGO`~t1%{Mx z>?_{&`$@9jl7;K+O*S$;v@j6jIy3L-hjUv#to6;l_vWVA_U#{?v)}$^2sCK-W{65* z&jvJtj5RYD-mU1mB^IxeY6BolCiJH%sKSgJ4UO z&Y5}N%jX?8oTe^sS8b=qw@Z_={2$Ynse%l;sSQtkd=+}{{d`mO^xu}+`U$t~zf3y$ zZexnZXXDpv?yQf0^>pw4TmBn&Ke@oKX~dJ_o++`sGeU4$4cD1@Z-pnU{^K>{mi5(n zcZ~&e&W11A|B5+BRgl43?L(vC5}s1ap0tpyF}tId1bp$T71(oWRo+B5k)ST$d};DzfAmDY=lOl^W6T|E>kQ-W=W0z=Fe-n-6vYr{p0(C= z%XOtFR^NrC4sNEr!3L5(%^MG#xOBiI^v2m+GatRzy^yrkl{s#L%AdYug(C%1iZjG^ zKPcpi*|u0`%dETX9R3FwRycG7J*ttFlL!=ZTAiiNrR20mN>=J(n9fa>ZkcI@U2Yq* zSgH*ddH&wZ!O+YRo_UasVaq&U_M9)=?R#z86(4*5pWy$S(af9YfVnW|se4Jn4_{1; z_SEcN=CD~LMC|H{OBrH<<*cINU&2&GPbap`=y7pKNZ-+-Cic0SYt1BXsS9g;Zouf8 z1{O=nN~VTw3~p*?vLo!+wOu!^>JanI5_R3GwfnK^+PwXb^SbH#Ff5F}~ zTZSoVUybdPs&(S44~ctyEqm1Qc4E!iy7%d~g;P~7ha7TKSYkLuFa&fY%Yv*BfzXYn qQAasugsq9*Y*MmX^zE#zQi~0YA_@h#wWoAw^Z1B(y>3cf!T+aM6srm za~LB72Ll6xp^w7Rh6@uy85jf@7!p)8`6j1%YA&6!P@{6j6b}&Vs6pq9DV;|pl6wq~ z!3YJD6j25S7KR25&c4OZJhRSOrc0>z6)mvL^s`v5z}^-3z>@ROSGDB4Wm}eI=bh73 z<=~BEWnf@paPUxU6$t_nNgax95=kA3?J`9t6qnB_;?i2Npoz=qghI2A(aR;1{j6TD zSlnmzN@L3fCvM#>m%MxouZAVB+shVPQ+&?y`5Y+03HFBq0|Sc_n`DZB69>rn4$WmV zinxqUK)j{E&;ate`$Q4XjUuNv%ACEZ;{Qn}P}uaMv1@RMZ)j*}XlZPCS?cw&((7fl zkuzGOchpAiXpO$n8vDI9QKAise$?Lo4nknBD=;!FP_~@*SaXq*)S^e0idRy-4O**GH@qm>uFfy=!T*I&+bJj8plomNHl`wM1 zIHAShz{KEiyin$Np^9se%JCu{c5n!vU|`^2a0t>lT4ds0Y;wHV=6JDUPj zbIwUVo>P2I^VH0v3ua!JRea8qXVy{(t5Rq-``VS4W)+{4d_ITom}KId;&YjoX0fll z88N%~T;zpW&sOXdnO%IYbINS>tvf>?=79|@KDRP%&bfn@59bu0>%28Pdnae?oZ@po zQ|7!o%Lx)gPd*L|3@nK^B#zB(QmE}?OA=9BrZ`!yq@Qo{0>cxUOXPa{+`Lvc2Lwr~ zFD+>T`&@y6p+x|kieUseDMM26l1W`!r!+R7F*>aSBGw!}XZ3o+VF70z!!4J*bWE>? zCHHQ9Hm`V{rAPMCt=FQomre=t(p(A-KTrlyNSWZsCJD|YZ8M5aX)a&T#03dXNW^_m zIWH)C5ec3DC=)288YrZC(MUJg*fumIG`uV~a(e0Q?X9slO7CB74y!;{Vy?qOfbAiEprI z>_ySi%VMd)X0ew|Q!j_6UM)+#xh*w%du`-4P;PZ!e zz;Iv!k2km+2@KM`8f1DkNH;XZ7JrTj4Gq0&;(OVo@xp|u3=EPC3{RFUyHdp`lr+Jz z(=mg?^N7sR7^|0a7RU6oPf&LAe5)9IMu27Oj0>KvB3B+oWyuzYboZ`J@o?1Lb}UHo z=?Zoy=P(Y2g^~<>#~EdOnPt40!G#I~gXd)iUlGQ$!l2rMfq~(`MH2^MTL)oRs5C{C zj4!iEAd5*LqyS?8S#&Xk@uCUTE(c-P1IDfnCZQBr0@aMgu0T^pe}8~$aS6HNH$v7c|wgf#9z?o_Chv*Dk|ewoDsB=P(pEL}4&FnsV4UdDN` zC5y@Ca!ckRlf+dZ^_aMUfuVtsouPq2_>=?OO^ZE*7#J)jr9?6?Eby3=%E-`=8aa=h zfnic=r5vUaq=}$e$k?F4z|g)ZLaadMG*e%4q{Ac~?u1ANU*-xa2N6b)VkVI5q)k-C z*fmU2R2c+V86FgfoW5id_{3t`(#%CC3U$0MyG%^YoVBb|$;A7zi{QNHmCHEKf3~^Y zqS3V|lPS=|myv;i6%_1d8D2Vk0U0N}7!*_(4m`A&_Ox=5M%S{;S*uPJ>YV=U5-8#u z92z_Qam2Leor^SPEnBrq@AM^;^WZ8fv@|wj7F^iGSH$Fogfodty;%@ zUfA`riEn6W>~+>f8MBtHT($1?E(fr}tEI8x9U!q)yVkvC0x1fOy*@RyA#>HLRlC;d zFo%SK`H~A(t$MX!qeL`dkEKh3jJ$N0P77jHoI1&C zrNWY+AWc?=23ZS+2H6OX*0wb)44)VnIFhF%ow0nb;^bxcY)-L|;!=s?bCxSbl0i-6 zDU%GJ&nfovIys~GoTd8Glrxsk=S&W=dOoL^&r5S@$vMmCOQr-ly_i!Rc_?#sp zg99YAyK?*tghIfqFZ>;eWj}@%E}!ppZUL8hgDoRdNTY z`qtrQVDK+sV9?r-SlTjq(Z&N#&S6ZT`m)84L$gI7h)r>cfRl%2>jc!~&)87Fz|bH7 z?V*_UBtlt*T*$o^ME`}BtQ%3;Yqy3mNSteBc8F~0HD04KSG12!TxydL0|zGqLyu#J z;R}^1lf1k{oq8-aRHsgh>RRj6VaTy`$(5)aL$ULg>-2k|kH7dJK<6 z#c(Swof6fpyG>$tj^dIjLD`1KqLPihwoZxaHasSgt>d+GN>KL3qY~M@t{StWL9*Fv zO*NkudvClNmAq!F+Txx`hR33^*KEC}G$qLBm`L!Nt=DF?7##a9k-Wz6dDLW~LqFt# zbvIs($`10!@ROae8np%R*^AVClY8Q=v{4ZKg}nLCphOG$lw2!ewAszziz=l(lq^_!+OWVR9ES@^Jv?*%J&5 z0_+>NT#H)WQ*_GHbFH(R)UyRkZg{dQZjJCxRd77z={2{BLz8V~Yme5_8Iz|uot_cI zlca4}(qrgu`834oxC8?OLlXl7v!IbMhloRCBM*axgU19W1}<(M*~6|54tk1<4=gC~ zu~46D#=zj%0Uk(zw$LC037}f2X6yZ@j1$iYbaot7FkC35p|y;;;V5fc4a12GH#~Ol zXwYMhxo|X=-HF3VpeaJefsxa~;$fTmy$>zYa~1@LymA0n9dZm07#S39GAJo6n)&#} zhaU`_f|81whL(Jy_SyBTetRp2>2`hk68YPCtLMpup?`KBP~+$b{laC& zGe33F65pB|lXZWrVe**$Coz8;{{#hf^>*d}p&9EQF#T+a2wl6I$7ONHqK-QrumAts zSAOTtofA?1b6z>Th`ua$Y$M~Fwu>&^w#5RMdh*SER0GdM=C_zWu5Iw0ut#78=Ld_J zYb*y=Y|U6ZW!sAjQ94n{qDMu$J9>|86U==ZJ-LfvS%EHXWa>ZN%S8I3L zTi&`Es9+Wq_?hv@yjHhmJDx5PVL3MMQzR zw4|jalPQB@qFsE)hL|-gS7ov~iUw}Erl6&i;d*4%foAQutVn1MXe0cP?3uo zN=c%jt5>--ZOo0nniYC=)vki)N0+V&&5ei@j8dFdsN;Rkit)|7RD+ArR%zzH?{4O@ z`ZZ&p$CBgq3Jy&;`%?Eu z_RYM+@b8(~TB@v#yVEVM)b8@|+}Jep6Qf#$5TApmLyzdf1c|IuF`)-_zs2FBknCL4M%9GUl(z2ogqiFI z2~6G$)5H%fR+V%+(Qta>jV?2ht6f{U^p;M)y(vp}73<;~N>Q$7Lf8K=S-x6gf(^r& zc`xUuy^JpIGB`VLWqjJ{=-EdN{xHn$Wz2|VNSr3f?aHurg;e&Mo~fbPq0+7wZ>+jh zbuetHhErs!j-zwsM&;Fqw#di)3<@c0 zZ>enR;rX3$)LKyZeh8n>#wAN7j3+ZNIP_{w3~JNSoVGkjJio<(eVV$?1kPu!J`;7A zmibKj`tHsC%PS@_z7EsAeaJYkD9Dg!^TsV_Opb+A3zlBt>d*+|nPFg-(AvisEMeNE zsq8wbrP1L;S;qQph7#*7SX4BeSBPj$)o^IJ(fam+gED=NbRc`6(LlZ6-wH)hhoR-rb#NN^(CJ-&ao3MJb?yda)ds{`-=QJ*He}3w7`t0;p zolQ>|9iD4%UwZQNORveR_Wme$$>VnM=4xTk$a~-TWa+KUOv`^-iEY|5b8X@0Y5N;oIbL&YiDhNGbC&UFcGMOtmzA0& z@i`(PD_1qGy}Z%MrDM^x6{|VJJ)2H3ada6?TC;(3|Eg7emsc9Boyqv8iF5kJ$->X} zChDYy2-!!}G_>gEu!u4LNp}mHaJ(s_G{clH&~z%3w&>D3vFwQgY_1|~3pdEjEE8aJ zn`SK=5ixW9WSzyP5zNhB+5XInELJSDZY0j*XUyPzAXtB-FC}t* zY)E<0+u*sPD@<74LTq*TFzq-rI zJ-|Ar>!w`6>ejUHUPmkZ-9HAfM;)(i5H)98 za98rdQr@fbq5BTWee9S%eRt6BpMK%%Rz8T+T*{Ofsd5i%u*R1W6t{=G- zr73$OYVp!tIkkP_^>emcT&a|nF4^w%B;%s{+i`pl`5A2-X?|>kH5|Psu1iNzL0T!ww_~bxNFfg1D?Yl(pH*E^(OQi z$Y`fVh^_5fq)~83Bh-QQNY~MZgLp(ml7IPwKzoM+0uv4~m@t;N3W_d~ za$d{DI(6%4(PqpoA&5jkHc9g9kj!~)UK>+`md5)|vFZHff`0&-I zG$DWQjlOU44h|L%o-pXxHGH0$e}wJz=Q&S%Qn#+y{{3Y^gGkm?uA_>&rxF#FS{SzU z95EDd73?pUVYoA|RQvf}4@bwC&FSye-h6N1V0~D@AS0yAAlA!rk4<{QT84)L(!xh> zp5RlRnb69S?VFsUx`g*wm+@DBm)+kP-?Wv+9uv>p5R+#1CbOY9nrHh@21em!5{-2# zFJ5&SwREyODTj%yQg{@haD}UD(+-O%FYMjx0yoFEyX;h-70$k8QmM1{Bc1QkAp$$S zuJJDI48K)>tobkdhb_k#ws<~J7PN?RzA3ONByY;9Uo4I`iC0c=O&8eMuqZ=&)uJTs z7mTO9vK@VR1dnWNc*1&R-bBUV`WyH6)a|-$Y-Rbw`t$7T{@)qBCd~2SXpr`Kutz9u zrcp=RvPHqh-J&Z!7IJxSP-?xDyL)xQ#-NL{S1&2)E&94w^0X1tn|Z$MKPOENd6Qya z{Y>_SQIMR7^_F_ZX&a6()Oe|6Y+gUp(PmbKo$AZ7uhTCd-Jdf5l6L6oP~VP4875M$ zn&0lXCrY#}TdEk@-tYc79s1YE@Xs>a0HLoq;l8x!aa5Q_#G-;+&W3#Gu_}Dn2|D7;4f^ zN3PsB@#H%9&8cC{OMUJcfB&*sntK)>u$7x0CCJd^<{(JPh zjV5b2GJ5tMkSP++o-%doawgW-ZWnJW1}(U8r(pe}43UHTlT%$AWsWOyx$Kb0w0pYG z--4kh&GwAPHeq|6*x5mA=SiQ;_p-Rk?%~tmBhWC7X-74Spodmo>f6FAhq}@fU1Uu@ zwRdbg;j&^Ki_7XKUle#A1w6a!dG1cswyvny&Iq0(^S*lK*RI~busv-XB=`}}18 zp9*_<1;e6@8LSG>z-u6`O5 z-E+drMMA*)9n+mzD_@^ftf*I>Q?DCYaqL;q{-&dDclkHmlxZyEE_nR0ny8&)YW{F!%f+54xVe|YQe zRxk4_6;A)hw*Mc4DPyN#hS!G`EiCKj^28psS|cgAbd{`Wq$RVp!>SdFLVH$(h6ajW zzty`UKxWOvry5hLCol4sdor!GIw9}T#{GL#Uw;?+)OgsWwyr@}F@r^nRVG{|#bE*W z!Pscm)gP5Ig1y2oMokghDC&5Tl}kzK+9E-gCjmK;tcwJXq;1^DYRDM&pZQ8xE8CM( z4vtS&OPrmgqs+w``0k2t3d`(*M20t?C&l>sduxh^uFvvv6m=D>Zhc|+;^>U7RiQ45 zIR?+JFW2Z`2^DL&aPQxl>kMc5w$4Af&3zvP#TB7k^ zrPXbt!=1#Ky1#)!slun{yfxdqPi1T3_t-;M-!c0H%$Ot7n7@wM|JQ#H&Zr3?H)N*m zx~7%YxJqACRA6nAt9q{M>V_3vYb*@jmHmi%(09SYSx7(V7-jnMSq4a~G{WE$o_K`t<#etwG*vwIW=uu8O*Pp-X79fY-vN3y$r( zy44gLCtlmX_12}X4_(p>cji6Z;1xA1kz22_dRe&W#wpI(%D?#oxD$05bXf&*LxfH0 zcX2CyH+}ibvo+v~Sm-KMH69o5jnQjDL|nCf1^9ivVgr_Jx}&+iGsHQQ@xWE4JF`OB z(;_uksv6!-(@~zV=I7;m)r?}Hj1H$I8>Y(`TF;)XkRLxOx?H>|u69b6)+s&ft6?IU zoJ^jri<}oX9C^A!{A1|z3ofgwLk(w!y{bI&^O#%NtJ{b37|zTJoph`ylC%8%SDrSr zX>WD5RQ~3_5OtG5$B${Y+NYDpQtAcYKfiVPNYA+g6M7T-wi~bVnAGXER%LHxiSaJC z`DS538drW*6sCBK&9G2(_;%}ajwHjLX|0{Irx)>TX{gPMyur{tE#T-sRt-bZX$(4| z4}MwAEsc^5yB0g!Ws&lVMH*S_6s9zBJ+%->J@M4nzYNz7wH}x+RFQC;*JS#tP5Y9*XO?Dn9}-`9 zB1?CxM~Fyl$;Ek(1zF%79(B10h`r6+Dd~#ZGJ$)emDu8JW&Z+ba2E+Tl5G z{EqHR^w?<9`jkCGJ6mvrM#3LU!P8G)FHVfrE?Ka9)5a|S^|~vHTd#0m4OtrIxLULK z$fb4SVccqb3$Fb1VJ)=FKYdEK+iS_D($&JyaS40yxCVGN259`Et^CVQo&RqC1D);M z-2H>Yf}cXM!ebPo!PiVY3*_wfzz^LGpI449>@c1!LHKaY7u`O%7) zN!{`fIP2^g8aAECc)Lb&v!M6o?~=tcZeO$tTx(=(%*ep7LdnH}V^PMI%Nu28E!OXs z3I5gF&YI5AnsnKQD_f2y*yt;fXS2{{!>S>)@ zueMELdHQmn(1}FnBqJ`}5}#9fQ?m`P8ZxZAh~IRiig{8zunx&3(N0pH+{GBd%BL0U{@*Put_hxdeTvvhQ5BY|jni2d zG`?KqwN>Y&pKHg*hPOKuI(8X)cEuciIdQ`qP8Ua&%!yIWvkFx>!?>b!Jn}pn8=Qqt zDtS6(Io|#z)y5Yt%^>0_*r4Jl(e{vwSwY2RLjuczTT@q+b}Z89>If1Q4Afn4g)wYv zROo6}!QMq0N=a+hg!zQ}X$m}GniT$4K~2B>wpOU=O;L`+>#lJ7S}BUGT;-L-sKWXp zYc7xT0=+k0ti7QM2N-xNG!J{s_`d&jujr?<`C+@Js2_-X;Q2#;+K-eY&R!c{EdR-J zfoaYxZmkK^e?H+pIkQIfx3z%xeofm8{}=-f1#~g~n9085&rB0V+qk>S`en*rT*xwK zEKO8l3X|-;tdYbd8I^Zp=I_%CNAgNNkM&g_sLQ!_yQD@tP7fn73G@m?Sz^3pg z^Thh6>z5jPyNT|;zMz(ocshT6@oB zQ|TW5fHWEA51z&cVm2?)D{{T+`d2M4tAG3C9bw$3m+p8halS=(n(v#u`ET0Jc{<%( zc=&2E`-;5t2`!IUZ?U4( zc}v8!)X2E7ox0gU+NVzx@%uQIh`L^^Eo1yLEs?$K&tbW^JW2HlV!xis-D8gkaq4#X z&9&xF(!SJ1HMMh2g-%}?GXL~u(Zq`lO<}4XR(!2%6DJ1fmU8-s3v4UfRl*#)zm_v_ z>w-&c%slNgS?=8F;AuZDxM}xCMX`%l*)N=7`oOe6)A9MjGe1kaPX1fI)6Kp*_VulE z+dfP*x$;-^M52$tmcu~`QF?X49TszVa#bsNAFunmaYd@OyIw4PsK#N6~C9USK!sFO-ij6LE@~+K zIX83LUarHNR5;)C$-3XlU($Nk-n zr+RNoS=92N|7&>DB0Xo7C##imtZS<$OLG0%y!y>_5RnBDLFRV}Fn($)o) z=*Htu^MZljyg!5OY+p+u{z8!;MO{ApH*+TH^jJ{@MO$txXl)GPGk0C1N)=ZGMEnc0Wjy)>dloyM#UiA++yo=!&Bf}KG zOzt<^_#fS~otnk@qiE@gE6vYp>L0lt*>u~>!jWr7*|mc2AKrSL|2FyVk+W9Mw-wj? zjR+Mzx6|a*npkV)u6+U`tDIiW=$M(Xb)AC1haet-UZqLlA2=D-H0|Zxz%PGeTh~^d zr6x}&mz_%FXAIF%o8z#cmBHto5%W4nGY$W;!fZF~J_A0F>YGW611I_mFl;Gm3_aC6$NrpcckJr$Gd@x`{x!>`mEU`EMdXl@ zuZqBjb1!%5>fGX)|E?n~(yRJthU>NU`ZAeY#oMJe26cyqs2VpWxHv2j@#VBIFHP)T zx#}%5yOqzh&mu?oUDy@h7euZpX8X%5^I>1{s(ZIq-O5xp+LV@*o&J4JL1|9gq>hjl(kJtYU zf7`qL<%{q)k~^hl-QCVp{e4pS#dFuI%NH!ryM6WULG!eULV2e1X3msoQuwkYZJNt9 z0iBa9B|BCvIItq-PM3DkVuy!L4M$T0*3P&xS+Q|?fB>&*d3k44<%21QZaS=RYuKP7 z&S|z#fn{qTr$>|FLK!KB1V)CG*!@wVD(#N$t9357rt-{Che3TsoTGCHUyZ*7&q>;(@te8#KV=rwX5AFzt(`T3DpK+{6kG(%L z&F^`N%*V~!{e^eEUBIsJ%}ec%#RL8gjS)sOpY{D`V83I}&@fR?i~nfecT*+f^^(b+p@IW>(BYVA9-`A#6u=BpDE?^g73IRw<0fSMg%+%wp~3 zDJvw{cBkoBdc2MGOnUpa?dye%4M_(k>HV+GZ!EarDeUaZb1cE7DR=4>0R{$XF@vlN zBAZTaT=J6f0OyvzuYT%t|MDHk?v{N$dESk$VpE^jGqB6B$uvA=v4~%x%Xh(cUhST= zgDYKx{URTG>oKmBlaoOEY>-V3*&|JOA* z{xCT98L~YPI?#2*H*HPnqGbwO8eQgQh{mnm(8LrMFz;7a?Y;ZCv$wxHRj;?D$(DP< zYLhwtaw25HveIudc};xFTF}G893V8K`@ojM-RtfZ?syvM)Ym<&J4$zvh+DUaYiDCA z*JC!N|Z_h#P9WlC-}t#`hboekNx=El!27YhECbb)40#a@Zj%(XN`KB0%U>kcy(!E;QhvR5E$8X5Ii??l*k;6tE=_V-8~HLy z^m*2q9F3&ROc}prXaDM4@;W(v;(slhNqzq zX39%&M3mUaw%u45F`_B#DtUuShv|3ls{djr2 zYN_Js%Ju%|y?1VBIMdh4{Nv^lnc&6yZW@(tco=Ri$>BYB-FK#vy-Dh#W(<2-aykwR z$zPY=y;Wm}a_ympO$O7VUq?i2@(X*Tc)7~=G6Mtmn%NOYSM{#s{J3iallP{MrCR=l z9cwFiy%>(nd&xQDu$<2J`s!u;cCT(o`+a8&Tg!96{5(r?`QEu+k4o~VEnglWDw?`9 z<_dF{R*{^~koHZymSRb;pri?-o^U>}4@yI8w*m#Pgu-f< zYq#i}MWGuaE@o|!3T-{4z>^mnc}Ohrz>+l?qFqOy&l2T4Gijym1!4Oo|Ic+Dwf(@m z|G{qg1Wray_Xm>>v?(3^+IVn9;hzZ2t~aZeO`jB08n#7y>Xy*lrHk~Q?U{J@`~KwW zv;dYP4{u#N^;ySl2Gf{>+YC$6jvjNf zsd&et$9N-YYY6+Dq>j>kzkj}*D4BEU&>;pJ7tD~jzx(^ET8tgGs@k)I3jb4t6ONaq_+UW z!$;Zc1+oK0C+3^p|HRpyTJZG4Yn6YGn2xl)l)i9z`W){C+in=tGQTP2*>d?iqgd0S z0v0JIlZZ{;M_RTYntHT0F1knOeAHQ|jdx;SsIG0gtQ0VHs;Ks)+wWGbk~rddk}K4y zrnX#%QQ}LNLp z%vH4a;Xc{O_(hGYQhumM=(Z~@u|4+lX`EZeLHRTDjATb{=UAxf93_3J_r=Q*u3`p8>ypqKRC^n|7Qvb z^<;|B5!y4^@Of%d=$+7)=_hjxD4)?9lFr>zn5JuFi52wOb<|7Bv0*{+nfTi&n&C@i5$J zTiLQqed3$s{nBD>vz~>C<$e3U#cHCXnhUUn&KiC3n-+?bn$sHHlDno zsA!m_;`+Gq?Tu8%J(F75VjiBqdv?-9mM39Ts&AP$Y%5|YQ06KKEiLm|(-rk&g~`7N_fU?M{m=bgoBZZqSw15<|+s@DJpN0y*-Olt^d|EUAP1?Tv)_w-j z4aXS1FjwrYy7^|C-pU2+$uBqQU$@@9s!EGPHhRio0oKNZ(A7$}Z4(w}m=xux?2+=^ z@^w4Uo~BaX8U0%o!UI;BttrhmnIEFD;wQsdS2s2XO`&@ci7yr$PC4HBo!eJ`QC39M z)_MF*+}Ud$U1&*cPi%AJTcxz%sA7^zkkxtrEt$KPW;5+++G~75T6EgY?Nxh)FN6xT zyHw5pIxWX&Mgo(Va>BpgeXrlH6A_L|72L}%8mN`zDtdkQI;~@qy23Utx*BokYSiWE zE334^uAF}twTa9$~%cghnUXH%s zxM|&~!15P+b7rqvrWYEav`TOPbdCK}(o@&iR;-+05X8o(QyJ*0 zzN$m$)v;_Q_Juqjk2o z&F!}rzN)WNRM(Q{(oUUNlX*w;cHWZKfVCSpDn*%?b!E8z*uB^#d+kQn39;IDpIb7% zndZryrYxLhpWQa|Xx^DaIr0nK^b{BlL@?B8_wPUOljrHRnt$4#7tGaKwdzHv{+d9S z2CbmBV^OY!9aoc2&YxYMBb>-;$Em%oh4Ih4!%jI*7ks$&b>2_88KTM`w$?VZ_A+L0 zY~bJgaB|n5E$1#4|GQNlF4J1)n45NWohTF2G=uPKQBy@SIk%)Vgb53mtq6Gi=%|xe z#D0b+^H#FGYQ2Af-Mm`Nx?}CnM!h}!27+N+3>!Ee>^dkVdd}}OZ;aNgtX+S$#R=}o z2;Chbx>txr$w+MDfn7IF)~yuO=}O=bIz9XGd8G$eh4wU+O3s+btebXUN^G*kWhcMF z0D~jq2~CH@*c^mse7{(=H|XeEY1>w*owickOLey0o06)y*L2m23|G;D2Nw!II8EB? zC3t9>c#6~7I%byXH&v9)RJMr!jx;u9-21}e_pSPdO<@j9A2^vKK7X?ie$(+_*UfpM zt(*3BbL8?m_Bi$W2)MNzoMFo0#O<_n+Wt?IWN$>Nh6!xj$9iYlQN`tZCeD}K9kbb@ zvG_6bZ~X%&gbx+4=rDiVvBjVw&i9(?O>a@7nSvpgw7T4SIzFAVx7Xdf=pcvJ^lr5a zO)K+${pPyRzmhpENt2bo+NQ!_+HgmJsq5#~UAIbWLrui{E5Hs-ZqYC-1({d_c!iAB_i@88>|)KBMXQixDtm#K~{empDkn(Y6k{X1TJ z9Q|_X*S&9yn+$d`#Bh93I9>fCiZ(6v;?f+Mn4_UrD~ zD(h|=1@Bgv#`rN(fjxV}sZ9(l^Y1Ry`xww(U4Jya+$v7~`Lw&gzcUJ{=I|W2#B*V* zL*cHp?LT+UpR|0rdT1~&-_p3Ln@nwmLbtB7IDFs|i)ce+Y3$9^J-_%m8m7*g$M9s< zO2(2zx#|twrrE|9Om&0j-er%N$eqBj$yVXO<;01NDxF0ag>Fp?U3kJP`(V)OMeN;c z!mheHDu^tpuUfPwbd&DF8`tx$Gu@fC(xvatPuAP9#vVQoGxr~~*ux*7J>!JHikT1A z7@fV~F`w~b&&7}wm&mKD0;*$W6EazkNL@&{dLwCXoX(LM2Bp^gho7wH&6_uc@y)#4 z!)kuD4-!_J&i46UHH&%qcSf`6Ob>!pe!LW_y|mQDHfE)_tLwe$?Gc|0w(fdya#O&I zE}e}E*VZ4=jMMtCMD$#h>eZ{~xPlT&df$s}@W>H4%6O%Uk)17M$KfdbV+xI2>His4 z3yHZbnCo#slz-8h_{CS8G+i&Q;))6k(T;Ew-4YTSsvOmH)oz^r2(wr;fkw*xDo{x6-2hKT$`b~Htb(7?72xZ%o_m|xx ze7C^v`S&;3Zn$2=ytPI?Vd@082j9;!UODn!Y|AgxiMzfehKBkEUe#{WTqV_;aJ6Gm z;Gt!$&TIYFX5IEPPul(ARsC(Pj+SKUHx}ENwq*U4eR1MYUg+!h>l}MT-_$m=Hf-g1 z!gN9VHEZna=u|aR$E6bv-73)PR@&y)!gr{ZA=*WE#VU^&)iCa+3w$4%)^f0jIVP)K z*JM~y_ce4;?ByBqZ{2qPTb8(9^Jep3b^&)kwT1&q4M$#o70q8MdE-aGP7R~0ULry* z-n-7YU8vO-T%2)qQC7&rGTrE(-PcS0>!&_G$Q8l3Wztry%iFTz&gcA(`gTq$Cv~T4 zz;5;fPf{e9FE}ym3|n!#`bhCa#f|aYGG?-Ztg6ae>kEZGwQg_qG|fL<&CrwPZ8Y{*_;gRGsJJ#Mp_&8NQ8Cq@EtIGY@WRTUSR48*7eLRaXp4&ToDmQPmdm9 zm?F!2??gak7>~k}u89Xd5-)u3Rk@U~;miSze^UHq@(In3eC`h>F}!!v-Da|QvPt%L z&eYsSqix4rXS&HJ>uPklZe3xu=0?1>Y3-@?{y#nch`F~Uc8D-MNh@V&QHj5_=i4h* z1>*Vgwz6xYf}VKnYNgQSS+2p3fw~E<>zA%tl+b0j_x0|-7Ez(9 z`cvO0q%txelwvbt{WEW3&bv=x|CPj6=jcgV{Sx4>@zkx5UvO5n!C~qGFN4=c+>-<{ zTrX~3#kb6M(|%r^MS|SgQ`7la+RBBi2kwbX|SJcWHKR!ow9# zOBZEn37ST4UwhH*6sLs2#d8NFZ$6q@CL*~u`{&dkP)?U#5$*WQYG>LLmgkc=+rKl4 ziMl;tQ+5ok5S}Nc{OIKT)fc-<{T@bXWs9m>r@T#B7`ceES@rMhX4_-CkKNz>&mzv? zW}The`6=qn{I8s@{cnuDcu|7!$-Ik^y1%YoJ8)3%dr!!cT@PDk`jyEmq^q+qTwvI@ z>)IUkY8O+@t5Ja>tE#Tw?)pCY_WJ``o`DfzVoTiq+Q%6F=1|I52&S zj>f`HzQt{cFC=a!O0*S5D0*Iq%&xsWHEhyN<~4P-%rEl9<)X8%+pkpBf1(_BkG(@c ztWCMV_knWeOc%GCRaXkLOivjV3iLLat}$8MYG9BpkP#AUxS~b)fym3(1vgHd3l!}> z%#m2Yv?i}q`vP;4_3g0jx0q_C6l}SB%j;_HhD{9&Oy94jC>)PoxMtO*TaVUh-&NA) z-n#PaB6e#Hoej)_%Qh$rPKx?<@sY&Im9j>0J*+WlrSH$YnDx_hJm;EtF?9+j?S?YHgh7CEZ*--ZNPjxpo--*&Mq@%(tOi;_;jJ(wDcGl;s_Y;%t!Q zwdKuQdLpdrR@BxNtxgv^Ts=iEZkAXR{5mL9e4?jd+u!_d$JSGA;T+SZX}o59GwV%!zAeD0jfXEUo_7T>+UC`^3mlr`a} zyaGiJzjL}8E>d4ETgPU}wK&4Ts>}6T`SV9iccwjL{QU35{)acVrx!5)4XQtEY432h zjX6N*ht^W9>$VC(cC~8R`?nWY1%|b+(mJZz9@(O?`O-R_uDFBWIvO=P3S_K}O?6or z1=+GvA{ft9m5M$I-d9+*HNjB$ppjig|93{QLr)GdT;bSoPjaSs_qC;*rq)_pw?&=Y zH+4&g+m>Zv94W0+{8&Y`PjwiSoLGI+^VU>56YV1pW-sP@(zlZD%#w$3Z?X>ml6+yr zTfO-|!`7Atrv;1>3zUr=SMK$hxNcFHNc6{ySdFe%e1~RyTa?h+wJU^GAX3v!UHQ_o zFRGP{$~|i})RrvMxYBfy;mu{cAGg*wnX;b=mD6zA&A(y82C>GQ?0zRA*7)`<_m^Gt zaMd--qqh#RNF7|IXI&7W&oC`JrUurV+& z?6o~mWa1Oz5gZ!m6X@gR@9*#9@8j?7>E{>V=_*F7Z@B6=Hu<} z7aSAn7yhTu@%rgIuMV92SAJ$vmqg(Lg-^^mhZ+Sn80Re2K6QCvi+1$JRZnYva)gSe zrk;GYNNi%)t5v#U7Z+`u+ZY=arWf9*w#{XQf=AyZey%I?p1K~I@YR3D+pjUZAMX5- z$u;xl!~G1I9Ma4MimN9_ zl(9lwsOD$90u!)^!C1n67GAEn0XsRfH`uC9vnv ziBF$fjgmIzM{Z-7GijpjW@G7Uf!%hhi_PzAnCS{`uV!3z#*iV`)8M+4`nB_=8XoU^ zop0y6to(OJ@0C*Go?C@)Tw`;pMayOy^z52$+SkQ;dfMVgMnyfzdyW~a-|6yv@_5H< zewjL5iM0#XRCzC+eRuEAEgL7@vDj(AaCqn5CC1t=shyFppN5HNTV2pzbyVziplGj_ zQddOqHO+5QZHXM|LJ!M39JOOO&dj@dMx;_w)~WtY(fKsyqTQTT2j4MQOeQBg~V&UY0-o{xyqwhiqGm;|_~d*Q*((QAZUORxO$uDHD-wc}O-(G;GGso#zjA zF`j8UddfZiT4Ph=ny*};_fNXYZA(~mC)0oJw?-+RL<^?Cp3uxyJ#DUQ^cJsi6=e6| zx-@N-JHz_et4XCFkAHd-@L&q_RHc{K`vjB{ng7gt>Z5u73-fxS+y$C&#q$AhB}k(MUSQiEOZLF-DS!W#C6hf<^{!tVP`g< zeYsX($-GSWo~L>BhhJ`;_i{!5H-mb?gOC3*xy1?b9WbBGx$pnKN37fuL7{Vl{_m7| zbUcbQiPgh1XzEL>j7@!==+Pz?F$Eq|34~6K1 zEi6&BiW^m>EnU|9yT-7ktu)kmP42^#>r&T@th-7rEYxqa-$)QLU|25hV0F7MuS05vX-Rr#%Zov1uzLH5slU6T1>Bz26?1Kl{zRMCQ8L@tb$=d$9S;ufDT?X07|roU<&2L1%5l z!I`CtHGeL85oq~YW2sJPsOB{d*Vx?;6#TOSOsX_PlS5ZaS?jSjE^*+y-rTnKTCa)? z!=Jj9X@`!T6;VkReIxIncXdirMomNOh6V+O@3s%7zI~d)ynlLSpqKCZw3SIy^;mRo zbR{s!99!z9lXNtWmF4a0PcGppN={RSS+tTEu5?X2r6hOsz|D1GJVwSRW>*w^k822H zoX)YuU*XKNcD|6+4I%g9>O4;=NiK5h<_t?&leI)dhwB#Sn}!M7I8?hc0v)0(6^k?? z9p41(I|DG>)p5F&oX^mPiNR0Ow!8o z2)%g2tjp~p%Os}WT-PJ3Tkrl3ZAqVaNvY+-ssHs}+;8eiwLfg1Q*iR;x^lw@@0Aii zGU+(F`Sl%eV&MKh&G!f6!p%o_>H5f?_g$&CXjRvWj#sO6-2yMJxa0Zt?!|k{LWRq_ z&+x^*&|>&9?`kVwnMB6r-?o$4J+gKDuHR+9;W1UBaT4RD`&RE(cqqG7N36Vbw5UoX zHFmp}_nOifI#;<^kFL>K6fQC|ziS@X_QwW1$u38}%RJR)SQ5AQ+KB^^7nrrCz4ks3 z@X_h(S4N?xrYBJ>UQE;H-k4ZWek@}1y2+1RV?*vnt-qS7UwHWY_wV~xt%|x@Hc^;M zZ2g*VeN!UVXN87lZ?@sTQ}mVV$;1}3y48X9fhSb#GYikIQYtc%Nd zs|0_YeUp5A7v~k-C1>9;yCgjkYAk1qQJB(j&p>>|siNE`i?XJL{9*Z~b#)c1_O(@F zSFf+N4-}jz8qzCK`m^h>aAKs+{|?40eMfno`ReWOeG|U_AI~{onYin3-hXkw_)b#m zfdLESiTC|$t3F4XyxNrFyLNS5h+|8+M3ivXfd&mL5gS4GLYd=1hrJ)i*>7o*WB4-Z zV&`N2XD4q@&NcV(SGad`V!8Wn{tdk{$_1JZk9WOY82s}3ntG9rMOS-{hODg0h%M+LUp4V`^J^PL6Nn{X%oc_Umy{}j&9$@%2Z{3?KzRKZMD{pZB{C8u= z{M{SFa$N$KM8yX9ENO^&qRQo*(kz-8m?0_6wP)5*wllM|&)RN_+Gud{E{9#;Q~d=> zYXp955z?_tVAGCRee`~`R+R6mUqw@dTzh3&xDx{`BGfnZO!Z2P+}fh4^U1-=esOf< z;|I1K(lVQtC)g6y|W?z(u zdABJeynB_@(_i0rt^2nk`{bw3*V-1YUi|dCu+8bB4?p9s)&HAOz2lY6bN6|X+vogR zb@c4<&5euyd9fXt_tI@kRkw7!^~R^udR5&kKQ;$%5RPwfEl^}w=g(N5cT0Qa+Q&Cr zqh#N2-gRx|rj#pQiaR4NE}XDUlx1BHU+=0W_akPPwr7NtKGP`jSzxfuc{0g9?ZdhC1qf;^={^@}??@hL*o}08b;S$q>Zx78EzWS-G%spJMyZr34||Spd*X?W+#%5)qgc;mU1T`tY`j%rlc~1Kg4t>-?)_UM z-@9BB7>&wdgH{hb=~}RVw*cUjxFp`XxYfb zso%m>`&zJ9aJAJpt}F9C9tw^=ad%Jn?%T$4ucl4=Rgm_b(P@q#LoUPf*N1AnW{G_X z=sxORS?}9=@swiJ)m5*R+!NOXoY>_m(6*{;o0z1grc1upb`Bm5ChdC*&di(0ykWZh zx4N|R3C#Pp$UCjR&%Z${nPHm10p`ud-XYJntNj;$eTskmmRCV1o)%eozFsONzEEdt z_SLDclK%R4tlFj|71*R8kzBwtsb{*YMVJcnnYNdVPp+|l%RhdIMPg&YkMG9jEE6rm z4>2rRmA7Txbcwr7Vxf_VS66jpOkJZ<#~hv@XwlIe(A03O&q3(g45kULH#b~Ap#8v= zZOOd7>K(1Vb|-&H+s-xnHBy&K-3t<2 z>+!L0m-^COE4=2$lz10MOj|XjYmrxO<)RXiHVzrq)CoU@Sms}SxIn$IrPprHgW@?m zH%9L)QGN8AVe6$N1}~;<5zCood7S$H{nG!_o|aR;XZ^gh#>LS+YT60`k*~A&dX(rL zXIeVXDMGg}tZ{8tZu04*`=6>A?o3-7u#d|S1BHG+>x=wK;%#ybL3sShe`~BH<_-? zyUBIwRJ-Ll?V0D#q)q>)as4O5Rt06|gh+;1%lGpt4_mAb{rC0u-`%B~SDs4z>a!tc zzCuOwv{S!|itJWJ#kTJ<$Z{4~{UdCG*0uV>vfA}>Yvx_#c%mowFv&c6nY3@^b?2Qo z{veT(45^VcRJ7dL}$3{7Edru|MWn|gVBISE?tIrB0?rmZ!9AYLnA8Ltgy2yHD-bYqv zop1Y39OYN~#-o??`Sm|`Mb&dZ8CSKiGdg&4p6NUn<wUO8_sOGN)9BR^XC9r@u{g15 z=QjR;#Re0Z9~|SHrMzanO=DJFYIWR|wKgO)w0Dt4#Z!v_fry6=Y?3Q(Rf&5z78Dmx z4vP{gxVPr);|y+@`iX3Zrm0tNKbly=c4)!mpFh&?{#x2Ig)8gi7LF%!vpWNG!m`U! zWt;!zP0WoF(lGOWF?+fH$5W-eiCeE|WEk6NcF%uaD;OU0;^Pl-CYjl9844#Q@o#%z zG+*LO)~}nFYZ_W}85T`n(4FjZV(J9mHIu@kuNSRzv)sBOc6IfNtsx?Pm=NZ%_{3P$ng_X41u9#YeAI=^gLneKYSVzt36myLMU+-dgS{OcejeIqCH$W}nBc zn*02okpGz%C&fBC!zdru+?dPYTpFe*)9-TLP>h$EVb8jx&dv&M& zkJYQHV3T>c?Ra)13J2?mBY^A5kc^(8HDn`imXz;J6W$zSb)I zmv&x=*q3P&BbVMwF=Ab~KQ+bB)$X9*&HYEeh)RZKhPiMylsoSa+cH^7f7g|%SK6;O zEpqeLkdZjk(=}u6oiu^9OOo0ah-7Wo5!qOHH7Vt2X@ci z1qQmPDyS652yE}^F%aw)sk;)iFBUQ=!7u?aD8bIaz;NMzyPdV~MlZf!l&KrrY0w>?Idoug!m7WU_Ld(AzoF)&#y5*c-B1Ii-7%_?l^1JKEUR zYlq54x$x?`dMj}5d0+plpW#p6%{NU~gKyp0eCzF`n@cA1>AIiK`pziEIpYLFfKbcd zisQCzfoV6Yr|O3W7O%b*)%h_bRx{vG8s|plK-S(~iHnOg`(+|+Zk@g!>;IDBP1Q@q zSvR8CXU?u&KjYN`yHhFhzxf3^mBiT=sC{^N>cOO<7Su4Bv_~wEB}4Fj%uDGT8zbJ>slS_OnfH2m7a*Ub%B*@=X=ypU?OtW+<Zifg=SUg#;WWj&vpGFth1Lvj3SCJbj}{ZNR~6(d#@<6mDnUdrLmSbT&hj z^1;n7d3)C|2I);*uiD*Jw^Zlrwbm=H(Iwl=V!!>Ir0;*<`%YYOsm&_=;wi4%F6vip zTD?CkXYJmg^DM^~N$&roaZ~_j)h= zb*nc8Z;cLKv+1+iuCnlqi$@oRcz0_xPg`|qmC&PkLBf^KU%vgEdiyY*75Y6$EwxL zivq&7OypZ0_*K+(ZS1Q{X{}w(PBPj@!cJr*@l4pm2AW9w%_c5mI}OFrKHrfD%ADhw2jy5zOP)C_to?I z?)g79$6b_rGjAfpldQZSx6jUdxkN#{>c#D~ciAI&4>LRn7K-?_q3mtf(I5NXb{@NP z$}!p@P)zIVu~)iu=+Fq1n+c-25I&W{(lqQ!(ETDE=kwD_$xV7Y{jXtj*RTHd(L(!?OyiJ#=cZ` ze*A^_|5y9h@L#dl)OKQAGVkd18*awW+MKV;!1%_5Sqf=Nr#Mvi?>+um-cd&k7z>0Q(2**MeG?nc^ghS?9FFw{6Rv@K0vcT?@e z(eAf~-m33c&C@)xZd<~uC|6|(K~Wd2CJx8dj@nPQMKCZu*b$n+`lRpXsW)$&HBaqu zzrAk8dIeiC?p=%jvag7Y5NO!Jr2I|QZT#1KuuIX2Yc2C{rYon8B^+dQ zu6QdQ>w1~3?^Mo_674Xajc&o3P8&tHH1CiJz1r907PZ#+c2aMg;D*B&TA5s#Zp(R| zzFf9r-TQMI6F%&>U^vrMD%;|rKj&@s_FrsCiX1Qhv)*{X$D+q*Bbwr~y{yky>#~I5 zu?a!pt4m|W`Ls8wty0!IDz*GukH!k_?Ho^4LL?$1rX4&TQMkb_KXuIyZ=;|qtWWx8 zDzoc-4OrbDvvJ}PJI{YtD}FQQgt{{5rZy}tlVZs1)+n2M^yF{X$%~fhl_Z8{nk;@& z=ob35bJeu1VR;(H6SMdJf1tCmOpxVQT|pt zpGu@|c*0*bshV+{f>gsaBZm%uo7frFcF(STC{B6(V?mwFmG#A{@84cpzhD2=)%N6t zVc}aB^QV@IUa7lrUTUvM{(0;FtViC+o@-q>JuNm##OpY&pxYz4f0a|Jwe*ohQm~M?c>l_V30X*}7>TC#}AkE&ET8uW<45 z_2*^Emd~uYbUgOI>~|Z}O(*s8p3HJ&s7;nvYQJqd*;%B>p{^*fqY1=}7?zsmWh$dq-; z2K_a4dlw0&OyYNJ|Hr#sF%2&b@r>51>2^a+Q9ak#bjNFw#ZXq->7LpbCOKTL>5mty0hhHgj&9) z-=msGuh(4XuRJ37XVSu_&9Pmx*M(NkIMZXd%(>3u*3Mna=N+5Wa?^2gb z+@;B;@NHXB&8J1$&FZO%(n%kh!jpb(ovK;fpZxLrv2AOOOSBoDvif+Bl@i2ALVkZnsN^g{o3?Yic8o3W|zB91SUE=n$m)%#wyHLb>8`*Nb5V}+{k%5tPJlSakgTQ$R{x>kI1 zy7AGW z=4yYz>dBNDC6dBOJ;mv)`CqrCVOIr`Fk`RnGX;{nna`oF;d$UU2+}7xvW;(#6!>!H0!cY+65Eu}$ zf{8tXF@*7frhft}149baf#8U>5o;f4u3=au6R1$Ml4<5itrk;;1jjWFvEgDYj0Vhs zEPdLHY61zS7iOv^sI+u8h(#|lm|&2xq+}0=1j7T78c%b{MGSYQmG&;*=k4ft_VrEs z*K73@moE6hpuy;6$S^-ecERu9+q|YX(yGe@Hn=T$vo&YuD!*BCq?U+QZns`u`~G6~ z_D|IeEVCWMZd<+FKkdnBmOG}GLvMWd{V#dySPg@h`qU(bD$blr1!etB%hTO28}hw2 zXxJC$(7oZ{>Zy$eW`9bBs#=73E*_e!$S^0XTg&6T$E(8d)mH4=s?E2iuj5ac9LRaV zn(0Q>W98<@+09$u=SO!6Olw+@?EHYC&4VvJHFhIQm`v|ej?){q8@n(_^StRQot<|k zD#qw+)^+V`e4?BC#8lF6uU#Iswa6`Np@dk2nZ>m?kH0=o+Sq;|XoJT~VTnT4dE5SP zI9qSrIs8SlI<*uzo%``8{nnWGG; zCr`%K-+1KvErR3Aq^T+Gz8{v~{iiSKlCXZ#nX})RSS)uw-oe&CKQ?ed%yShw*UY3`5*CZatl)MC0|I!r5{!6*dcfGhoX|i(n zgsbckT8SJC0oot#o#CxM5#YB^AQhA|b-&ZM2*S|B+cNfdRBf$Ic-?vTva8Vr7rpj} zKX0!*bpN;gL5;n&@7h1>?f0*L+PFWw$VyC}Wxn&0#ChNRGq%6~{zhrT{kQ%Z<=+|A z6cloy0q(+P)+Ed)fEnzueo?%tBlx8w%{+@A+oo`v3Re&AYGY zM6a{zlQ~kym+N}22G%a-)BTQO0;i3RSnYLVGn2pb@~dZ} z!KA{Ij~~|VPP=!zgR97h8!J_nYB&2ceZJY^;}yN$g+CXwJ(dJL``mpEuQM&=)uL@ z6=opT&Dw3qp*clKQE=TGhCB1#3UAJ~Ki$3R;le{zx-Nh^~7oC-_0s{G*-A%hPG)*%KTK!;kgD;(Wq;OOq-?d@S{?&Im< zHA+kIM~-OG(6bf$IIWx*T>g4D8M_=KQJi#zsrBe|9i5w_DWd2S|}a9b64}- zWg+@~FPU{D7#OxpPndA?JI9pZr#FgRUH6CUufNUxeEB?$SKE#Sm3Z8U(_GBaF-tVEbw!u!#W0>M(WysIhqy9cTooqz%0V~UQF4+?hpZqcxAgixm3^#B z`d+F8o6RVzTAgAQon?M#$>g`p9DW;4FhsBtY>??r=U4f=?ohugH$k?LP99-7G>iXcex@G;!KUurD zSmv)~%zSO{^zT#ES+|MXa{i`&^DkdM+svhd#d0UBz>Ia~D{j3y^un}LOUiZQs%fs) z{y#sTtyvu9bN_<(hIQLqWSlq5lXPX`+0yoxbH-+i4Y{o1E(zxzDJB#vFj&q!B+;-< zNZXsr zkHjwF_kKy*6>RnnO><%-*qFRE9A{3s2SB0R$71mf9)J|bMu$WJTyf& ziM1u>%-#{WCS{3|=8chDGOyM1-r4paNme(SxqI9Ay;f#* z-N91(18NF}47x@QmYj)vJVLd1?|vR7ykm-Zf`BBYTf^ z+|Zgfh3g~Nw&*$LpSMq66n3=fbilm5Osr>Stvq|DyIXyW`|UL|Z+)4&4h_Ohhl>tsXmzorl{ISq2J4DR;%u3F(oD&X$nL;vwiorIM+ZG)QUc1@c{(zG8@vz;AQzWOgU+`WO zdD+T@_14yFt6VLwWh!@xGOKNw(E5^Lm$53_YU4wE*O_!V^rK9+D(Uj(O=uBya%hrL z?CNRQ&>_aNP?l?o2iK9$)h^Xb-PR=Z3MzM8N!@i}O-Q%T9q&K-4FWoiT!%J_Nw3~v zcwy3M(GqPFy(Fz)t^a~2_^G^2*OxC~nKbL&e2$47dLQGZH90T*%yK*5_uM)2(DIaU z6(Qk^T#Hm$C$P;^n$A9pcarkAidoIYvx^rhf8t!PThM2)=T_6!O2(GHuYxZ;Z|!0J z8+lD#VcW80e0TH{yj>VSNIcLFlj?t1VcQk9erwjWu3ZbVj(YVjTClP!BOsx-W7f9N z-8!MAS1)IXc<3l8EfT466@0WLd>Shc!;(p!58nQI*!p-)U*v6)RA4=^;CgRredRxQnEqc zfs4CZ4xTv0x@OwNlO>hgmmewku{zZt<RLYo#pezL1dCv;`j z77dQBFcY(`wV}PHUQ;(DZHeRDnxV)SAnc|%cd0<1_Hwta(kW>xS&z7iEpNY-nzog> zqg5x5f9qZbVHN!%hA0jNnK|z@tOEsorHx;&sEyN_ZI>nDy)q6TxuqHEnk1$J4B zp5LA=${^sVvw-JuIAciOO<{re`N7^9UzEjb86Q2I62N4y?;t&0qS0UV0JqUQQ-v^t zE8nkq)LG^AWTt=I7*=$ZD|K~gm)BlR?V~|j-8xdI?&r2S%J51Z?N;9Gw|ng)2ga1V zR`Ut+>*b@)Pn#S4!%?lae!hU0$7g1p5>DnuRpATESEWBln)}LkO{{KYM^K1}XrSm+ zSNq$1hw8L=w6$adzZ}26Klb%~OV%ITmoI%BsXVXyx!~7@3@t$uIc8McsG9cO(^ZI@ z+xF&ZU6%LEIy=l5F4Q#{8SUwa*w=V^(VhIY*M2pf(w(wuTat^QX2&L(tgTUNv!;gz zn#!^U-r@+&KA6=fmZ0x+_0|fuma?Nh5gU7pcify>_L3#yS$p-ydPXrlBZg^{7tGK1 z>pAZrDt+Sf6^UHKhhC=_bp%OVjJU`ZXt9cI<1ryNmUTO(&Eeva3SrpzMq+{L*0Zcj z+CFlf;yC;!>~M5yVgqRPJ5E^^5XV& zi?ditubtvLlI0q!qT;yu1ZR@+qf>Q{lcE`>)JpY&ts&v_MqygggM{x)IxMY* z4BcK2uA7R=NceOnZc|M$3TsNb7_l_sOLn@`n~FmdoJw|hn0~VB31g9TnouI#nK+Rl zCatzPr!?BE<@D?`zh;^IP}7b1$1M_P~>IxAC*Rihrx-PTsm?zSvZ;P+zr@6$O#Xp$?+1%NIFniae38S8$rVFv_Fu zruLs~hL*06Jk$BV$ya38hVY10cC!CozhK>d22(~)h6im7ucgv_5`Ea`K;zOujWLFMYlH++tm_3`X| z&w9f{^cceyx2Et@0){Vhr&iy%`*nKtpX*jv)8C0My67IMWE!R`<#=_`i{!xCYt^@J zEi|6+R-?^1u%>P+PtBW2++|@4<6}cla__#F0c>h_@{Y*YV`ISV2y5fOWzZ*8GA=jFM^=ZGc)mH(KIv)nwhKWR)`iNdBiNXC1tHc7y#heVOO1H=1IU zE}UREUM_NNvBi{U&rb9$w3AvK8@=Gx4kgp7jSE(Fhy||YaN{!Ra0@w@`L@S){lbGc z_ORI)c}p3T{0QXBpA>ngVc}bUi@nt)RTCR^TbLVd^H+udTCQ1O)mx2pDu~WSn>{%guV>nn+R3Vy-48AqJjLr9C(kF z)LiR6$&tyuR)Oi-jG}^`Fn33f6^_d_R%s=5vxOea-tD&4EpV&GqYF&gLat$9D&ZQ7 zqFzp39Tt@>k}X)1;wN}q;QiJmVs*1a-gGQ^Z}RY+-GNm)3=Yl>Kbd%?T-YwW*%afp z^_@{@a_^$3DqXIK^~YLGCr##SGMM17yu)hST&1q|tp{B+)V2j>?9Jt7jw$=|#_1dqnYE9Y0h9Hfi`%Kxc(*k8G-?GG%9cAB`Z})jp|2D6+?-ua?p6;^!4})l# z;DJYK3K^x5`P=wHuXe4C66sy^D#z2iF@h;@;dRrvmE1}}?tuzv_e}Y03!)sanB9&` zuQzl1_4w&`aRV=AhA69}ukW${V_=q;+w@h#>=FBov>!8;ZSxD97C0r4H?Y?z^_y1e zif?z?->-2y>h9tqQ7jN}jDbNb^7yQ{rsU2|f4S59%>K{4zo%a8t?pYRgVN ztlBaY?;5<}y^?f$3_7NPt)bCwy`m0^!i`RX zE|L>DCaS8tg>^7BGw4s-ZLRWjM}mNc!6v521kW{P7m5^1Kc2H~zQQ^w$s@qc)*vm3 zAyJtz@@Phx3M-St4Uv;4g1kEx>MD2~_z=QylFcQ@;EE*Y>|-1gW@;xivM||a?UFuZ z8Jkfn-Xh4*5MYxc&M6gb(!lT{!0^r1BibiL1riJxvRTy`?7VY-%bYpSz#INvXX_g8 z&OgQz4;kz(S|2e%<=f4w;vjXqRat79U6XV;7#ij_e=T)gQ|8(2vBzs;(sQ0?8Baey z+VZ10#YC;U|Ju|u*S=qvCtmIUPF&ijc>dhmS-C1TJ&B2VZ+0w=d6nh*AvB65=A@Gn zua>jEHPcd|3OWgn5W9LF2Q;TKy3afWxnyXEoC;!C8wk(gV0>9s9II#d59~_e8EkA$K>GCQqI)Wr7GxjHwBe*0Vb6l?dO9w9AIF3&JuV?CVTCndFojXQhOx0g6#@C z+-4POvhF$He$Q-)DI3!S@c0NT+g`-@2qyyrgTxWJL_YQZ7B0^AApyRDUOxZXRWn+S zY+&N>V0pxI`NETpJfAcEYIlC>PYwwC@cCeL^@(NvqJMNBFbX((_7T@s%5|KR3K3So-M1#F<)~m&}~0!pP7u z$+t3d`P9c&`7frL9(?nAUevn6y50K4f1kbiee}(?C69md2(YW4eEUtbZ2P;rZ)$97 zt}m)PQzG&=Au(rKg2Ah(;7zKH=^_)ke4KPPu=K6%n7SfoYQRo0>*dZpD?bK#ky+OBE-vv} zE4V=;W#*I1=K51EMu~(3cMBF~s7+B52%F~FaL%`1e)oh%21c_lk@GfeZs}0=n!G4z z&U`L~M%}m>`+t?~eo`#ee&a~`?_biN*4CVpi#Rl`!_lNzFye;#Cssb|Ir8Tg^my5Y zngn?+nOIgh<8b_xCYCdaT?^i_2OOFc3|bu2C%x#;ihf~%$K`uC)V@h`y1Sd_83#Nz zuo3FLaf?moPy?eWpRe`V4eTyXA629`uUX%B_T2|fy#vena_k&t6tXzzGro+UrrF|{ z!tH6g%6j9*I<3b!E0=Oj2{^q%c8Uu_OZsjdyZ(tYLKW`m=~yMQ96ltU!!$RF>FK%V z%e4&Aft&}H`#kvgU(#0h$ws{}#|<);Vv1{=%vxM_tlqL}qN3lD2`M6t*QCXmgBWC- z1Q#dzMY&9C4?4W$_&Z0PrgNW}rm#M6TcFGN?ZZsZ(8cx0LO=!;U&5wh(Oy2u*#fs18LSq)p&I;^sx?LrDROy-{+rlTRk0(0yyPR6+ zqFv0&I;}#~YognV1E0iHyh?>9xEtT8dmL=esCbKg`(Fm`Y~BM!jB8d*-VpPlqkL(! zNX$l!MOUXOHD&d-39%kZ)Rfwy-LfftskMpMt*mSn@5u|7id3X>ayWZ`k(|iY)~i^( z%TC4PjG3O!;b))Dt-c(Zd~&Oxw?xCeWWIYkpY!92-9oOdXw`A;-*+UbWW}PMRZCby zBQwu^s`mHX>#%U{s;&gXO-U>Yi!CylzHol6K0IT|zxLJNIk&o2O_`~7Hh*rJpyx3z zH6s=`c@>+FB2n5A$?SYnAG$73+U68uA8olQNjLlVfflFZT~qS?`fe^*VfH;hWo@|YmY{q+(ZJhXTf5Yz z*j#JzbKQ{8>KMt)#q4Z(Xj1>QSv7ar7^>3#ltu?jAH02r-8}Qy{q3r{ocB%@F~869 z-5RtuMEj~2n0i~byZ7!bvpFq0xgezpi~0&qyB`lM`h;tm9yb^l9q8Sh6p{Pp?IYu; zt-14Eo-aG9p&hn1Vr#@z=N$oGMQdH-FRpf!XmONiIk+q0nn}u1QTIX-HqgTU4SK6} zz&G{E91W}q4V!oO^P1DUKnfitjt0sc4Npx~Ww>zpa@@7l*h30D5cEi+FUeB7@#REO z*FX{1i%S?@WS%~~tEC(Y0(DMDGJGkq=~|@GwMg?p?Ube0RG~T#Y4qu&s~XsD+Ljl3 QYLm|COAH@1x)yN&0J>Rs$^ZZW diff --git a/src/main/resources/assets/ebwizardry/sounds/flames_end.ogg b/src/main/resources/assets/ebwizardry/sounds/flames_end.ogg new file mode 100644 index 0000000000000000000000000000000000000000..b3488b59a1aa96af874997ec807699b90cfcdc0e GIT binary patch literal 37073 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 A1poj5 literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/ebwizardry/sounds/flames_loop.ogg b/src/main/resources/assets/ebwizardry/sounds/flames_loop.ogg new file mode 100644 index 0000000000000000000000000000000000000000..634727f6c1ed524dd41d15223ae7933084f66dc7 GIT binary patch literal 285773 zcmeZIPY-5bVt@jPG6>_G?X}yCa*Sp9MM;^(AR#7~H6V(CfuRthcn2d`CsdGu0i=_W zfq{XKw?jiv_dgn7hL|MFz`ziZS&*UUUzDzplbI9-HebP0!N|bC+`!Dp2xJ^1D@3uT zlXDm&0|x^GgQ1VY(S{2XLKzqY7#I>%H2Ef{d1@}5vQVRP#uN__>!?BJj47Q*C6ap# zkHH89lN3<~1{Q_}4bHyB&pflvS*A;<_Z2O$%=EKZuE5?E_`s6$&{wtOyk%RKW#^sK zROR4}WMyDrVsP+KY!wLt5lJ12Z4yZxitRE*Clr^@DdN&vv7m{|=!8PEkI~B|ll`n- zu2|e>^-5#Q1t)IZEtkA}46lYIuiMKOTT^__^7$Mn!3p+<0s{k!6Psj;fD;GE_zulw zGm5y3PC&e+z|a8lx%)&B&y6CdH_Dv7sN(-gCs5e*qOogmh;L|UXlQ9{cvX~lGLI{mW!BM+SV{J zq=14%fpe0Q=A^}*%hIyeWzOD~v3gtX=}kJPH}Qa#FfcN(fLz0{Aam9-43ri*EtN2G z$T*?J;K0P-aJ*3Fc%h1Gkjn8Q9d>XCpI~6%U~mZ1Ia*}mUTku_*yeb#jeCj9$tgZ( zzxeQjl`t@Yqn&}l!BFOCq0GsPD*i#bmy1lpi*2tL`(7`N4F`n?e%uI7FDwiUigVMZ zWi@aZPe=p@3n-u^7IHZAKx|@RVCY!*L}Av2S)b2Z^38g>V5P|H%Lh9{W~=X9Ib$|B z26N6yKAuy2PV>~vqYGwUm{okvlV{da2&+q3=AxZHzbbDZBnT1V@ncIT&6f#uB4xD@&dyXnoHz*``o-%HU|Vr zsxK{R0{dKnfuThJoQh!tI4MI?@sdehTBkHNpD{YE10vQOK4Xn{ymU;j zh9&oIeKxOnouxFf z4ucbiVhcD=PD$!9JU*w{&xsQf!LXcDC~|zF%*lx=-kVf>FX^29Wa9tXx>JYts++*MPx`987#2LVTgh zN2$>epk)X!GB7amF)%QSIW1JwW@@ltWN3fvFiFAlgGobj!eLo z#n?4WQdAiPSQ#D^h@8G;68OYo+S1HLCkl1EFS|@k&78HYQ^~~pvWwun=atJi&wsYL z+@jI7D3dAB#FvqQffW?&W*J^Od;u9JyciTz7!EwNnD(@Ckw(|D%vq~W73!S+>=G#A z8yp%t{c*&!=bei*W-VK_OYih0lk?yzDzr2ajXvONItHt8@hJUGC}pm2c0>g0+|9MZl!J}`(# zZBk|XM~|gTf{eU$mre^}Rh&A> zYo)@Hpdd|Fh6Y&+h6dRPj@Gs{EDWC*7&wxrB%QH*uHxin_-szGkm6E_;&YZOMUp{H zeT zBZC7Zw7YWr41_|!!7a*g-~lMQ=Balr%k-SIta6_EtYw*5la^$HMP}KYhlYOTJZKmf z#Rh^x&No!`G$@W%u3E))*~Is9NN8v)sJ**t)$2psK;eJAH1YPTRiKbQP#Sx^G*xm3 zsQT97W?=9yU|`VNkXYI>dC|rLPR?OWp!%}KkVCUYAc#$IiGY)bX6pphepz`)QT z0PUfe^&~=Bgc=`~)XGFP;ZONY$kk*(vkb4pP5#-kG1y{;Owqd~IS zYfUwu7JF~J8kM|etJ>n8NruOwve#_ArZgqU=$J_GnyuGnwHO@xE|I*(@Oji^p+i69 zf^|1ujmi%4(o|0AU3o03*w2eIwWnA2>XhPhtPBpe77Pxm5{~MUp<;=PImP7~z!9^P zk%7a>%kUT|g@Mvl&=QH_GnUU4T0lLqB^+Q0M-Ign0Vfa1WSGRlmPtXUW)z5?fyT#79M zU@Tp){kQd0JAg`4mA&5mw zrv!m@Xo4*A(p(Bv2kILKc|pwsTQns|3&Le!SilS_{gkzIkN6p{vte=@uIi9?fZWowVt(ixMdIh~#n z#FM0LSkhzYZuvCC>9_;~149!71GAu!Fo%dkVOHPC-dUO+!mZL9nzn!w&`qkD!K*j*Mp(RyKAHPA+a9UOs*SObiT+;9Amwfsum) zGzJ0cH#0DBaDW}lz@Pxu4<7XZwQH5nwoKIz4h)Y92o4VX@9W~^;uaDR@;~sur;D4t zlc%dwK#-qLSZI7`aFDN)o4b2RNMJATUSXjX@=gubKj>Hp3x!&t181^yz zSoXQ$({}CeD!u)StGNPKc?kwf%T) zmgyE@_0rhW=gVAqWd5Xe{m(CTx$)lp`S9z?yX-4ujxtnmKVafNH|JHRR$j1XK_8o|1I|{;~Tb3 z;%Z=JZ2ObVy^Ax}vS9b29jxZ}`{HYUU!0t~=byZMR-l_Af7ZKr_t@vt<-blh=0AG= z@ydCxe}1_gK3(FEdE&-JiQx=AaVHu6<-}XOQ5W-Zcz<}h?LPj1c`Bj}Z~i+>+%U6WX;WX+#@sM9lAm9D z;%wFBDvO(6uU`J9ziT=B--1`c`>)47oj=``^I+cpq(ZSJMQ7QPGV@>T(!P3Zrf1pg zyu9mY*(1&bFnF=8&^8m8&RcZP$$4-3(W$%UXMFJr-Xs(J#c@IQcek}~p0?kdzO-Ib z|D)y6e$Rc$ruOkU(n>7VvpIXxp7NY&(>K{IdvufN2~GA{f9_TJ`L!j4nlT*gEBCpk z(-j%~t}Ar6sdqq#=-njGP}vJx=V{J=A-!hFoWt@TZKC~a@7;b-!RnxsanPY<2?ygO zE8nH8|Jjdl_5|(K7kt#u^quEDKZ8S{#i`kgqf!*M-{f0u+UDlG^z<2@Nem2)`ve-q zS6B9^-n7r|lPq79K0A81#T~|(;^$|$E>hTV*+=_!fW*|4X^C@VwcQpkx)|>?@j``6 zhe+wG3;|a$E^qOufXIoq%52;{%bI*1Q=`0QIE`8}I55@`kYP94CpD_5cB;-}@eJ>@GLriTB zdPW=^8^vO@Ia~5(Y9_Kg6*-{esSl7uHG3ap%^{<#W zr^o*auba`d)4n0|YBJSTt5lW4wjW=+GBM5bS~Qb+ao+NITMMi`CQRWBXpywai;48S z{+O>}Lu=!W{?DpTlb9L*JbOP`h?RYs+ONd@M~n&>V~T9G7w;2PJ!^M)<$8zddWSOQ z8#btlG|ZoL;1y?{3v0=b2`&;R!y>p1x!7ubPaV>6yb;P2bWYLfi^jP{kveCZk0>yt z<@BTGbEnyx){T{1Q8 zW738LS6qzydrvAk`k6iE4Jo^LkahW|g7wysqV0Wgx2Ak5e#d^GCy?iWc`R#;&F!k& zpZ9F)eYCZ34`1H~QO=dQyoYaWdX=A=ef@k;w2;(#?M!aAB}ot8O#8n0o~h$?sjZ7v zpZR<2OTm49hVWwn48KHg=q-pyESuHRZpx8*@_vfTiqPCZ4W3uieq8CE(c%5xwcB$} z?wl9vubQ+(g|b)qxh}c5KOo0XB{R|Oh}5&a>*tqAOkCsTz+~{Nwq7`Nf1L96jO5E9 zyTgiG*#k|&U0s$~gqF6cM6Bu(*(%bWTD8)GXZB{7e>m0?Z01Md%R|g`~QS@a*?05%RV>V|L?Y=8h>ZoS*u9XV==j*Cv^;k ziepVoQ$^QI-4&3^CQ>S}w&kKxYIkPx6St)^UaIEvJEk?VI@U{Uu=Du9<*`kjW0t^F zCr+<0gME{vY|9Q!U=T=%Y+Vu6dSp`sgG|7(XJ78ly!-Kt*-TN-g>5|%f@>!|oRTTI zS?O`$0x|D|h6X*U*QV1>eLTUkZA;$;olPC$Q!GTbaBjY9X>4n3qj9j~1uJ|1f^8za zd2KWFJf7WDU|65(kYiYqljSy7^tfK|CD%17uX5)Y1W(o!-FtYKIv%E&N%*8io~B&F*<88dN89Ay<@D2po1?fN3$ z^=QQd>$%77HT`2RX!zdQ-uWrz?#(TwWj8mUQQUtd>i3s8k*~^UZnd30!z0AdaOcZO z%lTWL+aJueF}ghUvwziMznPQPy`Pp|E)%`1c!J}b>*}V)`k9H-XUMT{X%|#-i)QAs zoWiSd*2w6c>WeL3Q*ZMW3LV+T5jtsAR=0JdW5&@H*N*J)FhN?}V?w(>68C3oyn zr{G$l!~mVgtq}{#qQ8`6&B@fdULG{H^=sk%C9EIB7<$cK8Ey#cJ2#8jZSmA~`F|xZ zrOng3Tp2p2`>trloV9P)2+j2TzhYNupz6ImA?_FIiFPiB12|QVsANh%JNL$K$DURW z21W*-pzpt){5HA$+(BWzg6z^KG6Ht94wy};n>ceZ_s`uA^W1lC2!5hiKk@xD#tlJE z5)Dt44kV|#n1s!>-R85#RZuW7YSQIZ0b#;Rj9pZdokh2VT5Mj&#;!UiRdh<%MD`io zUzXg6t#3Oh`^2?+(v#xa1}-I51|3H=pW7;T<>F*-M!R}#e6%5Pso)LEzN}k)!t!#g zmssEMRIj^xo9%M^T0Vw7RkK~qrSCPIu6{c!XJYur2Osjb`bj!#q;@eFT)$QR?qcn- z#p@Qo-8^fHQYPcgh1YlZ?tIS7*c`s3K)zRWVo+H3scwBf@a+8Zr86?JbPDxJqL zC9jL|hh)QjevZkJoBNBFE_him$#lX+F71ht7bb@oZq#^lDqSn};GUhccty@K^pt(f zoc3DDPtdMZL)>P~!yNA*yYK89d>1m91UW=zM;qxkJ6(%op6a(#E2gV&Ub6T@3;wNh zRwcdETy|~cn?LeaCnE&&Z*1*k=t(OS+oC;RVc*x(&=Uvd9qoNv4luy9c>9wSllVTQ&P->Kien2xcN!@xy^ozB}Ol~YLXHHy;z-H z%`G41$uXq*88ZCk2zVCsXp+>UrHMC|1_<1Edq8h%!B*xI5=V_T<%qmn7h4n>ucv+b z?y`Jmh919@JP9)c1eR~{3S*EKo!GR&?!clgDGVZ_xZMX$H6M-mmRC3=EZ zyZ_qVu!P4OQ!Jl7jJ9a4W#!At}YhImX`jk2M>i*yR&gF3jXN#&!>vJ#3 zySr%nFQ5Ni0X}STb_ZRyRO#FI?lk_)e5Nai;a(EUofr4tN_{Cz;#swA`2oJuUi%(Y z%--7O(3O6|K>2;Z}{t#*?i=-vVIXxIzM&hQvVD3kDkqa&V1yQT0_4N=k>dWRXQ_YpLNX$ z3tFl7kY%+9+tMI0ZO;|!t}2Lyilv6?oI3L6_~Xo_mlM;K!ww|KtWk>0@wly0m&K41 z^s)75{LAL`H+l>+kHl(LnVWApQ^lCH(w8BhvFGanzORxMOtrg{>?Nen?xeeVhmuXJ_B{ge1C(D>u-QDv;HSE*9bY1^x%KC-^mW5KDwWpu|w>Milm%&7C<&i1- zHoY-bUccayS^0m~<=+{_RCAbqs8$|O3+lfrf8orp3(+gv=G~6+547R!Ouu@~Z{6#+ zAIe^CDw3J<eUpofkgoDz0$s&WB99 z1B()j81}!HT5u+x-}m^_s;NR%*`}LvszNV|DDJw}wN|>lqCIxiqAnMxcOqG+)?OnXJ4 zC4<|h+f$;D;(R7DxORW{VD|K@UG_0z6J9V@aYHe2vCA6(^U$mQ;$ zZPdz_8L&D}^MdyF=~7#joh7(;R=Thlgfh-aI(jxS?=$c6>Z?k#QxE$%m8X7|I^ra->~t;iFT`Dt>!~H&jO^ z7cR*8`sr$~Oz~x}U3CnnmPs`H3~uOo_3~~+Z}{=oQnx&ggvmb*IDP8|?Bt>omoM2uze_XCG&CmpcAzW!N}S7c&Iky90ek5eXV%{%#9wPi&gS&lri zd3C&+A!lw9!@pmwFFu~l>D;4ub^TJ;QRp0_Ex6uNbn@79_Yn$f1@=_9&RazSUbnP6yLiyKM7wWCr!K1f*;skkZ!@a$i7xSms zWdHdQ$?{QkOVnefWbx14+n2AjUt7bP`kjBDfA#e*lb@<>n^LTpaA%domg}j7_V*4- zt$bswzSqh-@;ZO{%(d&IBg3BG3CVo>FJrs<&0|8p|0$LzZ`ELE_@27=Z6j!C611R$ zp}`t4Kmi)aP`RQx&nUnpFvLG3!X?l@Q7Fu0gp>=6m{km6&k1XFH!qC_6rM*wpO6D>{P0~S@CwKoW z+FE#|>F^tm;;Hr5eoWzSSgXOdAf|DWQ}eXo;EnUToF^o0S(U7GdFpA4#{v_=43k8k zttotZvoLZ04n7m+lA@nXXHpl2Xcf&v3?*H*{zac_ z1#0T1pI^j&!e!@ziiW=o+NYTwY=5P0@##UqspMUL-3SP(Ay~w-sn^9Eg2QTvk)^690*O;bf>6vVbNVNXCNM~`w zdKr#mjB|2alvtDfZD0CYhd&oh>#gaYU2=zAA@&Bt9h(COw8%y!XBqKoII z((l?r*NZ~yoR)`OTx{Q}mFl0+xi_V&PA+%nsYpHthHjlo(TT=vVT^0Sve_y{<9nXh z-95+qW$7Q@^1|0Pojxlo?=bKzbmjFsDdN5J-T&s=>z5_xT)e&i{PUnlzK=q)47N@; zC}LMVt@!Kr+#8>zqOWZd&z-VK=IF&;Eo&Af|B+zcQuc7=sT#BTm4QX)uIbGT{dDyY z^Dh%Vi`-jI9({`>8lIRvKIYATU3f~Lbm+furlgZ@%0kY^yOd77*u9D8!iJxm_LoFb z;x4*)%kap=DPNlG5Z7Dq?h$j2o+HCNu7sPvZXH|cCw2Xr_9m^PqRHEXR>XyF343*B z-Lxo;&#N504PMtQig_G%t#_T$jk25#OzXU~7p-aFt;xz{Pcm&ey?#noo5a)&`fuzS zR-b5d=w`XcJNIm1$npcBS3{>u9d~S3;xXdkU|uPrHS1EN`&$bq?XOx>6c0^2^pEfE zUu6z4Ew4bwoD}{PKTn3TQ|y;(?bR|_BbN00ocqWqmbzA8$7zP?o?p%^{hr3IGb=7= z@{6EPiy|Usf31>o4SR63am}i{#cx({UA25R`{O1zm$|Z>0xoV0abMzI?$BZQw90p_ zNQeCa{vTl*H(pct$B_TwF9Snf_piO%wa%X6?6J7aw0N^@r1R_OsXoS@3=9lGoeC~Z zFZX%ByTV@lJjYF}bm2uSGwEZzk5}qNuk}tpyZ*3n^zv@QS7mnJdRX_)Rxn@e7y71-9-jyde&)z=w?Yrr- zX8n!%%_H;cY1(6<&);JIq=-fCymKLZ>yFJPb zp~F{JXiC$=Wrv+amaA{F{`zTMa=GQE8;9S>G32QlGI$3&tz58WrjBos_O#qkAzfYX zbtjBgh;?(>G-bt3`99@`hCxToF*T-^xI%WFFNu3@`|21mWb5SEIYb2V98hPwP@mtc zzIW;mV@!+{oF+DAv)NNbcvv2zboS5KqT=@NI^QAts7BZB$39{ds>ugc3G0l3z z{@Lv9*7v?V+HvN@gJ%-V9}E}2yqI?6aZtcj*N+KRYqoWY|Ja}aqe3^1W40iji^KsDGQn1OEVcQ~!hU4EG-Fg&Xef(`}XZeDo|C;ukrD1{DCb8WK zE2HY(l}0`c@Liv7nbzVRb?juGXh_&rmM<&iEpj!)Jc~M4|6pDImtor?k%se(Z;F#W z*Pm|)3Ktc0QCZJl?&l#=>Gv*|&^?kO~uB<2)b{99knUh2~7gwpDjdHm*@nM%z ziK05wl&qUP7B`)L{#YDk!MuNl^t$)VDrUtDRh)keqxhcvKCmvbNYv`WUJk1@p>u;K zx)x5qm9-@4wM!J=Q;SpYb60mLNG@0DWJn1MUE?H{$mpWys?NDN^w3@VDOq8Q=WH^( zd)w~7rjxw~;wL#w>8g~z5>a<|$}Crtq)^R*t1kq3#V&4366yAtbn(RnHJ290Sx2)Q z#9r+b*$}lSP>55SQN~F#eRIxE`E$XMth`4&?-kq;U%+`ztzp05hh=tGkI1>TuR9Vx zJ$gzje}wrNmpw99r+QnSI`LvkXs}1kz2|qDKX(Z(a&6esu;fGn_r;0Zs`dmhGxS)U z4A`6Jc3p#S#TDJ?&~s@K+j3vAA22)0@WtqW+hX6%Rv(jItvq_srOZFUtFZZyMwn~Z zj*!5TC)*xG&Fs;dWeKwb?ZI-O^1#n=ZITw7xG`*P_;+%jn_=&V?%@J6qoOO^pkD%4PGt z_T{EK#XHVF(tEWkh{158|IGE1R!K9=sXHw9!{}d1H|wQLvs?wepXSjlN4W*Er!aj8 zV_2yB^}@x(rc8~Uk=d74GH<#fj-k7M^oYD-+>5P5j@RKLuYuH!zwI)A_H=rvgXI8!Z0{_~9N+J?0! z7#MnaSQdAd9ISZqyJ4SJ=(+rCu}stMsGIlqo%{Pgv0Cow&jsPH1inUmvZ!hQzc$r> zsq>ae-?o=B`1l37zcat3Hm7{DmgxO?f~k|<-DAJOWyfImgss^A$Hj9gd#7nt?Y&pB zFl(*eg0>*tDSVQlp<8#wO0`~C@Xj*Uwo@g}dHuiZi!(S?7-sLfko~2Kkte2zQ7xzX z)!q*`lxAwAdK`{CZ+x0RpsA1P!S)#m+g1M=ah-dX*1gHMd)t@!eii&%Al@ z`kcjwM=px1J4Ej0?_n&7D?Feu{ki$~JJX|P+`Q=b?`+I#=A6k)41b>T1Z=)%8|QfH z#l%!vj z&$iW3kijKtC1*$Pj{|?h>@H3f{B)%8{71%XOnD4-CJpPR?^&Va?{nOEad6kQiHkI} z1y7}(4O+26D2Z*Fr1+Y>FI-vut!hfnzuy0)U1{}p#+%$_4j(g)t~|l8ChP1g3ENAV zJa6yh-)(!Rw`-Pu6W?#9Gn1njve-Jl@UEVC_Sl4!*^8%NX1nWJdTNQ6>guaouWeRx zca+ed_+D|+)Kwz$&)kiz$dQ8!(d!ME` zTwS4*WqNUiQuw<0F+Vk@$gJ^nRR~|BbR|G~Ljg~A!pVt>Jv`COC1t74GyfS}F8H}J z)>!7*;z*1C;tIV&ZA=BRTrc|fH+`+DHIiIfcAWX_*^6nB35PW1T)MPz*Wq)fT@jN) zE!S9HyC}Hz-c{Lk(;QVNhGjc3)ksa`x$|K1LYw&1z!f5iB6Bm>|6n*!+G@zeFZp2o z%vYP0*{G9*|ciU`fOJ(u-dvs2j=o#S&r~fUDea9$Za9pBc5@W@!HcsgSfsT=rm@aYc7M1pK zkXdA5rWW9ES0T$%^75Kf##|+Nt)0<31=hQ<=Nqq{?P%L6%9d**zhI38+XBOe$owrm z+g%pOuiUO6nh`6a>LJG@+_ac$h78l$3!?2pm60bJ+Kw`u%Vy|_dpeZQe1uLKgSoz3vd4{J!{{Po+y04zhBg4JKv@lpKC=fp;uK! zd>tgN39)o@T;J=mc$G-i%u`jOnj$jm{5+4WwibHK*q$hM&cmXQSEDN>nqkSbpNBMS zzBhZ7EsZwQ=zXV`5pbJ*h1bc43^kK?Hu1}T*LHI_Y+$$I)f6w*K+{!=7Flp8%d9x1 zFf}XHKs4)&Uv9rt?)w&7v6|Q?m)?ASCUwJ!;n%FMwY)tV+obPcpM8uB z=W2{+Jw0TjzwKJ|*0p`tR5nX6Gcb7cXVL4v1ggZ0Xc_$*M`^(uev8lK6v(CFoC zFBYaMo=0vzdv5eOB^+48q<`q`G3CuY#&?A@A|~c|r?rGfGF-jEmDK7oS&M7Oy3$2= zwOM4Q1RK9g5fb5Y@>sq}L2HSGM6yy~Xm73Cd`A%|UN zXH(LVktlF}v~-1noRH9!R<@Gh?aGBE^SgOUT=*M}qog;1ms~I&NJflkure?(EG?Cp zuj%pM=D*2*FLx&wJ7=eq#GtUiz#!+~0AK(A&aSSGUQW)w{(e6Hz5Y8)?{YZDA+*#z z*}?J5*JHbkS8=Vo`Fcy$rq1Z#t`wCS1``%uX2|7o;gWR-IuM;8rTWQuLFLRk`zxNG z1zPs)h@5cpcn0%|rfCdy+;gM+KO9%dEV!}s++Ot~{l120D&F7S7qiTC<_?1g?zOL7 zvdy9MWN2tfcki4gz3r`;$z$nedDZ3VZ=IbU<$vQ2> zeAVtkxn*nJG!&8)8NcrS*k#IS!5?v`?+7<1mqQ?f+#cI$nx~j;dR_kQytcHL^XK6s zEcgGauRXG)Y{T}iUk%$`7i)FS)D&W1$hrFR#f=_$nOg-VB|TR{YVPjqNL?41?dkUQ zszzhWU9<1$Z+xtSCWT%7zBE7@G>Y(n&H~-#1J7oAyknqW$J+~96XawFa@}ArECfI z;!fJgz|6s@*k+>3beV&LDOqym0#-o=!6OP>E813h^d0Tu3{(kpx}d*iv(>qPS1$!r z4y;m`8a(BKf$oeY8e*YRRbMiVD_D13+;ZBFK>Qt#xT(9-9ZotQQp*}wMsiP|R&CmQN%(|Xt(v?E$IBpO+`zU?Y~EK|aA@p9BF z`>fPbu1D;fa&=4pGcdS)3%fR7=afd;#y6j%dII%Zc<)O_8Jnhg2{AA<7`y5miBVYi zO!e%(XNUAI%kKA`w|W!@8EdGvn=uNX%MiS=ca=iRH6}BzD}3t8n%_2b1WsSddT9}(b(sC@ z*#RfA7p`#*X`7^QyN$(jqQNRb&A`|NjL|N_$J`j(6ejehP7iEaBH>bS)I%U~0dJe5 zhX8kH{jy71z+ndKy##)edsczQ=IT6FQ%ls`{ zG<X*GwY#3tH_VRAvKU%To z%<{U1FEVYHxAL=SoYP=?ps4gfQQulSiPgp@YnP-J)6tf#>o)INm7~+xq#=G|j!m5cu23$`k9t>Kcbil~_^{1q-6St?Wq{;V*=lW;%4PXABROS1j_|MVe3%i2&vk;C3H~Am-ISrRL)dal^V?0{F zPES2W=16zx(>aSfgR}ljo*5C5-}*6|xg>0HV%s)8_7$=bCrcbBW@_%w@%zpwwp52@ zo)lBseAR+J!Q84`o7;bnC*S6~6&QY6nQwDw+8d*u>jk{mzkj{{`e9|>*WY^Yt1Wf@ z9kKpaaekglxx_!|ve#8t&Tq2O^_(Qa$&g|c8B)en#(7}IEeTf96TLFa1Xl4+Xge)p zTPL^SI`jVjj}M(>-8D68?SA{X@1H+EnihWl<5Ror3E!p8?q$nl*HgXl>Y~@SYW>yE zYO1QLZdIM`N{uXj6jy&OJ(t^1VY`)ROi;Gktn8nzU#83qvSf5=^$Zmq`w?-7f-^ruup@t=C$0Qrqjz1&_|Xw>-Kw zBuBe2u!R^o1|3^;s&&d839qA}Sq)t3{~6A1GhpgwF-UcZSy3X|8YK39YG9Y^tjyA& z4Xcc@w_FbM*q~9O>$vBJqeQ5th;Xa;>PH;faT~&Jp5ArCTjIfPz2^cwS+Pq`&Uw;! z+5hb>KSA-C2DjNG);;3*^Mfnq?}6hf%RJ0@wATe)U$v-fQE!!_&YD+~HXK_zf$w*l zU&x!a@rv(`{`&GsRIa;_LE{YP+1pH#OjEjUa=n?jFQ@(YBuyTL<5Qxa+Bt-7WBlQp z)^t;S*5zf-3|zjfj9S^JC3P*!_o!K8U{v4L6~9#dECty^AvIwSaZ>4RB8-BDsI|4*81?I)bI^rBu*3PViNMAi+TpWJ%5 zx9aXQw|6xkxBjpbNSJNOV4v!C=&Jo~%cjYR8`kZc=1%=PS6ALB?Xx)AUN(<^!v-IPVB>}BsgdEip@Cbp1w&o$b2~l|5L|uz*UD81+OK|Ue8{-@aMuD?#wUwq z-^|lredkQl@49oo#`z~-r>GUm{xkV;&i;T|E5nYI2JOcSdu3{DPX5#QZkl@cn)vav zZsBV?azzEtiuUP!)s^qKSFCAueYU&zVx>)6R4%c7x}{s&S6ujzU8(NXwJW9vnGcIA z{pV+RU~&8N&yy1FpI`WD=PdpjcHb;2*z=4J69dDS^(`KfYGv8ZH!gnt_TgQ=R=C-R zI&qoOYcg)!Jd5@hdB(q=>o#xW`)fMeZ@!*Yw!8Ui^~_D1-EF7rS|g>Xd0|CF=NTsv z^B|2L!>GLxlQ~+iHVEmn8R@jHYIPD=D7vy?N6HhuDR&K&LLN+LxSGH*P0L4HOUc~- ztl;AVYaALFCkKc!wD_&pNpq{Hn$aL;)~&nYsUe%8W`mq^&oQpuj?=`OZ>{yYbMeBK zl`Zc?rz8qYQ*_VJZ8YSNU`Xrm+!dia!_k>7LG8|^%d@pM6tOK@xXHj_=Cw5@%`M?7 zX9U-Y2~RJ&!&$h(Sp4v|4Nn*%i+J4?dYq4N*X$f!71-%s+i@Z%gK1yv9kv`j^EXl>( zdw-sLkgP|CvT9A-L|e_e{Or^f6-=g)SJSTD=}&KaGw(U$ikV3azl3`9bC21m&wL)- zsSuN+lkD3u!*%kOt~Jh&z6KdD+w}T(-w*3zshsvxWj>5+@~-L}*5ZCXKWb{I>mAoi zTR+@O_n#WL;EbjU1IJ-+FaL{DI>L*l{E~HH@9X5%$&C$j$^NwQW3X1{v?s2&oVcSI zmxTE;9Jb<~{@>HpN@8D&#_{hAEtW?azLYoc$3FB`R>)fk?$bx6@s+ zS;y6!?pn0YvykuF7-DUoCwyhnWu}@V^EtGd{)o!3CtQu^*!`Y=gP0KG1&)OFFUbWZ zmHXx_TD;Es>k99UpM+L*MH$A`Tzq-r#mOwiS4U1sUef8i)cVC$zDvQ#=%&G*c~_Nk z?!NFhT%OdhIz&e6*p^Sv3)qfk&67`<$jGq3mFZyY(>9)krJ>n6-!re-$UpY9oAMxx zB~*E7^VEsXdnajr7Ya2Maoz5+%JVJXZ-yz8PWmLQ`+4xA)8RcU4Q0MQy!Tf;!L*Yx zV`f8gs;9B(`-_kMYV6*0VwLw!m!5rmJGJ^AukfEcW%cX>-Fw?Hs+|9Q@x&4~(ZMy?Tfeefr#93$kyEVVFSAy4ge={l z*WEpFMbO&aLMOah43#-^yV^?Q7m2%QdQ6&E(DQaV`>k2N$^ED0#V$I&vfaAtTGJo) z83*_o68wXYW!&E(vdl2~^J3*1_p6>EOP53%xiT>%T<4f5=)_??$vvd_m(lho+nzse zd6%;-Qp$U`*0e2w-*;8ZzR6qTJK0s$cACza=os5Gfz2moeY&%1lU~z`$pJexio9M# z>%Y~UEzsmDt31Ih)|HbXVo9HN%MmS}(?T1#JUC2_>2PddPdT=2jR<=Hn_*H)OAogP zld;*fuSOFVO=K}tR5Vo85?jUb$c(GX(Mc)c5NB^sC*uSO?kaCDvq`;&FNm_SwOXuN zz;s%TV~NROuFYW?%)w>tp3>nfM1xi{Fl1dwI<|VNt;YhzuW>VuO%Y`lyL{3oBJZlh zN+msB1)(Cr&%0NjTble@W$%Ir{~f2jt}YGgUiItjsZ*O-9HLYVE^J|xzvlI5^@a8S z<~!})ByZg!z%Y%yl;PfL+0!##+NT{|Yf!iU`p&OD|Box)K5*5gEkS;tsD1Xnb#1LF z%VsJuFeLQt+L30pweXgFwn6dKFvZB+Ta$NAJho6MpCdEB?&c5jI?S*p6Cfu}XxX@T#JwpE6DQ7#ERuIp~NN|kfwD8K3IWSJsv z!2BTlq?6XAl8?Mg^@IZ451*cJs9AeeQvAmW*82UDtMUR1Ef>yO#y%mnb(74^cY3#` z6#ZW7xQK#Wm1B)Z5d~CoC|?KiKcT$Nz9QHxD<*@DRVC;E1rO$UtA0ebuqQB%U+d z9JG(9K2zMqUeR>Faazo`o96^YO{E02jwYr}U|{&7%a;3=y=wBi7V9&YCOFTYSC><6 z_e-=rcgv34D{qx0-`$ltKdWcsiLTXR&3}uIUYqFX;~AztOJdpy5z7--0#rq;mTe2m zY!*;plvokDsP~|lW4nVyn?QQ1Nx+TGeQ)_%QvuS+aStx z=E2rA66?b(izmCf3iGfs#AVAqmbfl&p7Y^r+I6#~ofB_94mr^wd6(?I78uz(C3|gRYs$JKFP}a*t)d%rg(+ZKS6G-XL)XMNfjX8EVTN718BejD z*LprfOKL_#nG3^`iB3x#!fx_KPTajfwpgUR=E{YLjT`IMW^_xoSTaOhyvDL)o6_5@H@-m44JmLf)g5C9g*8ziZ+xmG|qE5vQ^2} zobTGPS8$qwf zr1z}6KIIt4PiC8gf0-Fh#Oj_tvnJ()>9u#Y>9?blvqO!JDljrQq^M5RyeRfouGek5 z%Dn6kf8IR%GSl?b`GDhF#kHorxSkz9?a9or_3NLlK9^kfW9N&)JD0Llk|g-N1Xc$c z+n!#qAi(3c%G#MuUeY^H#3ijdAZBc~chM5wLXGDMryO1ccu8mKuKpl0@uil=5r>{I zox&8CsX}YdUV6#6jFqh+Os~l$g!9w^sdbl+`K%Uq*!FnMq0I~W1XwOCTeabB<3XpX z(>QH2SOqI5E@R@Z-t9cw%jmlhQ-Z-Jo&e4xyvNQyTJuD)mtlAD-VL^bzdY};74G_Z zcjA+^qBc*rygrb8g6)*|u{A+VFRWr~UzSYQn(KL9XW@%?iW@d$i*1;;@iBu2zvHWW zCTf#4?3RC%(l}}J^3e=+BcCUXQ~GWO7*4MWzV)!I?d3_8yszpKXD#>}8iGWaKOC9y zKtg~1{aYzJpSl8RPHqRm2`jmiA&*=)XB=kTm3DiCHk(v@A_8u|3l*R;c> zEr-^)rQZIyjh{i^&yeA|$A<&Q)y_OMx)!Q)eCfG}o6~KxA1?9Q%We7l)y{t_{?0l& zVe6r%s&}WUu(rgl*z%vDDRjdjjyvodo=s4-+$D3ZFDzQA z>)EqqX0N+1Tyczgof;bHCeT{QyXfL|FX7Gw-7=DCfw>nmw%lM7HQ`xPRLGJvmHT=8 z@2MwS*L@O5t7cr~G=ryc5@()Oio`*WUS69Gy-Vlvg`8ed+N>n35jQ<3@!+hb*L$Xi zE_9mHypr2iDalP$|LLk2%iVw7Sf@nACh*Mu^Y)L@iEF=jwL8rB?mU`xi~oWd7yE*8 zvm4V-9KE1<>7}%IZiTL_b>^|F+g2{s`1xWpf8ot3Q#Y-Od+xCFjh@}q&kJ?DDm9Fy zm|OGNp2-@NWPN;a()?SvdqiW#jjJ1D{+>|(t-h#M+1^1^U4bF$3$sa1TC3bj>GS?A zaVsZY%FTA&aD*%A%DTMM0W}=c*WIoUd;8Y6opYOqI>VB<>T8uzXN6C(Iu%SynjCub z{Uh;>HyVF2BnI;wFcofDJvYy5NsK^6)uD&h0Vz)|XukLs(5x=7?#7DXCw+qF9!Fk^ z?GZaStAe4V?I&BrGwJv4u~mhp6SM!d`dt6ZAl$CV5b@|P`}Xg;f}DJ+t2b}SUi;{B zkZ;J+OPjQcswX9i#OoZ)dl9$4*@e6CO7**mhrXQp{x*LiV@=u0oJ-SrL|DqIF1|P< zt|P)y*P!KX#2}`7pgsTf>{Sikd&I7`t|^UeOAA@55OFBRDLX(ql*@Y|b9g|U)ti`X zNhY0E)d|NVOM979+-5#GYPVDKcz4YsmNSW6%lrQ_oZco_F?GS^M*AQm(L}E5g*EQi zBU~b*ujFY(+UPy^yI7YR_ullz^OlS6MU}4p`L&bz->OXRqzkJq96FLEXy_8w%(N!U zlYQ6O{k=!is@8{2pJUeZ-{Iq|zrWvoS^YWjW}75aCTn!vRnL{8KPy)1eA^TxzO`iM za`|rUsptB`u6hMOoTP2KcI&EXkEdoGz98(S?|g-ON!dpg0q(!XZI7Dto_;zq?cs&} zj^(rX1G1+u8QAM4ByC6y&6lkY2;Y0ZHEg|B*4`!CLSNrW+^hX6HdIWErDQ>b(XoK2 zur61TP@M-SB!k{=4ct-|dVO`ok@+9ate6&hK=Xgw<(h^FQFet{2b|N-mOdTb%ps4+`rfE1wURc|`qJv3e(Z-UuMM8X9E886Rcr{Gro$!>Ec}mq`rgh&x zFy*|pI(uuD&B_)lf0MfluW4+W7St2o>gU=K`K4(^qbNIb_q?TNW=Wmu z>NzNKB#J@mwC-h@FHH})_g&9<87v?_A@752yxr$D!e`^wUe;bd&thUR1H#AGr914DA?pWag z&MXlMJZs7HRfR!Kag##dX~#y{mTq1r2E)S3A_)boaSLWNrPMQbzP{quzi_HhG{X~V z5s9N26VkTqN)ZrXkoP~|7*HlEJoVPWzv?IB9#k%@Ue_mm{)CfX7f<iWs~ z$l8|g>d2h=dhcW3ChIUYp4&6BLR{Ae&%RfBSHr*R+Pk;4K^NQ<7)0ow>deNFb(Nr-}PSwRCq5WBbDl;57T~5r@Ieo%G zE!LN_+f@3%q@z(grUWrgt)2Q=i+i=lO9{#8Y!f6^3|u%bYou!~VstP|dRn)`GQvmT z_P1-7d~OJSm0~@)Mklss(#x68L(2TUPn(F$b;-W}-Y@jH>8v%oBgCR@i?)U_2cG}i z>U2YJZtU$Np7UR%88U2Si#wq3Ea!3g-@xbk3XCCcwy{y47pL>%$o{rd#Y_ z>y%%6R9kwkohgVk&Rf-gw)Jn1@0q5@PkLTXu5|9 zaObu=Ws}}`K04;O{xxp}eC3qW?e1Y`?|dT> z;nB$O{L~ebzTCNArn9W+t1RB|dd7zvZaWQDY>)_Bv*$gd!Olez4bO}xRGF{4xnr4v zV2fifPoGY6b3kj%;xE@-mtFFo^TwyTVyTJ!CK-k$WuF-e6&HFw5830AuzimF^-9J) zla?@j_{b1vy30kQ7Z&z14_t)lo2ZeqC`D4;w2-)XV-^N;=}`P~+oUG(qM=PN(I zeOo?1_2z4xRU03-zWIM|)2lGX5HZcCj6O4e*!|gZ+PFaXZ-L!i_7zjb#2WkOv4pn! zobE|?c|2>maGWOBRM((YaZ3&2nyxBog@#2=J-V==OKG)^h@XQ;LsyfS>bs9?m7>C3 zOZ^zWbR9pq+vaKG`RdbvnCivg@TGBMo$VzPb{*YyvAW+LFIp9LKG>`)$U9JUq0PULt=+G$tax;n z_q}CBG55ipZ9iQmi5d7Y_xO2=nTgf3Joy#3vuIOJ{D;*7lkWa~e3|d_ktk1BhM%+4 zT^zSYMQ2aExMI}`t+*xE`j2@?8mzq-`qx1*wRYB;xM?Bvq1T)Art9PSi@6Sny<6g+0uv8%5&R#%^Vr0&KvcUN2cNA4dFM^58ky=s--L#ejJ7Z!Yn zC88P^h3Oqs>YO6x8MI)k%#G8Vg0BAFCpo8UB1_3v{@c%$^ULbr2d`YzJgavpVSe1FXD>cfGl(s;V9+l-@TY*; z?@qDXZ?)1@zUH6jHnFWry1sCChS9toTH%{+3HkksY(6ES zbXFsL5r0Ha-N#kSw{ErH5_f%h%qEM}c~97_cF8AbYcl?5naKATmp+gS`wjzce*g;Df{w*z# zb`A~;{2%?_?!WVYv;UU=UH@DC_y2G8-|oN1{}iK@EN70XSnDrcY#xIfS zkrGS)U$tqWjOu|=j&t}YtYZ>ue9rda45PGa&zFwKiyFT(a-)58CEq5V>|^5Ao|-jX zuJ&6Pgj!quc;#MTpMnHBU+qN2(~J8<&0XRT^4`8P~GDHw5r;ptA#ofA$O zy@}YG*4hzPIDL_p+SIsJSK2R1cuV;@C-!a2MgIhC-q_<(k< zw~c@5n_ZxT4R|W!({?Ys{_{S+?OLzLrLBfKAu@X}-#e^)JNnJ_lb4EWm9|DiiQO{U zmD;+-q%-8W(UDbx%S6wnhA^}~NzF})yp|9h)Z60BI$@cC|ugo@%I@Qxe zc}$sa2G5c@q#%-Y%xIfdb|J&e3AQFX&t&Xg+cZOmVPeR#wdWPwGntEY7k^pXdD+)` z`i+x1iVizB3r)Be`zvUgYpQ@Go5t+F6L_@4-|_Zd+oI_*QM|cp$*yH;4?f>r-QXGU zh_#tn#=S(?e#W<;#dGWyXUtn0?(pZ?stqc~47T!H?$eqQbj)a7(#h%3S3e4vKjCbA zx$!6ezPs9tc@6~yhn<#)Jmik-x+*1?kix)VS?6~xv3ZSz!LfDv*4fwCY;&0!80GfZ zKGSs4XWsYV|7zRihKl-|AF(U_+3Ki$^Y!hEecKMNnlw|Af#E^kZauTOH5VOfF0GiX zb1Y~2jSX8&AKzGC-eZ}y)9>0ryPI#%Uw?bmnmc>lG|8Y7FRYAG7QLMlr`~bxBu}6b z7qiqso9>n#?m|{0HqIw2iZ(T$5nJjb!^RXIqFl+#X~LAFa5-&**i4@5(Jp6`He0kB zOXzeg-N5;FQ--Lv%+jN;G8`6MNI5xq;$blc+lD8J2dAwn=x}IAI3UJ&tYb|;RH=ef zLr%h#g-=2|qEcN_ohQj&X4-v~!8A$(I6hKS_L%ns{b%4PQ~o$}?;o}Z%8 zeEoTKOXUB|b6>sRg|Nc&5yI@4@uw*ew5-{3-s%b>E-4G=;s{z<)m~ zd#i+UaPq8~4J-@~UO(FS%wp}up3qqmQh%0g@6SrK+19e_)Cyld>zie5UzKj3(7khI zlZ1|Y<5b16=|*jP7oDAx(Yoo8Q)2G3CvsaM@;}IRptH}~?l^oKvwi$Rc@U|{-%`I5SeRHGXwv#(HaV~V+ zY2o&X+i!2y`Yb1TXL;m0ZSfo(*U8p*WxK27_s`rG zKkaiwGQ+}<4eU-a8A*W$%*43Ok{b7fyl-96<-sJKBl-Go?5)k>EDT8u3-0mU`;qEX zFyW&*qhS8e-5=fiKR0|~pIDYDZDD_0&&q0%S=QP%uW+9p(C~HGqc^YSY%As5UKaf5 z?#=BRFV^38zr(X|;)HqjU2kU>&)=LY^ZVn}@SB^9UawnyZ`+J_A>rN{Uq9WMH}|As z&)Hj|tP=z;c=K-+nb1_RLX4B;Y?JAeXx(c{Hy$eFJjr6VaM{GDuj{*Rn&y|JtBowJ z6B#*lh1(A7cv5Fv{G}34*aRe0B6ueW&CW_F^>n_> z5E{c{z57zA9yeb%&jN)n9IQMH1rA3xm|ly>?Z}wuuE3C}(vjFJE@Z#y!Pk>)O`!*l zH)u21ow<8_)`a>6%W^+j{m+`damh@31)n{B-=p@nTz%JG`?jO%y4F(zb*-5*9T^x7 zq~<1Vs|#4Y<86YI!G%OY*p;2TCei)(SN3eevl+yI1Ht#@DeTQ&)ArS>V|p zog0f;R@4v+T+I+xRFelpn#lpY7wtN|U3~_tz z_GJr*e`xCvUt@dBR7;Nep1{X<>(a#Dxba8d-X^>C1xM-3nT!k!X>ZbmgkA;B4{%*P z;m*$@iItTvHeB(o+!|?Ea>u>h@`vTCH9p46-~mxA%4>=(3ocVBN+r zv9(i%i(!J>s}n7Z$(x%FDFiK2@m?yy{#eJDT_MM1f$Ll`#RmpU(-tgncQMrBb99mv zpT^wN8OZ3AHC=kq5wtd#)2Bk>G|Hjq2o)=#1z20>< zo7Lyi6VLtC`vN2w?5uT5xjwO*>{z+I=s zZ(by)zp2V|RY$g948L=trp#Hdl%APPI%`j;TzRqWw8MNoR$<2KDGhTRJecpykJ{Dg zq7-IeD7cQ}_=$IZ)-yz>dJAvOdf)8z)pr>8 zWy@Zc5to<9GdOrOsC(w6pX|$|c`E)2Pd;hp=I*Y$rZ?cEp7CS`2AB2EjxH_QoP2gB zyUN$--Fshebrs`Lo+i0QWyZH8iD}bTnRWav+8XAxF3{UoJ4-(1wU(QCm8+)uf{7Y0 zl%!N7C9b5lD@Cwg6frL0ILPy9P4aG^vaGEs$}9M;1s?0u<=nK0Eg^`l`$V$mR4ySV z&YQ~8d#V&zA~=%0Z*){FT(>QBNymgY6It|Fvokg@KAaI0B;~`#w&vZ20Q=4`j!c!~ z2@I`fD|kFil(M(v)XzBXHudzRm23w(u6A*pl-V_TT0w`BpmlRe2CI~~pz5we6B|M! zUAflJop^nRU~<4R#ZK=G)*DL}ZCcvPYSEL>z&uU!QqGb{6D7qhX_MB=uN7Fs*1~e* zc*2tlT`Ww@e~K6)BpB-M*nYD;!gx~NW!J;E8+9i3nEY^Zxj(tPp(VE}@by~dMKf1v zA3LMMz+ljKWW)AOU)~#)$9J8$IN`~eWfwIsHXJ zUDI_|WoNnWexb8+bDh$~c|oPiXH1t_vH5CstK#=d0eZJvmxy?IWExiqN^ZUKa;KSg zc-$2iH^z3&wsY;Ra?6dF)#WOW@f;I~G`@C0LcBvGF6YgPG*5Fe)j4u3OIafgSCz!Q zY&*T_ox8zjTa%`R{bHjkw|4*9L!Y-$f)AO!Qciro^!)K=8f;A^sE^WFdy05yZkBKSSO2F(2 z<5vblgG?5QNe}X8G+X|i>9PCTzGJ)d(`_;e<^I>ZZj@lSH+yX`|66$pwn=~DZr>34 zE8m;A;DD{AHdB;v&gJcEE4#NXojG%+Btyfu$JZ+h_Le5CT5T-t;kV4HcE*~sx%p?p zHv1Xp&AuURYSgm)HS_C;tcdc!)l6Q;JZCy^_X#eWw@C2%<+v3b9IQ%bmP%=A|pyII)F{OLcbj#g;i?^rR*1m)YTF@qNLco_Q)?0E)|1CN{S1U0wtW%B9sC@-eXzVuEyBqHqEog>43xm zh80XHY_oqwO_6DM%H|c&Yr&`OpPnAfz}RpfF@C_oz`$_D^ut?ihyM=$-T!<2PjYgN z@C)&GbqVqhb8`<0cXka9@ed4e^K=gN4fr4CY476SCHLL*WAsfirQ3qBf|ZMUBt`T( zI=*f5jhrRkzvy?;+b6}V|8bPq-pm%;$H$;9;Ir=k*C}iFY*HxUc1TFjb`Y+cJ=d%M zbU&N$pY+wqIfXwLA7t2neerYi;F-&MIo>Q*p0#!D(SXTYB+jxhFeFU5`#WOu_QDrZ zmo>DLubg`pI zw`O~&MWfmZ1%ZSDo1RGJ&6<5U5>lE%R-`2qlWIz$O7_((8J z;5nwL78ntd^Sn!CPfLJ@Cui8CQ)UgF3l1<`NmzVG^GR&K?D8lk9?uYNhOgQ)k4&6; zZS(C#D?(%@bm}w2`A*DQz*W3!UwYX#8##W-4p|R12Ob6n84m`Z(A4{k0%?v47hefS zeidik;I^TOk+X2uDjo)rdEK#Ip401dBo4g)nxPu}&%$;V*S+5?Z+*F~jnd@jrd>2E z*`^hnmd3{L;Kt#c#SQ09ZoApbxA@;$U&EPN-wN#uAFsB#eD>km(A&%I zCgeZ#=UWyVc6aNBUC9AO?KbJ6!KvwyBD-&Ug=HLy5Nr_?vM2~}OV})-ti`iNQZO{6 zw|WUDx0pirk(FyiLT}#gRys1RD^>8ckZiwOl~ha*BS7pERmQX`eldUmUp|nHtQLute@C^Geq$*>oT$I^<0+^yRAog3)=7PC0fVI^I&@{;*M%O* zcg#rGv1^^-5&Hnc!)wjfI=)gpm!-1r?TZ!bTW5Nyaqi$@X!ux|v^%prBFFsOs#Wu* z{IuNr_Sv1+;op_#Ts(GqPtnAn`vPzD9`Cl%oBaLZHPIHgh$}f!4s5d&q)y8A2HJ$a z5V_+dz!2idvsWjAajj(N(n1|4LAJ)tx?CAOk0x>7?l`zwL~2FX;ZLuWwk0tIObCk> z%gjBoXigfFqF0xy@?<^9)=7*EiM(7Bg#uY~JEW#uN=!;jVVENkW;CTo=jaJd<>@^> zDJf4b3Z!TSEMFZ_;H#l?XoYTMZfVE0i&>ST^W1%}tXz{|ka=m#%Ph&YQ`OYPIobOn zHD+_L2%6;G=y`c}$L;wg9EphrMwg6crgv|1(Y-jyWf{Yo$#T-0e)HZ`|M}xWiQ&%+ zZ{8H^RhWxQ%sj!NWNkE2S2^14!gY7|*$iT{eUtegu}e6-HuXy`sym^v>S66q{pF(l z%YR<(Uw*~D`g_#5viEz=pL%!K{@MhV<92UuqC@EmcQP_#~ zkN+*+tJzOpr6xS#)I z03GDEKV5A{@spKnZ>^lu@GEh7ZivXLh>%+grI#N*=B++W%{q2R!wadeXBR(a5x4RC z+B>aeYxI+Q{>!I&vAjIBaPEC}4bb_Yzgb>oKRGtB@#v!qS{=H_LXS0xO3H8@^{pzr zl~iEchQuJ?E0(j${1a3*-~DiD&zKNR_+@->IR_fTpR|YO-E=jFx6gnR+zH`%7>nk6J z)t#2R>@&J~#2Wv9T!a=LNW23Nzqg z5ULW(TqG>I*7fR^8!YT9?prs!nC2?*-YQaYWx)HRIax2%`Q~lda{tCF|4l6df;I^} zDP9xPj?DXQ_@a1i(od$6_3g!mjXxR60(lNxWfPaR*&Nq?dSU3*-n9!SrZ;72ACr>2 z_Uq%$6Jl46ukbkGcE%{Z;e^FE&YYsuCq3DJ1njefPb+%}+aFQ7An&ll$B^N^NrQa7 zWvGmg!fq>;Z8IxYo(Whjz9Qtfpib_|Cz}7X;vNR2e%u!N>}w6foU*$YTyHH&jQV?e z&nd4-er`SoPt`T7QWIrR70$6g*7MeL+q{X70{cQQUJbh5<)q;waAX&wYqOb&K+k41 z73JUaJ^fot4>GM0wmf64&?frGlc^>w_GpA$?X762lh$2i@(` z@8g+NOjosOEu5Pa_{CI8c6+#oz^0bhAJpnddmyVeq7-5+-JN&`6-hT}9{0tdP8>jqS?DD%pV%2LmL&Jv> z%I=9>k&$7-CkubS+rYwPS|sGUXa2s5)GtaKYeieiPUa|m`*ie@MgFU4{Prb@`)^qN zi)&bQP?Eu)J>b~Q>E;`(vT7eE1|^$Z>^xKC#&ORe;?TydEz{y;tJQjzt}`u-v)VH0 z_|s#ts;&yZJDvo9&iWPB+Ww2%Ze5V4h+|Y2bNP2hvBz!?%-#6sy#8(}>hf1=*LrQa zR`0;I8K$ewXhijD1-U79HCq&{?Y){96coMa-R%>zPXt}Bp4guw)7a~?>({W}t%6R3L{dUC>~uIs(x-JKD0i+mDH`&dgF z)I=6p@kj;CSXcRydyO&UmA=nw^grILbKdB9b7yI9=e7yvA~U}+-(X~9sMyW@2f-fH;;VH?;M_;C7eUsmNQz5Jr!-fO2`&9Dg+xw~q^Jq-?#_NzMrbe)ZRwh6Rf z4HaA&xuxU91|21B1BTb9wM-def?lS$ynFP(_O`3jSI&;R{8oRz);An&@n!HYXX?2- z`I(}M#`4Ypr?p#K&l#==>;E1Un-!{-wJ(&F1#@p|=$43b z)RRw0O^jf8cKN_7z3KMb7Rt?wiuK&eBo+D9^Wvfwt3?%|qF$Od!bh~Z!gcrhJ=wbG zqt>B`P7T_TNsaPijto9YE4hBD+3&cQHa-2pV*Xh__A;zhV_;w4%TRok-{n@p&MO^j z)g(8!nzi|?x{{UhGAR7wWS;rUcArdtd7cWlf!Wn!;W9=>fkN$D&>B= zZ}!5PFX^Fkc09=RYt6Q2*w(j@p=K7tyz2J>!cF^fVlLkL))d@w(^bNBnvcorLsGhB zkHiW~i*DUCT2k}lntu>OPudeldjh7BSRamNN+ZyF9CPN66+aQPEfb zI%KX4&$`*IwENKZ-%0abJ45QHDMabCRaJWI4U@`Vx-#iWfBUtsfvb4d6va-OIQxf# z|BvA9W{exp%D;%rl~3R+vS4^CyrZhT&V85E`fI29++svs1$x!)tb7{~>Tkn!Sc4;( zRY`>_Mtto9!QLP2_pdy7x2=U?Nn7&d*^wRdTaOv8eR3rwyR7c~p{;QZF^Yx^YZ-HF zk~X-_TyZUXqw1Ns$&o#-AGxlHrSzW?oe}a`gw3~=k*j%)yx6(TBBcw}Omy;Y`z478 zRi)-}{b@Ys^8A11(v9qY8}Dt&*eB1>@G0PI=i@UGk}-7LcS=Bh$a zcf+blv7ssw)+U@Sie;s5QhXWSXhm;3&XTogrPaMfajq+wbq$z2U2;})RPhF_igcXN zw9#8w$+CxCKUwDZGM#7+VX4DR52gt+a5Qc7oEV(&_S7`CM)zXa~KRRtQ z9d~K3m{M6TeC5)-wNuU~^0wWY@o(#us&uc_r~ggZ=3F8xEiC535XK_F@Fb9Xcj6O? z)+-+_pB3$1ojzOSt%7NW{Z(U*4Zem9_l+Ab#cm7NUCXbwG+@QXu-si@sq1}0a-XR7 zESRvgTW5~H?z~X@JY_IEa|waykVW94qNLn28PvhSFTL4 z+RCD`UHnbD(^pOp+q)lb#5J@oHDHn#`te3Wyj4Vj^=7J(+r>3*kJqfyi{cEtreSui zC8PZ0su0cNvh8KtgQJ#&%)Ib_{>{GR^)lwIu)8q07{S94pc_Cr85kJ;%9IBv1pE*C zZ~Wi-zukZ9|BnC7|C{~yb`1^;iH?j24h#tj{=deLS>$$^gN5HqVebhV_7>l2UrTp! zD7szYYlsP#a~9hBb={?_797(JIK$cjkHOz0$#IAixe1WE`B6R#1 zb+STN2ReHhTFtsz#q)^yka+tE>8-DBFxNX&IUV`S!0_u~fE?e`hqo4Pot+}TR(z}I z{fv;Av1vjK3^umODW^D8GLNS`7MSewKh92;zy8aTS(gMO!(^qJCcl{McKp%7YdO1h zjDEfOJ#Sa!%{dbf{+sjdnaPb=T*|qcmrvN}URx%`&9yZpmV00M-mHW;JFLric zyKs^v3nK%=nHOz)PVwls&zl#iWA^4e|K@Yn->dIb{ocMd?bmVjYsQ}r$;eo&>pU0q zDxhTTJnd%J%Bcr6*f&j!bkyGUdO~A^(&5Ydrf@K(X|7LMyGl!G<>TWCGg^H(7E4(f zNGxHKQ8=B@E4sSNbV>!|a%S&lcZMknF?V(_-r+6bSj%*xYuPU5OM~cZ@(8(`#p=3nI|B;`bwxNL(hbVvMoF%t&A5K z6kKwatY!V%f10UCimx`1A=vzS!nJvxXF@nRzVxIo$%tLsx<|jLKzZquCz8VJ8CLD! z(qm<~%vP2AZ&Qn>ZQ~^g1_o)CB^(iKCMx@8$7XrIJl-Zz6QEysTqP67BtBZDBy_vH{L|N8qNB>Vg zL!NE3ER&XgK9{vKd1JhG@XC`0Lds!XE99n0aIRdwT2OY02*=W?!8_N*^{z}g7RSBt z&5a`rir;t|r!cy@iF7chK-MVh$MiE^{5mm0HIFp74e4K(415AWk8D?na z)|4HM3N%0P{eWPFBRAKI6wS=J$1IO+Ubsy4*Wo!OFE`A7r+2qWqakeawWO)f&a{f% zd-+kbE$TVf70E3VtyGT&E?M%igmrS=Nv6cN$1i2QJ{ZJSax~H1{`Jb>56t!q^Jc%@ zYx-h-;|sQ;rF*aL_`%PtR#2axtM6d_*33$J^S;DqYbV`IRbynZs56`}Ywa=9bGN_y zhxgA|)|)lA=k(I#m1|!2X1ndGZgCXPemrO8#8-fSos)21Wi)e)i7;ZU+P z!zV&f?aQmi7|y-B*qyAG>gl+#^n{o$>R_3qwA68x5<^B)>DIf2Op0*_(geC~RF519L$(<@>Ei~M2sK987=lM zoyiA`loS{yM9`vCI)QtMXZAim7x^nHPdS(sm>qHs zRaS7XS<-M#bdwG9z3jQw+<%y57EHI=E_TrV0L!}hncHu)&o|t(E$wS4WQglRr*z7( zb9L`_UT@1hcIO1&>CKxK^lUWGeNlT)Y}e+hotEE!iE?v?b8ElL4y&9P9(FcNcWZ%T z(ps}=~VI>?+@WjrxeP>{8-MWV1JBh}G`Nr^S_ zL0Lmi!ZE3+&;y%;1gAT87_DYlpv3r&Wn=IK4!uwltt5MeFBcj)Pdi-}o8r}&;lp*v zj6-4fat%$7-EVl1|8 z+~}lGlvZxYA^2)f$hMW|PE0e(F+H~C>WUX_+ty5+q1wX}q{GC0HK{{D%SB_g%#6g$ z(^9(=T(%^`9~`!Z}d^OXbe?wV0#lKZ2a)g-KQrrdlvCV`Ofo}jqd(p z?{z4!_q+IRJ=xGm-|Q0UZOkc#_Q;8>npds(hO%wGBC8H&k5ao%|Cgo%4<~t z&(Av^-3aen{LnD^zR%v5dv89!+oKb;_KnYp6}3)D`47K!8uiZbvSB<@*gMO0jcwnW zBFhqut4Rji)bF2&a??5?v_PPtt81f^bg~zxlGA1Z2Qdbrmb5hn6PkilQ@X$Y%v-GfB2cAwwlZW{T{R9EM6>9^y# zbMwAGznQv3xg;-R+R+S^SVzICi#(A^CM*eJzDo~uvy_Nv8w*S{GICtnaodrJxhdeT znZT@V3vCZ%wL9GMa$dS1cCNFe{u3@i52n*Mrt~m(x`eFUF*jHGU3t&qRU0k1?_xEXm^0+?0H;s5m%iZPd+`iFYci z-n~hkx2H(g@R?c$$GuG|5mT#U6VleiD+Y9&@QGS5p^#rt?I%I7qlWhx^MVA`Y`i_+oqnx6h_9HG|vly=Knc`*8RMhdeG(0 zBkk7ppBY<9T@4w!?HLc*x-Boc3Ci}e>6VfeZwyjoXaa`59f9C|PFfqm{ek&Q4=+w>NZkpqF zkzvBmZllM~rC#oi4LujMs;5RW zZb@R8Qgm49@$y|v8?L^8xq~<1+_$#my$oyDCNNg$G=Bbnck6_+*Oa%`f4rTT^zqWA zPmf=_=D+T@e_m00uWIMl_1kS@eG5At9ln2Cu)6x+^*-klrk@(LCap=(ZQR+%I3?|8 zlGuHtxj#3|Eqj_~c7Mv{hwtnTdiCN+Ni%wQ?o_Z%zOOp^s6T`Ll9LoE=~+JO`(tNV&3Zal>f~P zo%-f&j#`pRjq zU+h+TdPp>V$SvO5aM>GbimM-szcmr9XIHy5a0M#%%&- z4Es-tT(HjFkeO?C{90(>lnW8oUDw{#rLR4e5$H5mDr;@t{n;H#l25GWPuQ}LU9B%t zNY`S@BabPKkJuP`rd{N_=5}Yx=hsgbNxsk$=Ss47=r)pMu&-vYubugA&Ai5qs~*R$ z`~0}bATmmN8F8wC2TcrI}MWho5yt5%*xwak;Uu9{9JriePhG5Ow#;XD zju`!IwyN!dbRmz!d!+}?;u6y;GrHw=SS{K;%QyQ0^X)(L!%p%1m5Ok=_or6xo*o<7_jUPt z_OC@V>@w=P+&PzItu@~A>)L;jqe)HwR+(93CRqPxJIc4Ky6W$l17R_YAN1#Yh5CER zYEPLSSo$=$q($n=>dh-PMH26=PbleY+C6Q{zBi^7$%eO=y^>&HndDQmmPyL$>N1vp zjStLPeovW|#P!Kup_=JF1H(+~wRN|a<=+n5dh?8vk#VpPLqocx;*}E(4_|%1-O_mO zYpt=b`);e(&4)rCIG z4OSd92yFM=p0Ze>lZ(4+U{H8)sGFO6NMNL|kCT^QP_S>vf3N>` z|Ly-<{Wtn=E$HcRWX7%w{`cE2NB?=ZY@?i)PCqu$F^W;d%p*jm2)a%B2<{WBFDnHT18xiZNLW^px`EX{~k z7ZKAkJ;(k}+JjH1#mo0o>sR@QoIAeKe2zx>?+xa+-iG#Mn@N4R+@F#C z(0$rUl{B>kVHSoZfxA217h6RdR@d+76%Y4oSJ#)H{yRVa*}8R#cb=Wz_Aj@pPC8p{ zckA6thi>pJ7PNVDygciJPSK+``=qv)8a&#yO~FGda#{K%*VW-|yJS?uf93c{hSmgz zO+OZ}aLVE-iVY!6LHWC97&#>vu^hOi^Eiz4$koG-qLSPhv<^(YeTn1xlERaUeq7Uv zQo~zrhly)(yUb_|z2Lc;Vb?VlHls2oVed4<3K!Q}&+eyc!qSoq(V|8NcFdS~qEAm* zsCjqd2@Y;!-2)sE=e-VcsTEAuoN?d~AJ>6NoI-|5x0KedG1N?6XZ8M`L zy`^ifOrF8#?&lL9bX2*r!9j_koBtBal_KZMhRS?0|8>kwM0ZYP*W1RQFguB15rg?# zc@+^3x6NkC(Mv=1oLrOD8{NNYX!p$ja-~CCGv?$me<9XMNfF0c&vYe+73cim{kqF+ zPMi5}*SgcUVr?0=X)-McNw{8M)qK^_IQmE#o7d{6osqIZ6})d-VvJto37Q_$)!T99 zZpAiv))c=^rm{!NYR)_tQ4_YT%9#I)vBRj1IUxAJ?W0m}_`NMxZ=Uw@(jkwMNY&NO zQ{J3T6_woVAk?~GS47d*Sq?j&NN!ft%+y9?ow)+x%E-h5tR_L=C#3e3$ zvUJDHB!j#cQ&lB5_V}OFZhBwgm8*TaR+_j>qM1T@fX_Z*fp|ponI1 zY3O3N!?sV^^!akuJa%W86SQ`!Td{HL&7kF{7z!shpLjWc`SrB6Eisok?mT)w$HzMR z=G?tqQPaGxbzNy%6u7E&%c2e^QTK19i#*?yruOV@3C^DF(#`Z$FJ@!sS!Op2hBIw< z4L;WXe>wZ`*}l64f}8&qn9C;!9%J~z{UP}Anw1r^-*J@2E)5e6y{L67Ds;=lyVurC ziAWU4;ti_`U8%7uBt>oNydV2HjE}OpXNNfP742uKamr=6oKRQrHu&|7hLqb!ipu2^ zX0rM(~Q0tzbQyE%l6v2bsAi^pHnkB}} zP~zp8R6KKX|IxAJSN%vhf|Y0kLhmbSa=~!H}&e3rC*$r zufJ7Ub|OFiO5y9pb)omGIpy!G{S}Sf#x!Cu8UJ%t;XyS2opaq--XZIfkhli&o2nC5stLDzQs$%P%3HXe5;oiwcIV-KdW_0NdKIb6U8ke zRqB$gaH^4?=TGN~DQ4HsarDlUKd|()L&6@0>$4Yx%nwuU+Z}d!6}PWI@8Js7h!qAV zi!|PLt(xVk>)NHXGHa`M+h;CMUx~844=i|kUzkd{9$;P*mRhR(&E?tUeM!E&ou)HE zNADTj6wqKSx%Oh&vAr!7Q-X9wHB0pOW)?Blt_^j*pc}dH)|9KR0y3?RD^z2gb~aQ^ zxtCk8u*)a*;uNN&LZ+Csw+g9pKe@XYzn#*Fci3~Qeccb9QjQ1dhI))YE^)csx_d`7 zbD8v(zC}lEEjwLE`XuDh`xYIqhqUK*$35iTma_THAHEmjKdL;5GM@pcIcGE8NR}5>4 zVwux4Czbu#cx&2zs&S|%{hG})Ttc{FV;WXDu zE^N^p)h|)q+|Ig>E?N~EzU(-_)silod_0l+Oy5q%jeM<>lEkys7=Ki*iFl#9n?FFW zD1t%G`+>VwXrcb}1=p&wT;Z_EXNDkJJw}Ka4~5HeCbjO3pG#dXu7{8 zxNdz!l1Oh8WxzFUXXQd-NkDT0Vg;vIZ8-wxWgIBm$X6TOjoqnjLAP- zt^GC4ExdOAI3K+3KeNs$j)pgkyWdxDndp8v^yxaE+G|@fuB?mI3pI@M7PRP5vKF~E zMK9!tk<*KFUluKtkt3izM9m7v z6LYolU!C@Tb#D4@yZfcAJA*Xdg=nkQh_Oy@Dz~)1#poz}< zJ=o*GP<5;H^F{YUhmZW0kD_+w#&=)znefM1>SG-PL#n=eSogKdos|-n>r@x+%e_4@ zaP6uT!$}Mb3=8J_Z}aKwbGUas`&!E5nChu7%Qx9~nIF3LGO5$oB>Cs!=oem-Egzfj z`k((^JzXreSx0+vYF4ih+eI_o9@Cr`0@DH#-RJc=na}7+?CF@E>Z;c&d?c7v^Yj+( z%xRaD1t-}0?KV_6UKX|?fbWiw7klv4ZP#SN7dIT)CU7Nch4gwwJ~5^ZIv&D8O-xL) zjW#hz-rU0cSW2Z;DP;MjR&faf<$$GzE=`o0$xO-!ZROY)Q)0X|PV~=HRowr(rd2)mBiv{yCI}Fy`Wl(eoX>yggtu>Y7 zxI#`txNwlC*Kz9`d}r>R2-={2n|0p3U9zDKYtonZt@3tYns+<))|^Yu%D>y+eDA)i zXKT>(ru$9x&)!lA!FC>|+475XHw#`1>y7MTWMKGKaBj8P;zdcDmQ2#yl(2U1-B(v< zTD!MJoOhI)G%@;|ZA4zu*EWj-c`ss41+5Nqow=wdG&YQV4bx&#&A`;~Wjz}UcNJcA z^hz(wl6F=QbIfwcRd!o2V^yqm-enJ#o(mUJ*9&x=kiGHX=xGxHE_H6dg zx_{Ym-Epr(YN{kxgp~k;!B3wfX3}*9XMD9Hgo9_S*kEud;pi!u__&g}{W=F;+q3Z% zykvG{{I~ke>cg}2Rer)Tzj`*TN({p75kl)Rl+E+(3Gr|p=z=9`4+yWK*w zN&_Qe1!cWf2SvQiv=n>LsSt42?~NkQN>0Tuv!V{J?dh;(;#t<=xlv-N(khkk)2@%6 ztmNUboObq1*+#R_CmKE4&QA`ouui_36{f2@A==>Lw)mA#O`o;4V!uU4R&>{ zQdF$?^XJd){~JU$T+e^0d;WFFQl36rP6dX4tLIKP{J`u}aPFvIa_=qs1fK_XZuJhY zj&JHM>$%8x*-FrT=1fTz6$S^XsO&WxcV)^v3M~>Tx*w{4ab2Cn@3i7$($z_?f5h== z?JnAwTYGfYj6;c*-KX^??dZ~;x+=rU!@_NNjZwV6fYB_q*H^{(=KP z#jSmlrRq&)JSe$-(`&=--8qM6@!qdmdg#dNlr%O*28Pnmj>}fNHTqvq+nl$Ay*BFo z^CGEpOKw=a7W#DQ#M+4Mj`^Z(HZNse!-Kht1a^;VvJTmi&oVIn9Sov*9SHo!rRvk8(O&1b4GdMcM!uOrM z$qgPq_3o|S>r1uIoz~<3x@nGNzv^0CzGPvJR5#m8O8Gc;kRK!f7au=dz}(F>$!R_(g8I+wrk zI=7X|W33fiJ?2mLEG+b9yr7rpn#-y!7<^Up;g<-hB?7w`6E3DCM0*M_v@CSkGo)Vt(&?_w3<+&rof-)(s?P69cTJM|HPNkE zZMi>Wydw%R-oeelz#yQ+?VxV=KRh_tFDTSE)GHwHzyE(PFOPtb|Nj32f@r7tDz?ygx=^!2ye6E*g$XYDF($eK>dTXX(a;?Z?FHuAYi?-z3!>KJHo-1V+% z>XCYJu5sBRj?@xf7MG7jAqy@Tn!e&-6)H$`)x46n=v18HuHwZlJ35??m#y8H$)&W( zN>{&cx2pbPzlTj5barZ8un=*c!OP|oer{1yo|VqY!mf9s;mT_h4lc~Fo~rPRF_T;9 z#03jC2B+NRArC|L-1z3e=qsEo?R{nD#61H44<1nP)d*p*wdFo_SE~4}$d0Z})0fG# zbaMI4vDtLb+qu+ihj;DL;N2aYl22-hq^wc8#eI2;aYN8G!$^U}m#(LNYLS1EY<6(d zXZxVPoQs)QH<@_xS}-t`MBQZjbZk;V{&x-6^wv|aXHjOE^7lmZe4d!Z>;JAzp2WPy%a@7kWBcJ&ugD7tf+}y{ zJ>2PfV#~`z1uS3qez|Y#c8cW;jhHMIam{Crxajr36)Urrhg?{wrEQq<_Oh$ytr_C$ z4>7%aB_i+Jq3j;bx+LzYapR7uL0vaDEDWz;-?x?9^+QcVlvc09x5n4KyU))5AYrJL zn7TAXL}2YDiz`k$S~|3pGQL*yrPguIwm6&J_LP@HSz(&^;ydS=#GLQkW?<|oI?KG_ zlswPTa~h?~MJ5_dBkn{W-pU{{Ok1?61U8=fxON$Mo>u+u5=~s?m` z)(`%%FMHT{i1RJlXa-q2$4_5V|B zTO+zk6sPqpJ$GE;(1qJ#E&iuRhte zDyiY-wtF>Kue2K(gSJYyNZ#b$>R)7Jg@4LXd$>-nQpU(R!Of5!PtlhY9=PBK~ zt>1I-VAGu7DBHG-x7+QY@&mSsI_le>}1%W5_T%B+2>MEi(9XYt_zT?+}mK;8Q z7del(+0U^1x#Eh9;7>K-E}oB!pbOittMgCz%Klw<^`aI3)^2)#S#7!0C9}r8Dc{|? zjPC!ooqta5TgVjiQn3)ua~IzpeecXLB`bExxx8&l-neZ)$uX7N>~K!rZ^knsM;UZd z82;+Zy-z>#Rec|yVzj)>>`u;!iHnX}hi=`tFmcTy?VHXAcZ)v@2-*7gdwed#p14>6 zmAv{n>(+na(w?AH%l7U*`wD?;T*?J+nVI?CYwS4TKBI7@tM2KbtLu71H94%fI79?a z9Q_&dnx}I`VVmCeZ>vu)(%tx%dE4QFw_9Zy=1iM8xxMZZ|JzT&N004jyU}rd&*Znv zIjXFTKhlmdYEP?PmKC$GSNGQ@iNCHTff1UbQ$t^GYY@%8uvApn+xC>ws-)D3UXwL^ zxVPVS{1Lf8Yh?#3vsAb5W0^K;GE4MxOf9l-6jSLA43=6&sY|GKEld$A5V3<}_ zn#%KweaFG*DASGXAK5KHCF6{onR9L$+24ARv6gpgOqv=4LxS9<3*HHrR`A|XH+k~8 z&V192V`u+qL_cY;(~eXAJb%fj>B2I*dbixYbK>4)+b+ZEV-eCvB4XE@YzzxM-=&pZ z8{+d;Wvzbbb(af`+EZ+^HYR7@bYZaFs~O?w5$hnbs)yy5wuX+5QQrbik&J>l>n`y1 zYB64Ak=&KY?Y(0$opnE|`W^RW>)D^|uxwoqW<8rFbrL2~n%OSU- zKz6qrGheiBhw6qF7nTzYObvCj!kG^$AGo1Zxc$7BmoUScs+&(#ayuPY{Wl(iqSjk2<8-lL#taB z2T0^Nbsn0L|44B5ADOVD3*MC6LQ&nY6vdz4v(I#)t_ru3e9}Z4hGEQ{_G-_2%En z>AT)PhG~8xYVSU)Gz$JN#R|*kw-86dA#FBeS@y38G|Xyl34*hLH%LzE2jis z`_Fa%^_$o=E7U{fRGaelJ^m7+)TDR6J9^D?TYDFimrEl>(>P0}@(L)$IdKUr@d{pY zVy$7#tDqIW4s(1m_pZy&y}OBP+aieun;F}Vc!WiL^r%!g$TCh(=0W`*ptw{4FYu2cmVFJ`x2qV)J$-RBQUc2(Yw znG`SEF>EtrTfkzlu&a=#b!yV`xr$*&8DDLQiE?CXDo9)udUJ>3raNr03uj4nF`k*^ z9fqbnEWEnc;F9n(dP zqZf+SPOY$0yc*S{(X4R7Rnhu9Uv857q1B9zjC0a>P1^5X6}tR(X`b%2?QbWv+^%OZ z^LAvYl1!L6JzeYuUsN8uH%H)#j5S&tG9olXcXNxf>T-#S1bVY`$!?je79in1(U~=ki!(bTGyCnkT~<)Nh&wAN*3UT%cP#8(})PAku^3yescncw^LtJ5sbNnO5c*?+QE zFs-~E6g|QIfcOtKhK%fN)o?unx7%HpSM`NKj^FrL^GmAnj=`B9wu!$UR2SP^o00tL zM}ms<%hsqfbGP-!1f4SVkfKIUNIyJZ%a6H>b6TGZ--(vIAahY=2|lvF&6+ybWrsZ3Lta6xGblbS}> zvZ|>YH}=Z5%`@OhEakY78;tw%0XGsC8A|!j={jwIeM*)84E&lF+8&v{mn>m*b>6hi@%d81#F6+^a7}JJN)-_cM1*tAO7F=zxRLp|K|T|+$QQgc%pLm-Dl3#0zsGiOXfW;f8BfL zz|vrz19vxN7X@hcOmJFeoYHElaNtnfR}1S&nrH8p%$XXq_1(Gjgb0;3Du-S++%eU?_8Oy)gnUEmA&JIG2jWV2TbOr5tto8f;&9lrq3KoA zqJ%SA%B}NMEuAw@%EYz)+4U*f#+Nxq?;;D&`TDYZnyh>q&ZqGGWz6w2WZ3I-q4->@ zh?CChP zL^pKuzuY3PVCZMaaNoXR+0Rs?JrxRTjaGHc5cTSv>a#neC(rTxk{zN)^L^SZr$~Gd z5oc+MD`ZIR<*#1rwQ5>}WzEE{JUNC$Mpr|I>&$P$e+w*To1)mq6x|UTv3PlwN$HX# zjQquI0^@!TkI|lbOuk$KQPkZpg{=lk)Lkxc!j2(CBzB#DM z$hdLqE4`)joVQNcb&V_OV$#u!z?oU5*^R`O!TvFbGKdA^*O-%^0?eT_J|iLhdAD_CS3AdxwWSEdbvkvNa*4P9b!{gNrbZcCirVC z+^Dsp=_^uSn54&PU8LA4>g}&JlVh&tdj~nIWRRC%EhJW1C4`$4qA@lx@kCz9y)3bLmV~ zMh1m*PtQzYP=BHw-1q(S&kJGU*8&-HXUM zb$4Hs(b9JlH*rmzsC4-1wXi99^HV}vCY>-kws}je$jU=Aw=n9mX@<_4X?3d|I%*VCRVwHm;#>Shp8Rl^aYB@eLC# zUtIV4+?%V)+jgAzcl@d2BD*7-Zme3ayFcM7yJ+WMMP`XG<^%igJY>{vFkoP)YST)Y zXnmtWV23;dvs}&HYX6h=Y%(1?9=yJHyyR!HkWWX&_ZyriBoEsy%Do*Wy)dXJR*jM2 zz^yeiCm8t5_A5KKATf8Dsb>Yva$+LPmJKr{LTP?I>5?cpLc{bN#^&6G+XcFx-3hb&)Y>S**>d29F;nS-=hs6S=5^0qZn#RmgOBO|o!2(~nje{EKHRg8 ziaH~3+RUxi{l~&v0aNvijX4<{zKhH}7c+lCX;svQ&7O}p_?qss`}Eo@@Ornou9eXw z{covLL)+#~e4TuEX=!-L{PnIGTZ-+DyQ&yvuYAw(dakd75?^a%P^zMK2v>_Bd+U-- zflE#rtTW(BWp23qjo}E_Q`MIf1Qsd9@qY8tNf2H2B`1I(P4u9N+A*hWQSOj{!z#y= zuDY>sHEd&O=@Dj3%QbV)k)76cOd&+fF+$rVB1bS;^8~9&lkTDgNjDXvSXQLEhF^XD zt~cB{Hn;bx(vh^KMrzw8o#s3Qi*i&kp?xw5h4J=Z1~Tc%wMTwzvI z3)h^mKfq$P@OA0a=JXx%loZiwFb@o)o(kekd-HyXkx&qn+ z79M4DbZppbF|TUMA}+^_as}z$rqBf{Q`H26xJ_^9Ze9Aznjxb;MOla=y0Q6~O$=9& zkK27tUZZIy#=Zt=TSVkC7{9z(`AYfI(v@ZE$xhp^{oCuM*pQ%*le@iOjifSoceaaVvwuu49?|e_q@1T1&ypg`Y)^`6(d$nX|GXQ9C5L0kw(&D z(XHI!;wM*%yM|s_^?H*|cXIQ>vV~Wd1_!dLl<&Q|(tv~6oz2SX>Q=V@{2lYsB91Ow zIlaT5G5*6}28N)PPXY1TRT4+vS+~vHdUcyt=B%_JMur)+pO@@8HZf@R)7|s$9SJPY z`FDip>%X5SG1s@R-T3z}m(|%dXHxt3Y_a<`^G&;TFX!(gO(u&cMr>SNqH_M5iSJb& zmE(q9uA-hnJWXpNHgyEJG|iIxt?LkE#%L5(JZaI_(uoSaZ>KF3VJV!Ywk3JB*`g~A zO>SJ;Eh(7{hO2h1mO6Jj$zUc4o*8Lez0pDpb_p?diAyt)<(p($4ns5vYdL$Xy8F+Avm<(z_Xm}T_;1~-ZhU%D>B`=d zTMza%m|8z8ims5c5DOFxxwW`)nhooez%>F|Ngf7Um=zg~+`5dnXsPJCMX6d+4 z!q;)Z4wdzXoTtBhC%F1$fS?7#1|P3?onc3|v?@l52P^Riu(T+!Nips?%%Q|=o9E1A zIgDn9n6l$m89j=S-1bbj=IZo!tIix;aN0(2{*JmY zhi`k|jXh%D*QmeDurt#A?$RPQQ9Xgl7Y*h<=yX$9pPrGlx;0RlLEyAQ^3%)fZrw0F z94F`TM0WRl(-KRo*wajPidzl-O`64#zEMs6wcmYpugUXP&pj^ohuP-f|L?o>Z9D7_ zu)W`1xy9|ty7D(!O|EUZ=gby;P0XFK1ibM%|9nkN)#I9HA!5?ovo4pMGW){+T*g3Y zQ%cDFH)m6Bn^?OTZCWEaMO1jTwf3rXP0@`S>r$7vuHx`zZ!3vMR zUtW;#Y);6DUcf40;+Vj3y~RUGHi`LIqVH0r37x*r7b(m(+q+=F>z90?%Uy0NO;G7{ z;Nq#==V2(p@OVPV5{&@m7j2ByX{Kwo9hTV4;<&_N3ro^kzor$&n(bj*m*%zzsC38# z2{2A*T2;j{XSGAtwACx8Z(MG6STe}}k)Kihy?Mt9mI*gVCwRK;Pd~Xtx-~f1At)g9 z-IBS^XdHT!>sdHs>zGGR)ihi--= zqg+kwvUwNm)npb(>^`r%@c)g1hS_oYjT}kQ?fE8uIC{-gz%vFf7F^C)k-sAT%n?=f zKU1m>Px5gK-nXcK*RSl<9?`>Z-Hy4dJU+Hz?%WnZ-i4d>Ot&gcO(;pfdc=igLB`f6 ztqi;iLIf_)ieluhy0rKmLyw5ZiC&G}&8pMa2?l;i4iGt*n5rOIs?ZdWsF0}Ka$AEz z$3uA1-aOAMQ`SuA-gWFi!Zj5m#XQcL(;ReOE!e=V7`b+t+7ez7+pWQ+I+NtG9c5I- zy4Q*_%Y`lTJJ#y6Q5&L|uZcot{yy2{h_j0pPP&n* z#=yYfeEsVD6F>f(*_e5s_uKpHSG|j-tFTN>3f{DLsgYEe*v^zYD~#OQLW*T`uPgLL zWd)~n?7Ox!>g>T+k2u24aIAXESZ#FmtBHu1Yva^e4Mzh{FM4sqL1BV}8&|PwqmoKS zb5H8R9+j1?Doa|Vcq4kUruI!@niQp?al3KKmIaY(v|=W(vR#}K<}#~m!3FMaw(To= z95=6dH>H>1L5V`E@U1{a!GwgFdK@mHo}R}Pp1eIase$Ej*v}(eJG6w9A0(O_k@MmS zk!*~aFaGBCiKmZs*(O|0vXm$S4<|4(tV0YZ@G>wkG%@8GX<7Vt`fvK*$vMO?EFdf} z*e@g`I4~gSzuW&17xw_)kf6W-e_vm}fFS>1U#1z()mIV@KVao~BNBR8#^sTq^( zrS3eat=+iUQ*x%{#3cEB`$Qv^r9wT=oMB;LIMDk}d+j>Ue6OmqZys51PCvR4Z94hQ zh0LiDr!&&;8r_cAdero+$gbnYUpdsGyYIz18qK|R$?M|+y^zqoGd3({e7NJF=d>pu z-mW+%)GVhHrt8(PK`_Jd!pDe^X$sa-YowaYa%Xj9EL}BeQ-pwnY?2dmKr#c@8-tPz z|4P%chc~3WdQTRz?%ds6-hJ&&p0~pm8QY-1&U?Q#wplc$vMvL+XT@=4Jc%pHFH?4NA(*wAtc% zD)`m2doE%I_q^xco*`uKW|;HgTikW4WiO96s8_sSxSx^xTjcxf#k}2Z7J8c{CNnS` zFf#Ca=4O8H;<|&|&WVIN=g90$6gA%D`g`{|gI@>MJhxeplbqP(di&<|S)EsV9=qMU z%Jq~{M_fB<&6KZ`Ch%VHwv{@4^%$3kqQ0W9ivG1Jw-$oSm#Xo-VlLcYa|&pHT2kG0QTUMOv&?3b}U@Wu7E4x3I-D zJj;Nb#?O*u*1R~j7XR-G26U>Kpm#L#fiX=`DB=f|%36W#s2ecLZ8sIYlB z+N}9t^=4NdLxPJ}>`#}c%QmQFBr{5Nzbsm(w^-n<6mx4Mn+-$4QHB}s&h2FQtmnY~ zJNLKA&gpM_)D8Q8=zdzs!K5+mly525C&qmb%&ST_vj1ef_uwxhL&$ZF#X(OxgHqCG zKXZ4^zN+J-`gRu!0|Ue3mBEsR$_FKK&Ts!;{rvj+Bf@XzS?A38ApWNEnWgHx7h7_o z_ozO;X0zMSsLI^jRd?;0S3DYhR~9-3tyky@3s$(&wNWlayW8z(lFpmk1JHWKN)19kTaCK{l6h}-0=b>$; ze(`c|m45bwGqkilo?u?t-Qq9K)ffBbk|)RMzyBGs^*9fFVqP)x=bMFMmb_QByi!)K zn|IFBzG(F=ubolboGaval&^5J6gjmfOp7h6^GPZ1V?P$QQr9U72NHP%xO$pivRrC! zyjfe;%5!VGq6p6m_8UGt3{i}q^QWD;Bay1O>VoR=F6l9oEbl2-ug|YJVsN>s;9&2V-d$`Xsd0o@6YRdzL z9_|Y#-bbJLxiv0qhgfQCR)|Sfg6b6U~WkSf}`4b6kU~7bC-7t~>kMEeqDj?cBSu zcCoOOW>)V$^Yg28WMy@xFY(Xjx;{7c$hOz|i`{hR7TPpN=-oKS;1hMRQ+MCg?H#h| zf~#|-3Ma)ob>HXT5SGeNSGDdz*+<_+sylVAUB4D}<#ycK3uaxbL#MD@K9LfBw{%)o znBL7G`|N)!tY^MIrIcorvX}9IVZ@WJICG9US-}d~ksbR5`0u`)!Z?N1{HxXX_xUUC zt1Vi)gYiO?+MeC3T~@B!m?gDf@jDQ%SJ)-l0^5-ZjAPw{3Qq8F{>;(#c@adgV%D^L#z$Y{j*QYl!ne* zyDIGN{rmqDGmdA7^lFsqmaf(4Dq0)1*nw#h%MtDM3$I^@+bbpD)UCkaQ`E{+bMRBz z{h6wqFWRKizjJ4BPv$z1Z_CW{&*J)bH_e9!JX|lXWPX$*F;Q1+iIS)*Yh+2J=Sq=V zk~&$3%<{s6Wm-4sxO1FYUHaKet0wE}DrK?4rmgcTj5pR8vR7UaZkbnVf51k%(Ty=} z&zoyk918!MhPbZX6?<`wh>qx*Gl?RuUCi4KDe%ns%WvB8`>VyFwe!;$+&3~bD!*H577(M&d6x4G3eV}Zl^x3b}tvBLq zs%oNX)zn$03Tx+`R^>dB<+}N}*4Gw`d5n!>l|J8elUNznOiFf2d=>vGXF1neE$%;N z`4%_g8m69Q{1L@^?ZywGV;?7(KK`_{;BsA%yK+~{iw-T(rQO%eVpr|DyYSGIrj=0z z$GevB>7+_e^AHreB%#3~&Twm%Z!MP<)4m6BdzYE9eiVGD$?~3`A>nOS?n$e_l$9y+ zrB|XVvbU_7G-HM;1H*xrWp|a8g$l~{gz;^vF;n_hQaW8(?CYIR?cc+yUN)+o4GgrN zf5$L;mtR$k`bL}H^t-wzr}}7@<*rz?ZkcDs^gvNp6UA>zjtz&C9D55zGz_OqFmUs@ zWKrTN`@gnBT4~kk;@&HqYNAZ%6@*TxbuA5A%dlWUi$Iv}BEzgst!9CRrr*jACrQXC z-inWbBGQaci5B>kfIK}ihnYrj`}*WKWB z+0w-%>%-wvFd63MRL#xFs3Hkv1uX zjlrR%W=ojQ_kDMtd?``kPhPX9#NzhWid&o2cZccfzBzm3P|M&Qe4~_oO8Tq z2EDpIC0t)K;fv{{ZzfkJwC>Ah>YVAhmqp^q4y)AQjX|pnf@XG2YV62Ke>_cGIWHwg zH_2g@gqUKZtnMUtr**0))}0919Ui>#0o&Eqpfz5W8(fdMZgXJiS+ra`Y>J5YjgYNd zt8C6B`6o6e*}Z$z5_vm!p{4cIDvbZ(rJw}<@$4mt{E0z&NevxN$Z)mq+4oz z%d(mRst$ zY~2e%&-s0)cWU{ioT~ouKDc&rcI)R^vrp&9a_(t!FG{g{qJQV|lDg=C&eeZ~Z!ffW z;Fe|#Fgn1p-TUJ9O`MDN@3|JLsW;D1)TAfm&Z|XPd)IBW4$WTGwMgXX4>Z`3B6d7DpdL_zrYFWbHs=bS! z-zuCC`@+Wi=tHS>d}pha75)qIPGsCuR9zsRcv}CX$lO?asMSF906@_H)ZCR?c zDsbx5q%{Sc8%5dFWRJ{>P84v9J9J>KOC0m*CaKViSs_PL*se6ap3GzR@p=8e04;k4 ze#dvu%m4q|V%~JfER*5QCwo8crSGa1hUEBeU$s%T{Hf5ZEyrf>`mw`GY_lf!(-YZ+ zGUu-5TbfN%411B+Yslcr!!W1qDMRVRI^|C#t0H_C=$*~CxXvEYY9P`uP3yy@zQ;{+ z{ro`}_fCqO>Xo%SY>~#EE1N;&Neb%vNI}D=|RYxUme?;7KOH6SSsvTp8e?QtH|YL$1}X9 zm`)QCbeXt0+Ri`oqJmNf1P*5@GTiA~{w^;~+`iz=jgNOyvZwuGeqP0prE19V zR@rezQOS>J;Rh$OB}xReR&8RbGS$AYt8EIGlj*CclcYlJje0k{TUuwgEcoe##MU1> zrDf)nd9t;6)MtE?{=L=nn2(~#kG~94FP!8#u!-f(qEDAUh&)|XxK`uZHn%IAzP7M% ztyK;EvS^jae*U9T+M(-{o&{#^^#A)lLy?Dbk;Rr4#x+@Y8FY>w_#6GS%`a{L%MIbT zbN#pTFIi>eeBjUKkYwwWY!~%i&vtZ9%UUB-UyT@sNmImNFn(9zjwmwhNfE%xGs zg()(UYxZ`Y-6+`;$dIE}$y6Df?<0HuluC|Hadddp?Pq(^gDa;TS+zv)LE65{e$!qx zo!cs>S#8o3C&;-~Q@&LuY9fz3Yn0WOMS*_le>GO8ZGC&FMa5N9_t1~G!p-bGah{vm z;!m+xuM7!2+c=T^`4{^GSxf~i=Polo<29L~rRW~HRCI2~>P1^CCLUTXW;>~FQQP#R zTyHX%ax~9x?aq25ov^&hqmOZY)wPQaQEY#FZLgmAklA0deR9Z>=7-rf9}49YHg6F8 z5iUH#{L}e~D?JsS3#P_})@oi2%?d~@Uv}(K)=Z_?i~ei7_{z6*{M}m3%Q5%R6wWz( z)^2@0xpEEp4B$}*28LURQ3pN-28QsI2VF{z4!&OA|DFC@{rCRw=Irn9@8kR5>%ZlH z&;O49ye(+ne}+3%rj3I6gm!D~|v zELCB0Xxr4A_C~d5*Gko8B9CTl?G0JM!EvhVgjkTi;3w64K0M0~3a#lnyoPJ<1l6~H z{ElW#x;R-PPktZ&hBPA{huy*%5!PmtXYsGtI^}A>>ZqBTVY;i9Y&pi7<)wBzHX%DC za!=p%zNWaS^N~%DY+S`sCj|HSNiqqY>faW*)N4iZgt{$fdxQPYs;Es+5O;CNxxyH` zXzQUU(U7_BO9Mg$1Fo+6G{09t!Av&e!m13BKi>b0E*&w~?^cNGR^nqg(&x@lq%G$6 zzhn-Rfw-97HvSDWWtcylR7_z1+_u@^ijmb4y}qpQ$DV7?KH_|NYt{;J&6Y^#t){!O z1v|N(D4c2kvumSQ(aYLTV(L<-b!&Nl9r(yxxBlj>aY7c&AW(b(_c7<+M>cnK1 zH_6-9{@`1yab>E`GtkCQziB>_Dw-CFHpeOod+PsY-aj?LSTt)ziPaLLCm&Ojle(K@ zf~=)Czs<=o>)bmjP=?K=$Hp|IC^c-?w1ZohGPwCl2spBoG%~Ha^5hB^_pDV{oeK?> zcv+9WJQ>F@E6Df7q@I&&D%N~av6y1xAjZYrGS{F*Ywemvb9%yVCbBp*TwS_t)&UKz zNF|X?>Iy9f_C@VjGfVWz%T%2wK1UCWoLhBCLby4n*>LJMMQxKZuI%YO%~uVK$|tI` zF`ipmyj6sOVL{ZyWg-sK(sCuLkIzf`+@`vAd&GtnyMxZ%n8h?9^xjP0WAE$|O-l36 z)cKS-@onhg>TvzI?I6>QRVC)0ihFpcq%4q&Jz3t#Xdtm+(uRK<>lp6sjy*j`PjB)A z_l`IFtM7Vye>8lc&9Z;D=(HnSIDThX&)K5+P!GU$v5Gg+vGMRM{S=~miL@9H&Jlq(HCzHB`**P5uIif_Eh1;vfQh$ zZg6mkT`bbwk+XE|te7O}O&b)NFNhW1;Nw(FyZC^Wt^6jF_TzvEGXaP5ENz{vdE5(D z2(FMy5;Hfsmg1nnU~nSfQaE!(%Uy>S?+JXN4UPgrHEi(Msu^1M}PWiO_B6HaAB?R-`U4{ z+E@B~xSVt5LP6R0^VWAm4N@5AOlM#|T=eRa$m3OxI}Dcp@7(;P-A3%$?d_KeJ=qu| zn2!4K?O}k-p$iFV`MCC9xGW>o4R{d`dcmcbnlhR zSBYr#e-F=oEuwsLU)Cu$D}gX`!EMD0GnBhTlUH1mxDutrmnc~woxJ#lfW*xxHvVNC z$*yN7X-X~Iz{qT{(UT`~(yS?MOMCZ}F$lFX96y%j#2h$fg@%{c+J!7D$A6 zFp8L!_@qts$%@_RymLbFOckeq*7Btf)0BCqic0D-&B_zx=RBlaBY1TFeDQr;X%5W^ zjVI3c@gF(Ad_q&IzQl@IMlU%l7wkGQtGH_ZjDFUc8tXO{S1i4_R)ZmC;6*=JvK?Y2#|>t}sE_x+0OGv>)Qg{vhEuFaZTvLaQ>z=&tr>jcSV z4q9R}H@S5gXi107?67U+(J)?c!RSGiXp`^bo?8rRy^cv?8c7KgE-i3vS@BrZph+h= zz&b~}N=dZw*RyB)eq?m)5iy!K<@lnB$BuHWvR!eok>S9Ny_2qa9+3B6|rIJ-P(|4`;^ILu1 z_bT=W5+^y7y_6YxEEs+;9_hQ=%pGf~Dx+OC$NYfY{v`*OS1_Df#?TPdxU=i!PP>+n zhm+p1YE5qPS-H}}swiFDc0p;wpYCPeMXsTtp8jx1`7<75N0z$nFFk6sI$dO?MuXv$q=zh@!fI~3=HI)COM)*ZSAKz+CgX`&3g(`t zq*rW-JGv-i>71icYqPbYe(MCeFD#tiy*X&rX%VH4M_(m<%I^kxTIY42%V$;gO<`Fx zsaQ4Z_6PBr=Q*<1eX=D#uRc@%Mm&LAmnmT5n-|uvF25Z&acfVC=w7KytuJI& zdh=#%VcMJ(yEenMd*PlPO~H?gSQ(RaBlrxfs!9ua9r86F(5 zn&tlHuwv>CrJST6R+6&U0^V=-5=&;|WH|79hH-Uim%xX!me;;pw}~{TREOW5?DciB zZtIl1kkeA(Pp2&rJ2^#5Q^!Ha zH`}P7Oy<$W2U4srxo$|cH?Xplxo9|b_@?q+^V_H(`heUo4# ztrk{+rh^+9IaAXWcnmv*4?F3txzuztNz%zcz^U_OzzyGJ2L!BmINwHwueziirmG)f zFl!_0u@_EdOf9c@LPYrr_9^6AJ$1ew${Ku2(=_wj7p@d__Qs0VhawwnR&t63Zr*j- zSDrc3Fin(Ef}!Gc$jQ6WYzzzyEfU5C4UUb^9p=|r&d%NQChczX5}iX=CV0)?eN^mk zXqR{_Gh^JGyXS&02o@aJZ?SvsvIWWy*zTWoaXNLR(nDhNJvVm~x2r7)(~~B#Fg#eC zw=C`bgE?PMwt3AFn0QP*J8g#MKE~xyQp@J&uilk$`DP~Ld!Ey)suO)(o_nz$GUaaX zo~gQ0n)76%fw=$C9ocpz zfhR=7AX1|9x{d&&L?Y+jB_)$20%C)hd{=ugO%)2|N|0@srV_2waPjipwLKeJ(sPn} zWRp#p1&vNHZ`l%8Q!z<$m53js1XJ*WMj?hLlX!!Y9lFlTDQ*zSo%Qgii;QqgzBRjh z*y5Efah8IISLAhV?>e-xdSi7U(-YS-M;`Yw6bPY-R@f^LZh$!~%0&(2zv zrMyPZSUA{+iQ$_5@vSpdXMg>6EltJkjOkXh3Ae7+yp{+y?{m~$^Jen}i|cBUN5zs) z-AJF3s`^-r$FOVNQM1scfrhN6ifb1nM^8!$XNy%6>%6SoXv>(;&B(GL%0tgq>fknw zM}|v0j&EiWXj__bK#t2ZV#$Oop^mdwx5JX18y>E{8@o1Tij#tGq=(v@C5BskR#*tE zDHGO6d9h0+jLURUlE9n|+zQ8fb0!=UE@zvYx43WXtC)p-?%G{`mfVgfyMr1Sr&Op$Tv{l~ zx@K84gWI8n)&ki+TNsO{Od)--3u%9QXPNfm|%Cku}~yVUDl zwK_KSQP9oRYGy}@nsZb0_1<3Uc)Rng-C5I9`zD2kt!WFhOOUh3n0K|0?{}E-YR~Wq zPJub?r+6AJ@+b+NUU6)l#P)-eW^^@bC~JByoycNgqI-NtPLK0$sYHY1gia2I?O&$2 zd8e=8F*+ixqM_-)#H_G#wbOM6;i_4yBt#k`r!mYH6T5j#`GZ5%qZw}&E=dbd*9kjD*_KEa z75dxHHXKMZRIUV)i|zWN@u3X8f;1Eb&iQ(GfqCeZp8)>PNi!Ob1yP)%n?Wo2~f&B=^`=J zBV^rO&6a2_?TBnoNk*oqwiSDB-1n|^eLLaMQx+i}BgaQ9IhAWRF4o!nV8&02?ZwF} z5*I`&b|vl<5fWg2a_gkdq|Qw*I?fzXun79|tEu^o4^QMtg_*8NEGxKNc#_*PZc9r( zKi5(w6md$TQTLKc!}EU|r-v{bI5P5H?P-<~sCW={<^A`|wjSCE%nM3vj2OHxC#E%Y zvo;9z)XQ+BdA#U^^hnVJdN4gXQ&9eJQ!j!XrUud{Jd< z6gn49zozAEV&rPSZtI^_Y`5%BJZH|SddTu6X`1buH1YEe`I)`CH~1U!Tn!n_St<&y z%ld4Vk$b}@CUVedsrFOOIX9=iv1s|DxVH7B%_ZOKZ_cXg`6$g|h$-7^eqbKQ{I|;M zTg4Z+{1WDx^@riKnM}ia_JGg-o@qx29S~X6ks+da!L~FyR5wWBmm8O>`_!ICNlJSc zcuY)-oR$!{h2@pQq!uO5l7Gp9(hMz8t*jmE3lslV=+21zQ(nE{7elwuHKq^0-?Cii zo4>a<$~JN8(p^DYwuW7aYt=fsG}v#slx0Ccqx0P2bwRJDov!<;7-o~55+JO=S(ttF z)S|%D#lk&ao@|AmM3UO0&#Il?Ve`~qeeSm$|L-dVGdFMGb2$HLmhpy%F_X@wJgbeF zoV8ZZFEv{vSJdm8#;Z%-s@-b?UOZXpdNH;2+K7gBf9jzO7S=3da)f)l1#WK|J+;l^2139r47;1doS*q@G@2O zXv?glNoS?M&+wKMm~7F07m~Z}YgM7kfR)!y6z8$#u_f|oc=&g$Ng0V-BA6frY(>;IcyXQQWi^8SW z++OP@*j2Q4e#adB@-Kg{%#3e0Yh*c=C?WhxQJ;e`r>V8$5qI>ATx0EsB!TqoIe+;# zXh<^De4hDW-giH~&MQ2@i`VJQI+S{}Rb%nGfT(7vSqc#{t2$zqs%fvz+ExF|4d>2>$gK-FnsD%Uw8Oq$d_u3G%! zYT?`%C)b73g7{)g!n(>{9l}3<)y&-N_6Rs zr%X|+-v;wPVzxQB{%e#MFK9>S@16gby!*J->g#IP)pK(EO)WQnvUn=Ae9GEGW`8rR z-L|gP+$^l-$-wYoy=c|E|5cwK{3&aabvB=V{o${7{?GZZdy7X$9GNA0o7?;J$~T&) zM859%#`o#g*AqILv9ea0v2za|X$s=<2ywVB&}yWm!s%rlB|mXdRJVkRaO0dsha^%v zUfw7XkqF4(kZLhF!P+hACUENnTbEPQB%#GRY7E-vCJ3;s`^aU%nC!hFeyCFjI!02R(SZfW!Yw1pXII-58eJ-m%J;~=dy9f2Rns} zv4>SJOlvvv{qvhWGjDHhI#A&#*AjnXiO~Y7@{rZbdveNE+g#y;bL?%r9Kv_JVf zZ}Htx&%m&EmgH_L{nJjzR=lh8>F&@_&1z06%S;nuXt@3SlAz#BmGdU+GTA0)n^ynN z|6Vk2d-w8|^%oQVG_G~awt9PM&0H7vg|n`xIadWlZk{w-jI(xubTjK=F5#7z__jGc z&P<+@_DU!GLdTTFUmd1D3+oH-3D}&{v87D$XmGPmQiQ{as9^0^xmm);vNBqjc+Jv+ zxTXYeYZaN1$~|IA|^jccy$onq_GnlQ~lvVZdAf7?DyQxR+I zWfJKqk-1&wb|PDDC)2K@msWD_p0G~4th}AY^C-{KJv(P4rUmG6t8HoY9&W)uztXFR^3VoORAWxp*wg}gOR5puig~zT)^S}JF<;?-x zKpUwfOXI$zCy_SZk648T-Hj^)t`PcddV*In0f8&Y`pMSXs1i#xNfBLfH%*Pkhly#dvX8CK!2*vGNwTb0aeZ@AOEm<=+ zKiJUvR(m>&Y_VzE_q&;X_8tP=i98II7vAiCAz)ax@M4?)+N9gV-utU@jv&_1(u@2!=_K@;y@x;j;E{c73WZTBL*W3R7QbQS3FVOq}0 zpyE{9=(vSuQD&3{-4o(@np$=#$;QQ;ihVfiVN*+o%$g`s_BfrC=Uz$g^5-#6oVSpnrR%0ZhpWm; z^Z$Y?Lm74?er3`TV?40FLT$#M#s|A*F*&WB94*1NDoeLZ!&bI^(XF_{mw#5b`%cl` z>d&=mzb*TxXNCu}=2)x?(NR(o(qK9_)yR=yPm;D*Wx&4(y=@WsY+1MXULGsiSk0I= znVsRUPr|3Bzk6hOSLZ&y%5L&$>#m%hkX3FQJtWq!EELge39@LEZCO%yU{}J<*xu}f zEo?1PSG%|v)>NH6;@NFEW%1fjnY5XkRxls`&&ZO-$m#Hw@%NvtriV|-E$i9pv2@oR z(d%z5KD9*5jh+8`-Llf`Q!!RyR=;fRCD}@qraU%sTip}JV8JL8#=XdP&R6!Z$zFRm zC%$`h@Q*)3SXUCmzgLQm`<5S*FfnN8U~}|r4||RV93i` z@Ur9P-;D_xYr7I$UoM<@H%QhwqJQ^|-P4x@t$v`^bItI|hPsRy-VAfnuJU|ZSKq88 zVSYG=HRG|b=3@1yhgHq)k+^IcT0D5|`e)cJH}g;?08Z1=9^X^BzO zmueU-w6?a4u@7RLlJ%79NbCKMx+|~D&p7CROtHVvkQ~v_unBCrA)>*x# zduxg7MUk0Z8EbEtDtoPTRo-|0kW%$V#lo+mDRE(LXRWuKHe`rn)HQOlVA#`kndQdi z`7_SV^v-K%uKp!_d2fA#uBto36t0|~`XA41shSXEp7!?9l_*!oE4!|}DAi<*TgLbI zTg;+q^6`r@dAiGwRz$s4+W2-K`!j}?zF783(fQ=?@2G7w5DW$2oq=Z+WVE zEQFi2r^%7I=u6xCy1a{QH#%D1vPVo+W$^zlbfvQBXU!^x6QMDIrd?MrYA@|l3UfZ6 zv~rQFU^`cbEXzv1%JnBwcnuD%-ni95WkND*i^pm)rj)LSOeLoBfp&T6(@Gyi%YFS( z&p1n0HI(T?xt+|1(8aI)x4X)0TXa)UCJq4o<3{UU$;8DZd{5=3%L5wbGyNM z?=xRkn@M*VUJ%<-_cJF*eu>BCwPl{>k^Oem{bo;dh8YFl*bjIumuTF@ z)Gw=g)N_5s9W%+Jg))k>6*eAn&@0`2ou?~E>eU(%-lK`eR=+;fq|6V6@i$m5FJP!kW7xesM#v)ivCSa^9siw&Zs>`mDDsJnrn>KWmnoJmy8D%H&Z9~OA+w_lI=%^0b{bt~E$Xz} z5SY`*s{882(XeujTbvdeS0+k@_DDWia_@%blC)IyR|V+?vD-tljr)tPH7{Hy-w?T6 zqM?q-b)Id{j%n{X&9|~10MRxlXZcz)vX>Rr#%T{gLt+pw4l5I=UO$N8= z_I#7rCtS(TP>A(i$bO@~p_TOkLyZRKuRU?`#|!(zUT=-v$n7e)H)MCQruNiLL8}zE zOjB4P)@8C(YL{qw#*tm31q%5)cHWl5tO8nwBjVa7B?B9gi8=b!2 zC@!9O{q18#OHIxLfD(1ul(1X?z(gBcfQO~p5yEhXV@NG zVvb9ipgSSQH)rtFucLnpWvY zhTjV2`nlzG^A6*4PyTiM&5vE_7W+3-k2iu=1B^ITf`k7MWgpN!i) zH5le!VE-1Qb>Zpd+fN=vtQFwbzP6V8YFF{a`>|btU)!9vK8?A%DQ|Jei))EHBVO$> zG>U$8{{Ul%QKj*s^g`#22SsOYU2QT$@VkeG+YUR2&}oMl{`hg`-LVU?zbi9+_H~Ka zV_gy7l`12yI7+xYSr@}~efhb%x@X(J6n1<%zEVpj>9PLN$-Z%y^?2*$aB<=G==Cm+TecnE z((&D?INj(??NZOL{l!c3er+kL$8O z3>!T;7{rVm!pgM5ml&>6T;#g7Y^8^{gGWa0%BZcf!5MsBZ-R8Jm+zg{a51*bG4ZT- zxX(H1*WZH~j$|c^XZgu!7~M)cxO4Ul;dqUv@61=2)L0MX`hJ+)`2EA|w%|pAf@{~V z5bIr0Cc(lb9jYs07V3oDR1wktHV^6tzNRQ&0xbcXU02S{k?~-{c)Jc7`^%R zgv0Zm#JU;Id{*<#w`_mco!0FQrX!&GbUHqbW-BQS9YaKwmPojS!MU~`n+RN>eX8q&-C4W zaNulAX_d49IZ`U?N6?ic0aAW$cEx&r@w$PO>w{~3(ys$WQtM+V#uCn&j z$W==AJTL6B}3|;|&L-m>56+bmgW10|Ud#9S^@~`TO_< zhq`!rhWdMlg!#F81o{U!M+W%%{15&g=;Z9~>K5n&zLeADf6ug&!tJR$n+xABPO5uc zut~qg|1V?KB1Q)DM?M>V-&Cxy)LP=XC41L~GEuIsR~*bDt<##iloki`O^?idpJx6; z?w(cdkl*^mE zxwPyc%OAzHTXt{$&ER_>%7Vds0^>ic_cLs!dtIEm#4q%;nUu4~8jdcBt5&zovt0z2 zCk4N^;ZO-}Yj(IwsTD7c3H1WYv4#7mxj>VZh#qSPJeW}_V zUff`st;$f+_1G!M>`zkH%_p6~NuqDu{vWIPCf^XtBg9bmjX^ABPx$Tfkovx78$O=V zJJ-S4^CqU1DRPI}3NtTN!+`2?biBDu5LDKKl!SbeHLFP z(OBOQ8o+WOc&5VN-RG}-dtR!vQm$&6NZQn(tj6!c%ja&nmUv+2q#CV%PdhDpFYr#g za59QvPTA9=QqQ98K5aEQ8!T1UZui5vhTTYqH+UaIu@)zTjbh_hUww`_ub9v8OS)ha zye_v-?rPZdjqglOzcS#FU8nfkCoXyR{Ha$q)a_l=T4bYfq3p$NfhldiDNFCHv7cWs z^LpVqhrDa^BVNVmA6Uf2yg}xH1ar6ebA=geA3j>Xrf8XmZ1Ba7EfQ;)7OJ%GU8UD$ zHK|KA%+hb~PB*WMQ3n=j={D}UPt|Y`tyaBobqu)#YDa}E4Dptp6bRhr|#rYpN)O)X?bPloJ+MWJ8C5| zgO&gBZ-_Z0)L8D)&}S{3kdy1<>=HaBEcLo=SICQ?!x1J=S7azGcHi_)dh1u0^zO== z@3Yw+nQ^{K;0Sw{QQ6J~6T zI{x%}Sd078Lq$H7L94W*1E;bc-6Se?%JtOjxBJ)J_4E2QrBv2X(QKRCi#Mz}Sr@r# zlIxt?S8wT7Z_IzQo@;NNU4zMTkp}zJh6j7!z4u-HdQHZ`B(H4OLWkr==I&E3EuspK zE!{g~`Kj*E=S;UMm&!9uX-nOfVso_L#KvD^O1SX-q-X2o8a6EAXqZ1w`^T5_`Fw`! z+)X5!ieGJcwC3D`WYd>(qV70`*?e1JomG`(yHRrbdaEf@#Vi@NbX{GueB0^NS3jnP zRyDZ&yzC+OsHWj86I(*0N=8P$c6Swr^6Q|!TT{Zmbj9iStorJ*@PtN{*X?Voc7)U( zUo0mR7A?sd>+w3AnQem7q$X~LDS0nD7rRT(xT_v2?Qmyy>fN*77{yF2818p6l11cdZQM)h zLKnZ1uH3c4Y=Umd8m)w6zCG`ma};|Re=xG_c=D~*mVIaDT$_LW!v2b@B^x_b@~htx0e_zO(G+J!eVZ7j-#R_2QYcO_VDvtB@YJpg$tl;n0%x+n*6LVj*p)YBN|u*?_bU0V0q=B!NV^=%SM-%^g#3^`$@+$sz8=ftH?+s5GZ=fNlY17bk}4M){C+@I5PdR~rV zR91EGiU^TdGpUVtw;ppdNz%_SY29VCkfA@*YjJqM;Rwf++l()-OZ84!C72R4lj)bA zFrWFZ(y-$;9j%Y|=U)qs(%jBDxvSy5-R&FcGF$)tJZ|%aT{L8?$V9G{9vPxM zcono`%H@*=p&J%%Y5MZ4Fzf2JXwc!KE8BlD-`wJ`YU?qnAB{&@zMC^J{HrXEUFnZS5@n(T@0r5SGn zR)`sR@NCi8e)Xo4py0_vPRDFLeJ@%vtdUriow2=8+@SJ&iX-3R9S51)yjDbg{PakZ z&AEA@9KXuVyS;6n_1C-#S-EBUS0;rOY-`uO%#jg3b)~;Qs&mUp=I>8`U9(eCGCHs$ zJH1IqgR{Hf-qdT)En<&?LlD z>xj=4Ud?m6xK-0FIFlyq-ITB}N0@hFlBL-f2@%dE4O?eJY{*}TB=ubsZ|W!}$UqYw0*+O=T~%h6Z{UbY}(hqQG@SAud@ zxleiCI#<2M<%sGrjgOX7i&UO4u1L*rY8PeDmT(Z#Z`ZCoQ|q(5y-}2*MTF5Tfl-NJ zP18-C?^U1qGv9CSH1XSeVhZ2+-;Aqz7#ZfDXNea0$+@5JywltZ!5#;9n0D=$(sGGo zl6KpQJ3=~Kwo`jQ$DdUBs!|iSl5<9G)U(UEX%ihQZr+f7_lr^C>KrA8x;#IFiw)b` zcVF?m)zIn2rD|R}TXx;r8zn;h5sJV5DTkhVxBKY9Z>-N5dg4B^9LbX3*S~g87xRa` zwF?BFGjc4|V0&{=ce+nkVca~sm2Lg+`Ib|a4#xyqFubkuyY$OHr2V9~Wz_Q6 zjiSozTYvYgHsY9XcsAwEUcm?t{j~wtj+|iXNju3T5w`Aq>GYc}$^z1b8@?vlGnfWz zFr+e=zlzYhx%j)_auN2PmPsEttV3j$811pytMVZ!tZ~Zo^)FB5JXOjIWY+BwS(4?< zTDP^nvET3LF&2wQ@+Uq7&%b(kYUiFwYzHi}u4W$-Fib6ZeKlEcvz`iPw(rc-nG0{| zEwmB;)q8vAq8)V}Uw7W#8FFXGWyXB=2NAclQ+ay&3PUI8|CX1~V2bccXwXX z{iULfs!X$X$1c-+!FrYV-}>wKqAu`<9Ot;t&#-{~?V@R3O3#0bY+WmV`HGH@kufs^ z!yFZ7PtH5ykEPGQJQ%xqPU7Q(p63i#?&?lwo;A}_5}VUF3gWFfdS)4EKQcPOm#d%kO(E2^%W0+PP7hJRK(mPp z*dEr^dW)>^&@?q+csxC)dRK+WYPaT z(_SvllxqgQ3U@n{RZ4F7dFtpKQ<}BSc41-Hkz*e3r2AVr8a9US*saE@*&VnhLMyDh zOX0;-wjNU!0j`Bv;rA674jfXjnKda)n@2u(;_63n9uL;CGDPew+GNdA8x&sam0+MN zZ5?pQI8<3m|6cAxjrh&l{7Nip+Z>&W)^crkU1D)X`-|3}d&%32O|ElD$S^mYJyf>F zFZ%1|c!~`3nxb&y$z%2;%?!qNnUfVn|5ngtRm@Mur`Q z50Z|_R9=sKm8)uLTy)zd{ZUks&+Fw|^~+|=NbfuSZeQ%lbsEaCH|Az4WnbBr8$7+U z_EF}+cmW-A;eX* zE3>0&9a?OgNSyaM){&LemoOE+_uNMgP0fuSwfaUt(Yyj;vQ4n%r~rx(%<9iu35~~=XfaPaC&FV(V4*_ ziUOVv>no3kt~wcY`1iVg=|!POik9wlbCy0T6=Gq#wY&bB%{%7ro)tdl=j@$PF;_b> zOu2RTtZW`@1C}@)W&^?O1s><;S2N}>GcjQ~(eg-yVcwa&>w@PnFOqkuJAAWPo>}<; z+yChMmIk{mlco0=FUmEQQk!dF%)roawxq8=^Z)uI{6;TIx*nDu*pl4WdPL}wqT7?Q z>NQd`x7}QO&2?FXXSYY`ydEZhBfZkyOWg|GS<}?Yj-OoJVH#mPb?&0;Q++0K1+VX# zl3HjM=6UrZmq;#GWZ9FXt%t63&79D9PGq@bh~ef{p$FD1YBFd#5+NdFt+qGOgQKOx zs8C{^Rr2nSQWv#nR$MY_kZE?BEy5t!CYRwJCK$QcK)U^ANoE+{C9`j&qa6*iE2!hsF zd}k=qwfpbzKg!M7-_JWFASl2$CfGj!yko=J$t}=7I4CUG*(Ee2ILJ59!677YRZzgX znC#MNS(~EMb~0B>F4`)_kZ|MqN9J<*_M}Tkn0)xlm$iGJ_|mA%Ah3;bCD)kjryiyP&dc+x@K^FgZYoP^~Wz=J|h2s?R{=enuE&j-fh=1blsFycAsHjU^sTB zXL5o-~d;OgAFi%u@_J!@y_W8J;EJ+@6yJE>4+^ZSoir+?{;7GFH$N?^GB)uhu= z!Rx$sm3lTJ*Od7v`IFfq`qmGkMQS6zw>?Y%xy3Ac2D zTv!`?B$}>BYAk4UYF3)1k#bGpiq(#bTux7qM*1*m2f1h`ymV5`im`O`FIjxAq^F!i zZ83{xLWqH?iju3;rj*B_5nOxMuq@UPeWIigRolIWiJc)~;sl43AQOva&u8&0*%n^f z?!f&e+bB*Z@ah7o4Y8khRdsGk(7K+d_g3b+{WDx2@`ZEOLasqItb&^d*TOjQ1Y=WoBSt zc(XWnap3D2p`LGyCNnTR&`K)5yY$#bRiy$}iR8EHW|8l|ZJKZOOz-@=9gh+dyRPLH zG#6RzN}ZU`r~Q(%!Qr?|2= zx&}TyDdwodoto@#!0EQEN9)+tsNJiCMWm+$zKtuKz?c|q#CM=T_ew*WlKIWG2As`` z%dTs&3UI(#t9XrK+j1A%E<<5aXS~z zPHp@cp~0xCAk^#jv}x*uH$jTwIZn&63>6wA7$lXM-M?4!xJCX{ zuiP|wvD*3+nW;y3iw;(WP77QlE?Mx<>p-BVN@Mf8NsNm{8=^fLQkJVVwUfJ@b%EK_ofUvRuf%z z-^_L5zLF}o^1$?G0qcGwTi8zi&DN51kRhpM;mMmv<3c|_;x?a?E1$qUnbAOxQEuO##vZ*njrZT4 za$2hqG(|MG^U{=S+{#k-m%iHMv#N`Q@3B+X`k+9m7h2OCx(X!PB3oDDGq`PE#>&@DR8Lg@e_t#AL5qkgOJmrqXuC9S=S4g#9jOtFc?OL~U5!cort*cYF zbgf|7D57T+#q1=xKrDM}x2XZcI^iWnLYh_lgAos=l=Lvp;vrbA3Vx9_1 zN{%?4@=^5F{W>{Jd-v+8nn$Hd9TvB=1#VxfGUxqkqc=($tiE)vm)vn*_-N2|&N*3! zxgOctZ&A9iI=Yi|v)!`id)H zdg|Li+qhjBrpW!Jmxl#z0C)v65V;DoP%k3?^s3w)n)g-fh9uw%OG6O~@wAlcN( z{JR|aHeH_VQl+ZQ$*?5rt?dbh|b9%)YBW>)hdtT`{Mw25EThUL+Ohu{KMjSEuQc3Yq7$!+qu(XeNoTh?Uunz+cYrqFZ84z8QBS}Xc&9^cE1-we5q zdW=78g!b&XXtY@})-ElmJ8TPEqOP>z#p#!{4|d63o3b=G_)HS}lx=gki&hG_-+WfF zK(tvtG9)ZE<#@>#{r!cn&aQgnAoo{%e^h;g-Yg@g`_mjQDV@`i(GPd;%96Qrdf#Cq zg~M^STXy^k*?)Wg>*agDtTffr->d#H@ngolQ-9{YJH0G!s;(=?PM4g6r>fR3dBG49 z*E?}dl8*}Bl=s8{+z({EST zT&#@#sCRva>BP`n)~hSFt(zOnZ?!OrS#vd$=YdK6%Nc#jUb5XdGQZ$mfZZh)4%e~jXWYG%Op0K6D>L#2F3<549O3Zt5j!XGp z4}5pDpzKVNQEGOi;Pe}}`{rI79iy{JS z*PjwRe2H_;gjEWSllJx;m?ZdA##2>n3j+rSYg30pEcc>trkP?~En-0jIhZ1^FeoO- zuH|9v;!;au+`wkWp!h^8d8(77(97Ae>(fl%vU2ZuZ8Syg+)*yi$C*=S2Vd$upeB+f z5;4hH(2Xr2HO48+yhUis0}h7Fsh1KoN_h$|)vaA+61ILq+2YBP7Yb*K^DBS(*1kki z;@8Yqa+8-?Evq>NExz__k_ot)9SnhWroJSFaW735c`gf2iI+V_jbL zs-leRVyRCHWNu!{PhFiZFZ)ROSx2Ja%qd%hLEFmy7}S|B$+=bf^VGZLM+5)O;jr|f;@mUS!R>N%yyvmDzx4h3+9hW^@kq9v*+=&G%tMSwel z(T#1+tvno0l~Oe%nfSkDbTSAwTs`EoDZpcS&OeTpV;htlS&Z({PC^m}20A=gBo z)} z2vwTx!cugWO)=!i066S zySi2+O%4#;sCTy~d*jaYmqS=vqE@a^UiV43$L!q6HDauv&b&{!axEBqr}6rGjMJnS zI2T6xy?0){;Yy>6%K8i))`*=}hTh?xqW5R9ZfZ@hjSJmV6XnV9ZB~0w`fc@T77A*7 z-xGc_7)&)}VVJLc&^+Ah{Naxo5w#(A4uzDi-;h0ZQ})YEHtt;-FGO{xaDNJPT6`&$ zbxBlgm~Y*w{KL!t)I2(pyYG4UV#!xOKKm{^%TE9lp)OSTH&ztPpw zE5gaVBy8zpy=}P$^o`2V?HfC*K*Q%7A%YsT1wRa`AUQDmO>3Bz&J$oHuw#`|m&%d9v*VUjO};32?2G%GGU`GrPH3i>W&S)3KRb&0}+T{3M8bE8AGS6QChVi1!nl5&CP|E#Es;;kl( zB}o%SS1844%sY^pH8GMw`+oq-J#GPQTY()P`3(LuFYS$VTQ46U{B4?LWOlE!<^<8T zD=tlQJ-Fgm&~(;pYYCU_i(=QvM2am8GreZfdmv+N*s4_pmV@n`BF8<@yGSIenkbU ztcg9fAm+;QrK=Bh*hDU#_(5*p^<~jqR=dE*Gmu}f3$<FSyu1FD~Sv!uK9eUU` zebFMOn}G+5L^EF;nQeKlkm*fZ^7aq2|0L!`zxIth+Osq9J@bs&Ner8qu4n)M`!3{X zsatUS1woC8OENZmjC#kG=JRHT-p3SG(F=>L{X;tfSl;yge)VkYNqL#KUc2=;r|tcD zTJNOrE7ldQ3?dCNFAkjFcQ4t4_hLoWl;yJ`q_^3fSuV9&)}2Lbb=dmn-ZQ_g;1|E@ zzwT8SOHg=r&3$2k_JteS%^0=>ZQR0ft>yTXou zha?ypk`Y4^LJSNH{5ls3w1Zqi`~&>`yaW8beEx_3k8-keba8bF@b~ix{_peO)xp`> zF(kmxHP|oWe@f6wt|K=@mVV~GyNTsVhjNqpZvG7~qm(~n%f4{=o@1!&U#PYzN|Sr* zf~rl63OORCI|USGi<+$BT(z=fA#ZkA*7x=1ye+G~r;G35*s~_rppv1)$#bdc?VI)d zx;D!LBcFE6Hi`LdSNS)^O=_Mdo5J$fAO6ke>Yi~jaQ&gKz{rgeUJ(;_9_y0isr}v} zeDT7u)X4gzR@Eh0j~yr9DKU@vpKfY?EiZe=v7h@HR%>W5#aA7;s-Lk^biwMyH|E*e zzPAcmb-b&>RdZ?IBu&rQzgNEQ>^yYwmy7Hxr5L0Cew;fRR&M3k%wVbZd<8>K+(V{U z*V-TdFj{?u;p?>Nk1OO8xEUE)?)_pov_8>n!K|v_l`)~At{blnruqd)q z!8@dMy@|qN3(+mj0x|6qKKK}*{R`&(r z4Tt2{e+ravNKIOMeOlJ@Z|7cpE=u|OXpQqhA(qJ^rPHf3W(7?7H<|0}Vg<%(US7+P z+j_0a+#*M^eoEb{@{hmtuHpn7G<5FWdu)Bk0=2q_TWUoM-Xn)YbL%}`|nu6UH%Qe zNeuJm9BA2|ub;g|hIwmPK$fkPs;cN}H{~epQ!iRevR%WBd|Y)-t^BYmD@rx6Y^HWZ zwXR5&S8poMKlV+{SHinWOZg0$?mhU<%#e{T82DCQo^SJ}y~l2}$@`|t=JKreN}JBe z!0_wW>o;C+c6z?7_V$ajf1X?;5V`M$+Nmek{%&XC``p5Y z*jcw0clf2uE!xE|yrnv{f5o<-=U%dzUt26X4@7m$XgV3Xy5*GF+;d!<8#%lRXYEpv zQB~!WS;Ku=g3abCt5a0y7H6kpWjVVYo$j+*MC*ox1isID>u^p(zsAr?@Y9-}9@_{r zKCgEH!Y3CxCu)gJ3Q0Wr$kVe|YgJQ1Ih!JVfVC4~6hl$(Xtm@;R(siru(Ffr_z zQYd~b)PjqZ;rY~d!OJHa9QIATtetb#QvQO?w>7Uyutdk)c>1Gg-PX-#f_|6oVs%@eeuBxTB}IGV8~@2{rwf_Px=ahX zteECKs6M*Qj_oI79_al1UsDs;<4lrv^+UV%rSFronsj$sPW*uQ07hn0GyT~#2 zf(S#+uIhsx4Bxk^esg+uV1bP1%CJSMw{Ixz2wuA^dS9$B|A|QL2ggkf4{C{7Or147 z+4>Ye|5eH66UVk3*vJ$uxJi2ZqW!gX0lNx*Z;@kQ5J*fYW1Mk6uxbUvoVba6kHX|l zJ}hx_WUoA_Y*J*;5NgH3_Fxw0FJ3E`OgYyZak5@pgBFB^d=@KCiWKWeF=gB05w*x> za(jNB?dc0*JyDKAH+*F;&>B_daa-=_Kx$3CTPT*}vE$wW2nynRqfUwaHA> z$u{cR0y94LpchXYQcBLT+LiZnw**aPF4OJau>19qPX|0Uo33wpUCY2|aa^K7n*Bnh zN9|9iHGS9Dw4Tk{a#=0mkVEf##<;92Vfj@`$_h``|M*tRT;dhU7IVtr`mZ^s7@i!n zTk_}nKL%FwR;CY92b7Jcue~^VLB{&`J90K$OK{?xHA6KbY?f-kp-B>=`o+uJ!*XU^ znEu3-v81bYuV?*>)8Ce?7xtNJRd=fWg7bT3fzr8540#da3l`c3DMx%`ncL!e%e5r* z*_7-nA`9ZCOqE;w*&%VI-f=ObHc8J}>^)tv>^=57-ep<%X(cUmXS(;E`GL_<1{+I8 z=lO;kMP_~siCo?DW`}fZcF*ZgHF5%bb-cviKe@W$K+&e`^CF_!GwMVbZ1PHlB{+&5 zFMpBWJWtfb;Nj%AtQvb0JQ(tBFm5VWN>x40x+e4LuDwc&yajz%SGYPhyy=R1rRN=L zrGHPpc45YD5f{x4mh1K+LhtA>@H@ z^3=l|QIU)H?h*;jIl4!Mv04hlpgs_sp-RIUHuoEUv1Dglc;&Jer%O zR(L%uc-WK5m}PQop(4>RMZa7oP~z)Jk1bsN_^6ci`1=iM6IW*~{J- z88b346truY-TZfS>+f4%mv6m(ZujjkUs{)iZqD3%quA}}J)z)ErZ1}{-WuJywMgsr zqDMb%f?B$!9SAPem^LLt!ApCai^J?2tESs|o_-{(YwN8NlwsU!bVTY=lgxpO9x_b_ zW+X10v?QR%)j@RWi?tHXh8$ih3k4?R96IFY;nXN5nZmjH#WKaDmnRzT2v>SudYo3Z zb_3`1#sr&n7Z%Rks5?PdtlVSq25%F#ATxmghla!(n)_0cPkmmM5?#L6fK$c$ikz6l z^4{}Gy>DL5>o{}CV5hOvQmEcKy4zhi4ik#h8b+?eX6H?r!?SOg)xaOWIGltP+#Gw=OP9_f&w>#u=Pi zw*}&}rg=@V(485e@TzOVOCGJJBU+R6j{>zd>|4M?)H8S+(XRHS2X=w%kIO<=$%_%-bnv#F#k8>hEgV`1>%f;@hdC) z=1=~h%P9Y`X1Y>ejqhsLfTf|#YS*qvDu3}!{r2K$#k~{rn3haSW`Ai~XYuY==$uV` zdzb6SykoxMD#&nu!hwIg+k>iJEw3erf;LsJ730Z5`Xsk2Mct_!~ATES6}v?$5Gn``alJ3^KD8eq3d$e!EfU zsY=MIn~OrXb^e@q;{4V_otrZFnM$$_$|;;_YO2^%^mbX(26>U382JRjD82*#*c7f@ zHdgh2wrk1L6}sU{D>bBK17O>|E`KG?TZ!U>`yCS>!{oLuhR)tL6C6=PP z*ia}+g>g#JOV$;NasTe>KMmp*Xsf7{|IfNYYpu(JOI$ycXKS=yEav4lN(^k)2)nqz zitEvlbzR|CoMhY_+nSed+qO44AQRnY3R%)#6+jJ^yv)%tq7l?n}qMHnueXZg>k zI7cv$@!nlmfqqemkY#@s%`T8po&4{1(9Nmat50s+Es?T>VM){SnWfuaihtj{ysiJt zti(6-vuz%;M=a%H3}CjXdEgNCOys$a(E0bZbIz~&6`{55)$-yErvi1uwF8tQzN|N$ zS7K4~YJ1)jpSqb6v6DntY~Hr9hm;*;dgUzj>|J=-O5QK*l{cnk#y3QqGGurwvLIvS zkxNGXw-OU)9sAe1@m6C}$i*2YZ{=RE5?OkpBP{$T_k=a7hDFiVvogvRBXm}uhz{xr zy4!RmUuD|)>oa+!1#WwE27ffz%ReEEQ@Wv@Bf;nWcj37b-)rj1*Y0wOaoZRCaN5g% zor_)^y1Q`BsR=gO-_9gG{Vo4~-`~4C+vguR6{XZ8G(k5kC$5)a*RHRr{Y8xa9UoRk zhxhNWX;63hA73IgM+L?5;78PVmAk59^#Y|2so5sx-oLPg2AE19QtLEWT+Y>-eU2UTx+mMOi-_j1_p+>v>V3^UH%6-I=i_C1%>>N^7L?XadmMG@DFki4h#$r362a3@(+uN2n>t} z2yg|RLg60}Fh#4+>QJ-w8q3&q$DSRLV&?HZ%O?N!qk-&~`2Ih8dMg)Qm?V(T5cX!V zhTyGcwZqSAgC6BKZk1>@=$rEFgH8A&6VrtZWnH4V{QsC`T)I|9*q&AV$6)?}nL*(0 zy{9G{)xH`<-Og~mc(JXo%_}WUh=F0x9ycvT7mr0J{~cfPeW&!bx!yU~N`5xEEnRN5 z>Z4H@I#@y-2{hW^t(o@sexEqv?WJ|Q0xn6o@z}daKF(hEl4VTa*!c!J;iN8wCJt0ri6)CJQ`Iv6{EOB40@e* zO$%UNIH%c-nS<@|*0Wyb%eJm&etycp^y%4Wz4mW@>b@v?l(y}<^0BT7E|)accO*Pt z(P_lEYxmR@kAy<*uG?{J#~;5pJ8D+%$~dmTbJ$>w@WCssi4tnF+t&RHU9hy<>hL1P zSKr^yZ)4Y4yJeB`0;%8k0sO(n`+VNjDGqU11D;t@K7!oQw0Au!#7g;}%yhWGrJ`Q|1{qTmS3wW2Nr9cUbkZ z#9k-&Qb+9nqtCiI z<}tJseOxlD`b^{b+n%A4KeU9G&t1%ZG2NBK{5_jf(CNp$Ykq&v?S zoGy7{w)oska-C7EdnmS8(|GzCW=kEB$Rq31hM zd8n8$p-_J6vF`?9B`=e#RJyJ%Uh1@H#!{W|Blmm^HnS(ibZ=hA92KE3!7PEHCTZf4qiLe8>m~;*7~@bahp&WN6ikV!uOX~f33?Bmh8Q@;h(9XUSLt!))$c>?Lj?J zA0yV<%v~ffDZ_RD^^Z@Snw2~=cYf&FaKB)2G-FNPONN^5O^bC)dfXQ5mbJKHcOd7X z;)j*zS$6a8m+KeWe@W-oB8j^}0UMjNys{Th+scy59w^}@x~SoTlwxJlqn!Mby3DTdv^XztAS-pze_}lb7yYKTWNIYgeP|P^%+}GB={;aMi zRXP{1+`9ACzgj2g?%H!gEvt2Ur&mSI_X>KyNOF;qYWvJZ$zg#rI?fjV+$+P$Eo4a}8zR;5sbE2!2A3MvjY!ST-7Q1GOEo$K!v=Bo2*gGK`9-WB4S1#_}@Oo_?k;0UNpO;s_7Fj~4^ z&;Om@s&f@**DTv;dTrGlKeg=o90wjA*&{nMGQwS-toiC6DlfW9C{-jl^x{+%t*f@O z|9P6aJS4f8U*Ax?S7Z18!4WC;E$@yMn(n^0ZeP`&|H4d{lo*&7M4OyCaDaKuw6haF z?*8MeYjkB*xT)yI82Kc@AMy*@<5^i5Y99McNbE{4e!ubKCb3c*(GBURSA-}wGtBcz zQ!Ul#QE6KAQgTt2Vds&Asjdurnr=Rbop<`~$9HGTLX9`uzR^B(_di1-D>L&2QO5kc zM+yx5g3T)T_DtHzagb}>m6)u=h3m>3G*dRR${kUk_j}e~-b>F8PZD6*lJ(F>i2I%2 z+rHkbO_5@sb?kMmetqb3-@3ME$(mr618+?(IJ2sV%*N z+nT(@P0qC6G~4O3{7l~4lu7T@9^Tt`efBKZou_Bde9K(1On~8t>VZ4)B`dmg6#iu` zf3P%Qw~6qHozv!eY)vo-4OyvfSmU~HZr5zXk3JvYFy5J${dxMnuKfEs&F4$`_Rc%H z{c(<6gVAz^hV`ip{7d+2KWJXHOvdrkMtdW(iCY5bq_oC*gl1uUHsXq^7h@e45#KKG5ngi z;F;L9ExB3ek|r)@2;9Bq0@KE8Cw$m;sB%Q)Jo9^d%xFPadII;axn^uj%5El2o$*O^ z?s{RKumkt%F4{e1&&WQ;@TZ9JjH=P}QiiEBzpipOaqVMG?iJX2t}0*(tLd81>l0Et z^iCQEwBHWP*){2m)m>Ls!x({64>vG}1Z~Z5&|4gEVZ-L`G==Ry54QhhUmZ0=x`QO;br~eIs6yGWcUs&vOXB>J~d;KNl6hhHdGpnbt1O(9?AD+0;s7pP5g88Si}Y zOf}78&a#j84OcbT7Ceo1`1e$PPQV(S@Y5T2oCsY|a;#ffI4jqGm+_^W|832B^Cooc zm#KMpHNbv>QHSYDTRu$=r({x$? zBG6kTCh+R8$!FQ)+otCJ{*02j=VQZG1Ulkh?@Fh#sZTs`A z?x>t|SMFEybI*P#nJDeH)*N5+!Hqam%7ODhRFfJQ_sr$>APTdojoIR30K2>nf?RPu`-))N^U5L?40v# zqrNb=eer?ymQTak9fp>y!k`bl^^LFdik5~3MRn}AsoBTB zfmh9f!Tvc*-Oq=I3O8L2j$gNEZT+O38R|WCnn$%SUM})G8xdfs+g&jwOYHr`qve|H zr4x2Ve%Yred1$?3=9aj%ms1b_5xpYRW?ggXRKm9{_l35!Y_vPDN`|4Pip?S_t0b^0 zNVR_T(W}QVEDY4>GV5~dTy*M(%8G8;wuRk%U#96f=|%?KhX!(Vm|241cDcG+P z{F3;eF-vtJ!ux_I!g>Z0wF#e5d=`cXSyoUvwh$;|br`cOj{N zFUGBM4lUcX#!(~vxZOG}rXy|6u2XmaYp&=GFFdj3)YgB-cb>9m%r;~&ZP+5OBlKY6 zqq45t_?Pn}->AG|X!FpjGbmi=r&yJ8A-g@sB&d?-&emVkx+Elon?59|oGW0O6Zezt zk7bR8IQNUotLJ*IOtxFDZF;>n&v2rV4qGPkg}JAvy$`cIRl4$(-na8Hnx`{2_B?W0 z-NL;+?5Fv^+U-+ZZ|z#YCd=+=2|Hg>FT z)Gn@f+Q{&SVf7gv2Yu$0AEsXy>_tNB# zbNB9hy7BZ6rR{Z9$$2)WHW%gAS58d7x|)R{#He|)Pt@b<4grEog5L=_L_dx%>}LJM zzoA#M;WzV{ZzUQ#T~yRV*V%tqVy(T}%kuQIuTwW)(ft>BrP9)~{g?5nsV*D8fA4&< z%S-EaS5<)Lt9jqJOzJWjYN9?e{9P2kWB--4b3?v}?brPNnQ_}Bp@t&HO+k9eEvj*Q z>$bi6y!YH1*W-&8wZ(<%#GW(y>ZR)vdChLcVX<1#Xqf0AyZy|_G%Tq-dv|2UVSiqXFR*3 zz_D@#VV%MkolQ|Gi*0`HJiAHc;F~igJ*YGJ zypAzSOjV{~{TF7Qx<{AfP8C@0Rr>aG!~GkZDoXiH!}2sA8J_QaCmL0DUg+`!17E#* zUEXi$eXj-PHC-({_W!?bW@-yVPt(d!1v4LmvZ+C_tVN644%amteZZDbncO_Jb4%}ei*6NI+tHPjEzxSQ!XRjczLt`xh^T||%9VE|{>O@Vg{6oHw@jP6v6Xd8 zTeawnr9T^Ydu@HTB+t2Pd1cmKeQcII>A@$E(ZTX$Lm_=lou&;4m|o=fHb8#=3idkIl*8 zn*LY0b-|>oR=&EODwbPBmo9I;Zu?W1|M3aAbKKjK<}lQFwR(hYJjE<~w64#lva zD+}hbFUaX){IN8A!QTbDJF0>VS&lNEh`6nFMYeJ4hJbDzo#`K)tm^`UO8ZTAANcqy zo}nh`qUb4!dJVIJ#R+>DHySV>WdaR^88URAYWQpuwu33do%7!8Gf^kY^tu`~T25`a zutrBcU#hCKeT8<-PWJAnvr>DU8ILqMFLK`ZQ>oE?_a(!Z3*wF_SpDXo5aGddK%K4N zL9(g^&yHK0HhuE4EWfr(WGRR1zkNG9qSmj!mU%nNl{fkJ_FdhNq-1iBCvMca@4sKx zeo9{Aw8>N6Y~T8r|E`kginRDBc=p^D7iZ*h-2V+3PMz_thJBsV#`EE!bGw zuquR``#}G1S&dr>naqb+L)XS{@w%FIWl?C3$ht-+mynrLH6AW{6R^>3#~fY5f3MXd z7v`RAx-Id#tn$N2*!3Cf5hD>Ip!-Q*{u5LAANb$qzr%lTci+H3w}60va9{tR|6c#y z{#*U`adva_4)Y87FXeSLkFTbId1BeB-a5`_o)6~sbo^&#=#Xf=+}HJZMN3c8=e7B_ z&D=uIrg||kFx>fe+|KZvlvBcE3pH);HNO{6EW9A_-hVRt?Eee0&sEP_a4luO;?B>B zf33|IuPZAnE8Vnt_L_*tdo;G2n##?OdTJUc6S`uHNmBQOSF7IL?MPKIbrfN>)iu7H ztDqJxF7ZU5=b%InOVq?PUZw(OmMNEx39nkcDym!kfY6yF>yj5&TSAYOJ!-Ai)}q=4Cy9MDyjq$QuN(EDXFNah;W<;P&m+%w_edKA}oVbF_`u8 zqN*g1gO6C68yY0k7-#s~2Ci_O@Ts(VGlz76mhK4)|FubyH`l6r>iL_tyO_kzF|I5B z|HArqMe>2qZLEFeE7fkj<4og9GGO9Sh}dAjCLJ?RCdI9YM`G{SMJG~O8B&iiGBez( zmc2bi!2SSBa{cIg^QjA^e<{-j}PE zemgH&sD8Ec;_=63;dyl`3^)3QC8^Jm&0vqFH^q^3r4rPUd@^XJ!2-1v&L?3})!nSY*Lt=%H&Z z@>Qzbd(rW8tSa0*!LN>77I120iA#3z{@kh3xWvM+bgNkML{sgChA_`97P}Ye@$5e6 zmXy|NbhWZ`P3(!F+e#;s*pl=a7QE5Z`POx5S)9+W^M@>!rR_-z+s^B{;9c#GIVwSK zD*KM?(&}D*{aoS;#%DfjvL?6gyPrE__snDi6-I{~m6o0C3i}>^=aNuKlwQSITUpt% zrL070Z}Y|IU;7t7Vq)09aIZV|nC3!x#(4sTJ8$ju&FpDVci9tOUn{EQRkX$JiP^Ca zxjzJNu31$AzVf-&=4MK#=&j$DGtSOESNmJ;Y*u&l_c_z|X6tOe{NzB0rH1k288*Jt zpKnfI@1gF`9j~7~X{-Nisj$)vm!<{GtlN}LOSonpYHE0^dm*HHqK1m@zKshOFf0yO zI$i3t<|Zq-$u}BKN2x?FSk)x=yrWxz`*x@|1KSp^tp^@=`*XLCiE(!`|)**3a=T*0!~^z5QXCI_Y*&DwInC4*H_$H7oY z`x%d~)lA0btsXs@!Y0$a3LO*{zB$$rGPB5Mxib#~!%dcBS_(SFFP-;K-#y*NHQ`2A z*oT#(Z{9I)-lIq_1t60|Hhj8Gx#fhGBPIfGEDPy&Et6_|AMFc&DlLn z_G}-Sb3XiLWZ1H5bNk97{{j!|~h!-BrKiNSg&4ZAj^zl>Vjp(K2#yUH{${DxBGNsSGvPjXb+{df-bZa9#* zeIcvdQkP?VLWeXYb~j(*XkhI)t(mhTFsfwE+B2$g6MWe}Z3&3g-XLVG+>{U`#1eM7 z=`hoTj}E7KFKNbd-*TPu!6a@)BS*W_v6*YaPPu9EODUY2kX5v&e*5i1KKyblhYx*Y zxf41oa&^13nQ-{`y={>Tc2AdhF|R?gXWB*q2g#NNhgTjvz%`@(m9=wMm*hFi{0fKv zzm{$NT(xPDzr4fA@BMo|FkfbMW1Lf!dVR0X6Wg}WYl}{<*%jNhyZ>6H9E13AiH7Z} z)&>7R{lA>T{!OdmRLh2GoEtvek}PZSxV|K0V$RV!xp%}TwRO53cweBxuqCc?n?W#( ziqYm+OPLu-7PspgTqW6~+Nlg6T}S+Rj)fm>dPE!`-p9d*=VigBN6m{v!Y zKyKBXr3su2Q#^OHZF@WQ#-gLWkIF9f}r9Y#vhkdBYql9 zWV73Q+0&#>D{y_p<|W6nz8ux%yIQs&!@GCUDqW|L%PTb2c{~i5D7!$rBT&O#Jb8ms zCc}}kWTt0|_Y3}RydjnnooC1WeVh0K(2B*NhTq=TPKs!XSA^%S)qHQvyD}|GyQS|< zf}o>EE8oR#CFPc>7uPWbU2E&u^R#x6koHZrwLg|!(3;YgTJrX^T>Ydj_7|57v)8S? zdo(`dsPGj2hNYTJ3zn*FxIfEfvw`Q~HH8dn4t&SDLsJr1M2~bYjh9{1#hk3sdXeYF z&D~sU`lg@iWdF-8((SnN$yTPF6YCovNqk{iBF)OM#k%pugUe|JRsN+}iOf6`L21qoam&rDl!d)U;OuU%v!p}HF&XRsAD$k)vFiXavQr=T@Uv#+1U~qvi9An zjVHFx%ZlV%yuNett@No3Emc2xUMc-IUdZw7O2OJi1z+n;SGzjMFEHz3h^UKesJrZv zFemHHEp<&(tFWJ?BCqc~E-bL_Yghd;by~Z8!RBc4@kDMg-a zZ%>IA=Dw5KoN+}W?pb$6ceTEQ_i45V?_<<0t|>@bfBIG05$4A2w&(7t7b+9_N`thz zRtShK?!C6@s-r+ad~)|DtN$zHPnspHk4uqm7TkE$m794=*H4z3gW|XDY>5hHD|*at z_n&_Qhcn|3O-7#F%hm=e`hHtm-2+`#YCq{(H1EQ~Rf{5u*dERjy0$W*{I8Eh$F}mb zTq*}vyJRTo@N8t5QuH)nqjLV^uSd(yzG_|iW5&C8%sDF!*cQ}_Dij=HIGvfgep`gr zE3a2sE2c(&X}TJ^X}h=RULCs^(ju&ro@~myy5)`Px!lESUV9>Te|*b0CvLXtljKj! z*VOC@EjTwP@z?q^(7=We(}H@TE9>IIJuX{xetG!vx68V@Pw3YcXVW6VXAiRSax;8mMLyM zEL|H83nVs*w6nG7vUB{|-K|ivZP6`Flh8ZcqY^akYf3HPEm_aJK+bVaM%jdJxyH}w zh59CU{ezMmjeX1x{K}cESE`)R`Tli!DvQJsg$b#QP99%E#JtKBTRypOnf&#{*ZQ3n z8dmot1Q`BV$7c6`KHehzV(z=8%a6!2f8@O59>sVmN&fAIhuN>b+XSCHb4G-LVWa+W z=Edh4TUH!eR68+B^>)vzE?HyF$tP#j=Gs=T)jzcAw%p#E>C=VX`dr<13vTpK66`*> zW$n$>jM@ajk{zc>VPmkvY&M$Z}cSqxb)VQ*BSH&ZDDd>FvF}pVBnB4;IV-54a z1#mQ4+dK69({C=YHesx0E0`cOVOat{Bges6w=Q%tGBC)kxqE!xG4>k|{%7BfK0U== zibuGvoc%^4%kM9;xzU?{txB0blZAmHKGjxmw~1lh>s!aHFX^N$;k$iKt^1he+px1% z8`YYs~^8O(J`b-3u2F?rQxZH84@SDj+FyDqx0+<=9{$zdXkXXhqo{=*GooH>zB znkyMQa;?*@OjJ>PvZ;}6LX(KZ0w*ouBc~krEqJ>5R3s+fC|k4cSeO=v(hLKh!;V}k zJ8w8!FA1JF;j99~Z4_^>~}qz_f^-xgf#z`*!z zSMO(uBkVUGTwm22+n}7 z6AJJ0qO*5zO`c=AUA*Em<62dx6x*kQm0!;=f2rN~@Vr}ZUEsF_-K%lxM}6+b&)ju2 z^`7olrCsNjZhNCT#mGslhv`N_yK`du3=6YUCLTi5G`=)=s3`YIP8G-w#1GE zsCYquDK7Hv>cfhkEIcK>iHn|q9 zI>_tH!K-*|$BHi&t_htA0^E#6VONCxeA^z23SU=XP%>4R;=~lekbL$=YV;&ZbHGNlgCM55Fv(*gKz#z4&8qm}>W}#LT}8bLt9>Jk$SOve3OV+2`V`O|fUM%(-0CV6a%E;kq%a znvt#Yx(ht*&f8xdQ7kkGd9A7$!1;km!(fuuK8uavW{00IU9_laI!j4jsOr&zCC-0s zX2(T)ZeE+ZkmC*W11>Js1Wu+S{*kk-EGKB*JNasrdDP}Z3BFo;;}S(Q+9Fu9C+A1a zntdVf-mbs51WAUbtcm+N%OPBgOX=*Z`aM>Ci#^1-c)y0Oy87#YgxwdZ zI5UPf)1Izb-2O*3Q_Jn}v#zsG+}vv{MHfG;ZO9d2ESUPh`Ppipq7|24ToRkMNos9K zv1ZfMOCchyQ+0$EL?>tNd9k!VE9iu$EUrtD4sZc}?{*y}C>5YN&o`qtlb% z-Cb2B(|+qcJ+Z8xR9D(YFUoNcpmmD>ujmV0Sw0yf;;>5YpQG-g@5d~?eTpQe2< z)-K#>rDWrtsiHfly9gfXs6NNIBEap{^ro^-gGpvPL?&Db1M12Ay_lJxHhAelLniuV2e|B@V)&Ap(26=`RA#2VXZRWb;C&Hh1 zculvoK10UTwFg-ruwD;2ZdvlEb#{5=Ori`#)d11VG>aW28NTnCVJ}x{CEE! z?co{_;P>D2f4qmAtE;Q4e`tuSb4W;FK(KF!S7<^J?;B@PbOiJ#n+`PVSoMX%kM{z`uF^&F<;{r6s9sxJHJ9zC^2;M=}?(hoCb zHd&}W3A>+o@mfxg*4Z~k%nS`d-}BF2dUs=Qw)CVeZ#S5giEWG6Ja1y?VzKb(Z~LNO zO|b0mj;ge-ToxGh-1+(5Yd5W277K`)g`Ki+-pnRyvdJmw(a{r3j3$nb(|A*Zm2RPN^LNY{?uTyZzml(TbI zpJCZ_vS)%oY|O3#XKjJIQR>d7jI4&nmLd`S3=OI)Om+A?Igj_psYN*MKUHW$*i%7X99>pN{wT9Dn{0w}+doQ1%VO6=q`@}b!54+#K=GN{dmYl}GFd;qt>d`3=f|ECv zSN>i7_srqDyXPjCSDcVFt_l9WvwTv$^#6NFThFdPz3%%_ov4ZHWhUQ$VYmBU#V)JG zRgo)BYAg=9vSLl*lP0q&joYOetRb$N;**Wq&TMjJ*}FdO5cf15;}t4u!A3e$cX7nG zWu_hvb!>7qX--+p$NO4B?&%dhufsby_b6-iDyL*?_)mJ3$3Xjzd97PS!#*(gD*ubn|h4cXBL@OF5c6%<77^@$W-OaJg%zYaw|*D1ah5} z)c4LT4C9)>c-i1+Q;S(aO!u+0ym# z(FF5}Lpb6=d+8xgqey-nIEUX?K+ti%gPgXl9*m#M5}y zu;n7x(_ZiFS?Tyqvz&wRR!(`jaB`8lp%E`a8HQVt)d)P zmq39PIbM&a<|c1$<2$G^Ny*7Yh~Z9O<@e)rd^eua`_{dCcFESM(-yyF?g%X~V)0^G zF!i&h`|2%SuAw?s&8CkXl(sIJ&(?NmO4lmGJ%Kxp1V@DQYCX9kbm~@p+?t5KN9$MT zs4`rccblo^aed>to{dlTFm3FK-{D(a*U-6;mBGa5fI6@0%IQ~sm+E)#@)7M_b-vGa z<&jM*yspHFYW2j`{5w;}Wj{ZC*SAeOlL99+2Ci{r*wxj$lKn3u-;botxjCS9C*Ro_ z6p})!-2#K1vZc2gTJMRpc2YGys=&xFLwVAUcRek?t|m+0_et7iHr+UDrfT)mFJ8k}KIVt*4G$ikrM^O~{ftn>3tnPB=D$PnK&Z z=iDOY?TQTAF~JI(n7xkFyvThh$LS?pl3H%l%dsUk@YF_0l|_1-0fo9skM!CnFotn@ zZ(8+og{S~0E3>NsOGMHpjW;JJunMT_tW;TOm^89mWuNQ9KoUtZ$>d8~A4ldWezx;dlFvI@$m5duo zXGgItP^nX8*uWB|b#*1{-}cbW2W!2)Ze{(+zvK(c((mf#d-t4AkF{T_(^VO{?emPjVoi?xmMS;DxN$)8SXLdusrbWMaR7T%nT9-3{6sI{NHVR+Fv%Kyuw7B z?MTTRktroAd$kXQBvdgh30rw^Vz{Z&+RM>@A2CnaEV^}u?>6=YA&v?Rzml67r>z!W zvH0rBd)$4_T1zg3^Jz}zYgM`W%5=uA^Y&VsUM$xzf6V$s)IOfOr0FKho6vg!J_+_a z4QJZP<@Emk&*Jc;ONpWG+q?zKR<1K#8)n=bcI@S*upQP9-*|0(ll)I6VzYm!S=XVN zpX`^ZFRRq|Vwh8P^4YPN(}(|8M(xb`rg;9*$@~8A89R)QF`Ox9cy zWO)XB)HRn`Z`A407x8puX?i{5DMv$w_@oBY_#Kuzbynr}ZhFVq<{M%%jm>Fo!s)<8 zo@*sUJ5J2Byr2zwNBS`aL%v@_n+qFWk`VVaO0~etNBpo;#*5*>V=g%axeRq1*)rb!N|c@R>G!6S-%3iJ%o5Y8 zmGO=2-Do7Gs=3%a@P7W=bsT(Ji>F_#+f#Q=;m#4hgry&w1Q`@{8Dg3W*{dd-zrCDS z7Rgj47=LJaty;rc0~Ut)R~Xg@{GFke+V8j_DEpR9>!H&{QHo|CgSbSuJzqa#w}=1z z*xv^6`QiMjefAX+jF%W{mZ&}0|3H3{ z)ormoQ5XNdshVDNwr^Y49t*D5YZn~qySAh6{Abl=Qw~3_=zXd&`_`}XUeOG33=Bt_ zb~Eqlj6d?ax5<~a=f?#5z5Em0pKvtzSFlR`bV%*F=&QDM->Z$gZ0EIUlp0oUN}s== zF~dY#+h1c<)y<{<(tpjaw68zY{p@k2NLGh9(?hOJ~oTS4?Z_E~}Vt6zTl`uD9$k%aJD!Gd{d$jqr73%#i2Y_Fl*Pnw3@2WvPc- zZhH27zZmVbm}iyN?)d-L^lNW^Gurb`;f+hk6`8xoR`6c+;E)mXRR6!vi?JoDlR5E8 z)9>GBgxC)qD_-GuqPRzxw`Gp(x#1CmymeCe~lO zHvgz?z1X>;o07j7!j6=HDlYt_5ZtIhSQPGh>iT27W=$%g+7(V3Q-4<4p7 zsgwruR&>A2Ps&|*ahKb2(KT+N0gL6UBgKMN{aUmndu7jxssJrvMn%WfO59;zEw6VR zkKzsDWN3-IsU>}1%KUq>)8YjEY>(IKkGs+@$SbS~)?k?KqflFU_GM=YM~7Evi*&RJ?s zVORT<7`pTCu_XzZX*Rio=b3wV=`8O4#e96<|EgbsYSX%<8wEO!t$3lG z9TOAezCLMHiN&^dzc0VG>q^VSl9IC{IMIpD4U>kL^q9WNzA6Z*iS{ zg;t}}180Wx_}%S(9eaGjA|2CT=S}b07O`~hLZ_V@-9k@fNlY=_=*1N}eJRKENsYf& zZU{?}3~Y5>?^U=#iDgdNRnAu%bxqFv-nm7V=6yZ!xBr?o4ti$~-TluX{FdoK8WY>@Hl2yS zC08=9e4eAfI(bLc3Zt~=oN@4!#9g&xVC>XkEgS2HF}i(;tL=G^q7_hx5A902-Y|{xpredPosFbxx5B-Oq+Z4-yCZGEi%+QTPY`~6*7xX~CzGfB zwdaeseS57P3?7(Z>0h+8CNaMof-7{O|)oH z)YWHo?HLnWP8?uom{R1(Hudh_Ep_SPT+b#he)6NaZtHJ`)k1B|1&cXlw6|xysZf!Q zxOV)LW9oV_qexv7R*%@dT3cVZp4#+oM{}54SI~m2t1~zHzA@OAyZf%SjJGC7lPeQ= zID&!UD`Gf8jDdk+@-~|o{lGwHCl5ClkLcj=upoa|SNAwS|G@vgE>3n19>GC@{{x*J z{e%Adcsn}>1^M}h?@1Hg*fCk;;g*GAEZ!R?Sj~CHZ1TFPiQ$Uyg3J3BPBzIl{b#wN zXltJSj@rq#M>;k&?>Z*HmMCy3@qm`hjjnBCTfZfSxO$p4WTcjJE(u!P#ki!bnfaNL zoKv5DY4)auwUR7v>l<=|7&jC!zT=#0x3q29f?fOSef zcd2dFbNO^J`dp=ytBW>k#KLW52R-^0b^6XJ%4PZZpuMbqc8EaZUDrc*YZ^F`c@8{h z>6@3fjB%d2LRD?rw&xp+7KwhJ6Q!s!L0pDCBg8Rf!NG|}E$I<= z?A-9&j)aJ>;v(W#=Kf2uR^BLjl;OuWfAOzhxsG(aQ7u}f?xq+v<7}k1UQ1J+*z6Pg z*LL5QbTH=5WSCN=o33pC<9mS52m7~0?CXyIP%JtAn;|h+gW)2>x9T0IcKJHQMeBQ+ z&C2wD(s|5uSM~w#l=6LPiylqvnAEv&SLxb_1(J818TK?iH1Oa5S-Ok$)^+`vXGQ&g zb4MFGerAZ6nZ)45blZEeq~)~JPTt-NLM}BfauXKc_Bb(n=j;F1&RIO3XKYdVsAg`4 zjT>W6UEx&T?El8jXR2=m8LYD^JQDxm-dXkyzKjgHOB-HKm8~+^ImP**lzXXT*teu7 z9MQ6d&Ks;Y_@r+3V!AcIQKx753Z^w>)ti>gyY_Hf`Sf3F&$h0&+jQZ@ef9!PE=Gs? z>nvw4O3Rzbuluxrit6GA7t5~*uzlQa`h!z)$NYd*O#ACQj%9MqiNBZ{T*NRX$~SED z`>*0P`>y6o*}S>?C)dnXA+BMqh)hGf(u36Py!ywF3)KE7+fnVcvKGB}y5fE+GqWpHbK#M|i%|>9 zG}o!G+OBl#5a+ufwuHm^kq0IblQr5l?)l# zSGBljhEFq{z#zV+tD4vM&X@S99-i+^yxwxni2lc0{+V&x0-1*OPuT?3zci%!#RP{{ zJ&n4XWvS=?xNh^`fY55gsfUBa7KyYLP208jmf)_R+o#m5^`G8%j^|!aYC$nGLrYa5 z`@XgHk4$#IOle|yw1oe5shvYk7{i`>Y&%LOR%WUE{u&g@rJtTVW1)yp#Oy_T*LqD1H$tD7OZ-5IXR!NyY2D|xQ0no@N)tRVJEXpX3sV3xxj?`YE{t~yD{ zS3B}HCMz;7iAybN`Kh=3dC9%YS}Vn#>9G4%+ob;b7L)K=h`C_hyW%dF#OZg!bl-2< zvy1D|fvU_!PA)o*x*QWt`ajHPZ-~rbe_P9tQ+4sA;gTaztoo(0p)pCG zW*3j{?e1wvV6maMG_64&mA~>JhJ@N3(vs&>lfr|Ph8$Cu<_{!@qHWi z&An1}=i`$buR8Sh>zvQbyn6ihYpzH}~yq z#~EwW|GtPy4vpwu^uABKAbz!0=`@jDp}vtTo2RAAb}yQyvzk@1y>Y_kR}3|MZ_nht zO!@EfM*Yp3P3O$2JL&`Mp0eNYQe>$6#`tZ40GyEwki5Op6{w5w!?Y-4kK&Br{*H;d-ylV z%whT<=Fl>6WjfcFR|#vAzQ|{VglmZLYQ8#@xYKRnL{ZJWg;yH)6>ylSM!Dv5=N>j= z(p;C(EiZIh_p;CtW}AccQ)k~2Il_EV_)k3pLwkGO6(70qDNkQ9IqqAp)ddTvt2*sopO#dZt z#M4RGFJ4W}r$e%Y$#jO1o<3vRTBo_bZ!Aod0@fKvcyIV3QM#W3aX5fNU>x$pL}^v$f?w09i{HF>#v@klvdNTL({_{R(@L8iyDuBQKH&ed?XxWdXI>9O z#U2*p8G7c4bLUAvcGdCJzozf$Tax-Q{mNd2oZv7P*^5P@n%X7|cP2f}3iAKPe0{I& z?4wKKpYY54X53)u#;~QIW#6-}-Ju^egGD1=X-kP|CFvg3$&_Z*Jt-Q#YxjjoGp5eI zvZ+JuNZw7UN%^l8?`}EwU25B8>$BhgX)_#U{K~LH#FgRBS2K%eV(Mu!TlNJ=&bjFq zCLSf49cHTk)Z;zZ|yOy*2Y+lYQL&9Pr*k?icje$qm-FNc`7%pOC__yY^WPstPD;)=;J_Loj zwl8oE*0?3=#p387A#`#fXNhJ~XsBam$Xd>W+Ac3Ia;#eWV&xj~zq^WA=k)z7@X>kd z=wZCaSMQc%kFQ{c=x+WE9GWZ+-b^V+e|RqSc3B&xxi0%`;>&9xT@y)Hdtomu1&0)Ry0$UnSmkYn5d-E0lDk>-?yBL-&FrK=i0jL7eaS$-h6iB z`Gn(VtB!l$j?b;CX!*+Sxj*=ak>~pBtFr?8+DhhHOq)GX=;r2m#}fsYZl2X##nr-M zvWiuOJttE564#@ibe6k`YlW3X)+_WhH>H`VO$wWPu|O?CJJ(@LQVe6^g-cIfwVf#| zO$`w{nXpMB$I~&i&1p$mpX-v+4?#Mr--Yy6ethJ#rC2ufe^;H;=?AP*227GYXH_}` z1obxUf6wD z$3KbBR%G?3&vU=1iKpaU(th;Tzh>(nDz%)eiD1m7(2Gtdd>sY_(H`?%2Lm%Vk^*_E{?`InyD z&wjv+6?Bg($2}bzx0iEIeG|%f%oXJ5yIt#^BVS&nmQdu^b=nb561rY8D>?U+X}`)D2|xI=uws)R!fQ&{Z0!#8a?>F|Vaeh=5~ZG}^RJ`CFZs>Q%) zox-Z1lO9JF`o>NT3YF~=ap{>WzIH{}S*AU0xlBo#|C$<-7^`okGX7Bd$M*d@)0HMC z#tgZH&5iZz^P`S?Jx{ET-lcK>aq#`4k<46+4Wh0&+NB*CF6X3Vlf2;lDo7TH; z?y^Y!`z`y;=5lvG@lfGaueq|f+ARZArS|(RxjQnODc5lW79y3>|$owi}#EzK>6cG_R^NeVf(U%G!CdblR+pHB8(> zbA_257BjT5Xyh)7mI>r(V!h4bd4EUV?&t?k=3Y3L(>-BniL6$JSfbFHx~q?J|LMrz zdd|0XRSNIMYyOoBj$e^aFgwZ+V|1|PNB@NhA%|u68rilVc6nD{UpTqk?_-r^MV*$= zOTOJRcb|+&_dPxL6aO~%0EQ5^qg*w)M~k-4j#_f+#Olg|?eY!W1zn64HVNwmkF9Q3 z*!hfkv59v`NOU%P*Tk$BtlBLl@A9r(z8Kx}YSN9Az~p#_6r+_qe=be_HgRe6G@mC) zwF_InF>bIt%3yPZ?by8^66%ruHw;#Ein~ZSwhO*IIydA^UHgnR8NR`@XMI@_sF$pu z(#Jie=pZLc#FnPj!8836O_`J~b3OXS5Ixb8>Bk(Qds@5CU$SDgi`p2qc4~<3tX-SJ zd^w}0muP#r_P$(dC*qMB=~MjI>SSZw;Th6jw~ID2x<(#k2r05%ZN{;9znJ|0qE)YN zX}tM#bpJj3guqEMjrYYnH_wzm_il>Nded#kL{_n72d#|^wOw*d*hk~&(oIvY8eHiv z4Y{yJIctf;O~!LK*KGHn+Em1JrRzA)mksqo_77iPD_vl1|G`jRAxwtP;U#15i%)m0 zs^qVmKj(cbCEU^&T^P`H^sCnbd8yEi-NjqqoVca&s;)Out;fd7pp3 z#C56j?&}{fnyQihyXfTdg;uZD{MgMCQX(GQ!LX$7@FV|yH|E`a`>g@059}w;q5*p;|``_z-OWH@yq`S z2R!T#oEf&N?WwQ6>+mY}?5~KqD>k>9dQViGx9OB>P4V2wt;ehM3#(O?s+?A71zwU! zGSK<>s5W>5hxD4fn_koQnCxG0!eDJeS;HRFdM7~<`2^E0#*Fz6JI}p{~GGGJE?PcO5^6g>@&Qb7=KiiGp(!o&wScpJ=3XD?T@93*CTXAuLOua4!s)6#hI#` zm>uidd30-;(b}VXSst*g{ZlPJli^m^*Gx_;ro0c{OLtkYePrL!cs|~5%GAip!>gj_ zocU&VKiSsqH+r?=AKrUe zv9RyY2D^gT(4f_C&#g&ZDx8sV(o-b$XvVxIMMd74Z$($RcgUp?O)d|K02`~R?;`$`c<&A^462rBzh&?<{jZ`doXL$rCBpLE{QZA z@?0A>C6P1jMG^ruE?2KCU_vzb-r@W*h1ZPBANy#nVJ^jJelN(pO5!)xV+sMy) zor>ecfXLtTBa>hLJ~sJu(zK(BH^RJhw2n9XIxxC&Nn3HRny{iL#dYba=h2GcqDFBw zyH7N0-e&QOJjdZ~%5ddj@~=1HViE&0!J0HvFR6B8<$u*7r_&;;| z*IREd{+<3SV&{=1yxT5uPc^sfxVs|f{Djhs?vmr~Ix5NfCnki=*V(#amTSta3>`1l z2}{DFIo6!F%W%A$ag%Yi!%G*w$%{@DxL#LSmK_|t;;51s?>yH%*KRMe)!ExHbJwf{ z22a-wQPU=5Hj5W1_i$x+9B!GqO<~gxw~ebEn+l@V1U@|^axU_O0^jE4d$(w;J;am| zBGP@SLQE_pS$9#_k{dfGD0=N>x{*|}h<|3p$qMg>SsbULJeyf}7}_o^Rh%Zc;zg*- z)eeoLktZf9@~mJJ;Z9LxwlH7_N!d_k=c;?jDad=#*2qJjPMj!NGmqcee4Fxwi4$9& zE@NOyE?~Iu(XrO_v0~zf+j|HuUI7zNj&s{A}eL&ZC??QJ&1tWcc4{3wNna z`1b38on6Cf4Uq;d$H@0I#%XS_Md$01!IaExAlz4V(V&eeo=j}+t=dyNBcjf&q6QV z5n;YCD|R|dqM|^cdZTUNw-y&uN7MY543Vvwl^uyprZSv`Jdd?otd6=}j&YdtxWz3o zz`W2@>){7EhT9^_2HXKtZ+<#)!6hc)=pNCpZ!)-NdSq8`oTH><-F+eCjI)_o{>c}9 z-!GqOnZeLgG?BBzRQJx_iyD1e&pbG<*D;i6cQICIHU72VP;*!_#!J@yeODmMU!hYr zdo|sog7zMGl_@&&qvX9`>$AVvu8LjvU#O?9u=JoJf6&6_Se4N1CAWW{Fgo{5UZJBW zi6M$*L0Z-6lv!^o{vCgj?sPI$a$RSH&0DYBkEsjqxz3(9^Y;7rkFI}j-DouvOJQ76 zHj(Yq%74CdL>goF8nHi`_CKYI@ea4a!Gi}F?#L#*GB=(6^vda<%Wu|&Kc31hR~7iB zJ@8m+Z&aq{-JZhC(CWCn%;H~5J=StexHR==Rq8K>oVtq~M;88fSpNUTIsGjn#ZTv3 zZawptG0gP{L(S*v1%kcXe#~}WIjw7vSK!oB+uB4|uIW4K6}WN5iXtsdX8wf{zhgqV z*Y4}di@f}Hl9282ukCKi&A)MB?c4J~Y1<2qZ4xtn{xWgh`yY>6)8Bk) zcw>`n*E8?jjl#=5$JY3%24BidcTbwpl(ly66g_T3-78+=my;#+d4FvR*tla=+R{g# zIv6X3_FP+K5aY2>My1hcU5f!vNAY@5S6S{>J{Qhvu~h;b(LsWtFDAw^wA@g*wAyut zld#4C50428cLv>mC%1bUkD&<9F^{kXoGk%dDAK)h^6k(GRVOE> zC;@>->#kjO(>%8B>Py1}X=w%Rh~2xo&)xFBrm*zL5zPe8ASJdtj?8zRRVMKC#%{{w zd^lk#OM`)?^aq9?Pi6Tewy&!D-4?{huzAb1N6YPxx|=T*?JJ98VdL4pV37^4-k*@7 zQr<7VQ+xCkH^08Z75Q||u9sc`yV(z1Gh}WeO9tuR6N?+PUrrrd-vQ5FL0kTI(OlcowY@su1|Kg?3TTC6%0$NF0Yh|{jq-2 z;)t^!C!Uhl{+d+Jocr)E!!|><1$$YJS8QKZ=Fp(?`nBPF_K0PVcZa=kl`RjCe!c&c z+N?A0)@_}%HR6s??a_#tOiS`ommZ(;QvWoky-|XO6W@q^`ziLdB4%!wu1Jm3MNti9eT#jUv|>1? ze40Ax*i$=)n-a_)%o?{HUlZ;pAir)^kF!RrrDV=>r^b*#{iv2VrE2<{e7+vZUp?u+ z+^tD`dy;ggWwiWjo;mOTEK`;xp#q10+aGAr6<`qI{E^x(?34YmBkSrb(YcF7qzp5* zx&^vCF^D<*XwOc|#i|qDO1L&M9lXEBqj5u{hR2$#S-eb3ieg*%r}Re%>^>D5`sK)3 zca4s}46Bud85FbxrrHUvn)|qF#no%8wqDs4=&szvy;e@p+jZS(Dbo#EZ#e}+*95X& zWVx36&1h=L-E~%C3_WR~lUgIrZf`K#=cjY}z?)Cp&;K%XPh#TOvY+AUx|w&^_WAj( zbXz%(D{$3}t6IK0g9KUI?{!UEnd%#xyjtK%)wK^(4ILyRztyywWHUN|W=mO;q~k40 zG(%Yv#D0obulT*D-dZ)`^dYtb`Z2os`dwjbSI=Fgb*+N6>aU@gVQb#>)}~~6Sy5Ag z&{dnZaM{jMSz)AOmA!U#qCnr0P^O%$yGb58KN^)R{5EE?CYj0y3&zMVFk2?@;}*-Q z9jA*cJeY-MTBV+RZTRQOg58f)_q{&9U;Wmkt}r$C$VHpJXdQ1V3p~~T!ddqEqklX7 zW>1w}t8~>WfT1Vrq^tY9zvd#61;JeAMH{>I*Pl4Se!%sJNW0O%q7w4U9kK)*Tnyxy&yL|GG7?Z2pva0FlHpKps zU-WI}dxeBt5ylU@)dHHOOe?urU;NH^VpY`PdNtNdacj`k7fYKr32)qdL;bE)SeO{c z7xC2d`K1fLPyeuQN0&CMPT5xHo_$Z-zpb=hT)_HBBtDMQ_bWT&#t<%s58*rCJEUKF zclpPSoOM$cX;w#GUZ+sgS+ZTpk+rMqdEnh?S7%kFZe-{z{j`d2&B>#AiFSW%74oJs zGVDoO&h=)|oeLJZ+1pZQlx)5Ke9Lb0wP`aCE>dwGLF1=%{SzOQQ&eJ#A+hZ@frecUfzj^o7}W ziMHq2S7>!IX2>6ydL4*E`O? zA;&dMgJa6W`%k_28FJ!Qx+rWg%$%iHv4ss%m}UN2%A z8NGgycdDw}nvDs8rmGTKyHoWSg63ZZw@ncBOTOm0O{dFU>k|{xtSHm9Z2ugXJl4*- z$7Ij&Ao$PMl(Q=@U%Tm=`sjr~*VV3T=XOQz-{5@2t|q$5h7#Pg6&y~IX z<2UO&=k)*67y52LdG6k;>Wb87)`wSJWZ!-xRkYftTP`=Uavob!ya9KahF6A2=Es(z z3676kd>SOfmU~_iO3RrsW!3J+L)<0FkFtCOZbWfzbZ0xpa_Gddg^Zpo3nOKlR5TeR zq8SuaT$?uJ_SGF?vo>Qnr68~&%1}(uRd7Lr#Ycq>6-5r`<9eK|Y;R;X$hJGMF`g)V zaY0fe&31#UhVv!1Xot;y(wlnQC`De`zmOvzf-=Ukp};-hh}tmU>J z^Y6(U{F%nQD3z7FqHtsLx+`f5D(_|)Zq)p9DCPd8bE11!8@#{R7oh*_}+Q^KB~8u^)s_f$ClNz_ns5Gaopg3 z-?bM}D^fs*D>gJspIK^s=6~7S=haz%lP=jDpU3~c{=sVfM|&fU-_+G+oG)LUzxURw zXEBk-@4r0Ezm5N1{{G}I9Z@-@>ivR-r@E9Dd+B;>vEF?Au5iXFoiLTt$y1m@S4>V_ zb?k0qqfV3J(bL^a1OgKRj;Y>cS*7K%VUpOKLm5k@qQoCn2r8WN`MyUZK~yTcp(WyS zUPgibrs#--#Nbk8i6gp7+5rp)9?6);U5yp>IqGQjF5!?EGs6a-u+wg-OQyO?Fz_<0 zcHMGIE#lEMr&30lNzO|I4ouN-=xaWryc2TD1Y?5_Vo*VXfq~)c3FUZc=l>f2?fyIc z_x$hq-|Bw|m=65!{XfCgWx<9B)!YvZ3W?0q!k#QkSt6>5_;BeH|K;dG<>;v_tnb0-@OikfovN0X3u@5YS5I_{9mthRdAQR z1M~Z(xxIJY+P_~bSQ1$1b>_^OB?=4-TE(~h*O}Zpb4F_GzY~%Bi(mh`dG-@SbkD6j zC!f9H(*DV~^KOJtWmD{W_M%$7t&0Nh=h~*de z=3%z%Y7&tMVosS`ay9DamqQ13s4SG(($M12^mp$y6MZ&ERZm@3#>r%so_6Jz* zSJ$4n`nxbXxz1w4E$-Vn+WW3$wX}LAB~24yW_YlEMnv)Ywyzt%JF{;p&f4ZXr{ku{ zszm9N9hN;)-<@k-w^d@3?wjj#TqkFnOub+=A+t2d)X|Gotd?!swJz)1Gq0R5@Qzy8 zf{uWvLJd*&;^SvA~R<2Fp09datIb_#opyp zzR;0ilBwX7#@cs|DLu+LINUTOUmz!VZqM(G^I^}vb59HOm@N6#Wzuf0X6B5dRkd5D zdw%a-puXF+VXy7niVbpAOJ124Nf+Kc+^wpr#L&By$uNb<#%r(lr9cnvS-ZtkI~eTd z*k*a3kblsy@!-v!y)PfJ-$;1lYki?LpA9(@OZLsV8`;~th{4IGAx-xMtAa8kJA?Mp+Mp>RDpH${XmjugS!_Mi z>{0r&h5cIA#i`auE?V`MGP5ZhV4CNhyH@Q7Geg<(y;Du<7!KIp*5>*1>Ra30>icF< zmorwROzO;>&ccwhfAufr|F$n`r02Jksc4`6@JZvoh|uF48R-kQ-`1X*aOIuW>vY|1 zVb3NRhF!j-w0~pnRTH+C*SoZY**9%q5>9gH*GgK}bEv_f!AxOULBdg`DA&X(Vm?b5 zIhW-gy*8c0!IL>teivvOo%XGsNq!d;&>Kx-bBoc8Y=``~cj;qu58aO;x&^noD z=$LVJ({sTxV~K1Ash&4xhlHAwnha8#16!kX5)`NS9CIlPOTEHe$i9ss=i!u?NY5=y zk%qY!P1Kk+c_~~zkgmIO7W3n4)l7>eSw790(A&E8h_Gbh6V+D%uBYEznZ3ei>Wa@{ zCG&I*=icP+=jE=kJI(Dc&`?@G)vl;)hkD}4?y#C)=Fg|Cncl;ps%(Aegw7O$O_#H- zGTy76`&Z`qaaqHV$GfWMKAs_DpVq!m>U#9)rnw5ai)9n1ZILnz;Yd0jqn5zHu*-I{ zxAUIITlQL6Ej8a{5NmIFA@`WS+|Prje|Ijge6Icd*W%d{d~>&#KHs}~ZQjw-s$1u; ziYYrKxOCme$lVjHjoDuwPy4hl*&%N0i9(B#c2~Eq2&Vhjwd& zWTe)$mIHpvxzDI5>5Dovr2YQd%{g}}TQdu<_xe+1o+mU+rW|f<)L|Al$6%83F{j{l z*~jwqVjk9jnsa&n?l&~W?~1deJX|-k`u_DFXU~6G%Bb+1tF@S!&3C^)6T{8Do1_mg zA7^kVXJBAn9iEcqy3s&^fro*?LF90}98-Y-Lxu{&z3jPA%=#UvJ1xdvbLed*rP8_RB9DnWWmi*W&?vp;#a^tRs%oTYCtD_oLn5{72*q*>> zpv;|=C?UelATYTiomF7DY2|uD#{>QRQ&~MW>Dx0fBpmrQ*J)wqd8saM=EPv?qLSjY(5+z~ppp zX{XZK1atipmyKkVHu%Jbwj9&p4((jF=$7K79_7^&b}=wCoH+8*=w@ii97*q>Df@&{ z)Xn%jPnCph$S{4Sc52b`jDn80guy|r)cyd=_q?rB zHJ{dt+-Tx_`MV{F+2e`b?Tg!t*9Zm)T|VQ(#PDHvwcu)1HNUH-YJS(M53hK1+oD?W zrLdH0)yGA5=l^}P_Oj)93Ay`wk9w3`-+k)Pqn|f>U7zcv&RkxW(JgN1WqH+?dzye) zid)CUhN7^i61}Hdgadq6=(u^mkYTyGL{uR8!UUeIKnd4rYHqIf4*uw2DnsZ#D=f9-I;pxX#1Pl4G?>k8i7F!b2ymV;+7ThlSD<xYzFVQlFvU|P zYI`#m>$F8Od#5Nqp60lTJxzDn>MqVuwr7=(TV_`jhE$r0^t4RQYDn`rwli>|@z+52 zqYl@MCj@t7?obgcdv#AjMnWhcbU_!>T>pl}b9GWnmO8kl*ypZ2G$HJ-LgXjLV`khO z-1D~7`EX{}NhX{WN>Fj-i|dJ9Zurh#LH+}4{P(EKN9C;^vArvof8H>M=UYzS#f#f+ zMR}xo8F4Zk_;L1{-nVa6*E7`e`p;cE_x{CIA>GIAHKkkT`g%q7-7fi2S#+!;=8|jJ zZ|CkKU2pGg&!4T&UwTXP@0CrT7QS&kF)J`9}e56dJcR$c?MP0Rw0!A4~PVa-?DVm7!m zG2A@NV}5M%+cTo(kr!@X7c!oa5+$%*X659=2R1x!oLp(m9r@BTJ<5=4;>4@bW!I{{ zGBhmIU}%(0s5&@_@5-ATRbEAhe+QOrJS)0N&f(HR*0lu;SqqE=FR{G%c0F*N{JzbaB>^aB!+i;rlDyN(lo1R9k z#Qv03PVX*BU3|4rL21e>r!J@44niHLZ@%Jll?W8d3G%Og=`u6)x}nkprnx#@!#rqx?xV!P~jV ziFHD+iR{jab9mJh)n(m1i^tAsK|Z3o z=Yp1SFs@#=U`6R3rsUJjB8Q*W`fN8;YLhVzd$WmAU-K;Ij0uY*O`6}tX(^k0G2%FG z@YQ93&x+lXUd~awt(X6G{ie+}2Y#pvO}ASwoz2ed{D#e8<@-5|4FxY;E*x(*f3|<| zf~3^l?^0M&9E9Q;{aZO+X)uV*)=lO5#rTr*-}NB3IoHAyzOgt)>j?N745sR&w9_NKmWd5`BrzY z$NJT>ckwl{vekvNyXVi{Dp@UkL|1q1oJu>vypM{)SFHkHhoryI+a7R%>$;71xJ96T z?7c0Ix;8C4@Xq5w9?xQJ?;BBfG{t!nk~+2smE=etn44I>%%{UjkhyhT28eR$_SK+} z;}Wbqsyrv=c@*j~++Y!5n6ZXMf@5unPspa1EJ7YtY93nJw|Uw^d?)^HOI+67w7qI4 zZ`a9?ABPl9me{QP{WJ6FF0U%dC4CW z&7%-u*pxi`{y$ic>UxO_XKX+j=CFi4AFr+2evP7 zD9pd~j4_Jmgq4Rkhc#Eo)mK+Hx*iW*?d_P-yj@ZJ)uM{myB2Cz#V}sUdb(y+-w(;d zcekY#vg^Exe{fmG-hQc4P+PMX!>oF*$=8ZlmHGs`vX5-N)qJmcx6+Hyo=2vP&sk1? zop4bq|As3AlQ?970z)QZEJ2cifuY)ed%Ur$qqAFZa7buih)+mJfUl3Aze_;Se_uBT z2N!!cr+}b{u;B2Bkf@MoKR*`-r@-J4*T9s#i#K(2etw8LKDBH%bDDD9jNgA55|ddD zOy1j6d*({OoGG0xc}t&PIc%OMR^(->d+d4 zJ}X0sYpQ7rZSAIH6|(7kz}xZK79oui z39IuW=H65E+7s7#WC^k@aSaRYUL+pfeQ+T+3m?Olyh`@8GmZV$dsm&gk(jdZ?-#oR zVT|q%oSC-Iin6nuA-rPZCY`WEUss#ZsUb%eomO6|q_u9<)#dS76MvtWvM5x?)_YG2 zr-So?P=_OveoqqBKc?5y_m=b5$$ID82`{hZCCocAe@FR8#zj+?F#Ng3{KB?=^*xOR zzQu;IV(+t73mz=p&o@6QHp;%?T2UH1M`_ha|To%iK}<9%NI`8UsRhKAV9=Nlv# zTB>fcy;}5FXo>D(=iNp8Nw?fN>c6m`Si420plAjDC@h+=3`kY zDYth8iiclzKOGt~H}cDR?U(bK@-JTBw7=(#$}v&z`Fu4o3=BPSp{zy9{~60?{@OY> zedE=7U%N-_D^jH!>KOX@_SK(MYCg8}>8e+`;U!I?OC?yjWLM?BUb;3*(`jXU7`K+Y z=fmXkoh?(|ypuR^Eh+i1w=~0?ptCH$nnbMU=dQeCA@En_y^-SczYNi$G7WWVFTQ;b z3}l}6eACuhi#F-B$1Psf_%%4_;{BD+i@O#jY;~EkT5e|1_op%X+~zC7@-}!UMtt1A zx?wuwn!MCWf~$QsIBNc$%6fRc=t077hSf@w8LlwwyDF%o;VBy5|6*^|qHxtx_Fei@ zxjn=Bbk)LIi7Qsti+%nqH`aQDem*?;UF z$uSI#=Vb%_y>~CyT4WNqv}f0~&bGwV60WoaR?*kTy(KoXEp%JD>Y7ehbl>yL>!!%FQbSi|wJp+^71sNuSN7X2-9V>sMHSbkLmRmQICip5 z@k?ZSE><6OZE4M09SGUc}WJDu` zr@rz_Js`SU-J@Tl>Z9k9rq*qbixw~{91jsaAMuEBPS#bHH!GxiJe=kagQ>SEl%q7d+|K*eH$(v+xGRjwPe zE^4!GTb0!-ay6YPuWwSQ{R36O>&xjEq6u6 zS2eq!7az`f-96c|RjHZz!&~F59zk!(OnKWy7I$_9T)k4ExiLZWwVH-jmzb%{){NyR zXKH+qQVq%ex7S>48pD*RNaoKJBBKPW#{cBo-Y+-sIBuD> zXvOrTqql-ILz)8b$j;a~eZtJbwUyqCW?y-Fg?afWf}#A{`_%v+LXE0)B( z5cm5nCD+%TE4@GC?InH(4gpQJ2m8D#K73m5?$9;=ox=24dPfs)1bz)Zu*l@=Dm7mP z*S-8pzD}BJ?Du2t(|^b&6w>w`E$QB<+zG4JxJfflv?xc%$rTiX2`zP z?PQJ8Ze4VJpr}kQ(fv(+6*^!!vf!QC3LVb^h~zMA_X;rDZ|WVD9AOqmmOhii6hch@G3RV-dBthRIo zzlgn>p}Op9bJW*)+xN&n-z$2m=p=V4!%iln-M+QFrcIAJTg=U7|B@F#j3tR#sEJspfUog8NdF|1P&vG8J9+90>ADQC~RD5f?y zMm}CO=?f9t!WVgLoqJa)bA5*z%i|!Y?uH$YcAW4DIdS7qYasXGt_wa6Djc~6ZYxzT z3#e&2n9i_RmXX5o!Y?vYteVB|jE$dodL@6`R%s5w&VwcAl5D3gn$BMG+{s`EWD6;nSl=uCsIZ+f+aFXgD}&YFVzl z!XoyY$E;#`7|t===}X?W5=2|?wZtoCuE&@(8NQ+hXmUg=QMp} zNO~=Q>gWEtn+#S}hkx2LY)edFcy!WXr~D;vhJTA31Vt3%RF;Yz(oE{Sp)*TSM`iU! z9~Dt&jzg>2?Hn2ARGnogG?dq=y}Yd{o9Smty}&x_Z_H=9lo*Z~C7j+|$QsG_+WB|X zxdrCVs(rDH!DZf#BAqEtYebWOnZ=c^mAd8dk7-NVO_wiKr`s>R`Ii-{dcci8r|)Tq zX~z@2F2)mQk1r{AT=ywxs;+laqLT9IqJW9|To(3UB6^@7EdGOaTtPYDLI&OE{QXvq^n$!?+SQ%XInM4A&; zK2uGu%Fw;|v*5c}OWei8Q(L>Fug&yW(j1|3$?gN=gESH44^o_`ir2lf{mRkc-nF81 z%KfU$t-pL^_Gc1XE$@eKQzwh0SFs;0Xt-Oo=UcOtu zcJ5KXBxARPySH`3m#pgC_HJ#n#)RumCbKq#&&(<;(qCM&Meo=xoh1Tmc8S(9Hf#)E zFUEBxZ|V75TZS!3i%mDq-q!J^zpIi-=eWMo@!t%hsyyruroUvg-t%MbrJn7(7Tnj5 zdle)fe6=fTMUe2CK$(`tK#4W8R%V%|CMd4SsO}MEcd*`cB6Zt4u_{*Pp1SI1H|8p> zkT@`Vj+J+oW!Hk#I{5_e0}GuVEPukHsBdKGy(a8($6*^=ojT6mMJqn;ydSuxGWBb~ z^t~r)1LO2_8AF@znf_XFe$Bu7-xAhkI|^p6)K+9-NGY0`Ix*_!gUhXMQ=0;lt&V?M zd7t^2K!YgL|3n7Q(WHYpq;OUkaA8#&PmC6*Nvwa%ebVq|(>H z#^B>uJK47M_Wm!dOdICDHpx;&h zl5T;?3(Z;@LFavLr7HS$-c5L^HVRI z$3407xFPar{)_oJ`VP5wSU!BsXD{2~aO}^9$JtM|@bq7NBevRVs^g)fA1_6;ubQ#X z#dZC*fDjkmoRHoymNOkkUL@T-!g)gbQ~!jej0`<~y;qM%{9rem8Z)W$qW>f2_TLOs zOQjp^-}_CdS+;YN%`PMD?oF5CAI(pDSfd$Qdp^j~XTtZ&npmT=$0H_$H3Us;UiFPP zT6VizQAeX_z&S1D1KM+nl9`X)$jdul7qr=sd-}1mkJX>PGCtcRSmDmPZkO#8H_^q0 z5C250o_p!)u65iKS1k(H^ObB*lvua=utACI)hS=&R%x4Vk)6e4B&u^z$pqTc_*})a}z+bLohkx%`4vOBgHM8TB$Itv}iKB};o=gz_$#tXR(1 z-Fd=neA6yGN-~OBzfRRBG;pfdS}nda7y5dd4GP!;)`S)cX!q$b^d!AL)0cVpv3bAU z)n%L=vGxUT`8R}xaol0w@WxtllH}{lnp|g9WwXP$0{2|`yL-o*iK(^6wnXO4=U-p_ zI)4BBpIz@Be}1)MbN54I>(_fPU*uxCYm*V?wl1%OX-iTlv(+>9=Xvov%b0dev@f{( zd$!MNm7GMr1HU(`teo=dS*qybz$(l4;j4bENW8N6$~!09-8!|A*W_5gq(*CNY!y`N znfNwz!K%;K@|$_qWStebarjQb_o&U=W=%ZziM#r{TInX!4O5SBD3tGuzvRA_ORDr_ zmMPz>6_bJjTdqAUSRwiY)^xMn{#a)aM*=jMLPw0791%^6UT%RPH%o@ldyoezxN*II z-f3=F`s~SXjx}|a;xl{yZn_?Rt95eUjZ??(+>~RGoa4lBA+Blu)LDfA!crCDD|MV% z-T36?3q=xietlI?c=M}bj&9d3t?SDejuhp7SIWzKH}|e~IPdYtj-fL*|J_(OSGb*p zKbV6-LikKXpaGxY_C)uI*1az4vIR0b+~-LgyQ_aQuvsN3_=Be(gN>IdTa1=@eR-w} zgFsN^p0Df?oE#hpAEKAF94*d1Tl#3JXQ`;`dW|h{@ftfq!tF$+hlH<+x@Ez0*uc!o z+`K7yiNo(=p>I;R*1EsB;n5|?P-14dbnDx!U03y7)F!ieZEAlLy!(lKg4l!&5;Z1` z$*Hx;Npf91 zWve9Xl&IJzM!9E`&*g{Cp1ZV6d4Kx3_pB#28^|>5X8M!#)K+=JJ&CgoUbbuJ%3sZj zT*vjsYg+nhxuDP^)3(k~Z#P=ivMDW6tGd0*I3-sgw)bvW#9k4GDMhK%Kdz40_51dk zLp({w!k;Vc8`6yw8T8&VPCgVa!mc0SyY-HW#nLC@pQZ2#vbUiBX?gEE%=3b#H5z|}~CVAc9Y1M8Jg$y=0bRz~Eq!<_& z)Lu54YlVckx&?&<1qJ<&_#ftE@8RYW5AC1vW1 zIe#boV~TxyAuFg$@ckF@k_x*6X6G1o_&m65&docwuz&vHKOye_Kk9^T3@TeK6*^(* zw?!dE%e;HT+QSYgDaUE zv#b0!Q%)kwfk!GE?yXNde`ey0KU>x=4KuzO&vj8LaHe|b%~N5Et8CK(yLWB-D%D}? zB6arZfrmdR+ry=X)1i;_8;Y+=f5&;nmyk~a@1qWSS)mpSIapj>b z-l(Tb>{^PZytAlyeYpDgT+a=ga^hcnJ6*!y5_U63IsT9L&lN#=ZykL8H2-YTKQK*G zrr|crGovZyaYFqYwcoNA)fN7|pso0H)z^*{b5^=txpM2&);}*|yaZoH&fE0SV_Vez zmiU1Ry*H{PH!XZr*7d(MOYjC4!WYxWvm5X*j&7q~fS^-3MVE!uCR zwzhL!n^v0O%Fgm|(-qByoSeR%TnC~qas@NqTIHL|XR~2%;D`RR(+W8sG46ZtpO@i+ zbzR2S=trAwdME!{n;Wq;QeE++i8lj7LkG`k5zU45sXsSc+Mh8Fet&(t{=4+G;$QoX zg{Lh)yECo#)V71YrShMC`)_(ZTZ`lFy4!DG#2Os^W<7KJhP#pHqqTO{X358G>00wD z%XP{wk<4pT^uz+w?<9K#NZa;IBSO#dz88Z*6aVr-$&~{3{nR!E9aNQWnX^ zmq!>2102_An8-G`giDoc$}n3T272_mgUE}s2^2o zRXdcCxNtY~8lk;v-l57aGQDrki7XK{O74FBD0Jt#8%1)=N`@@Q7OZ1Az$o;%GwQ8~ z+Pz4YZD(28c=$FOoHmJ7XMf=*{$$SUvckx7i&nIiE!Zg5d1*EeL&C3}zSV1z~6n*8kUY*C&U>xa<)kTn;#C6EuTDyRyLa*1z|$!cZ(U2(waR{ax4^&rqloN^>(y&GQlmo>L+`KF-Zz7V z?HA8Er2^e8S%;=E&EBy{$s_OE4*lf9X0b&lT$NaRBm;b=Rm~7oW}lc-ZPT^m+qPNL zma;Xh`x4Ts#d<@8#c0j4)F&pHS4{;%7FdW_7)0%IFI9D!V031KMT8ZnZ4g_Fp`oOv zS39fD5e_Rp!Hk8A4%|pl*l(op@S^~Ssj*V(q?kuaj*J}2KFe$ww6-@s+qpnCGUc5p zBg6KXysg^v1ogHH3&fUhTRm~@YLVS3j~8tdIcK(__}ikyyVqxKOg(&VL-6fCi?`=} zj=1_Qy5i*G|2OvW^t~(hwqdAAYi;G;{3g%hzxSF88flk>``$BK_-Ha*|K@PB>Ef^K zXWs*MTvN{Njxd_kqO@tY!r>z`<7UoFs(R!SvbMr$p%Sz5oS?!biRP8n7H?Kf4QY)0 z)p+*f&b5=DPRQvqWO(=E*nPR5>z1X+ENyBE5MY@ra7rNSXz1mIH4lnxo;|%Jyoz&A z-_?6tHeS3gRKw}J`PbCdr_W8^Kh36U)-z_2Il(Lr+42@E6Iwo`{I^M3Y7=Nuw_IK8 z?l}vC$>ozUf)s#7G^^1ZxpD9mMchoO^WcI%3}Sq_2R5j^#bd-AT{^L&5) zm&5OuXPXW`?0vnwqQIQLVd^4|hQP+_MVT$k3)2ss4qWkOf!8!qt!btft99M0gN5%c zz4hzjmG}MgxZ@8phr}hPY)foD~Ts7}@kalRV#pfkzaV2)KM#sNNUDxO;stulyQZI2k%0=*2 z10%zfw8n>9b{oj#%#PIMxTMIlxwgSKBBJ|1FY}B!cGh7Ut?rC9vb7I|PO=2PNLf04rp%GA=i&rKdqWHT8Df$WnZMadJ^mS9=E(l?j+fP~ z+J+e2$klu459Kty}uez)Rzv*q^A)roFP3O!ppq-&u9pKlGLO)=ICiQyY(; zGVT6!ByQqfp3`ynC1j%tORj_%Sx;bKV0c{=ZQ>N9{zZ~4{k@2!Pk*@7n|r&`A8ya# zH~O_;^T&^=HxkyH^`_pwr`IeRJJl#pKPIkeyK=LVHdk{g6PwZ#7LhWAja~}8p30Ux zZZWJdo*5vS=$zmr+R!Y}va;o3*M=>M7qyH<*Dea#wZ_+W+L^YkQX)+WNmh+UPlQf! zSZ?y&7$E}pyt3`A{*Glvc0Jy{?e7 z=uT<3V({u)CShy}Pg54XF)cEl&{|bB>)gv|SKT!;-E{imicB_riOJc|)^OMQ%7mz-*LvVCltmHgU^c}ZL7X%nX|f+N zt220G&yecJ$e>&0Fs=5_Vo!}97>=rbFA zr$*IOh5`%G>=zB}bIKkjbj|zmHGt)Px`@ikle6#jZT^omrgyD2;`!wMhj+R4E9NzAh79ky65>>*GU~T-uKBI<`N_}4SDH2Su2e16F)EGP z@=H|lbdf;!sufbUZ71Ka=eM|b_4l9}bT zd>h}}&!$t>-cns0iws$ zUW=7sKVzw$=WI1EXHHrZv2IzBX&2MgrQ3M@zE6tNc;p_Kn6l9|V|f;1 zli)c42GMN&zV4+nul@1`v`fvZsw%f? z?Je0+`_bA@r;U9=wjyIFcay?R=74)9%nI#W7M+i+HO}4Yp|EbXA@hZ+&dWFQPB@*u zNc;Ku>+TPASs7H$P7=u6uHz}7;LtMV37gi`bw4&;pTTc1@y8(#H?|LVxA(f8+xG3# zAx;H`l&VUmZx7nb*PPPna}clDalDct$JLNwzVU%GjR$>AV|w3&$L-GXoaN4VJ#O-x zH>y!a0Si`K)ik`q`te8g_hS!VPMpMTBgL&W^O=(lkM_cOJg?N`*2p&maXB--aA$bO za-3H$a79g^z{;G^1KW(#Im1dVR~^ut84$E@cGHJlXP15|nf_fxZb{f#wF%x^JMR1q zdA;JvhTB=8PyX&N&0c-eBibvE;fVC_+U%>3Z8X2R`Ykrhc71!XU&J^tw0A|2tjh&G z)!_9jrM;h-Z}iS~Uox55vByz|jiDuPC9A|k{mv&VO}kiygB}(-A3R>kxJ~IWM-20d zbzp#5z zznvka=_qG^p1A$zo4G};GvBSQy|ZlbUHyd1Cr=3cSlO`d?lLweSDs|o)!~|Ax|=e# zRE4TlukPULj}p~7wKF-8W9CZjY_Y$4jd$%n=YQwTd%t}=E>(%wA6)3?Hq1fFh7X*crb}~GP}qLSFsk2X&0AT-BezG$wRO%s7>pHPV1_RTB0jUd`<=F zEDvZptlNKXM|mJ~piE?-n<2B*o}}w+m*(zw5ENN`=~_d~WAhR<`*`a>mlHXHCIUZ- zt)4u~{&rn?_K~AE%oC1few=i*CMziM%END)3x3R>yza;Evu92}KmIgmCAWJ}?rWh0 z*;QK@G`Y_d9X?a7^Y-k#_%-G_FLs&sSMU4nwl{K8STiSc!QMZf$7Hq#mddSNrIa1K z;o5f*SKTmOsiScxH7ZUihi<*@Ex+$3SHSl&`@=uo#Qg6w%&9xvdC>o5woc&_o${CCVD zX0^{Oa{Fo#6}`dx##gOr<{vMy*mzycJAUie{RJ}~=&;`AJ#y(k^q(elX7OZ`Jdf~KPQ<$zj+h(J&IKaK?pXBy`R!0ju3YO;I zT4*=@`$EPmRiBScz5M57XA(m(_dF}bw@?3ly#vJmSF|#H!=@H}=X!JMlADFu=_iavvvn`a9O0OB znuLuV(I)R8wzH+p9UDEL)l<9Gm4S(3dsss)k=sfTX9#nk~G0laBQS8m<$FOy=Cf z#o*~2rBx8LP&{N=qd-+b$1&{#I^O1`TwN{-oRJr&sOrCadG$!djY4T>=kGpRjGVf* zMa$HWO*UhAyd>wi#D-PZ4k)^@3G7|6#6?(f*I)6=8NrO1$71^#O%`8WclAe4R{{%b z0;j3c^qsSW>IsycfPvOX|}36G;}kAHRsZ#>Sx0x^BMX2D7=&Txa4$EbN}t zsS0TBtZFDQ^V@Up;`%V}V~Ppf0e2K{f6hB066ZJPkjm3`M#zXm!*;}ogERvJ!?Cm9 zTU0%K+?~Dr!vdULLPCQ7NB?*HZ}#8rzn`O1P+;(X|Nr{`ee66PUD8&%n0%D6OI`TQ zwJMQq&8PO2JMtO%`V1NNA7`EM-!b~Fw3Lc}dfD?M4@32y)T}GB<9l>*!po{q{zo?# z8#F95ZH&F%*)Pgq61H+#-_JGst6l7pCUKiDSp8EeDkq?hA+%MKp*ueOz}`n4XBOGb zw_5YcOF7o@_{{EY_51JNR$7%Z-6m?8RcaDnzN77*JFna3F|@1Hq@6r7WzPw7kw&?z zZ5}*@o$<%+?UZXUI4sei%6;Lp;;s|Zuc)tGwes)3V9|}czCL;4{e3Tsmq_XK;;7!8Vrj|Syz`^-%=HH?9EGQ z31FTO{B71L(PamulJ!NnLT9hP8#UwAVR3mD{wrmd6O)eDEL}3=!H&Dy(Vs$C2_-u7g z`P9x_z;{*}9I?*^Zv> zOns@*(X?rcX-Kg70$*>Vo)>>we(A_w-RWz!g(H2}Q-+!}+j6CqyMDXhdj5M&)wew? z`SrJs*EZ;GVLf2|so}Hzm*lW-FVt3+t_ZrS+Z1+xk(RDgZs`5yMZ3Rh{VKVZ^;-1x z%!}PxD;9idvY+NxHH5Od?%3-x~vDhlF6JB1qca!{kPArW{T_&|4AgZxga@)mF zhACke6{qj%oi=4&rTyv@X5 z%+=}`o%^w=SWa^?i}336b6URoS?1n*zH9m7*r_*oPJjOMQMe}QDnpt$|GM9rro1yu z<@4lT#4zorUp3vcz+%KEA}IifJ7Qh3v6o&)@C2zkaXp_3J*fBWHi?`c_eKcAcNx?+}^j?W;|{{r=sjDSG&y#I{ot zJd)13Tr?EhUU+KNZmlFn-&U=Q3mBrdtFP<%pz$b+Vanc33a*;VkADfuGF0o(Ud!k* zN3bK)!GYzqp+wh;7an0=4F(3)swPVl1j00YmAW}YcZKNi+&Z*DYvR;irl~!*%(h0g zRtbbgX=iS5W%XRbp!<$zZYYabcj&fj0&dr|s_$%MbYU@V5?XZKP1*X0UT`wwU5CpI zK1QxF+$INNJa;C0O_;D(dRN3(5vgg9I$o}6OWU=sEB<{{`P;>JuJqryaYIJJb%#oz z-JF0;x^vW}KRWHZmG+&9#ifD8Lx@`DAo9W5GU|^*eAuBxR-0v0d?+QLXv+nLT_I*)j zMBdl3+S|vzoN+Ej?ECGU?>`^kZru|b|L@f1GQJ$%`@0|TMFa->`TB0%#}V1;)zo+T z?nB;J4lLgMjSh^A6W6Tx=p=bB%v+`{>Q)<w)0)Oqi@hkifbH2Lo5s}k-)9v;8H9$R|2 z`fs)!`!SC@`iyaRY_G{3VYhgoeJ}61*c0{}5B6?dw!i5{qqqNo7b_-jyE;o#RrbgX zP6mbpOa4xdw#-=RTEFn;lDKEn5BK%Gc`})^ugEyf?b83BrHAJA9%G%q=9Ovnnk(+d zE6?BSsGVG@cRJuo$kbJ59_40eee%-e-7Y*ea>0^4;R~5gDl_>nd$wZ98qt-<6&f5R zCoAzCN{C%hm7=q0)dj1KEXt=dl#*Ezm3_|fZVl;`;_^*9DHy>xBjXfruwcZA$r9{e zc7-ae;FDkw5Ee}oK2oM2vv^U!!(&X&4s%#6yw7c!6a4y_G1J8jn>qI~w@f_sj@8-4 zF}Ri2yrs-2l0mBVWQgvP!y(-z3vN$nVOV-;o~B5VR&hy?HCf_noKvhIF^UZ^tz&6Ssc4 zS~=&g-|_1KoX#`9?F^jDweZ-w-4myE%5fKIz12`@Jt(T?aEs&1sYN?dzIz>SI`m3d zU+VXTb*F_qf<9_V%CJV;#29Xtg`c-8Ud}LJN)o#hky|OIENrt$b?cTU zM%S%IilP^1<`wOS9< z84s*7ofbB+UW%dS-|LfGuWvrb>wn*Bb>R##xiHrbQhV(+Ik_t;0P+^7E>cg&tA*^B9^> znoY_+Byh4p+aSPjlIubxu0;;xJKYWN64I2r{c65cPAh1d~rZjC$U^KxuqkRIeV!g?}^1%izHUK zbc8w2X?T}s5@{Uvgzs4QotL|2>`TfI>{zuq+`zU?_yvPNW<%v?h5OnjX~GN{^Zk0` zzs@QTV%V}E>aErO2{pVt6I<8J|I4M4v)-)1f}zIjD9;%uo&OUShHPx!(mlIu-R*h% zbd@+-G*>d*iThdJDrzC3_+HgpW7UL0YcZt>Ycm+nUR^egnPr~SoO_2IcCv?5tz^4& zs`>G>BG0LZb-swP$=;E7h;&q7_$TfVccUUyLu4brLAZ~yI0nSP6XO4;Q@g6feL|AO+?W_7b$FS@(C^wqYg4OwkW2J2&_?6OT47QXDi z6Mpo?RiUkV(N``z&urdwGWY1iIefpDoID}jl^kCmzv6_i@a>9?7e1f8FT#)#S1MU@ z_RoV4!7D9ZIGf$*FRPSKxGdbn@u!D*&yR$|Myqz5+a1-rBFZGl(a}UoS}S!`wqWqo zkZT=*w-$=#L7j}o~DhR7}uF9AiYOt_NOFNP^TC4rul0|dAW^Gk6mReC> zevc_~wa&E@jf_#N)^5CRvzw!$dE?UC(~j{Rc0CYmbnG7k!>LnomQy1;%_P^|VN5>f zIr~yrZ0!oe-6{+W4f?Uic#qs{Zu#l_qE_F$U_xR4rZ3{RvlOnbD2lrBzGQFp^&9^@ znu}lVvC%wl=r#M)wyRHHIKIt!%&FydAt^Ob_ciO?&8a;d8yOd5Njvy7hD>#R>=4$K z;A$Vqu;Z+bS5`KIgsXBxO~S(8ENXV#o{S{sz{Y2x-6lLhi^Et_|*R_ZF#%Rl?%yvwp3b=EHqiu<4Ixi@!e zfkd=WbdXW%gkD_{i}y8gRm)lA7B>X)L`WpM+b#WKaVL!X%FfOR)(5Q2{kIyK?p4qI zEppKPWkJXX>3#D)OH7qdX#RiKW!r&ghwkyIKiU#_S%-V-8BlMuVsBXYtK~^k&z`!r zmTj-1^6Z%Nak-0L&Gg%zcI}1r+oXv%J8s{5tG4=W%F2nA)inweZNv|)GnLuhqc7&Y zLxdw$Ayh)j=j0Kk1x&6D2MTqPHP&RkZ4qH)^7Jrj?R{F9!OT{2XUVSpPk(Lh=-8wq z_(g1kly#B8P46HNEuSCjS{*w4SRb$`nh5mwwmfoCU?^W3t+kUgXR@vLWXYRs+(*BO zOl+CKXT4K9D55b_m&386q%iPyVfF6mPv864#LU;UXPtf;JX-OT;=t~wVUUR8nQG&M$sigijX zGZlWC#ufMQFSgxN{L4?ZMNK!?X489*jjF#}pHBXxZ4_n9msGmpxYLtA|G1y*{U@|M zD)io23z0<|SBYE+>%O3zs<>-g^+Ex*4FS;%+s&p$O_&tm5T5@G-7O=skNbJqmFx^U{b=ptuGRNm{0KNGznyHS=OrH&DX#r0<*X#ExJ0((JL)X;?}NzI^F_2OI}Ds-PjZH z)%@**HS9*l^}Ypy)7^>^Vg{pM|3~)@|~qmy&5YPOVF# z>!kD1__JrZLS9)$`A5c?S|>b)5g{ ztxYMBoW75@g*N(rP+B#eRsAJH`7DFwWvhQa&z;pjGeK4ZI{xqwG5#RKz`*e2{q_|q zo*@CgfkEN^;lV*c!6APC9sb+=_y2GD-{HUWf7|~auJ+EMzBNTxS(2ppKQL~K`^ojm z)#h7qUBf0#wg-t%lj+*S5QDW?C$E0g>#;ii!RSu>+8bwaP# z-lU|tevBcmuA6oV-Q6`U!a5|`8o z^}o8yr_A}qe1+*8!w(^*Z8yI6oMxJC4MguZ0Sq;M=+?SYmyb(|YfT z4hy_be_FF~lL1Shz{zb(n<^Q4nhu_MC{b@vcV^+H9a)OgQu|)o$R`M{;&@;_k@LD# z*IakM7tgG^F2A@E<#JJH;u_a$J-aqFEqFAcVClAy?xuB|kNeJh$mYKFS+<1L`}NBP zh2uSr+{c)XOgj0-NxaSA_jTQMYECoc&%9%eh&ZJ5p^v5S*Ml9Bw@ykeT6|T&S%-P8 z(ltXa&8X-=i?rCap`mMK9R(b&oYI(Z#W$zD?{Iy8{K~ML+gw{Ftu@{lUAW-Zyt>|p zTXT;%Z2iq39caxki*?680WPJRuMXWw)DQa=6et?HxkD=}dW%;l_u3t6Csc(lj*i#- z^(>bqNNbmAwrP}a(}$Z!g0z+fU0mJ7%CIJFZm^;E|5HnM-`=8ik|$TwZc|CQyu;?R zY!5av$Q8v;>#*rx6RGLt6}^3?`ckW77u+M0y5&N*W*iCeQS>^RDwwiY$x16L`cU`f zHol&{OBj?GrgWXX=Nf`h%yd`mUb<%4Bau=~xze|PZ*JUjB(v~OH{Y}LJNNotHt`>s^m>`{xySjJ z+57U&Djl98|MBM?`2_7wh6pQji)WeVXT5gca?fVo`B#^NZNKgc-o9@~(T&8nT$)R+ zdab;=_N>wrMH_v?UDxLKbV%xYDgE4T#CW9dwU)BkN9UKFo3BVIx3<hdVdZ_nZx|DNDCF!WYr*f))Fo_2AG)X@Tor2<=v z)<@0GUs@JAEpD1#eAi{6E0OQ-eRcCY-OKa)+s#?cEc3r?DEsl`h?$@p4?|De&qXU@ zXYt3ReUlb@V)Bx?{4-O?6hj97_Y7Wl=7fkn{luW0{OL~e(yX3Usj0l$&i&I1LT^-6 z^ILzA!QF1!k{5Iqhd%VoI1{vZ3;V(@x2zPUyhU-Rg89PdY&0%T>+O^ly!}fx z+g-0IC9>0}Z6c45*fbWGw=P-}y0n6H0yc?AiAxAC$jF%;q+lGvnw4;c)8b6T1-$_0 zWYtC%jW$kamU$~Dl(D2Z^gVIY=b1E9x5K)><+4)aoII8r^HhvyoZLMtWtH#Q5Sd#B zZ!aWENIDrVs$xB`jAx0G!zLf2w5REUhfiH)ohvD8X?fVgOL5v9fy+KkjY`6;%nn)` zr5CntJafil(UiVV6-mrI$9BAAc9`|+xaOq}v+q$22Tp6Xt)Kkzj9NIOT}|vY)enu2 z*zOyAi+HBsen7hB``o=@4Rd+Ey2pA~H7^Y1~YT)285Gy*@^R+a%@WAsm3|;x04HjFa)TBGU zoONPmxV#{0%F)@9yJyDQEwXjFw{7Db)eGk&7#L>ANIuB>&Xml+uy&R29G|6Zv)IE5 zXRcx5VPFtpm}forwZtFx84v#Mowt|$BO~9BySsA!Cq!5q%~-s7?azf_!Bc&9`vfvD z9O=FPHn+V$-)8pe^&i93Uft}OpSdA+_5OAD%(k9B_u}u>;PkIS7hi{HNB!OOV(sqI z^ICVFJB6xpU%b#gow0N>Yltk{jjt&u4cC~wTA{9?sKZkDhGTYOQci-~m!Q~J0(TZ2 z&sN{$yEU7-)|#cutkje%&FZLY#=xa8IcvJt^H~pfPO)3-KL7JO zzl(2|Sufr$b>>V1i4U69i-!^3G+-p4P@Ns?i%+}+K0?LdG5-N@=49sg5RO&l0UUyVyP-fV|yl>6k z9@}2|2Mzj>)!z)=|1hxEY=4_CpQw87n4a6-{xsRd#8s1Kf=2c3Y@c;Dq*nBO_~Ka- ze)})Vzn@dWo1Y$C?B>{`>G^(}{qywO$-j544Saj|-iqV3x?eVBYfW9RlO-bfY(ql# zW>H@e!BlgpQVkW?Sx4gp8kaJZDxYmqy_Iy4DT&D?OQ6?-rORl8%cV8>0*e&5lpa_) ztmjh@GI@8}GPr)GWt`>&F-12vZe5lIr(6_71QQa1E-as-@>^ZN_w-_mnMb*WqNcJ2 zniw%9eaZ0Hc<;nSRz^+%jtvP09G<=^cS?o$e(Ycpy3({F^U7(p;Gb!VMzR*_jdF=k zcxUWB!l3Zk^jxHeoY`}Yl`|i)E!)%StFTJaxv617{<3p{7 z=#-`f?Rvk@eS>A^1O*f2K)DMgy2_^+;!;XyWS?IZsD0$M(cP;|=Z$>V7i~yO>)<)5 z#jwmX<%QLgn7P;7R!qE9ss8qrpiD&Gg1z#lK%&5cE6qak>o?X|K7WwEu1LX#d9F9`o^p1z-xUQR%mr^^k!gS2>AQ_ zbb5ZTmq5s?qTFdmjvRb>utg{Kv2RfKm04G(P7Gaq<dC!LC52ynDqbiLseD|^qXMGe~o7Aq)dlyqtZ&gwXq$d#mE&=hgGOh<;8APnZm-sVkuHoIc4|n2`_cU_!1Y~O3ZfSII$!y zZ_PZGcWwQ*Tq^@uT5OYSrsf!OFMXAkU0!CLS8p(PQ>aT$@ts>PANU{Z`kahkR_wO< z#8r!++TE*b-31zYMU*{MmNINx)tkrnh^bEDli$WTf5)B%bC-Mk3=2+ZxCAcOSR{}r zz4mJPkA;E3CzE&>7#gIa*#ucWg@&D-+js0>nYPgRIpGn?ye5qzyX8!)I zGQm=kR}Or+6J^rdk|EM7!Wyy7Rrc!YO|Fab8mC-d$`iV1;>$j(009lIf-AwAXITWA zWXsmCTIxPUVFHtngwVHy>+TWna@V|6s8K$CN2gF=sp--klP4voO%R{p6;OD4LB@$y z7dGaqun0Q3q^PQu8L_m5RZVp8Z8|eU)aO{B&)U#8VqI33jhr7OG)RXYNSNt1^NM<8 zSJtwbSrLqv9;jqS%`ChYu=88y#jjy!Z%<}_Xj1f?_rRw+JF{aVwHkBQX6dIb44w4! zR$9r~Z+Ggi`-Z=_e*Pq3YUA?^c9SbS7hL94Oh0hTHuKu=PL7~S;omdv#Z8yhWn2?C zQFKk|AF)d>)7xC_y-P+!)17RY}2GP^Cw=9TPixOSq>9b|U#Wf3KgBQv^ zzH#;Ni?jJ(>keo>+ji-02@~s-xPwej+FD+3P5a67riuA`_3JA#;zkkXM;UmwrCzRj z@KAvDs4O8yAr+tTxM&n4a$dHETK z{xK{p(PCU7JmFr8s@tqdk?U99Xlgmds?Fn|Eimnt;+f=mQTj83q}G?VGWmY z6L*t2q}6`eXYZ|>tP5JD-{s0Dc$YGN&~ez$@u+#}Wi7Rmsohhv;-`P!Aky7+>eqI* z+=r+4`7|b9JA1vNV{ZN#^-TS8J$~Q29d2D+T>(=P!lK!wr_8&^b7{Iw!G@(>j%?pj zCpjqnWjwQu<-vBQ73=xq@4aVQ6WbmZYO*!dCH`pdJrI`CbQ#@31R z-=uEUm~a1f`Sk3U$M(nu?X!=w)7yL|`vX(wQSY7$UOySO6kW|)yNWnf;M+W zEYY9x={KX(b^(!w*S)G!_CA#Ce_|7oAC|g(3&#_-$j%-P4ZhfO(n%?u^Uid0TzmIu z(E*)ZiOdWw(|lPo58qEP!;NJe4fB_JfB3)KdgcV*2F^(*9VYU2 z`v$MQ#K-(6EAlO?gW=`A7@?c*mn?CuW0=zCTR!RL)8%KXZ=KW2{&Yf1PUau`4K)Xb zgq;xw_5J>9-BkbmG&Jk{_6Xx&S+W~fXsz1XtMqFT$CK!-t8RNMD=lJ7>zjI1wMe-^ z_IBF=mX@|erpm4SY2~k;au)cp^L>+FaPvtD!=BHqHzr!^MtsZk@Q+;G6?UZHb!Aq- z?hvuPTJsoWd=gS+EFxHoL{8bdT-zFT^+cc)`l!>S*}ti`%qX71AcDFftUR%n1@|tlqCUd&W1rHhGJuhxeBJw)rwk z`LO4b)fX42b;`_1yRtFQ&~0DIYq|3tZD-boPfr6tbTQpk+~^&N>ls_w}ROl8FnAo`bUa2Z7J6*9u{d??MJ3`0a}oTULads)4o*By3Ha zFOiep+}k^U(-odqdunc2y!KqPsBLO-N`G9+26J}FKyCq91Fc2NM6GqgxI51xhy zWNdA{qwHkBF+tIbfqzkSY?kG!e`~5aG(sl6d>LKH-LY)%!St|Z-zghx&Q3LPJoL@O zU1quYy0YV!b{bbRUS4d-)W&{S^n=)Q**(q%3{37!d*A*3-R%FHyL)<%{js3!=C%Ci zEm@~ol@|7VtXFBOj#3bP{a8fXPUxiY&HtZk{{Bq)yZBq?t*OF6VO54nR|BV|s%^XY zP&vy_$t^@RSkIGzfgz?oCVAHS`-_&gz5h0+eL?f}u(0{2x0O}y_59W7c8y*u+k3?- z{CIZRlxe13(-mhO&GcRoVY1?STuR!ZB_2}N9rLbAuKBWt?LcmXRqjTsE?0*_R>AC$ z2};JRHffklI>dJ5%8J-lnIkM~PUtX8JYf{SYw` zunBB(UO823_o_6F00*;%tyU?5D`vgR+T`(%$w^;1han=vQt(Qdf~iE*oZbLz#-S$2P~PAk@1;j>I5$xKrH6kE`Ntcu2so#KA3r}DJ# zU5&}{-5lqi%{(dVa@T9d&v^n2g2xjWZsfN+J`|~Gy6MuMy;c9rH8$y8Pp8fu6~Zs?p=TQ zW4$+DPhFu~XKv+(&2#H2A34XIiEa5_-@rL-153hB(TK;+ezzyKwJz$=&@<6!T@e*3 zJ3Uq;^r=o);+n5bVWH9A^8QBooiS0HuFw(m;dldw3-gtx)$zlBpWL_hq*- z*VB9N@Ao>bFzM#}wy39tEk}KSx!YR6=_wvv2^JwXT_^s1rH~MKC9Rh&K_j)de<&y#p7lf7xNTF zdwE!6#59u`&idud|7+AyG`sy`$&V-c2Uvvpf)31P_-p2;EwJRUVn?ItF*3Vqe}Xmw2Nt zes4a0Cg|dlnwe%n7sX9emOP6IVA|7k{D}Nh%bEqpL)Jdp!JeespZoq5^OISE41XD{ zyp=72o}HRkzE+xZeJHE1hMfe@?W&yKRYw->`s!%icYR@O=k#AG%E2K=UG?G`ZzL?{ zThn!t>rc+VmZ#|wkrzvzn%}v~pRl%v@rS5T#qm3DEcG4+>i-H{vs7klR^ZwT+FKWI z`10vOkJ>KRn2x1uUcb7!?xl6cOamhcr9^2PK87QG%UMp{tv6ntC3?Q`%16=t{i$CW zw+Sp`Fk#wpO2g&2mEP3TE6!{U5DC4g#D6MyW!~|{p&=9NCY7$PT3e^+<~IFItya{A z3v2j}W(%^Fv9HNmJ9(?X)A$2-=cKKj=&JmdU+Qj6!zRCJ3<|fH!}qwXk=-Jb(H9;2 zI&!U7R$zd$$b%a!jWWls326jJgnD1hShC_&Uf`Ca*0=dw*YBxTU*h+Xp;Vjay5`(N zd?lJZ*LMkDev+bcJBFiXd7-rF>6zIJSCy{Slwadm>a{9#b(p|b?p((QtHNZa>^gO_ za#KpLr`KYG0%?xc?oAt3zfL;s#CRm>GuJ0K`x{Zm&LutPoYA_Y(0XzH)@3?EQ`wu9 zAN+a2)~q3#zcDDQSEM-7h0{xT{fY=J;a9z{PF=0(p1ojO&gzc-)9d*|R*J^9u6h++ z-^X>CsU+^A;IXy81XP)(B=ALxU1}kjOxA+Uui+vKUalL z9Nijqg|9nq>x!km0s&l)1G;2SIw!0=ysiIRGlQ$bO&y6lU58&O#J}~oc$QB|Wvx7G7dMOaPVp(ML~#HOP)>6#XugymysX=EjQ9 zDLN0Y9;=DJ$TD}PGN-9V7lYN3D9J0Wjeo_JR(?y~+4iF)#$@W^mk0L$56xfg;}hUu z!SJJO*D~EJS3;au3yah~>o7k?cTx+5y6T7?{+@n)+<6sK?M{(3L8}9gUUiDl%xOP0 zt?SlWkCofgdZrp^Wb=j@Ogx&jP(faawuJXj9IU_JaNL z34uWj4f#F~4)HqwVqr;$-kep^o0_{J=*TJ#sp%ex3e}-5VbeG6d$aQS2`To}oso|} zDa|RI>^^z1gyfZ`+s}GxCkJ2JGF$ZeVV%D!Y`024(`+mb_6?TP_vU0BWz8;mm%4J* zYMH%tGHb%h7V0d2-udgZ)^4|ILGexPr&sUOS+n)(F;>M*Lh<)-jolxQpFOq3J)-}~LXWZs zQ5~^82M-@{5t(6 zsOPOpUb=W9YfQ+iBijVKCW&flOxvJfQm{>n>4fB}D1Drk-Gsl*8*f{wN!)aaKT^l;%ynBrR#|J`#V!*S zW6%Z6PJUJa^Kad_emv2qYISYI&sEKS$HVVx7DuM_nfOjVpBgv+j?s<6n|H5Xm3;Nd zQ`=AVO2pdIm#%4=rBSt3V$1w>Ij%79MQmoXIv+eOb%RStSirSh1)aza&YY>D%hV=J zU&E_~ z9T3XBncChkp=fpQB)^L;vZqqtyi(a@%n>w{^Sa$mIg_w88UOc~MCTFh76q6TTeCpJ*n$I6K7jBGjs8Dna zxY62T_$5NYb9>~4e6J<%{UgtRt>xTub>fW`tN*a=QEX%kn`K(pC#d{jTFd|Ruw8~9 z81g^-W@I>{b$#itsUBO7+C{~y=hj|XHEG6C2?mCQoL@&DYk5@vU8lC@#kaZtH^t}w ze0yT|{EzxSJ<`Q_gWSHlt~|GV`W>Ukt9WMSWSs33l`c_XetPMp0B6WuB~jm|zDrk& zf^2P%1vlR1igfaA?+MO~xaN9D(BqI7ON#=BaI#3Vn`i>(k%$Fct-Tqs+)E$iHE4(j zMRXTxGZ;?0BgwgP>9I*_C;4Jxy+ws@s7>Es@PJ_nE9WhNHnFm`i9vEw$vb7Nmc`^r zO<>?yV$}1tKsRUV>IN=dh8zaQN8OC#2YD8Y922-38IZlw#B%2TQ+l&nPDb(YRvr!u zyg03IxtbBP#pJMc>*P*2=$=_)%qGR~;)KfLj=8a$E7NTor!Cs*xMPvh$20rq)~m7p zD7KsZ^zwfWpLUOZuJam;m{g+nN}h22xncD=o$XDVGURtw|I~LVNH$`qd&Q9T_IC0y z-rk?rHFa$acZZ&{IKY;@=Bdr9=`QOyHf<6<#&~??X;oh4nz)lpC67MXJyjKbc|g4M zX0{!}HchsKopuJfi~004H8-4idf{D=JGaG?lNOn!VXgNKwuN7|*zfzNb*7Wx$+f*Q z-xu>kha3zLLk@Bb3=BL%7ktzloSmFq0t5eB{5Ss}859y3<{umz;Pc<@f3Q2~AW5J9 z?qLBzVN3c7%O!WtoPWxC-+2Sm(|YDVKlJ@)p1{7Gqd}c*!qPo)#*8i5ce4*n`*zIs z_=jC$ilWU)o3-~{OLC3Wc7D5!X--xp>!U;N5_5M8b5Cm9(IM?vUVMLzh@fW6SxvSF z@9x&FONq4ds%cW-67cL3^J?Wh?s%p3`>ESjz7;|mZZD(5qZsD6g)$duimm&5>#XRF z-v0-V+c0c1lxf)Kk?_nyyJ=g4^EJ~68*)z{++wJxEjDArHKXR&wOsFZTH3C;aBklI zO$*o==5(!;?tg8T)A~C5>mgV1=Z1URy5BP2@KR!^%VN0XYijBnx7|XOJ69=@B{6zp zPPALtgls{ji%SmoJu7-HCamZq&$egUS;g7Kv-W?e3(>l9#^mnyABXPRF>IT}(6Cf; zfw!WHtyN3<+Y8;Ew<9NKe>o<3=vJs%Vq2z!i1xDY^KZSsE}G1iB+^s&k*jSh*Sq>> zArTIY=67z}9SA!l)VTbd&x*f)JV%e%i8eS2rqg=9FZ~1#FU%e2fFzv>v z(3@WGyFzTZ#1>|l0e?=*%IH&^yEdY;z)>OoH&xIQcA+8tPwFp1+#c2n{4 z$#o_H-nOB0n^pz3cDaR4?Mm3aN=ul{qfjAKQ1@$-#UiEBn-w25rWFeQ^jjy;>gaRf zUkrm)_S(lHPvjGt^u?loi9F#iIPg7h{jFF!#d^CCzT%YHwW2XyLKq9V^NuQ;b_J# zHO3S%)wW68IY(YKc%~T0MVe$VdhUG2!|8IPMVX~Rz@troOL3772kWHND@@!Sw?dOo zI`dsvE&XVEDq{gta8|dFp@K|;Hy>-+;}yvJ$7Nu|Ow5SAp{~(e^zcQwx0cdgZ@UD+@(s}^W3jg359&0 zv)3)KXGYdb(RmDKP5P`}eNfr7Qsy{cWI~Y9$`hA51U9XCwLu`pM5lZUM~DcMfy0&Dk&^{eC4z_i8WFxQ=)j%I@^vJ zZJseLBFt&A>edR^+$RBASA>_Hda&F%X~hPPYtpSPH%fw3w1ehwzm}R3{BV^V(>28~ zsU;@_qKXc0X%Rocc(!dy;KTO45)JqKoU0}&WpVi{^hcTsXdF&+<9#)E1Q_)$7oig-%Mf)WEgtVj*42WHvfNa-4yTq1BrQ#d$<2)(Cu0y zutSpbRQySgSC2D09%*ik+t0D>ZBI{|$+brl9K0`_a=4f+5@?{X>ze4V1+0oOuhgt! zdpu%w#TXAr<@l{U$LDm)JtuE^#aENxj$5lXZ~reIpr)lTip`{*d8X`{Ht^NpjN#a!<3@uH#cvY z|7*dFhqsm-vpm6b`sd9g!`V;SZ+I0l>|=<#Rk%c?|M(@8ALmOXx6SUWO8v1!tSh)Z5z3GycFH3I*`)Kk^x{$)OCF$q9rRyK*2P``uw#K&S zh|xbuu964O|6kD$a=Uh{_rQVIK_|NvmniQ}?{*9p(>$obqoC8B9eeHX8lM+yJ3pTP za`))_r~@Be4*9w~*qbEK_u$80LnVeeNjJ}Il6#Z*EqHwjV{x|J_QF5E*9Na@xs%4` za7;7X_qEQ|UDtFR7p9(a$~T=_)~a`XQH1Em=x2f2>CY#wvQbLXKC-vL;YQ;rRV&Tg z*BEQElG&eK&=0!t@8aB8W9Ge|q#5@H?_;>#!x*8`xZ%P?XLd9347cwo=hW|Rvf19h zwI_=6RdbDR~f`A)fPbUDVz(#y7vFKA8P? z4@0yduY)~fj-s=)Z}d9jL+<8nOOI}BI~ntG%Ze>ql`Qp4ax<^)`)r`S_S4lwUBmEx zwY^M>6Am{q-e-7Ib@`>L*x|?9ev04bHJ;%8`Q!7uciq2=L>m`r8}T$)OIB5jZ`J)} z>b7`_^xAd3R(!8sTxwm}7dp$d{;P}D=I4g};-B|_v9H*y-)|pF9bx^`a6iYq zw_1Sx18eerMuxQHs;YIOoSXM0Uui4b@@mrzZUzPhqvm})ABuPFGqd9~f9`Sn-p!Cg znXBq&lFa+Wnd;7dO}nA>^a=Ao(*45RljUBJo@JKS=Hejr^vwX4U&Yk6c z@9thrcy=~+>hZftGZO=znm8zJN2$Az8FN}#0)pxAinQ$R+$-C+ z-rTTF@n)$c14F{;NuFMv20AO>JZ^n`-0|sbL)X&+Mj|iX9I|raE!p6EZyuk=ajB`& z)$WH(j@0=?HALx$@@KE=oxbjokmv11C9NwWec2?IY*dv=YshU`>u_UY!dmwLO-UBP zYkphP12n={c1WadT*b@vxFnjfsYqCw)4|rP#lunUXw>E}36pL!DsbLZT$H`Qc~Qnk zm$fOc^~zWUsu-h#j))1qeI(GlXkv^`0z-}opDNpPCC;0v3wYLcX!=WieROEk)?JZ% zuB3*ZeR6A|T7iCay2(|Q+(~&q8q}lXqPexV`p=x0q&7YETGXnyx~iQDGOkkE{c~4x zrC-j~za+sa-57qLwIy(c)b6&GhYm$Yd=a|z!Mjw4O(cg(h^v#(G3b9nxrtj#}HTn{Syujz18 zg7HET`<%ai-zMyfYJDShl%;ukh&Q9<&t(-`-`?1^_t<-$&P9DM7Iqb6+}+PLC9aY2 z&g74>@4jeB8cxYJdiRcXhA#Vor3|;fUCdM9|5)`sc`jq})DAc1jJ2^FOiLHI9x987 z>(uUXj`n)GNFyOJ_OJoZ-Y>Tlwl2HY;U>T`C+{PJ;|=?~)wk9rr7~>fx_tHdN}MEVP{yyRxtfK)tk%rh;g6VpQx?-{2Xf(DrSH9&BiceM&17Nq6xi*QSXC$JGN=f zoZ-p9z_7e!jS)v@Y_0XoD6!6^o{Ns=B^?ixp42BHa`}A5VM*rcznt#9J$!V&nXR|; z+?i4q^U}{vZtl@Aol>!F33qqY>O~6{N(k1Ts^G{xb3>HzPE)otw?o@B#uihp1i?&$ zZ%rLcw>NEkvv7^arKW3{4zXbouObnr^ytd54XWXzrWb~CU2;=uT=ZlOk(&#*8suo&xq zU!HRFTb$ypEA_jcf4F;kag?RZPVKU`C(18(nzQ$Q-C~?3<+-RRB*^+}NNJa-sm|pW zLMglS0*gs^-<8P+8_Og}UaB zrqsY)k5d#GwxmrCj=DXI`TG2-wK3WL-h49u**%gAj99X`DzeVCehuEszRJwoJ=RcV zqhH@&p&1GsOS4^zZivRNxWx2yR(p?(|7X>*XMqxeYc}|&oL39Phl{M#lrH}V z$@Y=^_)6U(-tSk7*R79IY&rGk{{A^#%g>nX{(Z1$@71ig4t#B^-!gAm+Qs-mczd=( zzpkxuM9k?=*JY1xEz44V7;5t|W~KkfQ1Q}l@8@4t_gEGZKP4{fV8Q=eXJhZ#th<_^ z&2f0wg#%&>Ss}v^2Z9j85b_KR47rn^sHp{n_y+h#1_lHMcm#%rxOfG+IJmmG1pE2@ z_y2G7-|D~q|B(M~|6}S_o(S7Gi~0BTkSkIXu7~yP=HDP%$?zdsXh!unp`w{G%Qf{g zG)u2HJ<}=e*DlQxjXoGU#Z>xgYuv&qYv)G^Dz~3MwZnC1l{Ux2)-DfL!z)d<*Id5; z{PM!PJFXW>E8IKMoV}mnbAlm*yg%prfBEs=!IM>f?OLzPcmMgH=<8ipu~}QHLIaCC zmCtWtOZ?QLDeiuD)sI)Z^|t5<-3VE&eU#}<8N-^s+bmD?{nO?|nr0+MwzO(ho=jB%Q zcFLX!{defgM)?HoPKF&S0^c4m$UdHU%{H(!@=4seU#GU#dgiWe)A24$xA`Jkt9j0J z^{$-a<$vb2ufBUQXxGFi2V5DZq=hCct*tb>pEKL{nuwvm=k1#+W{4|HYZI)n^PeZh?dmr{X^<~{cUTTWn1?N z7$zKVm6ev^?r~FO3|qpVXRf6xp)&EG#P;p?UWzo{lw-Jj@OjQ=A*-npp;xvBtze2e z8x-hLDqyV?lECi0LuitG%cI!>%K0VHti{geHkCanmp&!wUH<8^Ut>`jh>s-*7|SW$INrPce%0!1{z2< z$fZRluZ^9)DndHUy?aq|uVbM^VryItYwD_OhSDh~?!9^?rN8mzn^3nM7uo`nA}8=N zENSy)uQdMewCnr@y_t^puf#9Ou5Zw7F=SXPB=OkS0EMTWtO>o+W*E*?vX-XFHm3EO7m-gL^*l z`?)^*$Iw#R#Zcj{^5e!msZ>ile(S)E7ENUjH@s0Uo&8S}g<*UNFx=+p0 zy&|gPsPg~5hKDWds&mF$S?16De|UQN`IexyZnqciKg7%+$iNm7H}PuQyjS{3hSJ)f zPl+=>yH>yCuu^h;gKjYEf#YTZRmEF-Hrw&tf3-&B?}|fNYkQl{P1P_nJbmkw=VPyB z;?;Y2K-7pJHTimy7>sikV#WmmHB@T}c_MV|7%?>zqP*|bczqdAN^N8FExAsYMzVJQo+m-(T@Nre@V_v9P-Ht?93NcsFLf%DVeS zvoClOV^7pgmM<#Y->pwQ5qvV+K;}2|mZ|IqRGB1d#qDnHnE!h5o*frfRb`21=ZPFm zicQSRXGBHo)O z=op>u{QQo&rL>DNLa%XO@K3qKHrK7^Sxsf9-#4{wU*i?wvpgW9=>=Qx-N}t_gxS8f zNZKpQ*Z8gEN%+%NsVNr8p<+?c#eN`6g!ux0!o8DewnZNHt2@GadPOyijtpf=9i8(sM~-|o)LwU^H^nwYVqk>Bo<@u}Y4iIMfoJYO>g+!10fn9g}^cc4XG zVb&boTdxH?y;y@RVq(|igk~>X_oQ=?L!;5DHYTnpmP}*KZiXpN7kQGL1%DeZk6F?j z(Y3VhkNASFU=0R-#yQzP5>zd$bkyJ6ZdlI}8= zeSgP;5~d!fPG?_d>2;#Bj?T=AOgVhl7BtZQ;38+jBgfNck9^`@ot@fgd`qi3YPLU&PqDlR!i_>nYPUQR5VVAm1e8DW?6b=*RgJrzSig?;n*-L@k-EDy3rYADz5!qt0!q9XGh|LU*2mg7^WpX zs5m}9PlHQyo5CT+9rc&;W_=Y(mFU|VH)pHSid(6ftx=MTlx9UGmt1{1=}GiF+f#*= zzL}RaFAZ#C()3|CQ-1%Ng>`57_D$7_7ULx(}~({Z=;du3gRT zRo8Zz`4|PCVPHr&<1FHNXwScZ%8qiG>>7LCx?(l|DO$z37a#bUOk0*xf91yJw3@}= z!j^oC+UUGF!`^C5Peev;`Kf!_VjZDd#h&XZEnUVUxa4BgmO=rhhTQZW$vO@a*N;!# zr1R3qVO_A9&!xPp3Wuf@E-)2bAd<+CrX`y8U}{6@L|;ya6K8jX8?&7{v?-}a*X9t5 zLXXd>%H8W_^e4}rtQ#C4KEwQDRG5)q*0I$-Mjf5I1U?xt@Q9Qe&npd_KZDVQIkJgm znkFa9WX{&-m8)k?Y;a_nw@0qib<4sPG1+f3-|abd`Ezkr`oz88ZoK&Ud`nDENUhMO z6OOAxJ!X}fo#4pWbSIrB+qou7ZuhszJ$<~VW#kLquQe6T3SIxkp*vsX0Jj8hi_aE@ zy6oK2u1|{teT?@-zm`}&<&T8Hf%mmP^W0Y)-Q(dIpEEzV?8^2p9K9O4GeJ9(9c&I) zw_AqFBS8!`7v*&Cgbsrg1o`6i2UQ<7_%Y#NUfQ-Dd+^n)vASWIByI$*&f+1$b*qIkT}hof@| z#}Wpv*%Ja@2(n~0eXw9mXMDw~C|%%_|oG9Va}Lo<)?{+eq%yiwj-3e*%eYcpSLWLjH;*TerpMhv_6zKtHjsr-EBjkWC`w*n>WsiI4Aa7_v)EhbANN(+8R@` zandS@($J6(O>GWL$vNf9I~@8aNbJZ8Q@N=)&1#d5w07!*lx7Z@9kW)53O8w3YTQ(7 zm|!Z{y1OMJS7D;nLB+=Y!l37bsebd7& zsk4`wSS46)Xen9{qkSb-aBGGLHyeYB(XuHw;#zVW1sf%&ix?>0U7=aUYAO)8*Nc(W zljqw6UbPc!OW!Wj+4?3=^Nd3pYXXCz_7<0^wmltfF#$bd6L*zJL?nAkwy)SLWYW^B z$zoK}a9wf2-c1~8GuNDAWMPXqnIKup&l{$DLn+ihuJXZ`Xxrtj>?0t&Ew0A+cf8?K zzWDmq%?(Kpr-^#46V+;T=j9DNSJ`yhIu2Nv9LwTh zc0E%&Sz*Znt!-{=BR?$2WM0!4)_9HUT9?MOlKbEDwjAJDATd=u=`G(>KBq+jp{j*l zC)P$Vgc`L*sVrC#m@VDB%=F+6LyKxrhx}7Uxq&jSeqF|4+zVR_xMW2n1l^7tYV6IK zd7?wpVc`}f59R0uskc7e@v34s)9L#<{Tru3m`ieqNr~BkO0PO|ZMk6Dhb{we zjaC66jznQ6ofJX6wmOGnbFH76ZfNOfyR-i8VhdG~j3bR13+F9$Y%JawmZ{jfd|_Sl zA>{|>+=ZmoLPUL&N?flvZ&_uuPfvo`^0Q08X@kn!T?|J9V*JDl@49w&tuP8TTF~?O z|d3-2GO8}5#^UFC;Lu~v%V;pwt(T^?AU3l9~kmG zzHGi0bX?-&;RB4x@jn;zXWxpN{J@CkPsZ(wnYqSOkLY-^F)*xqpSOO>5=(D^tt(&l z{tiAEEtKQ4@|Bv=<|O6kad#4HYQKqd-!|K@y3=5q=gsFnAY5PCOJtV-_&DGVz#m+U*H!L7L*f;RM_kX+p-j2=zfnmY^ z{{BAy1OIQ`Agg{VX@-w>aSXAc)stS%}I0Q>KhH zdk%_9c;^3`cZG%ygd6moe8#Akee1%_^ti5_&R50Y!<*GH2sn?%4Hdp!j`<-nN zwRT8ZwfmSh=ff$PTYN$i)`&QETWm>A3g+Nsl4=hLo*@{Zds>#UM}Q+~W|c$!#?u8Y zhC&**w$1U4-YDJBCf>}#rQGk~?!nqDBj9=AR94i?OpneCnamq=Gd}L!dZ5L2hLY-n zmcpYgM-*6?gt_@Ox15Qt@?KZE!`^&!5>fV&CrV!@oth=X9cDU# z(>nCz?bc5bU)P-b!lI?LmgV1u`pYaney;2#tKFl_+QZIDvF*OnUVVcp=@acmB{o$1XdxkuRa!S17m5;tBk?8);j7t7C{ zb$iu%)6-(we+=6+!(QawowccFLq}Btr^AFS=X_03n`^>i!KajNs}<_%YzR-S@>Om% zb#dp*3yVwncI-;bD&=wwm~ZyQcm)r`nI`9}6Tg3B_SK6&TG+7VcKi2z z_6`w+oCloP1lCI&6#4nI>AS%5qppG`?@n)?v!~>g(hl*c1%0OP7BGqJem7-jgQHHI z0MjIxC6cJTrpZ`H_Mo>M+w;9_`pqBx$t#H!S@EtKor#g`(=6Sx(3JY!e5Iw^_aSdhcJ zo0SeplG4kyc9ye^R=CbYV3(sDTXPwMBWwXtPm-`u_Ik}lXcr;1#rmVUuo+9w|qSb!y zyf)RHU;9&7`i)lYoHe_r^j)q#e?`x={EhPbkDnH5Jom{Do|<7PB<~&g)NJ{yoq@&O z+>N{~d6m~T&i*lZ=k1`iTv|Dw`BVQh=PYbxJP^aC^VjA19og!@@Q~@7S1nm}x9qA> zRwSQhRqVyJlh(b-o>I1pxz%LBo|s3SlUFMHF`k|?Pe+^~$EncZ(z$1e*(Kq#QiX$0 z?>9TWGVp)x=M}Pzxrf*ktoQ%a@VD*Q^xD+_anwxBX=heX*&BAzXA#e?c~-ZDK8Exc zJ$rigy>0yBzMisqeMeoqS>l+vKYU^cF>6h1pMO@d{?>)nJ!TPKxpV)`&0l%OxHZ>| z$!fK!cZBk$>h;H-m0Vo4RpU;o)-H8@&$Zc_-qz1nED71O}38WnqW>!uSaD^6Bi+@d-~Lu}*q&;Yep zGpBTz<|s8O7qmET6m1q~xV36+A&-r~9|f70;p+{*9^fxH@SdGvgR*F$Mz(v$i95$u za(2nc`xtHoxaoI@5E!S`+KC%#pV2& zDYIblq%+AgBOVJ#4gKue78?r4et49u4UuOwmfyw`oeTqTxm_1^)kal?ou`f|Nouyc~((Ti_c7hFB^Yf)XX|=klkX`ZOF{P@WuML z$v?5=ylByE$&lSE^b&XNJ1eAW=6hSL{j}X_!Rac+&0aURomm?m$*(!l!)?lfLk7YJ z8fQm(7fr6S^5c<=^|%YI!8ke&&kL+W0LkI@-pm2SnOD17_+s&s-L}%<%_HdFw2(?$*@r0SqU< zv@T#z5aH4?D7NCZPHS1i!B7<~t7ruBCpfFm$au{=+eet=WcK!Sa{6td&=p zg?CenP`Z(Bou7G%tOx`1w_m-V1&@RT{84o{5`FboA-~N5aizQF3=Sz&Ba(TcwX*HvFB?)}oo7e|lM6 z%=#^>fBGDm)cZ??*ZN%V$_;0v#G_-gTHiQkE!?_FH9NKO!tuS!=5u7UbG`Yxv~krr z7N;kk*0(1v^p4d|^itTcFz zivF!8E@9_F8Ccs~Loz}vCGsjh>OH)}=5WT-^FU09Xu}5AKoe`{Zl2j8S2lA)A6$!Mx>6U*)D9*GPZEV>QKLV~C6Qsu^4Mv8{5w zaivJp_s;RQ-AcQdrua?dTj##BV_UD?(nD;YT4!G|`m|zRrJzP?7o$aC+}@iF&Kvbw zokB&AoJo=_)o7hrZN5mSaEhk5cCz@fOXoh{^I>T5o0zEZe%b}s-4`^^NELbnc{ly7 zwThfF>FI?-j3?CJX>=@-pY~|U#R;t%U2bW8*`brJg`Enkew<~Wc7)>?>m~Ed^f*~A_AZik z4PBiS7$UeTLUUT!BGL7$vZuL3i4-z#f69v%9%^;h6)*EwBLI#<1H`?{Rg z>ePDt^-5mweeTaS2c>*i3;BvhHB%ky+!p8Z##AGa!$U*TTc`i&hw z8O@}b1B7N|bbMJ;cxqY9J<+{AtGz|VqPkoTO<868eQT;N+6t`y*nZ2mylJAX!S!#_RjT$5-ItOW=9x4k%cVAVtEc>( zweU*B+S?a&#CLi~W>XDBz_ZnOI;!B&y;C<|8Kl66MAEo=*hirna?a^d+@2( zLHXCISd|4=r{8KW3vJWtT5vH$RV5%c@UX$QmwZgDjf-^Jze%-~&kUPTnt0>?HrF5( z#v=@C$|Bh|{$_udvo&_Q?wPCkIpy2L6}C4hGFo`E*8IKNF#E`2KlaU661Kej95QF` z52>w-BD9i}noT$CnzG~6q)oEtlp0NwUw5agummzob?cV)Tyz={1 z?!5ZFg?j7v%D&y)WI079`@-_5Kc6bj?cekFTKn5iGuKw#lUp6R>~fLH^_VT6gC@IL zu9)F`f7X&kGppAsgdWhDt={}{g>rc93MIKr<49>1qu|Ico-gi-YbIRfVcX<#g`?#q zr&`ZEkBDim>$w;?BZ^K=(Ar>SvbTgoD(Tjw+?5UjeZ3cxJm*d_6_mKZulT(WRSsX2{ zZ}>L3vE%QND~?{d`$bzPHj5W9{hJ+odWxQ#n$5xM)v>21rP-;;bZj}jWL^QU^LYu` z#kp%A8haTTPG(?WDDD4R`}%0+k*a%J`dj`kOuKh_;laS{yBB!puE;#9CL4Y1;tKy$7!eM?1O7yKU&0;?>&A<1DDetfLTg^n#`!lLEg~_g0gJ%>E5b9*kY9XCK^J z#y!WFY@q{}#LT((496uZ0tpR=aQ=zaO~mxQ(hx@T(@i z!0^5oK9ATK)U}mu_(O{32ppfjYuce3(O+Ib#wHr(A;u;Y85kIPT6BKs+5Y!*@ec?M z3=9Yi4hRYl@ON?#@(Boy3=0l(a|;ZL4iEkx@;}MR$=%&8C?HVuHHW|s@q2O;9y;dV z{W;h7@4Vwm_r4u{yQ4}>QSoFc>w|{m@`anK=hyzQSp9p|{p+uUidIZmasBnf2lqJn z%y#Eq-tnoTLH|;Gyg-3MaOcL6sz99ag#JBhpz7Yd->*io4>cN=;fqO z6Ou@%+Wl^cCfCBXZBLw5UQv3g*>TV#`f`)O)YU%hS~)WUZ^{M~X-tUXTH7^OQ1ghB zmWzj8LWt&}MMt&5N=3Kt+OnV}>n2;o9HStC$5S=RLUm20KBPDuyAm+v)~+%!zm?u{ znG6C^FRglc|E4GAEQyi`?g?a&tvtZv*yIzoJaWweHVsCFFJ(Q3-_?}m*p|h1`n;cJ z+q_s(YPa5$?s+N44l{pO+I($~_*TP<-_GZL;_;qhxyI4&_7!9E&1K6zwd(McWNEBk za`@wHkprzSyR0iMgoEFn{AsOk*YDgjQM}Q?U>3ucqQ%UG)9eE>{kL~Ai#=lZ+s5v2 zQ-nF7inH(X#|GUi$rGY?#68`#$?aU^b=#Hv>2dA8+S6AYjMLV;F!}B=TU!O@qs%>R zQyg9Qc*>#~TCzOZ zf{f&A-n_Y5D!lLpx7~U66+&h@O!3mvEIk`1MNORYqa{Q;?xZ7omuu)Dg^(2m8+8_S zg>i-oH8xAE3Egg)etOfP3{j?z^IfX~MYnp0_vBsW{ME1O)t~6i`keWRyy?u}zZq6b ziZ%R}YItWQKjrZYuVqtC&8kxQs@;3kYiX3#&K0XxsEW2)1%KDQe^vG0+8JNn<~T$p z3h1$IFgaOc%21Pclch#cZmarttF;@NB=UCLvO5qplj#Caf?x9#L94BAmM-dgHmi!Y zd zTefyel!)(tu+Q#5m{`m}ISy3=K^^ zwk9IVTV(l)r90T%A{3Xj%D4u8PLiC`RJ?raoZmMkU!Q!de#7*{w>95SU;kX&aP}C3 zjUq$y{Hyj?4qvZc`{wsr!IdXgNp0+S!R0GBTjiSRtiTJ?gUTu+#2>%@XeAuS;*+yk zs7XX|Pb5!|+f3%pjP@@R7Y8qOP`vEDqyP8)wI@3Sgmol2ws<@J7QNOP;?66(SF1Z9 z)YT_6q^rDkd+6$$N-M5utO_$}QP!C{(fLZgvW!s1)kWf0Js4D^wzBB_c(7P&X8~iH zCadn_`i5D4VJsi6+vGPjsqHKIXWZu5df@&= z=3Dlbdv=7Y8#pMf3Yx0(CA{d$DYKwJ^_?$F7sV`zG3s8lENaD+qjPpgiak~7S$?c# zy$EB%uMF)HuZe6)isH|IIj`Koym5g4BV9#TE?QI(b#-~F{*o~1hYEksD7;u6rgM^MOVMG5XEAk$|L(~P zUOq*+Hskwm#%-CZ3|a-p1$<{udmOiJ%Cu0^*H^M4vQj6Cy>^W5{S>r7>y>M4uwI8j zY{u@kP?w#iJUgtkH6<4R7G^lobaG+&{a24`_eJWzfA)nn{_$N~hNk9Vo&#GM?r$&Z z$&6j#-#X1OwbEmz z^|`8N;}~P2Uh;jqq`Fk}joZOB%`+mt{jqmg%F4{=uzNQ{@;%`_CDQ(rLQidtxEk@; zDmM0ORr&@u>p<^~dCR99T2OQ?^qJ{t9c`Yym)3;eS#mu}dxBUav~}t3Q>H@_tx%?($KJS>OMA&;hJyv`wT%rDb7&dy^E$@ z>Im3zL1`EF)%iS&6IuNjmel#Gb43?(S=?JLnx^#fq{`bG`32L|cn(yQPw5&i2x5-V|2weAd*E z>o$FH%Gz5sT&He2T+@@bD0HLOB8}gHJP~d=pQlAI?CHB)W&Uqseos5!)Khx=wYP=W zeP`U3!~EfJ#6h;n`#eu)NQP$5>0es)xBQON)tg7tyswE?^j*DkJ7}HXWck~*e{45> zef;xrs$^jCQT`2G2NZ+_k4Q9}U}cD@YVF*9zxuD!?EU__IS+m-?z`|T=YK<&z%zzF z>cSZd9&Hq8m0PE^YMsZ{MXRi@-JP}QcA|t1pRKoo?aFJjewh`{;s1U8d39&a%eXt- z9^Vwh+&DAc8CtS<*D5~yqy6mgI+JYC$u-~aPkEI1M}EO=1Lg<+m?TWr2`BJcl&!j@ z;ktEc;H7Nk^ayjW&?P3j`1rR@eQOu5^6qi_r#~m6)|{Fgu722xGx^d~hBH4SsIctmeFz8w(GfX?f&?cE)bL zx2SIIov+62-RHE`>t)YB-#$k?e+k!WrA`T*>Rnt*%099@DXpFH+57FOsS3Waae^iM z4ax>A4A;483SxDqUu3ydVHEzzOt7zQ!Lzj`?G`Kkx$ZNc-nsb7otp*L+a6AIjOvJI zyi#}f(WBcj|Gf@r@bzrHU$Wz)?f?$!-5mpC$1 zzNEWuv+@qD{_(ZWndbNN#1&vFTdu z&%#y{ca!Z#C7a#Ve|LS>5EgGmRDrKIOF~zC;R<~l zyCx({Vr9+Bq6t?|Hmq4Id1LB|Bfd)mm^+MYBf}Opwo40@GPF3oJ@qb0(=H%pvDfBr zM<%HMpT^)?P}8tyf!hPc2K#rW@g7VjZAq^#VwD;H_Qu@ndO9b| zCg1;2LFVcGZ<}^i=}oAPo)Rs;r-HY6p8ORDhLWbl=a=R`Di3Pbe!oQQ?1KBB^fUK0 z-jjAP_hvmH#Q$JbhxheaneX=ah=trZH~H<&nOW&SuL|Co);nvKeyaJ4Yp(*AZ&8}2 zP!KPyQ~4s#^FhJFh8QI_?v$dJd$&whZ@U&3uOS|D;-JnMrR4MP><(P=L)1;>v5O z(|UX_ZC+0)_W67B_1wFkuQFcyEBO4j<30cAqz%vKpSqBg*!`yTO}tam+Qj(PxkD<$qLo(H$=HdztW@ghrU zmDq|&Q#uZW94=X96?v!6qgiN4hf1nK`0||YGVP5V3|!oreKIYbyJQu(p0{TmWtbpw z&GVGgM<2y4JYv4=9Abao-P&fnVOGSHgxY^wj|6#L`mtiuDtks@(M6hzJ7XoK7#J9A z7#h!h+ZFSk#n|b_`+w=PcdC5c6&-ByqhRftRaUQEx9ErpgA4`IM;H!IGF?rOR#Qak`wGrc+7JuL0^Jr@3{^><*?OC4+Xo983l?>F=Z*5+U_No zmUvKUa}q08?!<-&MWt<4uHv!Fyj{3La=RM3G~Pz0Fbgb7Jf>S(-R@wvV24!s<2M;? zK`Cm!Q>GegzG8^vpK|%>%L$vC=B%q@frO6V8U3F=gIz5gR|WJs`l=lm|4uve=`_QOk#M&`oMPfq&3eiL)Wfg zd@JJ`agb}`3sET*>pfzVwXXZ0&E*MiT^KWM(w^7sCQ7!(5&fP4IstxhMZtR%{qmKka%|6Ado5Mly6^pKC;xqR4O0z88qUw;d>OynN;YSKxu$NltJL*X zYFiX|+D!Nip2qoE9y0y%NJahY=i>^k3_X4ad%L*)*@`qqe%jQMyWd^}<-Q3LEXKtGe!jW=#vPc-}u-uu=MG5aX8r$uIr3@ox~F z&auKF^?G8N;gU`JtQKiy?YO43>+&zh#6Yhtr<#^tiQW(w$|LqVe5>XvX7B#V8azp@ zjuJ<>QfKaCn3MIBC&Km6T;0u_LIT20Un=Am=z1{~L<;wOe44oMa>b5S7v==|#XF@5 zWzFb~dblYhm{rqDH?>eN;Pp+em6=oQvQwN|KNXm5&{NP+?tXFE96S`kz;Kp@0R%wD zO)4=kF!(&$Agve@_}}5b?SK3K4*wngTmHBGZ}H#xzoVD0w{wVRptF;U)10iE3}2tv zbL@VnA>u9|UC*)dyS;<1&nkh6ZiXx;HB&3Anp5tvD^I&md~u=Gm6K^o*A^WwPghlr zy>9D03={Qwi`Ms@Yd*WSN5yz)(=dUDR*`S2#^aL6xfMruaV^j_D%)lILaN$UF)I}J{C<4owQvLjGe_geKl2!w6OyHMB^d7Ap8MVQ2kX(>9US&&Y_}I*V6SNU zzq{7xam2)#ib72(()-@N$Xd2oOwZVuf#HCOt?2$U`*xKt4Sc`4CFiCFb9S)m!DAW9 zGx>STzD4fMxs$ZtD9WTXaBB04l$d%1zNL5_VOs=KOfW*f&~NF+G2&^nw{z0T<(`Yl2uGEV%K4-t&Lcs)m2Dv+L zj|-NtI5X{!&%NKT;BFvv=icw`*iISSoXz{}Zgu<$U_S}Iu6%jRE-U$*o`m=AdLMgT z)eEv+^KL!Mur@GAoOt!bqKT;~4(`z_Ca#VvynQul{foUbRu#6cyw)AstI@h+&7#Ia z&u$CF3lc%GWs)51tWl4Zb~8luik1XT(~7HHvd%kN>Smj3Uvg=Kb9Use>!(E4=&vl9 zslm#|sLpDzkl&@xCSXO#jLp58YYdJ=oH)mI$8WjEF;9hL6=$6mr#8O@UIu9*h633S z7$k3+J&kp3Jz&JF8e+DCJvw-aRdwnzrBfeL5=A(2G><=4?MUmrsJyC4;p3su{wSv< zU5pXScOCuf_OEo8Qc}aARqG;{*D`Vcn^PyA%_$aibg601(lT$4?&vs+d%kx9guS?wem|nGt=*=*{Pnp0{UzhU9OZWzFr+XY#2z zTO-1D-g?6zW3}Y365TToo;YV~?Q(6i2v_yfN_mBeGRBs3XS@AkP>2?rWIWF#Ppx`E z61&%WF)o#<944E1ZvfO}n1y zH$zbSo$4-+_p~6$bivyxI7I85#R66+d zIwl8;lqp1S67Q82RkqQ+CZaYyQhciF3)faAt`rYuJ*_1h1x-1+&A5-u6$!c%r?9x> z>!VATmbxj68Z>lY@ln|5(Uqmb&^0elb-_l{Z-*?duFmL>Wl%WQmG&ZWS;ks1PKRXc z1Xhlhek}_h?B{D(lbHN9i(!$XC40rrBNFB;E|E&It96)OBwqir{9Bjb?mypR*}Olo zf2na;uPk!!_1f2RNi3>)F@K9!m(F$i)3_v}@%#C`C+E!2Qu8nD>UmnXvcL4?+-nSwJE(|W?s-(cMteLTB< z^Fw{L0+~&s(VWT`Ia)%O#=X6|!DWfZ#Y1a7#Fpvk-dbgqDxTq#-0T^(qWFK9dgA`{ zQ;c=OS573JX?HvQyxe2)!w-6j4EI*g&GJ6l@3!Tjbx-W_X_xE|FuYSMX8vNZ?c%S% z`%xLIA(u<^RnK2FsrKu+UAv+TR!6BUEn<`IcJ;M3G?OY#xncXl_p8XtQ17i8@!P{9 zpPKLT{jrg4<1(HrSA8slbfjzrS1n!E8X)7&G!?rLc7Y3bd6PFWAi}@ZW$hstKf2-iK#_`381p#ZL9F8%~ zKJeCbm4bkUih){clSP44cfo-O4HMz1911Q*MO*knPQH~9WK%g7*yG6%;yKYmmPhQt zr)AGn-J4qyEHar1|#D+Hid0HS8phsj%-U)G+5{`?J3KPO*%)99B~n> znUcz>EG3v?eDW-7S@s*FhepB&!a_IsOkRKf((SB?S=SsT?AF}#1o%cce+`Qoa z&xQ{;4!%#?ESj@;bMCXfGc#JGy3^Gd84d(rnX^IiS_a<@zuOjb)wYKk-LNWayL;$N z(_E9b9@9+&kU~HMhfK; z{C!`}tq7dX+F@we;ChwCSO12>4GrsgYHCr8cUVh0!&sD0CUDO7>=tOrQRG-H&?De- zmHjqDVx8Y@DPO z=6lycMwcOTTIAc0CX+llJJuXy3v2b>ARl1=}qJ{cz8lN?Bt;v zH+oL5SXHRGsZEdZZNQrD-id0)Ws(}(+ZKQ3Dqp)b#VAyfDMKO3*=f<0hP@J5jFQ85mobQnXxB z{Fy?&_t+F^rA0_T@%p_|EH5L6O~Cp2rVP_H-S2m3%j{|AdeC+G_k*kF-m0%Y+Mg?F z;vD_p;Ow&hiJF&r+@s%LFncP@V76K}nfDR97Ms@gn|4KG0@|MT$0mc{P-cUjf$ zwpw-dOp-j`n^ixxPTl#oHhD{~c3;TUGb)V6oD2u9-a5SIHs9-4&q~h3R9=j)58oBM zL2dm$>!RZoiMr)CB3k;_yu4@{G3&;*^Y_lWSGBVwpXduXI7`#kA$RJ!K0%3`lvyPc zE@XFn?lL%ZYGc4gk!1k}O^z3C=)Pg73h7Q*#WmAFSgBEV>0vIP#z3A%9*F`*;iZSC zcnRt)X!V^n(MefnXH<{UY!2;1laH*>7U4X^QLWgwbR*O4R|T62Pbmv3<(%{o-X>!e zl;P;pFwu#7J(t0xxk@TRZo0bssewCryP2$KZ!?SB!IPlVKeczmeZG|R#ICMu6X%|{ z3b?py(VOqT*Vf4O9Y6g3^UsoBf9)z6_(X}2=;TrXgRcB+kI(DqM-kzB;H!kW5(~_XX zX{OtrpLgmKn|U-tR9#`)bAQe#8_BP=?%CaWa_N(i3Gs z5^dfXxBXSfNAG_VyIn8bnLTet&y;1;pD-9)dEv2GY1f**bt^+&DJ@P~nU@ur9(_S^ z=`;SM@|b*i_=VIw}Jozu+y5IJ7k}j{yy5!~ zSBrh@3DZQFH%w@V)SOtbChRq@Qvv(3ql?sc-Ai~YU=^tG=7iFM+}m-sH~;>9;?FM1 z02yL%c#RlhP-b9Y*x~u$yS`Ikp#OhITPIf+JI9c~KxYrnkibw+4|i9uz<|K0kO2SC zpos98P`}WC|Dpda|8Gfp$iTz@Zg&Z{(dJV#<#)VhU%=(3%COgN!G7D!l(MQ@{pB5t z>vX)6zr3H~tdi22(E2LF>FSlFZlR^zkue+*2f0i7PO_Xip`1|tDSyjpb%oueNhueR_ib)$2xAm%1zuUA<3!y}9Fp2GylYuZg$DEv_gHy&1JS z)haHzXJdFyHM0f(ma@djFWr8NC#diCTN`n3%T4*W3BMUk=bmBsBPT7P5_&5{W-ph( zT-HTvO*do&tZljK*uk`xLrZC@*kY{?Ez_w{fop?zuD#xrqa&zQpwr61e5dJg%Fg*; zZWnCd7;F7yp82Qdr+?xaasw zET{g~h?z~n4U2X>Ulct{va`sj*=;q$rB%Ll=ckC92EtT-u-?f zz@R0?qU6k-AST1u6Re!xzDy!rlO8j$3uY<5h*Nd5J-pzJ-cbjq^=D^BwlJ`}bu+K> z7PIx)@GR!hw+&3$+1rnvy{qCHvO7OObmC-{xo$gdid*iOd9t*0PL}A}O?4hA<(Ezh zO;c2KyXha0Gx@YN1TR53h@>X)Mxc$RH@XFlqEL8#boZkLwh6>T6411UZ zQq*D>s|MGUZFyES=eCsc>y~pf%8I5=iLBU^rP|^>&(qdd>t@6fDfRf2vXxIv-u=l7 zykVF0HFn0HSEo4&xU09)t8qOmk>1XxkjChTZ&B?H?xnqaqHY&63EcwHZf;WyROU|v$al_1(n;&HvDH0ooK-H+wg%! zx+>??G>6xrTZ2|qg>KxG5wluTGembzPD?Ujp;$KcWQ0daapdXbJojcDxNxhZHe7f(}+~xS*LcjU0%J!C$-n{ z7-LS_%3!lcE9$iuMDSWAk7oRK`y!nrS*12c?DLO{S zYzw2rCi=__VwmMzOsthbls1;t6j$bFTUX0B>7n^e#H+=_;SJu zm1nIhj9;hS`@wnbGQrl^dsl=$mA}?q%wyyNu{EEUt&w&5uOhQfbXBP6)m2wZ zHnlyJnzrhi$Hne>-jO>)B!5cXd~j8RqpV9XNaVD=n?a1-%9Q@Rl81lPX8+1^zx%B9 z?aoz;oo>BxQ1~;acb1s*q&F(_B$Gn9=9;wzg=uZlVZ2q4u|m8x$#m-nn{yT?qO@KJ z7;NfbcrbO^(;A)3ZWG2iX&)IX5B4rSyg$S{Y=a(;pYVVF3s&6H4RsznR(=!;I>`5{ z@73ZTp;_mY%FacyXN=5m8xA;oKq$}I_AhAlPM+<(Jacq zkmIz{FHHH3{OOC|UM`Wo9>J3Rb&vdkqlRn`OpP9#NM~kCD7M@AZ?F5@tpcUxf;&vS z74+u*OjCc=(3)(YHgoB}in6C$YtFOOGvy?`lw7i2@#(qVcez;?B~NTsjotj4|3F7q z5`!2ckIgPcM&XHa{#l_WQT}sPr@5?jT)(94RaAHuH^UwKYv14HA2LY2ak4C(b57CG zy_Y|^=>?}$Esm)QjL!MW?0UhDVcsH%hNCHm-l!KTDIR{Gkf;-sy`#+Abn3!2%XepQ zT34oc@WNh|YVrIS?b31%rGDm=vZJ0yw|`5%X|&hZU{|MrdGY3>Oy3wc_zE)kb4b@D zSMBe4;&8P4T0)Z5lpbbn^}-Eqi(Mvv++3cdQz0YiR=TlNbp}s}-%BmF&r_Ut`7I9F za-id1ymt1E; z`STXvbX$FkK}KiW;r|S)cQU+4Z|FBSTBCUJsgZZY{8etek=Ay7YC4NoY+^FuE>&G5 zdnDq0*flK+HeWA;4A!OsLnDS2RoyyrJUwxdtosbxfBXr|-o|s7$NA2GhHfL7hU-i| zKTb4u3p2ZIHJj!dS+;c1t6SGzvA^s(p)}EbA=5@PZWrIDKMl24woVSe%YER)!Yv8O z|GvHHVqwUsdaLrG_dn-R?xU(RWERMM%9lCX_>+0XR6~aSK5RSQ?d4pakr}<^)31N0 zFHirpV-@$$pWm$?_1Ue`oPTxwHn0D?~$i^MT>5{y5Hd%P}6WWh3$bi6Swtg2NvNTzqy-U>Qx7uT${$#owYJd z)-d?0&G)5J+Vj&MI=2|+Ti9R!qoL6}h5OI9E&=U{6B%3Fwl3^Tn#kiGtu<{Ht4!*N z>;DzUx_L*kv(WPTBU% z(~3Pzq96Xxx0oVuglS9GMrNLtyBVSy35j+Vci3+@SuvgoS9Wv*4*L^p93&GOV>bzJB1 z>!EDkbMz8f|7Oj2-o^ZsB~j?qiGhk?F>Bp=F{zm`>dAxaGrLmPrq^N zYu+5AUWc_Ur3{a9!)LF05%e_3Hac+jX1ArH>~7lEtVQltm1xgvTKXdAtHP}{iV@W^ zYZIO<5MHX3babXVV@lRdpKZT%_Ae-0<+~;~C;8L-J4zb%2h6zGADonYuxInO&31Cm zp{A!(<8OC~9BvP)?3BA(eB^7~oO(N_xNr9JQ(p)EoBk-`{3p%AKYMFsyMDcXc`iFy zjAu^XRh|-MyC;u0Z=KP8=VP?{Pl9&YgSdv=lmMoRIu@Bpv#S-{&Wn}bmzkp8u`0O3 zm20Wo^!LAhg!NYkx`t0_w0fT^cK20s={?tpH`-_IR=@vx<(HS53_Vc?Wq+8}DF&TM zi<|Y-c!Kx;_8aPRD2=EitCh;PZr@v1NRRVFX&VVIKiG$-)gGX>V2)eFN-KVLal zmUZVZ{|3=;h8h7zL8BbQMPY&O_brRi;?CH5Yxj{X?X|kQMavgXoD)`a?U~HJe(Bo4 zbMs$cE_P2}wbvkK1FuBFQuPUQ%ADEC67wwnol`&KkmJ!J^PfH9MgW7Jq(Y$Ps`MS3 z(t9(q#pQfm1GvOQeJfPEPCHr{2EP_H4gTmbBhH^eINeJq>dg&-gUkQrcc(DKI9=pi z@_fRbe#yO?db4)r-<;zAo>`~su+jy4&J$kUQxEc9unt*!P17qhUR$L5YWpt>I|Ys= zRX$#?y6|@s4xC;VviiDlAj`X1TbySfeYcIvZ(oN3LrYO4drw`<&EvPfG;wxZlvgaX z*LPSwiS5B;M(;E8Rvf=v(J?nk%}`3U*>tO#2FKG-L06|MUcE_7tk<;6mYAMe8TT?I zz+3Uevn^XWZXMxZ*j4p4mG2j0UdNu0)&9W(@(&u`vok1cjtyQl&2`$!skcAKUUbX; z>a2S9j0yuo$J~jgoDM#hPrH2E?!4)~eSmL@a9-_e$-vCiyrPR$d!65OZrr@$jS=ta zO$L_(b*-i@4~ub4Ub<@Ol55+7U#{wiy7EZcASmHY(PT9jgV#(a9&vCwx`l4Olr5s# z(s<;x!xpJisXijReY$iyu5_#kxmIz&EKbNbY(>FT6(+?Uxy8aq`?fC0Q8d(;ko%~O z;S|dxwZt63BqgREhlJ&CFQk;E>j}A;$NCCRO3^zZQSg4_l(k&RM`o1?bY${N7#K)B z`uHmIg_V4_&F@vhUmtbG`c!V;b;#z(lQ&MHyNg$qgtApXQm=g#Y{=wNDW(+Mw(#famp0m z{|^-!RONbNe~XAKKj2rox31LFR2B}WG zr=>#9Z;|$Seyf3#c}5{~hL~^^n+O}*$(?%BJX@KT7))5Z%^<^-!#q52d&|V#8K*Dg z{a7vQAFEJq#uDbxxQC%Z$9t2*L#C7JcUrDJmFb(dK;|e*;ju3|T(S?mJUX6E3W<~t zzLTN3oQ(E1$iXfssXS&)wTIRw@h6dvL#dZuR*upfhOJ-dCQP$@=DS`GvO` z%E6&8TQb=g7-mSi)*b!0s(;tYRXx&~Y6da7iB^SL`8`5P_H{qaZdZzJ|G6SM{EdG4 zn>9Cd*&bWH$vv*Ox-G4%Nc6Uh-|QDofopZP?kH%jxT4|Ekh_8_T$*czW7Yxf$1_Da ztd6g4-Q_1SnWf3hRilb!_PJdejc*uk@+~Z#{{K3|)hz;waqLr+0?SoY6Rs6(GajX>v&<{$@i z!Gwepx-TAYh)U6Qa(3P?+?n3Ym|j;59x`EUkYEKZ%3uJk%1~ioVDJjwH%raxzxRLN z|FN!4t{zSye*gU)T>}Hc!bAW2{I~xf?&RPa=;Ip@93po#)b&`>F^1h6CJ6m)dQ_p>l7TIRjmJ@XuKXX(yUHrfpq+Z~NNb4Q^9r&Ya1@;BeJSPwY`HZ}-t#I@j(^Kl)YwTHo8h zYuC$ZZ=bi^^H`wmr1bO3GcO6Q&fA`K{IH$%>VxlAe5@6FQF8hPZ}r|X71bgZL&K~? zS7RHTb=u$MP4(vFSv+ypN>{-XS*bSzH_W)P?98bk@g=LQCYR)}ib`K<_pV?w z^GQ#EnG=}|nT;M#;jm4SX*-aR^d|DSxBfB}R)dv#0-c<~ynLyTjLy8e7`|tD*NL`- zrU1^yD1odanzN=XQE*Rtu}Wao>BkHAh_&`kU;F#u+69`kzb;ko6!7A7PBXqcsXcw- zS?fc~796nYsXm!@FXl|j0~goEGzPKDuBU$bf4*YMToxn3dN#OWi-L;h-sH!^G3rk% zFMbMs?|grYr<~BS=EK4B>_t}o`CQ{tz_>4aZglr4`OQh%k8iJCxAw?c`>3NLEZgsG za$u=8bH5V)Bs*7ore+!&!-9i11N7Zewr;n0{J8siRo2Hg#8#N~|%rKZ?mX|Uixl7Jm=$dFghslbGUE*(bE*i&v%VODh&gcC1`;Zpoi?!>!94l#EvwOU>wPnAPgcs4caL z#o^slzYOzr>|LBM7%yK4m{sDR5GlIUr-wU(hs`>vXA@J;j>=h_Vb1d(J(%dw^-QY& zNw1E>!=JrbmW*LurG;Fd*mo!vIj_9+)#5*c@DDbI6MVOBzPH(S(ePGRP3e|bM#jd> z3>%!&(gc+X@Bc3QaL+=G$NH;T?9R502a9&PTbbuQdvN-e&b{jgr|VQ++F*Zv!;Zsp z(QTO%-Hejfi@L@7ULB=T)T`rX@k2rBq?}I>_c4CaF z_FTVf5@)x_ZgN||#x}jcceY2yM)ps|=PeiPI?>{#l=>)j8mDw5>z5{jw%JuFnsPil z&6>G=s+P^=JaOd~o9J=TIn#y1noe>a-g9YP>`YH?DW&tFqQ3DOt7Xf2mmTrdJ>q-D zw6*$p&NHnSJ=HHH*@PkejM~M>5>+SZvkBsVl_;*u|*Qt(*e@&M> zX2ytq$a6@txz)-P619@yOrpI|jr6rNp@@Xzd|NVW7#8^>1+4Qo3?m`tZcBx8A#| z+T7EBpL%eYK)39w_UNFPU?*?!SHT|(xvC#U$vu;7No(ahw@k(&CS%H~1%19R8hBH9lM<8syZyq(V%%af|62 zKh3JWi)Kp3-hQ;%YgfV~rX@{}mz>%T?~#T^VPF4IWHy zF3sfTe9A1G<1hZ{#rcvGFLo9_tvxO~r=#TCx)WT<_uZd3-M_U)m~l!{C{xbS#Qy1B zTO(Cun zS8CQBEn6S5Ri*1~sobWPRn-?>%{j3}b7981?0dmdER64cs@LqBYQlD;ERy-B65oV7 zjhkPk@?K%L3#f6s&3-~xL#Dxw)B3%7reA~Ba?Qvu>*AxoEag7h9dlws|Fo2ZQ!8Y9 z^EP^kSOrOVZauMR-9d&p%QIRmMP6Swx*oMZz?i?%|IB>L1b{1dZ`!7W+@0I`7{ri1e%IjNK zKm72T7rk+_XSmMh$+q2_T$lPR4eJZrwZ+X}+2~Sexy84uOE>lycF1<|tYljzz$I#` zwJ4+4z@de6qs)v|^B7uR+O}YgMpPZPEA9WNqH8})d!4W%N*WGo=z}5!1C6S zt8JQ*!bH^qo?~g(n9LWhV9?o>nb;s_GvkNk(sc$)mauWR`bvwsh^~$3v2xJLTi!5D zSXt!w+i8p6M6K8)bd)Kvr9r@*jr+>cxhu}OT%Ei7;6f+eh@xi>Rxi3-&2&OdmAi{h zzxZ9$?dSVIRjk36ng7DCdo~*`W$X~>ILL75K&0^Go6A3bX!-az<6#Lq&zws;y(=yD zGp5?CVF+P3()ROJ$Bv`ow+h!MRc?NuWLGekKVfMy&jC{vkLMkK&%E5}7raz%N-M*Y z0xs5yRF$nV5xG}%zH#Mmmv73;Jgm>KrS7Avdj69WPcF}Oni%RD9xRzz`jhdEN)JOt zH$!~c&u+F~3nsXTsz#|OEY)Eb5Mg1y8ep`BF$|)hX*N;S_PkRYwg-+OYrDN5NuC?W5G8McI3pHlOB((-gNVIY{ zh$}0znk1!Oy|vBo*p)|b?T(fj?2A8p>F#^>h^1}J1&gf??615zVa^pF#+6r&Uj5a+ zDJUi-TyNVZq3^L%N|)ZSN^-Yw|8sP<_D^afE&ivlad+Q2_8X_z9(c38m}QrFCSE}}du?dEzVWWBm$VjzB!7B*LHbqI z+IKH!ntv7N`q}YH_sVox`>Ao7)1AG!8TLrz%xhySar0#VHixh6b6(y_ACBTB`Mt0A zG2Gt5_TaX8z~kh(Q-o(cS{gg;+AgKg@Kc^HF1pulT@SdsMoTALbJ10sEQznbcRf6H zO|o6ea^qI+&i$8Gd2V^Y!Eh@xbr;)T_DRg^R^FK674wh5AGGbZr!0)mbZ3@Nj@z5f zzE?RmznCF7DY8eBfx+fX;m!)JZI2atud9gE-PQgs#uodfUTE^S4IjUoUcSDkzg=SD zt)lAP5nG$y8tL+GKjE-?>clnG*@mZ;ETxM;vai`*#79Zv4K5)3iyUn3&os$Ts zutMca!@SJizzl{C>6EWF{o$)#?3gWlIytq_+Ip&@@@}(sHN#6T5h+$P=PZ!y_HtI+ z9DQP)zUrnlhj$CbC7xs~O^nmA2oX^ey6NXT*EPaZB=1awSkfvBnJ3J>e1QUcV*GB1XGR)3o|73o_6FF>p$D~tRTrNS6(WK*RoZ|#A`)k-$KrcO($30 zm^#&IV?kf$<*WP+p$yNaMhQw4FfjCXt+I8UC^RdgNV!P?XAm7&w5*#F2C9F zs;s=FLb%0#^^kJa^K0|?Rh&JeOV-_Ns@}LIP9m83nCh`0QMK(sK|T+Tz9>KGwIJFs z)pyRMNdhfzA{vh|ximAICfqt(;iaIgn|V8As;rLS8t2ne(%y49HziqS2d?xMlooN^ z!a0+bg)`J6^NmJS%j32cNfTzdMSPRo9;Gd?v&EHXg6}B~_k^4UEF7B41dg4)bi+AO z>Qv(z!5Ps8vHq?ZYVGgO7kAjrKKt{V|ML@WM)EUvKfbRn&1>K8>*ttNes1qZ-}+dV zU_Vw5F3E!JN=lh?pBf3egx`!vTA16|%3+mtP2l+B1i6V<^8z<3GP_J;;JI-6%Zz>E z7ks8(pWU{CMTDIpCa;z2NZ$SnPquGd_1%r3V0N$I6;4eZyCmc_vc+ z8P1eNPuZ#er>We3>&?cxhvGHgStBfa9M&^Dy|eyt0)IrM`-H8} zy6kUuT?yMH8fYTa5#*b#>m(D!Shz!oMSYEXq>O6`%}U+SOX+q42#uQJDc#uHDFLJ5{K#ICNvjRwX5-BatT(A{n-X zMXI!AsptF1U;oA9CBN||>-S=NpXmKAVH3Eyg&Lv{p9$J1j`2nu;wN93OTm zu}<2moy)njJ}>KYrE>d1MJ<*kM^|=)u3crs!f+(Z+04*eyyoA^c+-X(s}^!>+sp8B zO{?pJi#HaO{NS8=<)ZfAN6+|PojkOu{K&V+7D7QWxQ0(W zCVI)0-B-8tO`Uopf~O`em}TEd`K*o1+dJR#%{X4+v$6RbYlN>C!@IcO4_M{*2e@vV zb77J}`j5(ubEjOKQl1wTu&Vr)w}$JR<5L$GNUeUcb?ptNRUupVCf@G)n$8(e5vUFx zVqj>nK@2gdGB7Zld%WqFmTzE~e`s)!lcQsxe}GF!U`SA4pnu?h|NnviBLjl|$NUd+ zad&cZcW{oF67_J6aCLRTccX(>7;6&kE?k}we?Tjk^FX}?L-Ftb%0d?wDdzfaT%g;# zDZ^D$z@9ZUxTQ7dczA1KPOCy!c=HO5-@HpAT;^9WMjT+y30j(bY|HcV7c=A4#lsb@ z{gHn6jWuG)G=?wy0vpq^9=n`xyy_xy^L=aGx>bjz3S7%n>zFzTl{h_oXlPoRr=@u95ZG9Ozq0x!!`O2eG}Xix*L2NJX_YK*7Nu5h$g`PIM&E?u68i(5}QWr?mnHRabwPuH+X zs}hceg{<;5y{NTTYpvGau84D9KRNX!?!@{}>{4_Lv@vcrBzi?K0z%B1g7e*Y_V>{<=l!RKT0Kdf}*Jbq%2j%pb}k9czWH z_C%K&t)6@|M*QNuPp_nEU4QJjpB8v&>bk|-Qbe?QWGuKA8+=MyDR64hh25PGlT3GY zI5O->diu)!-mQr&-?yF7+RL!f&~xX1`2_A_hI`+Q7k<5Vd-ID17uT(E+r=Zb_AXiz zxO%6VK*`-x0fCWWJ+91Rg~wKe=3H#{4CvUxBy_X)qmUaD!;)Ff!mH=}JXC77f5#^) zxku0D=K3>kQ&M1<*TS;gJdHa@La$J8+5CvY;90I+5t9-`1RbVLH_&*~7}OKae>xN9Ip0IdOHpmr1v@{H=TJD;`KN1SlW$UOw&Y$yPTJDd^J)!n*+3CHv_*gW=k21^=dcd0Q zqhYj@V~%q5(stGGBTSy=TuefH*0Cmpui=x3;9bVzS;RRfFO})E-~X1V-%&*pde52# zwlw@@zoGMxW6Em=tKWCF%5Jj!7kuKC;MBctD?MBtn+qbYJ-apAim&+U4!vyAFSBGPV!~g<0WY(*sT%ATxu`-=fwY}nqcc@KMn2YaTVGd>Hs?Y;`PL3PaF>XBIv~gFOBg2|HXNI!O z{3!O^wGSq&6p*eKe)pe!g_b6x2In1xi*B>lO#HjF=IU#;SJS6DM^F5CMEjsr*~*}m z#*cUw#Z3rxU8%P=KWl2iGSO4FR(J@wsWGG&1#*8n$^N<0YUvTj($iCJ%zw{(gDaWg z*F?st|IgiWG#3hsztg*?%#bB9z{ke%Mq&5O$E~W5*$P^&PLZ}Qxp!yNMm8HR&Erwgs$u~?h}6!+!(SX{M7QT_E$Fd`|lA+tvj~te|`BL z>+`cqwp|TcyirHCx@~oKRN%%0OBNOV)sY+2UP;V}%Pm?MEp~3(#T>3(hT^dqkNz{| z2tQ+}(PQ}k`1te}y1$CKu9@vX|+RvosC6gZWTB;68pN3VffCd*d% zL~{LuJmcLjcs{w+Ct82E<|v4i;5s05j79i<=)3Q8mhXL|JbT;wuloKgt_Er}&2%m7 zSap2u3bhX9lb@vSP3v^eJo{-dYf)Y89~JkBH@=1`PkU81J^x~`x_{iW)5YIGclE#lNHNe_mnx-e*NRMjBfSZ6Q(_sU$8b|5yO^#7HgiQrV2~ft@?{s zZ+~m$KY7w#fn=+?D>HYSm0Ugi+2HBsWw)61ri7WHb;IG@5Q~QW0%XytRWR?fWLHET>wHO75po+*{r5aCt{u70Y%} z+NyP7`e(MvNoRL^&dPN4wvkHDcPxfp6_UChb-nY-~-TAl5a(3+LXBQJI z_t<&BG#1d0sKX&gGfj-yp; zRrN|SZ@!}(FVvizJscQ1-|Njd!60x(;zVKFmg!f$GzC15C1iKmFEKYy;aru(C@@iL zL6YW_3|A+O7Fw09Cl~!UN<}>zv-F3 z(x3K?x8sbD@@vnV^r1erSf+B1l5x3sVVR`FzI}qu2iDBh0_~e&@cHk3tn^xL(6`rX zEKYjW0>v6OFOB7cB{SUe|#WCH@S5)y$G0WkoG=) z_7!%mRyn6#fkv5|CNdiZXy(ll-OnIUE3#07l`Baz<#kNl?NnpMWsO#PB_H!0kVwM9&|u3kDW`i7n%C$`LSc(6~3TSh~yIqb-k0-2K; z$A73@4Z9$gy~BiqxoKK>bAYA~!(>at8;;dItslA!cBB>ZCr)b!2s_DqA#=mD&|{|> zbWUxEU}lMEiV;7}$Z%q(a=tAC^@H>rY70JY(}T!{l_wM6Jo`FZK!B_`Yr8l61DbULy6N;b>-m(L??pePXeb ze)9JA+IZ*M^4iF8FPaA+fdWS_H9jERz-)~sC zXCp@ibZfVj{`-e`9e90A^hDBE&xq4-4Gu&F0yVUIlzy6+s z)2m8LxoR39$H&ioz2=5%?!r)$)w?IP7`nN;M|ZnFn3Vi+?OT+V8V{$FwcCEW~ zYQ(vqi-(=qQx_@)>hkW>+o8X8`kc6R+3Pd2RwhJpzY$;wiwMkGthbgYwBb(D9IZ1v zEM@u;OSzm*wLXnn8FBN7=IJBvgBi&CSoSI9ggmfPY z)N-Hfx5DEXkLvXaSL4_$jYOw#tvK?OEqNzXfq|b;h=z$+*JGa4W5R0!S9&(csaw<+ zoEAAW(eQx58rzpkm7WKgvUgZco^4*P(6YzkdW@)^aUSpF)m@8TEEBwPJHzf?)cYU8 z%nS})jV+wV&lV&Jg=!qn-}*eH__o!uRr9-*bS~^-kXXLCvyaKF%XB5{-^K^I4f-Kj zNt}P!3j{thGbmgM3!iv3&gJ5fchBfq`Mqoz9*BErs)y%P(a-@4oo& z=H|(wVf+5id!%@3^3uAs5vuB$wcp-X?9yJnbz7FH{%grB^_%N$jhZH2+jsHumX$j; z?$Hx8G@7e+{Ytm;5jF?02d6v?9W`|l3xxO>Mcr?C&Dp)^g0X~WG>i0F^FphIIf6|x zi%WA2vaQ_=ShsP!jC{F~RWiE4*m3ahF|w~Idg|*uGdiCeCWii ziJWXTN57r@W_@PonVzQDFor2%Q&m>!zivKk|8$jt@a>8Z|JV?1 ziH z#vil))-b&83S!XHR7{!mB&w#LfA_mJ2N!iMZrkvNC*{(`s?bGRZu<@jH2yDIz#Ql* znYbqGtX8=FPq8=YJX=qxUD1CY80}`m5V%aDVXuP2_X$h(F0{O0b-0Xeu~(~tb=vZx z7m`BtN5kdj>B|%dbkBUEdcUdb*|EJ0clsWGPzt^yrPp9sfUO(To_9)*P z5jTc6Wv{JPU0ug5$k~2MD(t)PiDN4-EOOetn|c~c5&ge-S&E? zB|7iKvN5>0m0sm*saTkhVm#f$B;ZSp=Yvya@(D|`69p@FFs1s(ES{Z^IB8AYE7y39 z(yZ|AOGg*1*^F@>; zt0!DNKGl0d)&!%fm8<;ETWxDB2xOR2wVmTj(ElYO2Mx9Bf>+J*{+pihp@wmqnIg-9 zOFRji1WSbvR!yD$^Fglt|F~a!;p|5tpBjw?e%-b|K%)yWV$&1rd__=+kI2@ z)8_AQty<_AyF+qLnyk6i^snY|jV=FHUMpO=sjI#%=<{9e%V}vrrktz?{@LFXx^+I* zC3tRE_S0R{v)sA2N=?5ND)(Wrl6B1XFQGA!_L^JVly&D$V2L{QrR=nkSj(iy5CP@? zjUIw8f;V!ndFb)~N6Ar+>-q_%GXxmyPkVfL6bGljm~@7XD74E0$*R5@@tuP zm3!{SRUutL98aIF@lJIPjY&@ROuZV%Hq+)L%ayL_97nAFi;6JLf9ofBCHUXG^a5Lxbi`&vpDk7emsXWCk9rihoso@~QfXNy)W8c4u}^Oj#m!G5eYo%k=)Z zyq&*)#4Ot4#m}%LubSbd&i}@qqpXp;<}wMtocV8CfR2Lwfus<|4|n8VZ2CB>@s`5V z^D(`%(nG&LP2IG^?((VjzU=lz3LQmiVMm|D2iBVX4cxz?u;SnMJsX@8BBfbpT-`le zaZ6I=leBrS<`?|WI&5jNVeWq(`O^DFf%|=Oj!H6w?~XgOEGRbg*Q||h{Sl$Z7ZtAB zyCO?3BxaSX;u}%Xz$s^@PUHM`g!9#;qZS)7K0aWW(&Win_3?fH&xf`yPu6Eo_AiuJ z_?Mwu={SSVKaL$*&3ojwN6hQ`*1Nn)%quo1f0g^muBNLoMoYG2Z0zvT3KCnD;U&VR z?R4V4@>XYtU$=B~UluUte~5m2Y#)nW#=QssnHgSO)LJAIxc2_M9;0t&uid4uy|^Xd zwCOZxm({KCiISa1S_>~*`qfRiuWQ`z6J5UG$0qBvt)DY=e0uyRJ?#6v=4tw^bBm6@ zTXDu<^@53FSzlVCblr2`99bcCSYv6hC}XbgHKqhb{e@OMYqSiRR!qoi%4K_@(zm%q zh3!Ii^Pv~vO`aVly-a*_wKBJ!5*AH4{>n>}MaQx|LTRqz&XnsjLbw)BYBAiY^Rh_i zppT-G+rGPJ@-lrZt4zyHgO#@$avzu>xisui;TDa@UG62u47Rq+i~N0V*qZMvdv=?x zi^bsG3hQK^#;!uW#VP>|^ZE9#JiBS%M0cS@o;Jp=yit;++cv4K;=3JadUNK3v>93v zX12>-sswWMl05x%K)2OE1Q2t3+#g-!h+dys>@O z)W<@P*k|=__%6-x;8$H#{O!y4qvM53-7+dBda0$QF)%#fP!-~Iw%33DSW2$_%^^EH_Nn{XMAhhDs`sSb>+>@^l(Er z#yDXwLB5NRESlF`Xb61FXT@iH=;|ixh(`t?4Cgr5a$2~Td!(wmN}ar<6vWE5(;+UW zz(RLrQmT*68Ql{+b}lnFdxcoMdK~?8i)#Xt!BJkRhC zuMG<776!?vKDlmiY1v!u3q`D!4El^VKJFX*7c?GMf6=&7ap|=5{=Cp!uh{hy3%i0= zh${Ii-%n@p`10c1I|s8HhIa$BC3+vN(W#xlc&06vVa>@1zHJffc^uwcEBGUyFmHna z(^(d^UA2h?OXgLq;nFMhbY11<5-J*a@yVsewF)H;fAj(-v*49bM=j=U=n={*5zBC)X96`_9M`9>laj<;LDWMeUpPj((n7SrK%x zOY5ql|L>DbJCk}tm+CBGO5K>`z4P#`q^Yy|QaMERzBzFORIzR9>RrkH^D>K#>SOJt zR`HMjFyA>~&T!ycQR~Om}BPor6VL_f!aL0j#pYLB>IPdbVhj~wUt52W2 z6FEOR>FX)JTO|t)+z^|+JOA#xs`iaJcJnJ&-^k#Td~?~gBTRYevjx{SmZ!OA@800S zueZ!i^H%qwon9hqcthCKx{go3u;EeQ^9^jG6MMGs%FYy>+;T`^s-ce4k{p>wZDEXJ zg$Fn;shMf1N*v?hRD2vEAlVxA(PFigD=%}>#Wt=*?vBSMN3ggy_saMrJF%Lqa_G`B zbCGoEN&0X}?Qo9@XRCk`x1vk36SI<%=Ome~$%nRV>1 z;_VoBU732;L@L?pQ`MdsD=$3WA*;H1)%6vbOWz&iHt|}{ynk!?8IeG}MY9FY)HPpT zUBg#?{Lk;D5dykLuIkzRXOsvNVQRRs`r+6nUAK5 z&0Oug({=BXx375j%=xp8VU1fT%f9XMUWGlAt$h82((>aq%pTt>3+(K;U}MJ+vzfi< z{PIotZ&%IX_ul+@u3{+D)wo{SV;h|xEwyq8ba#yo3JY1AYrL^u(JYQPg6DIQI+93!=;%#`EB~fBFU$w-H`v~)?VT2xiU*I%6w;8r0{DcEuPJ~>+}70E^Rtr zb<;TMq8;1A72-a2FIRA8U$C#)WPNwmk-K&sMy!?g2V8D*+~HOT6uGg}aQ0=*)rzmY zw?;?5at+Z8Y3e%qP^)#XMA-GNj*9Dxe(*B2cSUp-H16%V5ap1d&-kMDtOCQ7vf|WJ zJKnNaJy;u6%3?nw`v`pESJhotu;G7*-14^nw z1sCvru@>5{p(mQTzXGHQaDY0%T%byk{=E>Ak<;i5V>(Yk1H^cVY%zPr)erH{o zd_t%r+kvG_-hHBN5&@@Pti7gmE6F7?k#+46tE(J(VPPUy7p)Cgm@(OiKY!DjW+my9 z8A}gr^AMiOoRburx~*hJYya9iv(^O6`{ouP{+xMDkR(G*7NeQoZedvtZNJKYh4pgl zGW>4+nX*~t-_h#*Yj$k0zxpiSW_L*9j?P*4H+f$w{!+1W+abnG)BR%665dxCLj0PI zw!PJoyK`P8)QY)sJO8=wOl#C~81xwbyz+irCEE1Z_{#G1bhX>j#e1g2^qv2_{olex z`iqh^uU!3e{z&5w9j?E3=GV=<9OKpzbE7-Sm7776w=jdDCvM_Nh0lp~5B4mLye3j} zF#pl~Xdbu(tqDwP1R7dtq$kbld{Iwk6bB}tz zZ4x92kzQD#XrA+ntlIrA^rj%8i zx{}ydFROQPa9qi6(B8=~rXA)4BBw5LnMiS`A7y1&;owX=3`eRK2VZRe$)7Q+{F>An*PQG5CxZ+{&;QD(u1m-cEwSa)18s_H-kJBu z#ijd!jO=I0C%*p<)Y>wHxf(LeH({1}z3776Q_Xd~z8e15?6?Ev){6Q|%P0nmoOAv5 z-}jmAtaB%(vzq0GFv^(i<(Bug)IEQ9VDD}Hz15$> zdgHggkPcH;tFsOj3=WI%`7wd_mAzh<)o+ijA!VyNbbRD|w{G2L%6&B9-Q?&xiAi@m z-urz%ns7=yLHaR6&HD5Ohuz)I9F!D&>9cXQ%)h7px+<$~s;)dVRVzz%@$^k+UH4tqS226| zF6SjvO z*`Aa*uIxaSt7(qwbyn+Ht&L*YnP(DTxvJ-`5MN}>F>|IPb+;cq@ctcr#O|opcHdPU zvwzIIX!g9)>#y*{*qo&*4CP#}?31M}yK9wYo~~N?dB*fr54>(Ji_v}0x4AATz)Mr} z+H3ch6Z&siWLkfl=*4)vO&&5RaiASBD4`A-l(?p}RX)J~zsrBm|K|Ul|A#sS`uTeY z2KfFD`EU8({=ema&;K@gdu2ORnUAloc_o~n&Gni;K%24i!2Dv?dpEAO(Q&7;tD;gZD) zP6e*6vWS#fKWFmaePRE7RC*#m<{n=#w`HYQ+OnByj0~&&i(g&|jEZ|~@H{H#%IWpa ze-+R6Zri-L_VNa`?)j4OcaNU2n7ZXwT-e$*A2+Qyck=bs1xGccdUP`nDjrB!cGS;y z>x`osykWAP3wRkFggJaJ8y(@>aLUjv>B^Ty;+#2)6Ab%&^&UiKs^~~;6|gX2s!kGP zT-IoE!_-5d%|j@0stAkdE#;Mk)odc1t8%|g+Ps2OkZqw?)PXEFmo-Tut|>Mfw)i+R z{jt&)E856tppd8&b)?}^j_Quo#@K96-q6~Fh&5MC6@!nj=nP8mU~DaL{XKC-v4+B0 z^(Xh(g4S5}K4Q7bqifBRx#Wf5i(-Ga{shxgtj}sLP z_q=VR{Abu7U@2PcEgAfceG=mxMJIW-q}f}eZfCr9j#W$WoTG>blDJ{##`;(OZJI_r{GCX<4BH zE)Ts{*fxChidpTPRM}#^dWk_pOVo@`rtHFtqHH$=q;5}nt0uBw(wl~WqL9qV&mFoM zR24W1q7$zlStEK{%OD3 z7zdZFw_25IsB-3!Pls1SfLalgLff3KQ@&f*yG>hj#;RLz=DtVuDq5Dicbu5ho!?D0V&0+Fo0M2-clT0y_SxPW z#+j27dptF|mo(-^wTn8HdGjbW3M9?>!6d-c%*0@KCic3i*1Qz2cPc;L$1OKoep24U z?1wGi%RA;7N(Dxz=ae7W))%PmWKo!LBx8k0vYG-T!+~c9i))+J#oQO?`Ddy2@6TSm z{`P+JnwbaFdTxL3Po0^&@l`_P@{smTyFx;J&uN_ACpN2V!NhQ@$}+uKuYA@nlofIn zwAkn_;L3ljkMVNHflW7}+Lan43Ot=o@MWu}PMC76rJ3W(u{hqw6we#qIvN_@<+`8H z5OUhY!KoVWJc+4M_R^+~1d-Uuw(2vUMwr~*Hc@4*n(hZ7PN&66tsj;YG)_Awt#u;j znxTec!nwD(Q<$e;W@_&{{BX|Fc9)Avr;M4^uYL)U>6?6KrswX6nIYLn?z9<3MT9&H zdv)}yZeu#no7^_1#L{KF{cE{?J^J{cO>noRvzKRhLdmMz(T+~LDn)(8Vp`t%rhvd{ z${ey5+n817i z)F!grVDs#F$tc6=p{T$xEz7i)=Mnpj2hwx7?2rCrmpJhIbNTW!-xqghW~=pmx-xNT z-0rI~Z*CsTu)ZZIwJht*DIZ3Lf_T$AeV^}G#_YcSWBc?8bw-=s+aI&I_UX^{x|(aX zKdoj)N*lIsy0o)T_xe^5>sduEf*P-1X`c3WTqvd+aYaMvz^oN#Cat*18X_RbEFreX zN_mf;LKwS}OXJ%FMIKJE$(}cuUd%XYmZ01zp)A(E#YktXQ-ffD821gGiwQTk9Ew=- zWs!FjccbIPT-Fwi4reA!k!_*}cC0mO5>*mpn!?j2vT5z1Nm?%YOSc7N^-S5Ol)EyC zeUkRnZA-RJ$hi=(ttqhdsq4+(@nsDqJ%O61OIp-9I&5Q2Qn$Hf9{$(8_WupD{#`jb zGyG;O*vF#Tcvg%}EA)m`*iGTjn=(@vC+4(FOqpD7u{-1UGwVtxlZgy+4bLY0-ECqY z5YlbV)R-B-5aRaLSU`H_96PnmtLEQ5;yV3useA($V;AF&LMCoGecLH#3r!*!y%hp` z!aT$TJ6sza1VdR{Ta+i}3Lk#4YPZ^Ywic(0Y(jx`dzx!C#LGOlEe$<5`!D+mX-hGt zey0P^_3i6seyd4JEm<^ek!bkwb*s}74!m&O(iF7Hiz`ZYS@4A`mnYeliT?N7Z+2Zd zx%xj71H&3COXf*}`X4u}jb6D#AllJl5B~)oZ#9ks&TKENzm(cvcAUPdBTv@woZ94E z*^L6unZ2$p-t87t2?NkM?q(-!3g0Rkny0^CBW#7iF6H%-*`ZGub=;qEujx9@RijwvY$$PK z)m@{6tM|9~e`OSVJb~fEtOMQu-&xLB*S5h*U0;8yyXBIuE52xw|BM(zs`-G7#Xs6k(pP-)?>Fkc)4}B4zGCG+)I4kLwjh80)`oV?E;er#FD*CwqppE5j9*XT3aUIsIN-ShGB+q%qr0s zO)gK-tu7U*8QV@y^k)EiisG(SBzC);q*hXd} z=VcMc0&TuXTwBTJG(pMa!rX|o$*Z=M2G3mmxM)hIWoU?liUx0!g^FU5+B>&R8yQdR zI5_dq2~Q~oo~T3KrZ);^qzVXm`%P4J+C4EWS(&+FX0#BCpe}=kwpUj{sDt&lrYWxt zjxhwhs?ZnSp7A`RJ54c5UDZkJS5R*EoL?;;ccz~(=()zoP;{lWsM0R7?8~%Jg~(fy zv7YD5^lqz(**=K8yTK&2MJ$XVk(J?I_1xccCfOUve7JqqFW2v+VC3hpga7URAIM|5 z#`Decc1HBpz70mk%nS@U^7{Ppv!DHWy5f5N^ECOHi)Zez^PU@-SbE8{@BNx&zRsn& zv)>BG9@pI%hj~}>)90L$4T~SOBSt& z(SB7mu{D%wrLD{As|+3jUN0vwIC0w)UD3Wg(K*pcBH(hzHu1m*&T71j9Sanq44hrs zI`j_jh?pVBb>@Pc48w*K8>c2{PALd@r^JwU!nQ@#QS!u^D-yyj3=Cc8GW&`dCMNEB z!s~mJdtDYc$61enPlpa@G3rK%IVtk`=pHRx{Kz49`$p*rR$>QEnFx8EUeqPqxKCu3 z^D)Z|Q3o?tHfJ7&hStCy2IdWC_srfX@!g?udE4!#RhO>?vcy%-jqUF0=gt4{Hcx-4 z+pXgb@*nob%k(Z5o{^bq5}|v^?2iQRW`PZEptcJm1H&;<>*cpU$L_BS?R%AWCgs0l z^4kYTAN;)aw`$+_s`B4IHrHJFTDN868H2PhzxS>ASL?NR`?ms(FJC8K&63pXovva1 z_^+5dYhUifHDUit=3I=KdvzD*7vIQfFFnK^=NP?pT%RvIeGAK413f36ko7lHJ@q0w zL*BaSCN>*+Z;+~Dh+OLT{nR1{;qwNp9Y@U`U+R)Pr@nntS9jDRH5Z12FGuy0PYUF0 zN=UlZ%5LncdkRRx0yt8N@k zS+M1L#mcY=mJOQ8E;bD+P6m;Qypvo?rlj9lWmOTCKc`{BqiUv(8GgIpcN_o7=KG^i zvFQE&#awc8?nd{Yl7G-p{(aXJDf9XU=6BV{G7fsYk(Iqzw!$<-)ev+7b;561`wQ_s zyLP=f5T(;vCm^vXS@#zZPO-nXZ+znh1p`ERxDYNtT8J!je%_U7dT#L_(v@3N^ zc8ZM5RA-x(xBiROt7D4~C~kP2Cwm|%d2_>tOUj!c_z2`hG-MvUFpX!UWRSBm&jy2x zFhTaB1pO9fors)8;;SMKJ~G(Qye+~rc-{XK&oaZF9(lAdi7WW))di)qJhP^;88Iri zHm_aCxH?qB>F$jQ%~^t{-=>)y*m}fK)&Bh=e@oF+x0;4+-BJsDtPF3dov(UdYBeGG z>XKLK|0L(#G~H93E8ZK+EKw=VaIZSIw5PkiL7L;(xnTZ34D5TpZ~fKOaaDcW#fupk zrb#XyX=!3C3=cjXvvR+E>v7tl6$`_R-S)EVj&$8Kn z^oI95$MV-ZPUv`7h9>)#SMs~|v`(q)(RiwHHFp<}55uHnOScdKQGw`=9#3zV1tFo^ zzd8j<2;OR8nd}*M++{~o*VH~wb}u$&Imrgr^vcwe47&@ZBaScUo_0X**u*sr28JgD z(zY$i@MsrMIyq_M&7=BvF0U$knrwdPR`0fH3tz-6KM-gk#Br<4iKS#`bm;bl!mjx* zYI7Z1k0otf@hVH8wEH&CGVSZ-VJjxf9g^M}qsJALqgTA>)~au_(h^?D7+pHlW4K__ zZU1@ASsF~&oh-U_b*p7dV>hR7>baW4?0xB_az6WqMM3f3gK`wQKl{c`?0h#{eFHo1 zzSXk7CB88KaeVSNZF*SKALg69`+h$V+EDa(=IbwSJEEj#uJ@WX)02Urpghohg@1bc z*Uq}sZ4wi+?Y9cIKVF`bl(yrI{`#t$GOK)Ud*z?q<-TpP+TFlRr?9F*f%S{@)=k&a zF1)tHZA&9ZK$OFRQ%NEDyR5=I4{#m5k)?D{WZB&v=?8?)xXyM{JXmqCZQ_CEc8h=) z4iTQ&wnAZIKG&MpY*|ojb!CEIvc{c|2iJIOdeSwWBolp!O>c{`jXx;kHm8#%Q6)T*Ii^#TD4&}_k>%)TnY}(YIj95CA89b zH<{dCWttiV9^hbX*oYY5&|qL-$cTJ)L)-4Z`~M&pZ+CaMVBcsr#~^RN|Nj4N{<{SQ z1Ox{K`}hS1hqyXBxp@Qz2R#0}!O|~zXO6dAgg2+pomCRKldaz|F)%!Et(&@X>o0Eo zcU{Q=Ck{2YForR(6xf{1o}ct~=blSH+sw*T8W`r?+55)UNuT%Mf&CV{W1|J+JLWwo zzkb{3z~|M+>}p=$cFTy?jMR}}U{IKrFx%$Yi`@5FndS+5UrbZ~d1bxp<@axYeS567 zJJ3>hQ_SC^v$jUtuj#gZD0Whgd%y1Myt3Hlw+-v}WG)XV7Id6&i%VH+_RCVS8ud>T zUIoZTDd~uEY3k~*HeYsLD0()`r;lOrgf%;|t0t(gU2wA@VeOGkqEU)QYrG@^S#Bu% zXf1Nxuw_!S(UxghT`ZTSWYQVTj8c-d65h%jU9^5dgC9e7LR>hDvFaPQ9U)~Cj8l!4 z76_R|uB){WXcpuXG1A<;bN%_W3xSEzNAg-G7k(9a(&-rzV`cr`E9(3Iv=vLr*1tAB z?Ru|7>F}y0&DR4hwivNJKm5PDO8Nu~v%^!fPIi-h7E7)kakhAIURP1)vLdG>gToCM zhgPTP2Bo=-->PJ@U!UOr!18{j*-|+PM(_?&nN6EMD`c%Rtxdmq?|NU_wTm5VLQjea zgO;$pI30IFCE?PnV{?XmosHj}-vbk_x_wsXxmZX0; zsi<=(PA5rGhAZmh8J80WIwUtVuquT$DN2dY(9k)w;F{j86DwWxxSm=$F5EpSX3~tK z3=@p3nLBSWyi!}O!0@5<>BE^VZcS6Jdr#B7J$+5t^y}&68>d(|NLgI6u6=RxRCN1> z#);aNH}wo6FRW%=)|7HU?-E(-m5EBDL$G0w^IEt|b*yEU_< z=>6B%`NWe9YaZm;Im}Gtaq#3^IC*JZP-g1c>eEbNXL}Z(T5v;H_qEb)?PkRYosOxy z=I`EhW3}sQU9UFzmb{g|Uw<9zSIL_5H-x)g`-of3!opMh0jmty5;B?Qzq!0Y#6r$Y z?6GJTr;XDQ(G#jSvn}~_ByV&meLa)B_4S<)^V&xlKN(x1j&i;*y*p#w->%Tmqw~(T zUwHqVxy9Fz;q$D7xl`Y5scwxIu2{7@War_=+fy5@t3&oyKk-ObJKiVB`L3@$a>MuR zjysu2dx}0PDRX>0cvbIOcldISbL)@Ye8;TQF^%C2)18E3N7c4WrP#f0E4z0EWVr@@ zc^MKK)ZNd=>D0dQl(Turm5s(T`!B5x$kfTzeGD~)>>ROd? zeT7pSQ|DFv0ulGVw0rYeQ{qCy*F^jf+CDwt=G3HVrs`iL{xanpwPc!Z$|U#y(3_ld zr&)RmGAuUkzvk}x?rOEGoaXwe*S$5jZm&!aKD%kd9^Ey4-DMLG*<1I-#YL{L*yM0k zMQzg`RVO)y9qu{-C$!XWP+q}8Oa{g<#%PO`6aR@PF#U`$}-JU2> z&3esX5386gSMzG|*0y!`1(v7=SXa$v+&Jk(;F_dRhBeRh16X#I&X#$dc{1MX)XqNh zc|uAXOS>2=4ktt#YyQ5Sy-QZf#?7&jT|`oN*9KhNe{NiKV{SM#Va>d0+9mC)As z`_++EdD9Yw%}soMGd}b5W9SzOVE(FO7qI5)`u^`mYp!N@r>qorjkz{;0;l=JlL}j= zAB$S9l_0tKrT%esK`EY#(`K%6tJS}#@QEQuiMZ!u4OV|U<$ZVrQ; zoWu3vb9Y|re_?kB)Q<{PcDue}-QEti&{w}RTqC~-30a;wFfGURvBrT(#_b+)s?kNC znC2wK8YS@WfB3FHE7eS4dHsWb^$k%6mI&-qs#OiUQZvb63K23Xx=#e zMo-wB)NJmhj}EQlT*@cZ=^W^Kf8zB&1+E(z54mecb+3Ia@rAuhUir@E8~36f@PA-^ zzgxcd+LpgBZcg14bW`%Jz@v(9dspnfZE)-6Hm!3VmQGz8PpdF6oG90uzfQFJcm3P) zo8jeCYPw#(>e>AMao&qNn|l{;*!bPt)YN|Bxwb9m+d>ZMZC3dza`OC!4N{Y%=0rW) z@ipkY@am$_4b@dmrWsv+3`*^BOhO`TvzRzOrtIuosW?R-HR%|GY)gnsDD&fky<*&Q z1syZI_yskxauO9+bhI2W3(yc@+sUA;!l+?#wSnFOfCk77jnlL*utFC*Gjx#u{AU=NU)UdD`ySf6EoJ^&iN%3$Gghc9 zn>mw(A>moQg4U&DYx8;X&F4>xxM`3j%OkzdBfLB-bxJJT?B~YErr9>8@SaPPwSN8j zzVgo0ZF4n6O`H!)i6}SqxNZ^h^w8r<5G#%FQ@nF%4ad}K#e*fSUdyG}Sr>^3az%>@ zD+cN`d4(KsXy=%*b+vB>OAb?5r$vM{s~W4{$__D}yk%ly9S2{RT~zZkY1uL(A|ui{ zE%cmJ2m{kp?M7AE6H@HiM*UvX1usN2aV=xs7*KN4ZvKM>`D(8Z?NN^~3~1$<(Yir* zwvr(CX}gO5wwj8fJ5nFAe)ZUL)%g534|h&p9pn7>VR_~$yRBnYE_%IiIWT!a$bp7Z zxrP_EH=dgJ#0VWys+ ze)F4uj0|s*r#j8ka$6tG{eHVtdY6kua_Gc;yU+YS@Hb8D@TyogZ|73^SJN_;1eteF3=h@6c=cOWz=py} zd}=a5QZic$-T1_3mNYJ#EK#ksRid!>plMpC?G`QO;M+}%IqMH99P#Wq=GOB@VZ&aw zL!#ODV(f z>w%7xRnscY>wilhPJ6gdjzu>4b7{nk4UQGl4p~i5eW`vwPlHQ|LE2&2(aYs;@AWk< z>dVygu$QY!sOhR?FPy@EciH4qOed20?&QcP2!=8I*(ogXWqSR2FD1$Si)6T$?pnNl zQSkE6TT5djr_JCyWN_)j){Jf^-jzS%TyDOyH#P4m;%H&j=vu^~a+Pt-EZ=Pc-4DA@ zeAe5Y!LU(M?$2BM18Lq2V)E=W_U0sfWYSHJUVqtZZdbV1(gR)Yi`Pbn`mEixO37`p ztC)ye_C1~2CIkJVD+>z*l)c3ol33o%yM9&XsMEcQ_n%8`c=!GMaq7h1ng(4Fwgr-$ zatT+itxp#@zRBom+}=sI-UMCy5+`oIINLAmN*U|dkj`gokN&+c8FTGRbmh8WhU_~f zOC?#iv=uYuY1?Zw#bsWNIA&NNXLp{xL+h~82QkhgMUGOvYOc3ivmzIVJmR|+z!>Jd zeuZeDMyy80V+DmR+<|MhE)rP0%~)X@QS8b1yBuoTPA=i!IB~zm{MXEDSS6Vj% z!1Kvlrc9c)VCPKL*sH3m7vDNm(7w{+=|m>e+E2V}XQo|cD^dKXBI-ExRjRP>H@*4= z9Cz4naH;VeNaecmp>OWBK+87Hy;rzqUAeYs-G(WvOuHAmuD0rq+|jnJ)#b~o*Fx>y zBJI5~Qd2g|=d;d9`^ln`T>rx^uee*sLE{tq+vk57I+v!nJ@{^^?J@D(_s9O?zDhe& z0(Wi=>J$y^E;=@I$%d@b$e$12Y{{C>mXvNji{U8KzkhMzNpZ6^IGR{W_#!HY}b*r|6)2fQ#MQxN6dp6H* z_S3xn<^IJQDuK&58oZk(&&v|(=D|vtHY)*&I~`p zbxI?_P&s?bk3{PeqPV_T7?7rptJ=Nn!-=w{~Z>3@Tv95v34|E`Z!OO(t ztDc`;X|={!&N<{2F^y-6Mb1*C+iTWwNodYFe(u20E$L1-lG*1p`EI+Cmo&L>(_F90 zq9u2^uIFt3&7f7{%<$n$ECXZZwku4%dwot_mRYQm?7ZMmh4xlGuOyeEsb>Q|T-*Em z?T@!S3mKIhJ}|eqU0hOh`}ARxUcJ_)B}Tp94CbzUuX%Z@Wy{Wl0}Twx#g$i87e$4- zQWwdzZ|eSsd*;VJYl!K(UvP*2Le`-I zhH3ha(@)7vI)7O$aPRb0QOA-5m6t9y6j52bdhzP^z@vQAFC;R=O;KGF7MZG5p_P2t z>)g`iib;{Mt3Ylch9EQ<7#L!V*Xk$)2e<_J{g3?b|KHci(ILb;IN0yM!+*#Bp8swC zJNLT|`#HCEL|ScYH&$Beht=@7~w> z{WPK@u0)>wXJnh7u9z0nHHEDiYUyq+A+0&%;aOU03?7TNC5><_O^A1^j$^7eUcy`&^i0@4i zJsMXhWvDyrv2bV~@lvYXt-*L?QttK(Q}a)*JnO3+Q5yN8(|qyC|NIXcf*1~5;@R-* z&GCq;iTk8pebrd7YKG|xK^CpnuGMe8oVutUD)?}Aa_Og*cRv``Oe&sg!2i))qpZ#1 zYa7QC-~UWUIli+;@Tl<|nAET_{cTOj-@5hBe*~_S57fxoxn|0Qr6t#QndtI`U%Rl- zE0nAImeS(Txm|89BAl1wX4OA7VCZRcRGK97_d5T4>nYt9iD#t#|M~E;mLWWl=fI`q zjn6*I__WE&KVR`PZh^D+F-M6M*4IL17qYK*&vTV|Xw;>9eHGjFYb_fzT8h2C_!hC= z>ROwuKXHEJgYGNaqhzx+m;SxXG*^Ar_q+FZRn6G(@?&LSag42H|2o^K+HVhU_jP35 z4mhd9XUxFxqx#GCyLrLo)z6>o=zhOkzWtptySw|bxKP@<^aa!@>l?ImrJ#RyX4A&EhQ@i7%SjfrLKEd%KgV?1FEj-&25-(huH}l;b&x^WW zW0O6WzA?D+%j#70O2NA-C3? z-FHpk9Ldd}uSGuVnzUF=$7Yl9%r{#%UwZsa@|*8!^<~qSKC|7pb)R0a&D*HEdqeoo z8WnmZTFWfl=X`b7iWb2m66)uixkZvZF0nvg*6doUk-7G&M82>2xZ9y#Eud4r_RgoU@W&6hE(@Vcav)p40?sh|MM8X*Pl z+g;8JBBwA4Eb(UGlx3W0#=yledsWgx*AEo9{6>kM`B)7TvgQ zb>rV*4>cwOwT>PxhHLB$JxK>uGR_x0_~EsAPjQ>6?!DdB3~6(d7_wN)3{R@A@z;NE zVUkv=>Ko1wo*izi)jLaJ9nsS7hCOvZ&*<-*CjBno^o&_tUBPhn5@2u?lpr2<{V{o2GbTnR=_B#0PChhAnMB z8UHxmyYcSZ7H_c!@4q}SIsct;jfES-7KRw{Z3`bXZQ)t9>gXhmS1UO;%0#$mzG+=> zy2xCr{PyfiyAE8}kU3KI`;4dh?f{nDm*!`xvehdKx*1>bZ^-gt`p_x*;`<#xCtD^R z_q9)-{>)w)&Xt<7`hn}?V_s`LTHNki9H}s!J~8s`iDwF?E5$kEr^aTkS>mznKXXr( zAp0%J!yng|C5B}BC(pRc95+GpOim@eJTIoDuw~Idjhd)PrX*$V^xGNJLZwP`9=%NX&bV!ZU_}Y5 z-i}AdJlkaSMR&g1`r_Nh@Kt=T7A^{Zy2A04RZqsnB|8os@t&7pl6p$$S4qMnQP-uN zybWRuB`q8xIesf=N}ON1<6GbVE!zC0J-(U7^6!~*HZwgq>{qb3_`6q0$P$fRtEQ}4 zV`rhiC@nj*a<${cDCf*ljkWGhdqey3KlO$?c8H$bc_VFO%7KUt+q4;5>QdR#wCf$Y zb5>iV_F2rdU)cPYaoTY~hWksr1OCP_AM5^U^Y7B`O&zNoqXS-E2zPc73|*_BwD^`u zDetsH9Zp+M-dnU)H7lc6iK+Xlh}G)c%OWK#HV5s^ZZFq7Az0A7(Vn5f=(ZBSc2-f# z#NQcaM)9Q~t65dSr$kIp4OV+_tkCY+zNc2&HS$?yn|E^tKMa_-f7cTCvW^RF{(TZB zXVh5ayPm$>x<2K7d{jhL*6|`~$*VGJi+5dGc4;$D$3>Crk6Jr71ZfAZarN`LGoejj z_5v;Md2(wwmGxYWBHOBT7pou6>}J)T8u%lkq;k)+tr@eD7!0=_e=~LVR;#;fMOLtK zt(nrXOo353S#@S>hK1|I#|{JUwN{Lg*4uhPxz zdE4T0qfaf<<E>BpqI$guxVx5qW;W-uE4PH9ZuO_Tm+7_M>e84v9q@ihQ z*VdVC91KD$jRkhDDD(9Z)%&*JSev`eesT$;>U@n!la2>^CjHCkvsCqImMCE+$+?*eN_pwL%_UwBlLTf5TR&D+G^Pj5l&I0DbZIi#PO-K&h zs-?StoB7KQUfBR7Kw!|a}~@H);zf>aSf}mQ-F~(g9V#bM~c&8g#!!k zIw~As(_G*r&3f?2HeZDUikhXzB~+e9JYKjpuyf8^%~iKoaXd`ClzC{2NMMDGX)b@` zbT!{ZCZDgn1lV01c0|PVG_W$poXm1hNlF(qRg+U`oTH<>k*`ys+F@qYS$BoVuIf!J z5&|AQyr&mQPIp<$F(-7pNQ~=?(7hd-=5qLO#CooqmcneFTx#+9`{`>|ml=Z2W=(Ub zFkKkJ?^Kwhk|@o2AWQPh_oLPam{b3+`%x-;%tNRzcgg!#8J2b44gGR^<~~>b&=|}2 zgEe`2D%T_SWt{J-mD?0^xNm>R-FyDl2ia3+&hRiWux&fvZKWHg?A;t+c)Rc=8}H^k zzT1kIbxoY}uFhlbmA#x4a63%cI3h@5_EirhKUZC`RcS#dLO8=!O7C>eQ4*N7fU~1% zlIt3eV_YFK7rALNa7rglY-9?%ZBe$9gVTAZ(&X<-oqZmU)?{gGhhOrJT3D^o#3Hal z<@AY^GZ9l~bv)$JWpnP9SieB-&9W-NWpRs6&sxd1NocvwhK}CYCkukaG>n|uf)sc2 zhzT$=W$3)vs@SWu<^mV%X$MsXqciNc=GH|wG%j20U%E|U1y_sKlv7=NslnZ{Ykf>@ zlY}lbYb z6Ynq3)n^Btw7*hbTb>n=~xt2gOlez&_P=J2M1*oK=IxB0EQ*fvE+ZKe_< z!wg+>KECAXC38A%@8MC~xcJ}AvyQJP1}@Urc=2L>+w<<18GF}PUEX-jE86=0WZow) zE%rsv^=DhO`%A_K@ziN*2OkCQvC3kN2x4aVG;Fnd~wlu9~6Jk3k%yM~)QmbRC z*s7zm^i&qF=50*seR8egrEU`E9z7mE(FGc1+M7BLa5$$eoHlo63(G76P8p^tENp_8 zqj+9rO`Nu1%4r1_zb6+`xKFVpELtGrmB}zc=&|0RB+ZX2UU_LUyzuCqVi(jZ`%!3v z@V)qiWontv*cRAYp677+>MbpNv+tPC)C2wBdM-GG9J^t-SG@H8f;-oLR9wzclilyw zP@eZ;!^$g7Q^Q#H11n8h?W2Ie7v?+s->4#!zr)aWQv~A7AEG#+qa*na^G2;W%KZP^hxIj z<`Ih+_RW49?EOPNfocEs!n~Egn0X%fy=`5}fBS{NqJ4`m8mvu8OJie5xL9ZEbLLp6 z-4V$&)2+KI%+t56v)(w*;=e$*O#cbFtf_1>c*Quhm?(Ke@IK`2F z?d9s=;^Y(b-|@fIe~14r|9xFOSQM5UUH&nt;$7f0my>_^Qg*&QYShUyO;}>BQETeV zi9x$|PTzTz{qxp^CvV;0(3{XXd0%GEJNw)1XME4zx%FdJc^D(BT+iL-njQQF2fnYi zJtlU9ebsWteb%>ZB_#wcj9CtwD@oV2w6Uso-b@u@VEA&Y^mfa?Cnw9^EB<`0UY#Cn zb~<==bN8f@Q?F7s-nF>k+;>UKv}{t;$DoX<36Y$hj1w17_Y1ulBb}#UbS(EVjS6Lf76^U6ZH9aD2mxQ;W`Y z1-q|6IORAYnmK*pWhmYa8SGB7YiSni(A$k@pEt;^S&|4(Di zjD@1o)5U(UOB}F%CDW&u?dRtkR<3&LZePc}zH4@S%+=Sf&ssexq6gG|ym5?Qf2rN& zWA|R&I?69m&HMS~`=T!&o=2>^8X=Q#xy<)|kh#>|ZEJTeeI@bj-Kv>=YqpxN(CQL8 ztMq8saao~RQ$(7cS}c;jtmx+JkdnB3>j{CivozW!GIOW1cqpw{<+QRtEPG+V44>@Y zRP$?28lm0ObbY31>#M3B`_?n@nh=|qpmr|L=jvAUhw2qe&@E&a;j`vL6f$;VQiLPwqO?1EuRU0_FrpB*JSu2VG=m` zob$vFJh|=l(>WOSl>I!Kl6y9>`po59q1ElXrXRe1`38T0*&&82JPLbPp9;9yWaPqm z`kj`G@-Ml=ueg$SdmiUb3jSSpZLYT4UX{7iXBses)O|cOL*idsw2eY*RV@3nH~)E9 z4>8y`lm_!0m@mz_?pMI_5K--Z4v`Uxbc~ zsEi>)OPMG0&m;5qWY>iyvi()r|K_e8gWA+!4u*Mp4igd#re{eoIbIR=C~rX9px}ua4n9IJv_{1FB;N@5PyYFmRuRCv@&PR@(yqPS%Q{?C5Y`^JMV$AVd z8+5w;SuvIb8`eEid1;LE-ki<6xJa-hV)d%v#Tjd+rFOj7sI8STB}(OO1+Vj!q*!j& z(@KfAxs)0m|HYZ?VqxA=W~}&Y$MJ7x4(5f;>G84ZZk>FWJwmdLQ9{%r>wIA1*ScP< z{`a|sm7HF6 z>(lI?E3Rdq^SN90aq`j~w}0QXN_B3D_GDz(v_C%TQoqvo=TUE0UE3hT8Ypmb^s9g=8x@$b^}%T?cJ@+ID$80p&d`k15n z(@UQtS&x6XuQ}aLT`Hc<&^PHwq93rPVe6xPKM$+@Ym4Slvt{t(6<|LA&CW&)2zc?^SnBdnGlmqR6AC?(mrf%fFca z=vjPc%OuyhGx1{EZ%BS%ogsagLC5z&_@&pc`PY`%?6jLF{(DpN*1JV3vRA(PD#f`z zNPy+5&iqufMune~+l)_@y|`NbXnV+Xr(EVGX`$>tpVS}PYQ8gt_20Dm1vi?1F+@*h zdoaC{G4IbsQJwStuk4;II_DU<@7v*3e$$**d$UH0+CJ5h3M+l+dUCJ#WFPOB%&9T^ zFDY$fS^p=ArRZ@CLrqd8bJ6tp9o0*tt(hzD=Iyx6zoFz3!x`^}qx+l>R#l1w9ui%- zsxTgCT;HTYbQFQNU@!nlZl}bnX8VcHbF0ZWSe{H*!QIP$H zMNtZ)#7Tbu9S5=yX=w2K9hw}?e~6)efPa6V4|y>IdKWkZGVP2K^HwIi2hu!eEmswuvVFZ z%E!gBzx?J}nRff6x~ekRS>8T(J!oRcDuwH3wh3)s5}vcR>y_E+wz5^{bPm2N&zgOD z*A=ZBfR?(IdcpHP z1s}@$!riWO>*gM>o%Qkuyp~HeNb@|{@MV&Uin&lJt7x|u`;thtb7p}pA0KV;n0R69 z^b5r%`*tU5$am~#JTfVoB`tGbM_$s&t&C=OT3**S6a=z31UID~Icibo$8dLki}^E) z)g9Se$_+(ls0Q7fp)qOZvI*JGe6O1Ze~b2T=U&rP$o@CXYxkdP2Kfu(f*$^`JMc`% zA;GL6@O#S=9_a^Vu1nTrtnJah@~F#orLjn_Q%6&5NNSFfX%ti9qOQ9USECFVqA~(i zR*Ew+9qDooYOk2jx&CifxY~nlf0~=l@CRsTGI%j93o{d2{Nt2@mu>bt3%%*C>|IkW zIz-DPdW96VqFl8#dz%(%tvdGm$nK4(c7c?)(A-?G2S}Wo6GsB@yT(gBiUEC z-D;L)%*+luJ7(LmD|ggPLXBe;ww;dh zmi)fr$J&K@sTQOh8HIe46;8fJwGqwR+r z=KDViY!7hm+dcQ!6a(dsyws~VV&B^I6DLYf8o5oKILhb>q2?+;w4j_d_F(Upctp_S>m%vZIZn*0SAH zHk?%6o@mg*B;s=V3&&+85AUnnVrQ*Xnj*=fd{RJxn^&=lrDsFLj16pI*6t2YtB+n< z#>}d*$+ zH&3H7L$?PUl8vu~Ie)7NG{io<5W4#Cz1xybwKGoMau0o(+jXcztze5@r&FS5W?lZ1 zDOW?DXUXtJTnXEz;UeF)>;1*U2ZB2iXUsYkaqF?k<|S*+oOUwt-02ax!0A;7C;Li; zzZ~wLR!y1^w)n0W^On%0+@2_oISlt^$1aaksuQx{d|=;mS8uJ0J+I7%{qmRkRSj<@ zN!M-J%GZ0XC$kK+-BP&T_+j3o;@NF8mjt%YHG1h4FLUMgIkgi3RR*hcZ6=3idqyQD z%9!rnwK9H}+isRuEj%kM#Cc0oxutLOM#vtmFkBa!E#!Vp>O{*$KRFerP~PAZA)%>) z1^&^uGF3IgR?G}zFb&ZvJYFPVb!<|~@ja=M$y%JZj&v=|6tT+twN9}$L8g7XtAoIE z9i9ZGtDW044)8S8Oq{#OTG(UZ1ku#nZYfbK+b?yvWCnLLP2!LhJ7BQzQf=XpU1vP} zQ=ArPI-56S=85SRG|gU}a9qOu36FM|zP?FH@8+_%;zv0A{J;9V-=e-{>m*I5o>qpW zH$h91BRLpVJQ??TC-=rkPuQBout$H=_c%ERA;C=yLUrsH_DOIt*!9Gov+R&hQ2Jf9 z{;{QRhrK}V=2v^QcW1IJK5l2_?tV@1R^((8V_^n{hF^836COL>E&X~_y{%=5ihzAU z+M88Z|1GTY?sW6tyLjG2$2Vf>DJyzX(|_+sn0Ya2iPCw-@SbH!rB|Id3MFfHGPZfF ztMF|+JfU+M+aeLORuvn~Cfh)bZ5K6~%C>eeZPDNmh-y}0VET4SLANnC`=A-)2DJkd z-d$nZ);-HHaKmDU_-RYIS=qQ{)^X$nimV7w){{N4EiH_3Vv2*A8^fV*O{-)!vAptf z5o~T+!PXk#c-n$d+EZW>hjaMi+B5E)FQgJ!l3ERQf?g=9N+0QY==soZ>EwOuzgmbd z`8qRz%VfgDbBq&nrM?GsE1h_o$Y4{{@7$R(nMq-__}PX(Z*3)Oa&s25Ffb{oy)2V= z5wgAT@}I`~=L>t-8LplBx|P+=f%$vZwdrC{_$M^TGccrHySCmhEZmXr_lJGgIs&)0 zd9fKAGcZ)1mGWdbQI_++>@nB18QQs(^})T&)^GD}>{_<++?K-7`?vf{9j0wl&F;O_ zn|eF_z0{LxUfxZ|pM)@dos?xN;5#|hjO9|p=47LuO;MXp1%@#QOuO}V>7vJYC{U-BgCS8< z?7;y(nN zIE5;`OIW*P*1@;Bo#oqB%<euHmvae$z43L@}9r{bm7h*Mh=FQ-|dRiEnhm{I{i_wN63ro`l$^T zs{-$A-+%u2f&fu=eiiHQ5)5mCZa!IR8?3Y@@m3@^|&j0P4?cMx?g8c)6y#D+ApVN2PNuv6c z?rB^9^(AY>7W8kNvFEsw1yt*}hP-R4rI*=mJ`haJw=-<)4nbF!D6b-cr#Tg_m|$!zZtrXWE$_!ZIJZe@$6c!gVd>sW@)H}Q zw%ZB5YTNMClHpC)fHc)bRwp(*jc|$9b}L9$qBq? z9~GQj+{Tn+b#cvwcwN?` z3%iwEGpZ!@D)F| z?Sjra2k}piqPzJwgcdM-V=|a`Ga%}k@Pr3XLL;{t-SS9XGi~XkML|kejoAKf$>832 zIWlx&h_n9Y*J7(#Gg1#aEI*QAD#l<{z4o-s6ZSUdy4BY$`W$N-%q!{{7+NE`79YQw zv#4xK?&0Gbeg*K(=bd^+&zO_pz|2kaBb60C@PFl!g^Ul@v^%cL^RY|L5rP#I2y50Sv zSah2hJeRO3u2{M5z%nPv=36GU(bJ+_cQYD=oL;HP9U|klE@0gftK^q$w>l+eH{>|C zHKZ^o^%y4{T-3$GxTvVXpwTE_xQFx{*Y%s$e7%ro{H{^SEA!-S+t3@W zyC!o=^*fwcJ^7jDQ`X}d1ZwQ4Q+o+x2p=oQnpmXWHM?!m_yzBqhcWE-;=C`lv z|Gv_FIBEIHlM^gUnE&kHdctJa6-@J<64MtyOPhlTt&7 zcxJh;5r>Aif@X7r&&?w(3pXY*ODQQ%5(r{WHcgR^Vv5*aR%SDeUBl$SU&BtL%R-G; zSG<_Su`NyMjYs>Uk8&zvsquTK9bj;i-fs3G%1>~r(N*c34CkVaH>w4=KRUaAS5TOA zL5cZ(;G9hw>|qL@{`+rWU%((Y=k4n`9r82yD#|zJ&U^GoUc&6dzCEXTR+~-?a`VuQ zaR198U)Q#6p`I~luj!Jlv4@K8Po0%CxkGyOt4G&PrI@PReRZ?rXvCzxRS}luZ4(0} zbG9U3?AgN-B5rsjXo`WPcH_#QiE=&);&PK{RWE=$9)U439dbl2@t-UdRr0 zJvH~VUQh4jiOknK17DZ$i1M%~g@tT6w&47sR@F?84uJ!XOdP>q@7fA+eRw0V+3iRQ zCnv+!v?-lBLOK!!9jc69N@9+NXfEEjNR81)EbN-+Ch?xTfqDwxiymK7R!Y^}P^Q!( za7=>P`rdn&?H4DlI=s6=`|ig1mtJ2~5OnWvddS33H^+9_ybJbfG9TpPzb`%hwVzRX zN7psB+23=YZ&lJ+)*$(sCoio_tp<`@+Ys<;3Y1yAX%1F-4-NMb? zS!>2u8y0ps?n+n2Zk>>e+pf7vdQOpT->BZw*?3$7N}T8-!e@X(cTX z3>C;Oeh{%VFXccH%aojcr=v67%i5bKEG{@?;e3ZH_f6BA3>H4aw3#OuJ2tJ<=nvnO zH`mMYm1NDFIUbhzRR*>*DweWvFbQo?aSl4=5MHgW8G5o^&io<6J=q$+yXDM042xfh zDsn$LZLmq;q9>OxldsGYLw|-gE2cR8Oq)hei^~?94@{UF6UaAj&R#!TRr>?NfBM$n zz8Czdy<;)Q{nVF_jmiwA@6C>Sc_wWJX!`w9iQ{{#}xK^ZI?u zZ-RoWjD@qSbJFcHrFHZDjZCc9CC#*b`NF}?>&hpi#g3duDz^C+y|WY*(D3Mf*(v6t zcPMpHrWQ|^QkbZ;he;l%!two&%-Q-`HQYX<0PrT;wxgnRuLmK|x@W=i0{XgFnyQ z-@ZXYWdj4lgqVnx6BsztWBim}%`eavI3cDHa>?nSKy7$t)zoIG$pV{>s2td2R^@)IVs}9L&%L=hcjsMQXp_QbtZXUGS@-K#--@yy0g5q(Cm9$RvU26OtK6-8 zo?ckJd3W>PsJl;&KB!pyc2?~FqTHpW3)H8XiE46giZb?}7bmyVNA~Be+xZbXQO@Cu z`#^@W$aMFiMs(DK z<_$dWcRo}&o17=Lo%zIG+be3*iv?KjksDZ2XFB7w1Z~^Z-3$V z{+Y4mv;?1naU;9D#V!4gTT80Ul*}x`GCo;vij|Iv@4D*8vT*gL>GR%vx?_?2fs0{H z-$$Lr-gS=0zrGUp=S%v*dFXfz!#a^;3_9H`C85q2kNI7Hc_?Y)B_FGX1Db+@w=7m) zWI1-Ti+A~?Q^#_&8ET3?G97W7a@**C&?*@go~)MIJM0BLPK-Z<7|ZgG@LZNjc6qK- zX2Kol>U<*V?x!~m3wXJm>zm%H;_fV>#piU(TSCHeMW3Orq~4LAYkocB6>Vt}n^JXH%`5&G ze_N8_(Tp8@2NwNnQ#ujfkjulk!9p;B?Pb}*4u!-p-}GgBqq*mPan$aQ4Z3_P(f-`o z$v-Z1?|Ogr@Kcqq$JW*LK5|;&uD)7_+jb_;o~p|^kEDM_E7hKg%#YsV>Hq1x)KR9R zwMMl|c^?JoG9^?zjQf=II;PNRqAH&(%hWg5b3#P}*Dj8b*g8Y!%2hsV87t=38!8Ge zTsZ3`dX1?i?P`N(a=q!XXMuCW%o^gJ@Yh^n&(PLm)Zi3Jn;Ure`)`q3zbbMs&R?w9 zEIDPB+r&NDyKOY5h`yf6xq3$TIoXTbx3a{xUXO8f;$GGBTFCt2qh><0ZQpdUrizYz7bKS|xu0E@wl+++wUIeYYf5QocJa2vT%ErGCy$(AU|@)Szf#bJ zhcWrny28(ArJf3(Ung7pEI!ox5OIIE+vMl1t)t^*&N0zxm)a}My4*k7{43;iwThQ)yW0Ke|#}fWE7pBX& z)`o2i(Ntp7ciPly%An8`XdF?stkFy*VVc_l7v{KDt2ov(3=OQ_^C;tEcU7vrsEOTRrWdr}rA6Es)vw|!#m_3H_eH&xu*DsNlVHx_#R2X8pdh)#~61SIM%B=w(YT9NQAbm7H#yaL6ZwN%-r8DH~f{Tf0~U z+BFQOoe;@OoUlh@1C!)Q<;2#;+pX-gSd$|HEK8={NI#VNFxRb7s-h-rRh)YybA&K& zaEqtPttJo8<%$lIy|#2T9q_PVNU`KX{h6&01T^lf+V^_$X+j-M1Y-80S6s{`2WF{pI`ZLf3WXv__rM>E}Owd{tzJ z&+VLRWjlJKR=>IAW5mh8@af&vYx~Yh?<&zgXO+f(*JFCYO^c*7%X`~z>mN(8Z7y8> z?Xg^yb-!LYOPH%>=)|s6%{6X2wH5j-+CLJwnd~D$qW{2-g*Ve4fIGDGbD5WM z###uiaL5hpz4!m!^?P|d+mtU%t~Tme3Q;yz15Em|%v( zPbv%ouTG!N|ND6UaV}*835IJg0^Hv#GBd4bFnhm7jB$(L13yNVJ9U?zD82i{J%9OE z>0Nriuign@dB?mYOoY)ujOEIdbA7y@Q3dQrk^#}jIRp0Q`K&D|jm(3S(-pt@N{IS`V z>&2c1Mb%!s-???w+FNl;ua=!m(OoT_HAi-`c#yR$>&G<6QTUBi=b=O$F`sXTXOI^46Ns(o?vsZ2Kdlk7{=2lzk&*jtH z53ZV{rgP+#2Jga$)yM4lkCaUgzT5k(`Ps+hop(R!^uBEM|Ia!j*OA4GVXfNcz6alr z?OiHX%6H^jgjQIH_KHhW1AGLm3S?65obFL}VyaG@>U2qR=7G2lR)^jSja6S)JYu@i z_c`<6NpH*jw+o|XExsltvyO#Ha}&J$T@oG6GKngTb3ht{|QY@-kSHB>&#Y}jCt=_ zGp;USc_96{;qR$`Em4i9ZpGeLPwHuTcRga`6vc}AQnr=pU#AJrVp!}?6uqmD1GevTH_v)#D)~z3#eyTVMAk~U zP7U2EvUR1dw(rXI91Vt@AN>16K0%w4{XzD1&a#((r(ZiD z{nh$fSk}iyVIsb>gQ7iG%U*N4x-B?XXYE_5-XA}74oU4>)!AG4;;H>VF$*?^C3RPs zp6s>VaZg<|JYn6-16SX%-bmv+z~9AiUiP8%m4_C~g1Zk?d4zlAhP^CWy-KX#?MOyw z;FWdjB2x}7Isd5Wd+5nGX}d%s`gj!PKKEm0*i!XTX}g4cV#&7Nrj@-u&!4sL+{eD4 zDVXPg`Z~rlcG)o@M_C>?Xp4S7;=28nSiznKRpCX`x~v}D6W=eJdhS$H@I@Odt}9(v z7b;h4miNv~ys{2wu2-zmEMol^Xl!}H!>Tl;)MM{k4xgF#F6c>}){ zOM{l@X@1!1b@RQ1mPX*2S0!_~QX|8!PPy?aXwizYD_u%VQm%nXLJjqdF>aYB6mFET zd$ZqGo!TZd^$mM&!f%G+iHDOuR3Bm7JAc=e^9%NA>@qpDXlr;@W}pdIfcDi{20h2i zWR53WhlGa4uH~62x^Bgc$$$3V>|7)mo$bdEk|)@G<;j=D+fFTwS~_*9$XjifEu!D% zG6<_k^&O};@XV>(G4sdXko?WH9=`F@!%U;L#O1h5?Ygt;+N)J@BHAx(Ca=A+VoA$E ztqp4eHa$A8*VP>GfTbj@@{(87Df{_hELoquCNUNo%AYzuZ>#BIfi+&9EN!p1>8j_f zUvyH#>X*>c(5)hZ*EqsNk7llwVNuiQZhh-0;C}u5tV7oCzA_fMcL(N#?PhRc3tX<) zxo<&Mj$Wa)>)eNWIkQS^Gf&sG?Vz}j1es@pyrj{=D6jNhuxJ} zxt@5a$Hm-RwQ5!B%2nFyZ+x7!=;Dir#e!@dpE5S?id}clikT&D-4gp}iOCEtVGo&R z%xdWmuTqts@Lb~2-~Ic4T`zK3ay5k^VZBXS_9-jfq}NfL*YsVrrbTHdd4+4wnv<}W z^V*Z;ivq6JnLo*#uOzC^cI6&t!k#HL{K5=#l0LE=xm@?~hxv97=11q|7u*p~&~|40 z@q=?i;C;hv6F)^4<4fOmx*CP0UKE+VJZ#N0ZEdgRa{`vGnsCEQRP(#5xa?Uguk}JM z9ReRS%-1_Hx|Hp$-gNi&j|cy6oY9fv+Vw%-NVKt&3dCeDicyKLUgl(F2wCXM``8_LMF4{<}P2kF~^vz?oeSO?L7e z{rL>fwKLX=-f{jAviBO>zd=}kI%r-RmpXn7XC+$*}*$coSHl;6$z z?;2Zp+S4WYxwb^#R4=*`D9YRtmdKu@DIarRV`_QA^hXE(-d${!rP}Gsz;|FzZOy&5 zz_l4MAuh>RgQkSnFV@Yv`*e-5*Q#GhQk!kKu1c9M<*kWiI?h#O5qV01VUF2Vravd* zBlXgn=Nlbn(D^04dsn9tz2eoH{`A+Tx;HDFHnW^bX;$tzW3y{#-cjBk(cDwwQlFaL|K#8MxwYyiL!EVf zQnvYb?hTzWj2|}o2;49Hd7x$6+TzQ1_FqcO(o~stwPn$ZuZvzx-8K2z>%j0-Wec9e zTe;-F^|ibc{EYVqo;k4+PvY%;1_kK=xJNw0c;}wRl$9k*($|p?aDrVTH^5L(0 z*ox_9@3q3K1YNz}3aKt~4C(Dy5a6z7wKeT%#KT34AAD2pHCc6F137?!~ z;orQ$b?08x=YRS0>%8k)c`3s`2h897IC1UJCbf4JC)7`*_SYt5zP)xPaz~E4-)l}; z)6%rquy#%NP*FCuFuBT!(@eL%T-M$o)M6O4xrOoVDmMPWh7LQYfG0=qy2hLcJvfDv zF+iiMYS)t%1_vb#mKzH>FUIaPtgY^5z1yua;b10%pocf>$_*})8V;;lYL$0k0t>T_ zz-*IkFC+zf?yy`HD4C|xm~>TY?!+)D^$M8=nFxs^5!ZNjmpa+-Zaneys$zca=|>8y zpR8O_x9Ql%Napp@PFfdZyuK_os$L`(#XnQH)q(Tq--u}^7L`?JR;<^6khs&u;WFZN*QW-WXDwwCu1L!H8-t5wTyG4p?5 z{V&hpaOUZ%D=F4NT)%UoKkpMLmU@U7bN+sH(OJxW=CTQW5>86o3-xAsh^U5p2pkQX zcd6x!Qk&z6c^rH6EVYu2g*-Ku`!=X9;OSt{NSWy~AtrJnYo8W}a9cq0iA0~xJv~{j zdfbYOxej`KjGeWdVd5kn#)b~Q)N33QCZulZWtx^4vB%}h8sqLQ8>;R!a%`UE_Ce>+ z4c!H{ueQ$Zl5oxxTeTugfw`4O|C`zWB~c4A*cv*!yaM02PPlX7Y-MwxF0(-DL{lI4 zDS}QaQ#)p~&AH^V#lmKxyW6X^%0{9(9(!~?J}#O6{BV(8{obEXlBd?0JJt2P&S#kQ z^Y$TrhCN+3pRAbq`Q@?KrD+#kICj4&H@^Oz@lcl%gI?`|yKB?4dyBVZU8pc}bq(MM zWvx(Ja_-P-PFuxOS&X8YE)#Qk&9}&L)zq~{9^L*)FLS=W@T%1g=0y)4%Q4JOX4v77$l&mQB};5nq1x)JMR#Y#J=Iw8 z?U9g6U`xkj?y!d|9bHRV4I;Z0UPp_S!OXfoOCR&B(0X&aB9g8l>!|nO)aTt z#d6LqMNb7>Wzvp3%9$T+!1(!gP)quE#;6-Y4bto%8fFGRcM=K+6}Hl?x{_p?9cD6p zTbNae@xr7%T2Dn5Wr%MIel0wgGh`vl>ssBmqiZ;v^tHbH*94CxFfddj#u9WH7#R2> zgeR#71^E5<`5)mP5g8sF6cQ2~85Qt99XlsW6N$n8n%bFF(=b2G1AO6*A`TQ=Rxh0=7Cb#xUzj$X$Xnn1lp)1$BFm9&cg{RCTY7_W=SKONbH4pqf6I$w zn_X@VQ7JcOTqmsX4KmP{NnJft>S@iDd$Ie=+ljyZ_-IwbDE|xE} zVoD?IGu*D8P+Acf6nRRhJW^{7U#Z}tjZBk*j(+>k(XeB2lvU|cwttLy3#LeUbAFP4 zz_yQ(p=5TY%{L{cwAb$0VvlOwJ<`&c*ccM>W-d%&sp$HxV)#?wx6Q|Ae{Xlzo$gW7 z7kcJ#%;(IF11a)pAIi?B=5}{owOY`#YhJTeSU=0a(arp;kmJV_^noF=^6bU{GOAv)Pr)RZkk zM8$RW$)p9$kz7kSgb!>=NnyxoOvvPjW#STzQhXz@NUUMbG|{939jtkx;uaCP&El*| zlkf7LlD*uOq$cI#v|f@i@%s$Eu8nKWmT}K#IGH_5C{Ca^!N6^z1P5={w7$8OKGzo* z?9lc-Zo#w0hsE$}wkBR(yScl^LPG0n z^wn8j4B{USbZ4*$8L)D)h^@{o?YcP8<-^q-AM=l1Gdgy(gVq1Te@2EUYf3dXhiXTs z8f?27ex>Y6Qpt>zG&M$s1Kw#IOIpg_P00DFu`28D?exHF>{I4N8cj)#y4vuwadDW7 z?(tiasph+)jQvi3bSht{w`+Zrt0wp9kgZalM?DS*6dNw9UcsOd>M>Jbt$`Y&@uP+A zVQ~o`cUa2?Y!djeK%nRBiNhj49d{%JHp(1X#}MLbHz}Hqe_T5|lh*fGtv zRctoiH<#@-;+!zo*7ED*?!Bkd^;3hd-PQQLtGA>4Dd(oJxAzuiCEnwdcXyuk>W17@ zwbk!ee*7|(>ElDTsEA{gtIkd}(9L=1d*>9hL&HMOME}<{b*mno_@AlUJ!S7-GuL%n z^*@(pm+!k$-N(VewxlXn+*ALl$xe9#|_raK3Jzs4(qv zSJKp^mt~clt*qGzjm;kz*#)+&u70tv|CqCIF?;IyN4FTC=zd*vSHt|e{>GP?e=e@y z?C}1Nr|Rq4UPrKPE9=U%P-TcYE>Zr7@)R^W5;-s&ZhudFny8ESkw$AU} z)2q`t^X~OcRGBFv##~~zcJuO_XEI%~H~d!kxSiU>|Gw^B=H%5=gLVn_HcY%bTlC=$ zH~#BKgMy}CoW(ow_41fXrY);%ULAf|5m0}oTG~7I^k?tw|8|xH9%qcsW_cp#Dsa|m zGW(jOiPj7u8Yj}HXvHxsdEvD0!R4BUlBotvo7Ffzwydn#?eQw~v`%T#YD=%u{~cCu zEwr-5uPokiVmfQKbJwnUre6;qwb-^K>Oxe3BXhLiX(fXR3|G3&GVMzLSN`~Tz36Jm zFY~SDZm9gjzd=+|lIbmTgn{~F-CaiR>vcSqR;;qrsL@$IHNr7GU&(vz+N}wx7Z-FK zNm=+RG?0~<>-{?w`;*7s=BA0XG`&4FWyh^}>Fa;~w6*5i)p+(Q+dD*i@*LomJ|J-9 z_$scVn*WRH!XCZ8KI7TdIrl6V@0{MDKJ~h)kzRT1%2l~XT*a0yT3fR6Ysx8anO39j z>z!vzm(=|}#4i8STtn=@rM##H`G5RT69eTFM0pqkj2wPQE#eV=ek-7)UblD`zxMj| z^|5iUZ}Rm|pHf}Fu1a(J>$y*#M_)~}DP~>M{rqZr*^khLM*a#rUWM};pLyGbJ)8Swb=4;4fZ|*p?~QTizdU?oQ)hXKOaJ4I>cGm<+KGvg z#jFJ>krKCl&T7wOn3MI`byKBs{Zp5XGmdAN>9d`4{=?eE^Mi33w;J<@sD`@p{izJi z4$O916aBCLv1_jiIJL^0-JBisBaDj!_k3jDCv^Gs zH!g`KMTb)k#O+L7_IO`baJYcBd}RGS{tc`$TnE-P{MUb6B`a;mPJP@S0rBP&R^WSZSk2iK7kAj607%}m>HSCv3zG{MSc6U>9^m$ zH(M_B$JnzpJF0uht+F%u<#7{C4*oxtwfWH}={p-#)t35A+#0_1n%xznJvyt(w(N3U zy<&A#=F$=^BR7NdyBb)d4lX=)D9ONK&g5Ko6-j272!#&AUnM$1`_^(Oo)l_iV|{%} zOJZT_27!eFYylZbZzK&iD1<6(;9zjH3QwsvWY}?3=ki9aozqjFON2=ky(?K8s>X7r z;o8fI0@KBm1Z-7oBSV52<_YwiS~Mm74QIj!fko^1qP&zQDsely9-FMl^;Uu>R;_36 zji{$@#Q0Cx@^D_ta~09GQdHDj|M1hL_1-R)3DQZ8?I%w&G%8?*}VJ%5oa#WHSgc- z|3Fr-vOjY5%ZRL?0yJJ_L_LAg{i^5$lx}Q`E68I6}>A2ytHy@Ks zl($HybzEoDx(Z%d?F$_ht$sJ3 z>F`v?0?FdEU zya{{qe5bl|_Nx9{{!eEr3)vSk?a4aGRI||B>gm4tttm`J;{NmQoM#R=sL8e0iZJ4ps^ znc;E`t@R5cc)l{+SSHc1SKvVKyj`7lHi-Oyn$m`gv?#-$EV-?wEn$h-*3;} z^a7Dp5;;AeriIR8I5X|Dm)OV5?w6OZG(C3XZqIQRtl)2$s>$#msIl;!56A0QS(*>6 zPIItM74GE9{;kyQ{mK$?K{`53wX?BtN6%c zxr$go@k)RR;|{2OLn}y0ThG$c!aS>#LWLV^GM_MJuGV#YCAVG#7NLo<79->y&RU zR}ssfhV`M+w?!lx-*vD4F3qsu`ninK+MNo9ue0lTK0eBL)|^y!$cKS}p-;$>WkT^< z_2t>#znAcA|MU9y{SfP!Gxwd}R(6R1y|W3oD%MuqTE+NBsAj6tG{xJOW-YCq z_Pe}ng5Xp~BiGdpt*;Hb7tM0XXbd&y6K4qd=<1>2pfoMl*GNo4Tb6 zy?wNntvGboVfoZV2gMg2-+Pv%uw2MAIFg{*lcLD7Nk{B@z=~5`A(6fo%QAPp7EFBe zGIRq^Q0vr&quw*7TbT^qzS87*8xiM*Ros{a|Zaz(HtJ-e&X$R)0H2N%ZFW35~ z94~!YPEnClsf8~hdC}sz<`PGQW-u{`&Gvm9^1z<=&V%c_d~^AJIeasD_|MKKhQ_IU* z+oU_)rJP-g%~h9S=Vr&!yjsOK4jL7_S1@=9^ykc)j7Y^t*S=A!ag+7t|VRcim)K z{M34vxOZ5o_fpZde2$?a4<{T5`66~pdD6+Q)rtw01uD0^HJ-;DpOiX-sio;8Q^_Uv zxfhlhdmU51;QH&4+$ZLcmLm){iVR!bzHhP#(YrIx$~k=HsYU%Fp`3FB6IU$gbY8hM zaG}!zi#JgUg1V-PE{$*WRxV`NQuWwvt?le3clX~Y+`V#{?d-0HR`Lm!ErJYhnJ3)% zp78be9uX^1v&hL^ue#h<@^ckWh*^AS)z!@sk=M-q^X7fLlW(%-nvYoS)z$>w(hiG% z%zKiiUgmC(*|8@?&-0qXxt9k%);4HxOEo-~JK$ZKZPh2k-4mdDEsOcMW9o~b)f(HB z+zy8JR&e?V+;DtQaZ%_S%cg<_A&#+~3`VCPZDp2b+*9?MVNF)%;+6wtQd>nAbj{zg zGJTWvzu32XWHrNAsxmxYP|B~S_i(KN$J)Mip~s6>YP>ehn(Mh{-kMczi2~U(kNI4A z_aS}l?&~dDtxTQt=Xwx-k*8+TO@nl_x)`jQ}sXXu02uj?Uudv)BB2= zd(W4tJ#E;dyfj{Uz9@8HVkTl>LJxFkP(|&0L%+bFU_S>}cel_$uONSaA3s}{0N>#M z4t9=i0p9=JoE)8;ogG|!1N}lmf_(h~LjLdRyUY6H=|AqBF3ThG?=bIuYQNAy>Las@ zx)Q^IAjXpPdw1tJ36!kbn3dh>teYrt;?|>}Ew5nQHi@HQ663Zhb1HR07X+sqS>@Hg z{@tQC>()&Xcs+e?%GP61tm{`Ra38&t^mI>**?-~99#3_czTM|)DZ0s$besSCyY{4; zTrnT*w>2rqFIdInzF-Yw-j5P4d&gUwTK&B`HXZYhzI$b=@w3tlLBXY_t*ahMuGcP| z8U5wvdE3`LZ+XN#PxZ9Sn4-fZz)<2R$yB!KZ_0y`$x$NB+q@Njl-M^++t8rE@ZXau z{crHT0EggBTG!9*n!eF^TBe%ou8c*Cx;n&MLqezc-`6Q)TcdWp@5zPZIvYh39)IbJ ziq+;~15LwbzHQ&O{Z+5vl&$(tKiNCzHt{s1F>G98Tvaz-oP0HC0COj_aI?TI~Y0VM7wZ{^7tbC=S*f66gg>z3` zX!zQgGx?fpk7qtTwN7bS-I70r{pYV-J~d-0=p@gYx4@`dU?y2mp1EgH^#kFahV_TGV7uD`udL%@|C@*eXL8GKC^sc z-hXobrcfKP13`bB49}>}c+8wLS)xIe+2X|)uEPn_t}c&yeeL^;s+{GU%C3v9v=E=l z{j1k?^Oe1;!h;+Z-PV$uE1MLuWzmHt1$O2Pcj}VaKQ5?m-o1|ZIOCJf{ReCBX_t0S zNPODF^nfqB?*CptU7cT5j>1vvR(92SEe)7zXA!-HC2>iB(?;gm7mP&PjVw0Y<7PPW zj&V($@6@*iqTf}2Kc15os&r|CanRQ)eTSYqLJg^$CFY@<<}j`0lKFGGCE^Ba<1~jW z8KGMrG1dlNy`r>YRa98W@xo<&_a~|BY1=rlNtJ`8@9jtCBXw67P0Ih7U~y-qn4ZEm zyA8Yl7f;?aW8!Tc#vP9<`1WcpUE!s=MX5R?S#{b}agnWI$`iJ3%5YoJVVZTuqkUTd zx6^{-vdn#J0@&OaCe^a8Ns3KsUMp*{Cp4!c=$dq-VEM+{hOUoH56l?uiAiat>D*lX zXpz2C@hd%3saI>fyxD>T1R`6?Tn#j4P0Lc`klLQGXc3q6!B?rN2gG!`8Ls5rtEVn;%=dPd=Bn<*Ad6)b2A|C;zq=-+st}%he;X zcj+?c#PB<-lEdB2)3+);yr4EAjCo1Z*)_`7Bu;%@8uv6{;&-h_SKl$~Oh3u+V-x$1 zd#wj~t^3w~X^o1GxY#9{?0e8le8J#S13`^ugDZN1RW z>ATmKrR&X{uPHd1g)Gd(MRhk(;+O%&A(w%HyLL`>ozuUVrYSeBU=gum3e zCf0p~$tk+FEQ#{I6H#2_^K77u=_{M`RRwC7lCL6q-Wu4}{{h0H6 z+qW`bI^G0Z-8$#XX_R_ugH`SQ(j%Ov;cu)~m+t0S*lf7ynZR2Aqe;#=-HO?TVVeTe z7YHt%wBs*}z{aBvg2|j>EH@YHG%{4ZY3O25=y2~~^e&sA77^Ahs?(h4z_9wj)E%h~ ziIc^QxQ#bO=A0Bh*)PGyBQZ^YaTynH1Ea{YTTI-WC3LSPWPW_8t(jN3u1%NK*Dq{E zX~Thu-(o{mmq@PfWMpu(co1>u$&6P^Htp|A`)V9MZRN#xjq|+LrZmQE^x+bky@G?` zTnN)ci_CR;+jKY$|6Q&=QGRWw`Z0dfo5wc)&v-p$Ly}{!u-Ru{zAXkU%xlsT!!Ne} zIPh_4RpioH=RR>)%QL7k2J<-VXIO4`Z(+mx>$m0hvT9Fl*{vTl`?sachL9&rPmh{~ zxb1G@%w`NJYh~@|-P5`EpVZEIoJWr3XT7gr7fWDtRb=>~B2*&y`*e1YbHvo*KKE&< zN4+%`FFy0GQ>JAVi*rKfo*8PpcQDMUd#mIX|4n|+QKsh^;du#q&)w7X(vs~N?sO$F z%$m7C@GF~q_p7ft0)pN<-(*XiN=$FqlJ2xk&AQnyfm2j4rQEPt#W8{meiG9TtR_rx}z=&Z^?66zUb8_EKbYU*t_Cavd zsopx>3E_;!lE<>oUb7ItX1Der!{a&zhNW|t>2`Bkc5(d937(oKZ8b~KJ1tF!fuU#V zOhr}Br7s_GmGNx5eQ|r|KiiA%G&iaqudWE-)m-$pT}o7dcKO4mMcEZcO? zE^OOTfvBAl9jhNSS}n@e?O|+;hzW5K+I(up0bnPGe!^8~=Vl@X=eLmRE=MbFKxQO9Qm+$tT{6AAKPX2de{TZXm$@US|Y`57r zSRQ4V!eQX2RMU5Q;f2)!i_~PpVmLyzSTzyS@AmUWzb&_`%>*x^xD^;)fHtRs=oX zkkG^A{>@|SgURXB?yOGc5sd!2?Z!@rInNYQl3LY*=Cm)(e{ugzkm!f3_RCN08Ti}` z8NB%pyy5oRthhAAQuRtY^~FU(3)DCc?bo56=hx8Mk6YUP!o1T(jwU;*@EQhn0+UIg-mC`^C)q z(WiIy=-rZ-Dp|S3HEFG^Pr7$xPXBp?%XkIH&bBu8-N$h5w z?OJvqE8W4vK|@?hI)?)?8eVKyPk`zue=|w$<*F5koVRbFK5krnXv1|eulq^)4doO z7I7sUpQM$et`}(f&Y+LSyz6VurN9MeoW(_X!yHA{-slS8w)*kH>?*_RV~qz7YO8C! ztx00633FuMw}t!o{7P4=50fJ;ZqzoodRQ=-t0j6j8_F(!A^U$pbk8>D_}wvmzudM& zZCj8TZ#Klx33r|v4{-mv^n_u|wmdo8wVc-}t4SWt8K z^mPA~>t3>Mowv$uy|c@bb*ryxM+SPj=}uX-j7zvk;OErO_qN6_Qkl{l_L%jW#1}KB zj~;7!f>!D&+wWFRyf-iHVyNrAc4gza_t|f#Enp5XI%xOo$cdFDpHsr7bO&7xShf0) z(wZ3UBvaR!o08r(#Z6Z_wm@U4okwT3&pqo-$B4j0<`8FN%N8v~c21oeE<&bBUtGF4 zSO1ny-K~%_t%n^e6qmCz+G#hYSZk!b^DE@R&(AF8>*-jr^6`*~VNsM7h7JK^kT+Omx-o0{wU9VQ;MKOi=R zF@VXyZsnS$p1^?6k{9~HE~T|Kd7nc#J+Iy}Tvrwr`by`hzKvSf^S$z}@^XtMf67MZ zec3wwix$JJuC=vi6x(Qr{BanG^9gfpi+rr!OyBVxLkduk8|M@sWSr>i%2CTd4< z^yUhQ&#-8lvx&jsi13LMZH~uWf;3oGooG_&icDp3c`UU+xrc{|lSfIZ-_WCXQA*5# zw{^Vg#%arD)F)knlgF_;p_|9~N` zCU%+WspDxk)c%yOPmZ~Cw4agvPrmH!T7zGQcW!Q-XK7^}HPNhXmI~;IQHIIY^Yf0J ze^_#C>aPo&QJc?Kf4z48`(*a)E$JWY6@TA13@KeUW$Nk`+qS;hwdk7G>E`SLS)Ihty^>#m~DEn#ihw;x~Ti==y`D)+>;L|TwKi)5wo_Ct$Xf` z;JyWV-4$APTr*jckH#h|==2^eWl?kxYS_1soxiasMMYX`p1}H>NA%oMSp;}>CNU}c zMsPB^EwU2gnBKBQM|wrNRo1DM=_dkS-;3>B&i+gCevKTnhi%u9fb2Dz>+~3oOp$2U ziR_$Iyt7y}g-I;`y0ad~#(*~^#-_mv@z&?E&BKhkohKP}WzOkL@aWPy=*3V_(tTh3 zsbHeQ>UI17>+tUhbPl`PcW9x8Py@SN&fVjx9sC8&@#{;yym$SO_`q`C*KdFSJhcti z&81{-%~~&YS%=eufx&IN4{ubswCwN8Pc%xMmoOLmomhH9`27p5>Y01%uYG>KHnqz4 zjn3Xp?JAFjc6(h~V$`wswUl~f%iKP>Lp-8Vj9cEg`e%quYU@)@Ot<4x30&>vq`>5S za>5KVrk-5O1KdXz9X?Pbuvq<8@Xr-nZBE6t9{pm#(;~Z8l>LaXs6f)qR~D{o&YwB) zIJIYEb&Kwl4KpTXKQT?<5a7_5P+Y*wIAiCXX{RULn`EdK)0e^ClfvfDpz=kbt#g^@ z2cIWxdRj?EUcTD0AKUJEJz_JDi0iOy-I=?cb%J3Kd&R=En)mt z&VK!;@0#fT>dvdtFW4p=G)#D~sruo&dNT$Fh7Fwu^B?^2F%fJ~VL#o-e9wDsmiNzk z34_MiS0Pnif07R{yj$LRw$(R=X~yEnYcqn^uJuYw6KiK-IC4+vx|x|uYEqwVwe{je zjorOz3-5VI6|xx?ui9Te<@mCRU8y2&Mv2uv5xslEk`FC%o5WhZR5welf=e@ycdc9N z8s0qDBGslHlUW62I(3#hhNk%*kqTcY_4LDSIiOg7b0SGRjBf6PVst`YCh2TI;5B z;tl)e{=T;S=v?VZH&drEFub`I-gEo@?qgrBOc$~@h>4fFADS&@Z(Cquu;#z{v!6!X z!pB8+Usd~-RDJf9r@PYmtHM$owyRF8;4<4WWeT%NPjw@YOqeulMT+o>6&sWpg~S+L zOY}9oPV>30Q0O|?8L};K!;N{Ji;LVsn}k|!uDIPWIl)TgdiurdJ``%c(COG^+-fJN*4<_l5*F$c z6vC+T%|mu;?&KF7-1(g1cG2y2j&(1}BaR-JwWj9)lY*P@n!UR2*`Xz=A2xKgo(@YA zRb{-ks&^&($Ho`A4fj`G-6?j4f5XAQybKDrx5<9Hc(G65YIgKw6JuruhBcK6tkMMaQk+iC3U;{5>NFRsrD4{97*P= zGG$_TF>yx4%r=8Zxn?|Ko6;l&D=Ozl=CQe#Wg1PNs&mR<9(R9`$jPT7sT&qPyFMlH zfZ2!O?1mE(3<-C(ew?VYpD%mGr4L`vvaZRC4WG!pH}iP()n#iION;SAdL;qMjVE?6 z{p~F*aydQqXT+xvl_a$^#^p`H&OKq4o2(`7RB^Chh&(!JyQch^va2bl-lzZEnzQcx z*3;tCpLxq@mi^;zIIAhrAjFv!myosE-F;1(s`|_(q!NP70 zCq>;8St{AnG(}nxLL&}qcqDi=wr3vsS-^Cr=`hcZQ}TBnZ%J}yeJLRSbESd2!Ws>> z1EvT3v~PM_JAFB`(r4xdtHNDu(bjGi=`(%ejz2bEwaC52ZF3UyUFCIGJy@2cUG(+e zXAu3kX13p7r6qbfvojA_-}|%Xyz8S0B0>z0E;N0YWanxr%2~FRFI2ZpN(qGmmD&g5_gips_OKQ-Pa{uCmk$3!h5}b{?49H4I3Iv81{OXTQxc@)>(dy zMb=7XLsP~ptE*RzoZh6P6!&d+Tkdnqh0K}DW>rjmd*6+xD@MD2BjcK~NTY=KPx^ir zmjC{9Xu*t67xznk$&7E%WfW$6@Z0Ob$(*y-PMB!s&CX4_Qq-fQx^}sn)~+K)b~W>N zuaMYy&1*@=E3s73t!tV$&7V>Bmib6qEbF73|4(XWT-D3o(zW|f?YZ{f4ABP+8J06# zpYw$Oc*WBbM!VOQzFHv~5-J#WaqG6}n=j4~Qq}srWlPDzE75Kdg;^ilTU#7dq;|7k z%IaOo{+}`L!?LKo^33)Mxp(&EGc??Lcd{5XjMm)FF+3r(G<A+Bpr^} z>eNC9uiafM4?3+@4qYi&8aY9Nl{;C3d&%FV)soR7Zk1A2ya`Ok&Rp8J6WP3T)Z17m z8A&pq^GQ8(%B4+9C9zv&mY9X|*I$pXZ@w(Z)jPSzQ}CvuM)G8%ZM$+8v|OINE6_Ax zKkE(d870S^?!MZl-~UVJ`gKNY?^klX7a8Vu3JX4J(OA54&JGRLqm#U!Go*UXjppT? zBK2Nz=@hT$nr=!=JWM47a;C>a2-6*7^FP3gZKDA;v9vCwY>dJleniigu2J z&XL3AH^Acq1-6{?A_6an#C55kJT%Mn#7#l&jTdxoL~-8vc{Y(#a?$S>M{Ivw+2MAt z|4#_hp0cwnubk>1EY{xX!Te0quH~~01D~HE!~SySr*F(wT?_mheA0O1o(U5-8Aq7! zyI#I_=65x-gX^Piz55h<$G3Fdk)skJu7!IT=lB(dhU$FHi)eLQs2q~_%D*>TcD|*Z zs|$y*7UPbv375tD!w=2a)>JUn`_L58_PG_R9@XR3vYBp& z-kBk#9=~-L+pVj052TJi_e(Vmp3>~ZD6n(e%t>LF?4`V8J2R$SaxtxpY)n7 zTXpH3GRySH5VLKEO}FJ%KiyW*ZES44YWHffgx+;!ERR@AqP9wQERE1PEpSk{`Wqg`OemmYd%&wJ~%?~g9kW!t#CR@={9 zlGn=nBg}3N+x?Z%_fizMR~@t1&8`rV$aCPlM?zC__z$Os<-(6SdqmAyGDNSWCM3D8 z4xYPx>5{1J>*utbE@}U;<~P@pDqp63ui9^a-M?kFO!wWJ&YkDpG3NxzG(U;0ykt`J?P%vCeqcTEvlqfycl?tO!6O5Di@o9s{cOXgml8x{HdNp#(X z7w?!|MAV%XxC(e)PV;jroTg$Wwq@5TMGke2&=rezTVz_t9=zo!A*rbonrr&|p8HzU zB8QOM9{SV%r%&-t?B#9=3*OY5Yg+I0K4fy}rMDX=*E<_J{$vb$+<3s<{KN6n)A(E` zzupj--MJ>}de17^BkHerzc}i>a{Z}=)1DR_dN}vJ(%0{5I}6stY@EI>Ji3ALY`Be+ zn6k*0va3nFMHB5@qbBERPUYEra_OFKr!@!9vv&kJ1u&et+W67;+=p7-X#sz2mHd1% z))_i(5g%KUpPu{8WGBQjF~X3c#%$wcm&nijKj+Q#QpuR&T63_TA*b&l z!;#Gm(>Y@$1CKvXzZ?A0)Fp|x#b-eTLt?-@hUF=~zW>Uft=y+De_DRg#sh*mek)Ii z?VZIQ`+IKGl1)d?e>!;f9rKyXS`2wUhyJGT+pfr%WI3&9;?@N}_0_VQwU@b;Bz@#bTHQ2nuWm^fpMbREi_Tp6 z1!0Gn7-ET*+xj$sO@5yVa zd$Y@3LqZlumih`j18Go!Oqzw&;&#l6#CBX$|-6q~(b+!FQH=f1^lhEO7KXfg;_Ls@{LnR! zx7if56IL|}C_a)+@m;57rQP7Ro>8_-v|Z?AW~i!~TFUpa@geWM3#-4_{^0+>`kkLaq1z)gP*~FK+_sCqw%t4A=Bz4w z`3wU?gUrmou0ah_u{nNc`)+sY=ldPk{+)kQN4>weJn{d8$ONmaxi{BaDJAnw;*VUn zZL`G%nZTt>Rzf{h) zyUb#-M777AY5irPq)kjcp6&r+51aO6m^m)=u~lZsn50zwZfS;6W8<8-7>(jtlB(rf zyALn*tnECT=QC+uB!d=Y0OP<*!~li?0|SGe-}z{b;Qt}6c5aT&KEa`3L6PA>LBTL2vqJIHWC;J!8&wwn%tfsfAKY*`zW{xQwBMs@kKn|EJM zty*6?K`b~|*-Eiowm>{PR-tS`&lWdHUePP7*0cXyGkLZ+_tKxO)15U17zA$!usmRy zvQ>u3Y`1Qm=gY+hr2nLCHuXDbuV8cV{a?d*a(aFKb7$nOl2B6fdvl{}hT6Bt`&IWd zdcstNjX4<@K1{34?Rmdz(r2HD>SFo&$d#%S7q@T!{%@zd_I&x2mgkcEc1Kcoev`g& za@X@|#ra(&5;Yo+e%yGyT&$tx_$?>*_9-oyq&08ESI6rZPNi1_Y);Bji_0Mu7yAAafq$mMo6tFR%G%uaNY#y`a;$L3!g>kscp* zeviE}dyN)~D`z1n?Ni{;9JGd-IXm-wheX$G(;bQ}oQF)=G@ z4i^x+tFF*xYCcy|(lohvpT}0aqy%W=Tr(B+y(e9$PIM4arx*}VRT81mr-U__( z{&|kxluVax@LV)EZdzk6ZeYE|GxPv z|4gIOrO6r$--@u2u}w7ti^VS}Ma!!m~Z?9=@YvlItz6Fr`J;n4vnxwS@SiR)UT zHZL^_)-`Z_!5`X~$Pg2Ek@1nH(7Su7)6@?HvY-3T0Ge5d^5VQNuU_8R8EaQ1a%9s4 z<~>TQpS@Alx11g<`CPgo?`rYo+5Nj;UYy4p`&4j>Rd2{k|If|auX(T4JAHNj?byYM zSJ(}%Yl<}d>uXTA`?1O-mo@cW{miKkOYOhP7?muJ5j*t$Rhr`ck5*~-XMX;)=5l#< zt;f4#E;0-`ewpk^veW9svsAe{YAs6M|7Pgk#K3evOkLuS-hYYm#%sY>j(2HoU!@mT z@*;pGWNlWL0*8uk#?|b(DqlT+y>r%Blrw3@R#6tA8xN%p?pNYG$=c$znCWno+_{%g zN4*u!x#=Ql)*pUO&vQ;??W#>T;or@_;cVl9 z=S+VttgG^{HC?3FyRV{X)$%V{OLsY6d@cH>C~)$wsJ+KF+1|H&zWJ1kV(3PlS39<7 z2!!M?H$=1?2r~S}yd-F+^3sqe?DL-)cSfCDbtvk`3H}WloZScRa&GwKTb-6yT6=5h zBCqJ}d170_bk~V5xe{&2)f})e%sV1z+JvCRUe;WuTbe^HI9$!QhOKtf>=u|}6v{5~ zY<}6+T)l&g0WS=0|2=)U_p{lyfH@3pcdv^!t>ZoWTclKLb=BG_O5K}c#2xQ+m7P_( z9i%_qcb~uZ_kVK_Ut9nD(eCz_v4Ijtj;#2!#5iu-9#P>pTu1WmDstaHdo3jQ%K`IS zQ;l0JZttG+@$Cz{17Sj32aa!R5I19A`&3k8)568vYdNe=KW1He&MBljjxjKNalA64 z^3`7|M_+gU(){?Pq~@#C@mR$zF|wUX+-I7ynLpk8$F%yA_G<;cpVI68GOd}tLD1ql zLo%Dq%5)x!0^euWTNiN4YHuw1(v;D^&Ul5(@mY+q%Zrqc3if|0T(jM1^JC5A|K;r@ZEq@r#qNi04akmCpT1y)`udFLKJOg5Q~tdU3nk)YXD8*Sji|IRNFTN(3Dca(a?V>R=X!7OGtK|aG>Y}X& zf9XXSMm%5&aY~$S!TphW@8x-UuUURo{<$P-zd}4gdp1Lr;_22klx7prLOs_uu?AW_z>+53;N@Axw=Y=N-bnz6}Fidfa zWZpNClYRGjtxFDZn{K52W{3_{zA&HBsFzQVy^uY%(9d1EiGb$hyBpeZal{xrk#C3$Cg-W2aJtgBiYdD+40lDOSl_8VSO z4MGR@wg*18x-wtHUv^d9o^_?mmF6vy+I&KzKWM_KptDZbx{M4}3n!g=C(HWquSu*< zOJLS9wv-xXrY%LG>`8|Yyxd;)lqX^qbNOe6kQvDgzc|l)Rm$hc^LVuQkei^=+ET%^ ziBmP#9Q8P1HEXx9|M#Eow7IWY8k;II9k3K+Xemo%|D_OiC-(o!>HG`&Wxjs+A=fag zRe-_Yv|(rbj5YmVCO@j^jo@}#tx#sdvaDu;Xj03jSqVJFJAco5bIM#(X#)3|u4wi$ zZT{lDH}cOq#FgCq{GXw_sgbdR>y23gTW)rOQ0{4|D@q}Iy>hqideRW4dAs|uf{V-I zu{Fg^w|xKlSJ!Usw_up#Cds6dX+JS9XtoTa&{N@!SJ`J2aB?RVbh4zi zKAUnu$TliaEVQIy+ao9AD07XiyRIEflJ>j$k2TOFSGql@l5@k;A1fwi^>1`lRuf?8 zDe7c=ls9k9>qWU!wI_46`_6dFTryRv@4zLNBj0sTCM&Ppr+IqS*K>S3nI+m5R;X<> z7ug&jE3!6xPf73W^V=oz^B-+bcHJAercgkiL2T#zX48m?feco=b8|bp*k|egIGc9c zg8k!xFRc5^KQGz#)yHPl|J^6ur@rjEW^w!fKFM9THe1##zO^BeH_b4OfuUjF`}L|{ z488;>&aCfi`}oaje__$Kdwc%-oBS*N`@UxLoz36>Ub>grUbFL`O189h^M7DvyS$K-AU=E2ac3-}=ClaRyKSMjg?c8lEA`j?b7S(5&sO(|>f~ zA_1qx3L=5r7rRwD9UL2)@-E)wle%=Wr)T4#Ey4M(w}x%wVaSkW$rHJxrKpg7?x9BJ z{8d|wL_%yD&I&DK^;`SoLg9qBM;RO^TAshcGSNwo|KIo3{QGVi^Q6yOx$>{6oJVks z+T!KBmU}%VMUVbHcUC5D{T;qXCH)@p1}3*BNA3F5d;h!o^EZxCGh5Pf)2j0e$6Vm%GQUCV$Hf=RvrwT_A*4uvggSUC51y> zc}I4&Rux`p{;D^vrH@6zT9{3X(0$yw z-GGB3fRR7AS^1WkfV7>KWF+@Ip?&^7{|jprQub8T#9qyh{lPKs%-wg{AGm)o{(tm# zr;elk1NNR;pKZ|sE37R0dwNpj-)5}s<$E7$6s*F);P895$@RD5YmYo%lDKP@&E1pL z_tWy(n?!XNOWgKi+gQH)RA_?E>dI|WhcpBjyI)*UXfn7ac&bQe^|Yf!N-|f)OuY_- zH56?05jc5nqUgyjxk3vqN>;b%%w%D?C>7{txG;q?N^zQsP|4DqNpLwN5n- zD?5Dk-q~yJHJ`h(TveDR247(1<(_*;Md8>V&Izv>TuW60j+7n${VrVKd_~J0waN9d zEGBU!4C<55tn_l1Hee9oc+~Z9ntG9$NNzPp`RCiAnc0>GdzPB~x%h*1(xu!?#%Z(X zE;DT7*Pi#FeD&Pra+>yQ7ODTJWoC$xO}67)C&In2x98f$ENQiwa}78d7FP-%;&!3QH&$IvM{1ROJaG^{2Wz(f? zteI+CV_7F9rIt%f`=Heu%C94#lyEZ9sx!%`$+c*O#U8i5qX83V9N4ONB9DhdMydCp zhEPP;EJx8p>kXwhtYHmV%fX=5W5n}4@79VRPYk}9oZ$8DKBL`X=HnLN61`DCN+4^Y zp00Ce!J&h~w;I*mL$+zNRL)>%Jh9~X%qd5C1eg~zg>}3XTRypS-=f2_y)BjXH8`gT4fu#FQ_r)f-iHdC*KAUhXvh1s-L*t zXK0>J{9FE8y=w1dK{G)yhgaFDYq&Xjn2uCEKC*j8-QkZ%iw=7^%Y6EJapp6|6_+&G z6tpfJWzC-c)VojS+OC|fM~kFZXv-}Wo!E1&d8Vf3tYbgTK7Zf*oOQvSQQT zZnM6*`~E54PQ%^Kk=NG!XFZ{spvx55PH@Pv*Mz@zSR8t!OH0Uqs>4MtrB!U%S6q{iXtEz^oY)*7+3Vpe!nSZp zR*37G75DdYMV| z8Ea#&2s8wAc4X$gI5jDCj`o6Taru>>cg4FNpY^r1V|C1fZ!iBTKahf6!O_6a4!ZS| z0d(!BAp--0*docZ82KfJX`fu^y z$tlEt-|pCDnlG3SivKCz{Mm#}*6|bD{&KrHFI+die#7`iu6_s0nzgbImng4N4v7_8 zEXlxd;ElyRlg}SNr`Q*(US0R`{i~e^J*Sk2wded^;c7BDh>KHr%k8sHQ;RG6v!7&KW0*5TaY|CyTFIGH zJZ8sjn(1~#_QlDvj+vgE>4y$5t3@n)lHlPonZ-k+YgbpV4AbO9?pC+$qL&;ZqL^nM zWN0{a=+(w3t_f>rvT#}_ai%m)IN-6+D5pr2VcPtz`^pSUO@sZ?43Ff6rCpF{m|Xg^ zGjMlDm$wHa@0((|j=3C*FR;#>_r~g}V@5#D0=r_Zx;fk(Q4f?)NqoAjyE5~R>D@QE zQNQGr7zCIVw!hbCm0c@RwZ$Y;r>x`60S1N*Nx5e@*%-D}t*z@ZP+obQZGULCukEEj z4AOt<7#Nh#8;9+Ws;=&sl6*eR`qmj8mxWq0Gu0Rw4$M>fv@6&$XqSDAeZlg*&HU$b z&2A;P?f?GsYSk^(HrbljYc953yJ;O$b^czUHMeAH;#DPi(VO!+N{!EZ@s>Sx($xFX z*dMq+^lQ+uMMqm?_Qsr)QQSHsOz{@K_(Y}*D}imC9TOsx6s9RSoLZKg z`4s%0z_e73`J_1bdjeDEhAcwd&HlYYS9N7W{v6^StvXi>Rx6 zBN7z0ZP;MQz1}f^X~!DBgRA-`3C{igF?xTBvHR&)sw(r}*d16lnN#6|A`8#LkMfr| zSYuZ%)oNX|tT>-CN=|n1ZWn{UEtZdrrsboN_1&} zR7Cqep;bzg_O25Dd(ZOp1jA24dWjFtGd(zQN|*J>q^rD7vVYGuxxd`%>?+s8Zw}ut zh^pDgFx!{mfvIugBja?LDFVFVB9}K@-YWKGx^mdn%O$S)dkcLRvTfB`y-Z6Xu1=&S zm;FnRupr}#9o&&@C0#d-XFj`BCm7T-!EO6DwsrEqn&*VD9B0o6oy7RTxV=HOTu;U{ zYVnpu(aNV5t(Weeytlt>+pVH7?WHA#rFkI*P5b{~=CF`FntEQ?>aoyeF>K>wbu}9WR zPIUd$sw+#wSzClcS8kui6}TfvSmfBU4(n>RgGmfMO_$}4%&xd#^gJ~zm+i?m`^;Nb z*V#L?v>9%NJXoLIelXf8{OHcG>7Ra|)Mc&8*_*BXN-%!fcCVGw9_O$pM%1?+%AEE? zefk`Qz6)F@x*Qo6NW4mlVm#AyTy0jwWB(r?d{)1GaxU*&{*M#l3&hMA^nX2gFiFoi zJJcae(KCOwbL+97#aF@wQUzEYPrF|0X0`QF)Z|Owxznp&+IE#Iv!FK@;~gU>rx=De z)0VrgD-z!SKxX6ZdlmlCdpE|sXT2fiBhiq}n6@wP%&#wD?vGE3y$+A;;0wH~UufoYs-8S{J{abujk`^etlG)KmmAiec;W6jA&Y>W>Z{tKe9IEc7+Tsc3LkmG z?)%Sc>l&twGtIZ0uw`%&Z)ItiU&y&(deK?2V7DVy^E_5tO?vbx=-TAiHC{^5ifWkt4yWyx+o&wcne_pV(b zt2Nu4teoO`73=Fhw3^QtGM%-+Tz@!#9nW#`nbzoKmKo!+%}>cy)^ zr|91=bTMf?;lAo6*OiSi-H#^xF|DL-`<1!fwc9-6pr}1Qy20O#Sl+|e+Cl@8p)ClXg3-SzcjqHw#Wj)dxuDMP@b+S~r z(l_sG$K#sfR;x2jcofm4+bB9UB$$z5Ptx6G+je^JpL;Koou;tvnd9-h>=9Ee8Tcg= zcrL2`aGbWPD=1>>XIJC)r7xZq{aiZb=)=vQdiR_;zh2nO?^NW>)b;o5Ut6r$_jpT{ zFSj#KYNJG7ICGCz=%?ITMfSv2yT##lJA35Jyf59YZQuyzIZ(`~wM*pE0fW3^^{;~S zt!ti{zr3fkcz#0k-c>zy$906~y;`|%&V9>0cQ?d5i+FasjiDsV@p^9T)9K|qgI*r_ zy8P~D*&y!w+!xZM8E_OuQmOBp4{J@+4t65s+_uJPOWBb@_kqXPe`xnI=Fd(-H8z1^ZHZ0#UyPzkH4{N$W>;T#-{M?=Lds{HOpNtUVh4Q zM6t{!yQt&;nsZ-cXJ%~LRIa}>@ss-Il;jF-hBqD@bIJ~~8eCg+t?u86OZ;aD{XJhS~S_i8}Z0s_6=nRaJ>`)|7L7sorH2Shnu}Y`<4)wk)20 zO~^%4bz|hyz=?}AzBDBrU|3Ujk@?47iFMm9t=hKg%5KFu|JfrV6c{X252lvSP+0j_ zYG+Pv>CzRKwD;z5Uh~=2l%?8ps3U4kxMkm(qEa5&av9O6=C6JyrllV3V(n^<=x<{9 z({woL;`UF6<=$PBR=auR(wgCcYm(n{Uetp}ukomOQWA*R(`e!CZKR#TwqP}r=%+qHLYRBpiSK1v& z+acDF%DUqugT#(q7K>iLsyX2p?GmW%w>Ie1bDgc*vRCGuu<`w?RWwC4>rr$v`?Thl zGOEr3&VhnUTFe;cls#s;rd4-1c3$0U74i75`hViuFGq{gb(2?qO!3 zCi~`0zZH6_X6KqucB{UZX%$a7Z>#re`Z@lCsZ#=%)a-xq{o~#{%o4(%L~nI6Ps!TM z{K)QJ!JMn_I~tOIeBl4gq?5yWV1+|l{M4JQz8cM6R-S!#^IvUH?L^_GE=x%XSGZ%-UPT&NW5!SmKFQr`COya(%f`wqNz- z(!;A>i8?(B4_(WZ)AVnDs$tcYTctS|t{`Q9@G7Xp1tt_QYm^%IQZFTDx~KTJ2t&%ag?N zry)LP+c&wB9bNiA?1W40Qnrdtp1eFgaR1Aj+n%qUWxDy~U5%$^?%vh+vo^2rQUh%s zTCjEQly`c^FaEf<TaozQ&r zC~{TjuN0ZCtsERm+s`Hluvz-gU3$U5OxZio*=L2`$r}pY7nJs8woW|4vM8vKLn6h& z!J32dfv|scR*N{N0oUAj8ax}kP9(YLI*7S;ztR(JVo=<$mygY{pet-62Wz6hvY6O~ zk4{|?&fM6Ov?x);NH}>(q!_mpM^9quM5}n6iK{~I|E=-7FeyxfnaPNy=fjbAC)Jv3 ztRK8Px$&l9ZuOUdrZQ&bYObFT*$&5^Pi6WQI{lNw{3A<$nAi% zWt>|mUl|NFB~~s`6VPle)OdYU$xYvB^OUwO zrk13GOQZCn4s|wGnnY6=J>tah!;cO#; z)YV&)l6f>%vOYfA$EBR^ve<0}ThhTvb1!L`Ef#cAami6QlIFo0+?Z>syGdH0*@5BI zj9GGyv4!{B4v0RM5;s;?I(eK~u06q2(BPdZH=Bb}j&1t$`^b(&zy0w& zCwV8wt55g!_I{lj9WLKca%1<}mzjauu1{}VowX}F^}B26d^?vl8Qy_Q4IZe>+PYLP zrJ+G%+9ag~r?rA73Qz62mvquag;Pt2?Oe73rU0Xd zP3)~r8#T`L{^;T|y}U4`*@r3N%C;8S6&juzC9UBbCvQx(@-}VX#=(=tJ(FcYxTBQz zvV%_5HRq+=T5 zcFzYI`*apWh~EBP_`cD1=^uucu7{nIraf8`9cQ(xKlZIkiu6S5+h+Ch2~)Fp5A;4` zy>lcjh6Vv~?UYPc3k*fK^RT)O7Q`bmcyt+5y`lVBfCszcPE#m0!?Z|Lx@oo_5 z+;f1fWLhKRw^>~#C7Zl?i&rMSKN;b-&AeeE_hfFS5AkjcahCcW!Rw~w7=3Pic2mkK zBvfrmNNI>y>J`2Hi{9i}dncZDn;Khpq}(JcE>O^w6*}7B;Di`$Fk)a}Sfo5LR@(o6 z;D6o!w*PJZ>;5Z&}+F(UY#;`E8kE?SF%8iaI&`?9x2J~jXSr+|XDPpr~!O&5=Qp*HOh~!4wuvMhh`nt7A73C8ZkEVz0G6 zRQj|1gXp*Axvi;+)ePK0jSQiaN_Cx55BBBW5@vSWw)EY*ASb5NMl%i_TeId^!|@9& zC!C^$7%yrsTYH2}^0uE#-~PLYS+qGi+?E}D`~S(yS$v^u4s5^Vlv%_$LB*%?zN^Dy zg*DPn$GqmAV0sy|ansaWmao=*b$3+ZVRp8%{bz0xHEUyH+9sjnvWzNB3~@cN(=&(I%%MmvpLs#PD+|z2;@Yr4L>4R)jqoRap%2Nxt9fQwN1?3xY^1; z;8GilugLwAk4~KZwfnkz zY?`s^+l2>0eWwfG@Fh=}a6v<UaXGpT*& zr^~Lke4wu8)?WK=;g&Ps7R|Nn-t~OyPYrY7%X&GB^$$mdx@zxbQ{1>QeX09m-8;uv zPH*~PA=}FpvW;`2!wHKZtBDi44mLjJY-K&c)I7sf&`h8q!fgv{QbU)5_L?oChhxr7 z;Jg^(bCP+5tE(ZOMv+R5xgBMSxMG!kw(AXZiKEFymeq%jws1_JCDaqO zP|aYPliI99XJ>KyF6rL%X11nGWE)F_@b?p^QhR((#-57J;&cCgqG67n*pbGkVVctv zV>xvUSi4k>zDk^5b^U^%1#TC!m^qe6fa-$BnW=-w9uTnf0v`#xI zY%vwD*l%CIZ0A+Z21dC#b8k-)kk>H#@jvOh9jn~|w*S8?Hf-K2lw(Ct$U5@-dz^(e6`+@71jp z%3d`$_?&C*!%JSr|HgJOnJtwP)C_&1qtRY9IZaBb^xIKYrd@N)e4eDbY!7dbbM$P^ zE!Sew(O^juJffK*=E}h!xMXeEDIteBtBkK`B^_-z)yK=rS|#M|!KRxL;NGRuDUmL* z`IgDX$AxoT7M*QLjgj#0cp`B?gF#22aYt)n`x?a`KJqRr-tlvLdAq9yz1J$-vN8-T%0Dt9jV^+I!2&r`=qbvP*vRnOV0C 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 GSpWde({bPc literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/ebwizardry/sounds/small_aura_loop.ogg b/src/main/resources/assets/ebwizardry/sounds/small_aura_loop.ogg new file mode 100644 index 0000000000000000000000000000000000000000..77c76ac2c5644e3f8df9c0eae8f616d21636bf75 GIT binary patch literal 209049 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

    9X>UE2g8wy|3Ag* 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 literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/ebwizardry/sounds/small_aura_start.ogg b/src/main/resources/assets/ebwizardry/sounds/small_aura_start.ogg new file mode 100644 index 0000000000000000000000000000000000000000..9004f213ce7a7d196bb34e8825dff446dd3f79bd GIT binary patch literal 87860 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 literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/ebwizardry/sounds/spellbind.ogg b/src/main/resources/assets/ebwizardry/sounds/spellbind.ogg new file mode 100644 index 0000000000000000000000000000000000000000..d14bdcdeacc182cc8d20d7bcd1b082448118c21c GIT binary patch literal 78949 zcmeZIPY-5bVt|4vf)ECyy31omImWX5qNL1XkPws08W6?6z)%QLyn_*}6Dr8S0Mg0G zz`(HUvG;UA-T!ES8Df$w0|P@uW*v$42C`mM;k6o2xVXpU|>j4(d3()=Bc@K%0i9G8B;t!tfK~O!l*S zxngmj)hmrH7o50tw_Nh_F}xaut3>z+GEW{N>Ym+SuSF3X)J=g98(T!|_6yZ|Htr=ZC#U$F z{o=z9R>Hspj&=qH2Sb^og)%2Es`v-#UM?~XFSfm2?0da5HXIZp_;DjRy|6GaD9%lr zmes&vJRuPrETDjvSjgeb1F?yPfuUpJ6NOn9W_>WPV)I2zGIS!bBfPpUYf?ChPKv2%*g z{Y;tj?kp!r3_bZcFfgzr-jFypw@IP4k1a_=ahc*|xsraq$qNimXfBcK?Q`>5*&Glg zslK$N3G8zP28I>^a4Loo;G_&m#Y-l2X`Ry8e8%Xs4v1KD_?*@24TlAsc?`E)^3pNA z8kXF<_1V1Qb(S94OSfK&(q1|x$V+o6IQ&2vL?LB@Bby{RleEn!I;FXMK@%4wI3W@D zLFK%l>_sGW{-aEwkZPci>O~{nU}M|RkkIh5+{o#rx3{;(-YC6)z4rd~-gxmg^n?Y^ zISfu5iY?$gIVGvb@c5i&KPOH|1jBMpp~&%xGAAdhcyChiy`*#YlZpRllZ(QxfhNAe zqOli6OD~J12AjoRHch=8ntHV?_2#zJ=MU*W29(zn; z0cQ(v&RL+*_sF78*>jRg>@>qicCb*Yl1(jm~MA zowHW$T$FQa-RoTh5j^L(7pb@xfpU&(kqT1IIbbN`9Her5laB9ah#ze)8rz1JxQZi3 z00YB;2|V85awITF_iB*o)gax_5L^5?CNwnks)_Gqlg0}ZrZO-{GB7+@vg}F~pHR{S z%TC7(4$mVpM`NsB&RHDO(>_7j&GW5d@EHM?turoowu)SN6qO}g9MavpHpRnHciXWb z#iuLSot(os7#2!0@EvEA@nx3rW(F533=E!^8GJ<;&kBQT3kC*;0~bvkgl!#!U7^wx zQ8K>FCV?y_fsg`>0c6p|5XOrpP`ez2T@M($I+%n~WC>I=7P|sX8U2y$axn3A2=Rp~ zAEib^fR-V^$iTqJ$H2fS=Cn{zo2kKqk)i#u!z2aI4<-%CksoX-qwm8Jpb9| za*IaSqD-bh6JJIK23An8n`L$ z_jzI0%O<{|rLosp7iG*^wsO_F*Sj3R3a^&Nig$p-R_$8%nhB&RH1_(`)P~Get5)q= zr^6f)3g$~LShecau65d{8LpSc-kh2m$@T!m+oZ$5@ZbO=gTet0tCK4>aY*~__`o0{ zwMmJggNcEmC(+ArDNnMH6W78-A14pRl%OCj&81vUTB=in96gpU2{Q81T{Dd_Jex&+Fuj;&YbjOHd;r6uPqpD&pb^2e&B0fd`=Iny22iEYow+vdVetvzBFMOHWfR}aA)%qIp!V*nRj&_i1BL(f(!|@VR)IqLKxypt(p1SE zpz2$Pn}NZ=f>S`hsgTC#3LWv|^D#vpO7mDwS(rPp|k%3RStHgTykP(j`}-aty`JTe2@)G9{`@bK4`!=S!AciRv*t z78S#-xO7TXx9&EH**S_!rUYdh9*asg_S!lns@w3GM7ECC&M86J8;?q4_quA#jt0qQ zuQkVV=F%ykma34K=F%xaL0+1z0!|Q#rAwv+aVfS4 zfF-;*L0%w>g1lCOgdi3z zoe~7rp$W3cOLHky9jI>{qA)&W6cd#K^}1oM%rk zFbJ@3+;S~ybx+YLPtUc^Zc@({EV<#yuDCVAJ5|B)l&9C+CJs%um90HmOJ_`;=5%^S z5Koe}VM&jnyXDgmr{fX~3=B;S49tQ?!W<$Fjg34E77iX0m>9UYd1Mc}IymSlEj(~J|(2y}KFRWMvArJ=Qqx#1{lTMfgB3pYG= z?`Y6tj=69&mfeZNNuVi0#(|O3!s20@`n?Y=(sLFBhrDtCR~>Q;4;UE~ZZaq-Et>iG z#fKjZoPv^ynueB+kZ}%ch93+J9zhKq9U0FotZeKYoLt;IynOrum>3us!L_6V10x3q zXbb|>Z)RZN-~c<8;eaaGc<`tPs9l?(<#t;-KI(tnf2aRG|God4{a5@yCnPj1B_;F! zzW=lTr*KMc_!u!wp3$Xy*>9msa}08y&QH}zuVxHOR%^KJ(=f60)>X-O@iX>(nKZHB zN67k>UOC&h88wDn=P2AUKP%evczJyGi+3T@|JzMFI#YlDZR<(OlRXqN-QP<|uP{qu z?crrz^LxVs|C>+#BsvKmKAQT^vh#|~H|88!^~43|IFA{r8qS(Mm#1{%&%J3sr?lVu zbbON#Q?B*8WX%;MWlbmq}R2ml-!q1ooM1y*u+CCFHON7o6jnBFfIVZb87m&q>E$z73kbc_G{LM=YukY!3wp89~x$62~kMAy@yYJ7VPk%i5-p1JHBza6UI=(sF<=E;g zUa4#ot!zWuN)k^GVU&;|sc>5$vRIuZcb2(zBK3~u1aB~HP_DpU5 za^7{4m7|J-!zs3ebu%{^G$gTq)6(Wp=v$@Wc=VNwMp6+&!rC*fPb;UfuAbW#8W1}z zJaEU_b48~sZZ}RX6^_5e`O?TUa<1CTnUB{La4`Hy{Tg|dfq}Q;+~IgLgTTuS3_K1_ z9!1CYriJ_ctq9#_b;O04;eoAyn}EzWZ6R}$MS@l@){FgXGT36=EGj!^iv3FVQy04! zc>|i(R%$4yEL!3mymMjX&QRuH2BvQZ80NXF^!lA>4@#cYY+}E1eTPu*Y5rBZ2J$uh zVaNZ=BnU_Ha7$0?bP05tlrnXlmm1@nqq^VD-M!p-`Rw06_5#v*S0%dKI=|0u`?5a6 z>}_RPg=}<()XSrO?rXEv_3d>{=LTMlh%LQV`qbD*`;?S_0*m1EH3tNitV)uJ_I}cI z)u6*kNkuV}S88b>4kci76mq3LHQ?4Eh>e{&? z)Wo=4U`tD*qhmi~lY`LnashrdU*@JyWfF(7JoMBzs_qu*Tgm9&K zt9l|b5(+-D?K!#YL9UYUixT{WFq1p-_cUI?m-mhf@6$f$*F$=zAOk?Iq zwV0Hmd8C13iyq5YjxK*{$QNuGDv++anRvTmoW1t0oT7wjTRo>r;9W)nOQb+B^;1? zbj0lnM_6OvcOsU14CA6q93EVedAGTwkx}Z4(CI|a`92Ltjt9nH zwS9l}ani-*E16#zz7<~){NIZZt*TW_p$ zjGCapA#-HLEE$%Kf^J!XEnBtBny&VC-I*`d!=(}#=_oAGvwD&Ddl8rFdQYL&3*AW$ zu~RqdH#4*L4bzVw`i%@Hwgj_nGdq6HyG~A~U`J)&Q6>fk z7KcOP8xC!@v43wr{VA)G1{d23XQOQw7cZ#0&&JG=>C9&Bd{8WW%Cc~=n?(~PK2P;r zJh3TY0XLt9DBnL1m5qHD?WNBDoZtNRbBL$QB9@QLyZ>BB*mpSgj$NnkhNVKsyVo~t zOIP)Bv3w}Upkcal5{to>%C}FRzu$h;Y+uXNjM^#%J@r*rO}f@w_Ripa&Cj}E<3`qu zny0@mpSZW3{aD2IypHzwn+>JocO%A;93=P*Wzbtw6 zZnu5KMrnqILIwsswnsnSY0PRozkIRvGp3c#ukVQd!Zd+_fp6jQW~TlR+!hO&0^VEP zWHQ)db4l%H2E$hqhOS2e2D%E2ElhEdPZ;DM@z08yWf=ck$7mVLM@P|#p)*dtbF2O5 zRIl?bglW;XecsEn7VTtWV3@#g;a&V5zP-M4d*!U}p4QI2T#s(vtN46-!4H*w8>1wn9Ja0!YPiW{5FIUc zgUM*+t`O1St+&!Go<|9bhnEZd|6^0|_kKaX#s5qGHum{XZ@*r)WcTN+Ikm2-#@eCY z3=Den_t(fV*fW^z)mMf9G*K-q;-f`1i+GR{}0=F*Wtyd41kYj&k{CJ=F_e z)`C9en@A?0$CslTRKHS{@_u2Z#>XNzt9Oj+$uG`U)eND&x_YL*P38t541TI^f z!0FQCJfYZB;Kl<1cZ)MCuJ3Z-nYq(-L4KnLgMwV+6>GI)Y%8=RHl|KYEzi07>7)7d z1KXH7VZY43h~eg53XY5L3Mk1F1u7kbxscYgRI0l}QF zRZC~@%1+xf^G@Zi*6jQ9fA?&bJ{Na$jrjJRCQ1P@Rhp66r8iYJeBa6Q?{Cn7)B~w` z=Wm}r{d!upvaR$3;j4G|{|deS?DP6}k`FF1Jg{NNV7%~R+Ien=1cp+D3x5wiXX?^g z;q-X^e;&aq2hjWx8-v7z<@59Q+g!TLA!WnBkmA(s!W#RQy-R09h!&T_{g?3zBG%sL z7YN-I#!(}8fc26X+ee>eT{hBR&&_CE_5Gf);=`H~`@V|hPm7bfHs|oYw-%?cHWn+ZmE#8ElklSs9NB%ZqH^vT=joa)m0P-@ZS&m(E!G`f>R&D;JfgkJK36 zA2Hdbk||;;>2q$Mc<%MNpX4vU`ZG^a-sj`&o=fMwzrIObSFgv&5XPu{cQX^iBWH#Z zwWCRyTikysHHe+5+x+t4X5V=~_+3`cSbK%N;N~oo1|f&paYxecEO*}f>ZbMQv)Qt( zmYLT=lI4G?T)OFLu%asIoXdfI?`QorU|@K`TGIZjo-608D8mw~MzxdMZnTYIrrZoYX*T2k01ZzVqmcoo;a0Zin;4dM#Vg``z&xC`ok9{yPJvFy~>vzv={mz1t~Ty*E?{=A#99$QSk)+$%t z{(O~F)7*Pn&C^+TFPhi=IaLYnw-nzy;dJckl0cgblTCt$(gdfVGIlmz5Dh@{oeiC>mB3nS65qy#x7yfIFQjg zkAZ{BCPT#D{?YU{Qsm;J7Vh@K3)Iq~PJ z`MYi(cw~FBQv3by#f)hsZ!6{;{G^(%tyt_Razrol{^{>79)~V)MEP}TTFqO$!NZ`^ z{n){xwB6jr(kJzrC*G8c*8LOGwa)PAMIJ4KO-I!y&+z^^|LMVbP2c~WiU0THuBPr4 z&5q2n>-Wy&wD*$6BaCDkq~WI_|QOoiETuN0E5N<%DRaGGZswXmu6sKXn6Kont`F=wHE{1 z0qacx&ViNNK;68CBdL&HZK2KJA?j<059VAz+vw3Fvi z!z2Dc&wX*)B^qJweiQFRwTsluxN#(BIk&;B74uC4Q@1tQFn_OP=}u-a=KuY8S3Ea| z_FHx{p+3cLR}41oSFAL+8KAsYSNPaX#~ zrnPHrIOO>J+hQZ>-?x_^jwsgAId<;a`<|Fn`;N`%UjFyionsHb2MW5qUuyeUtzzP) zBE|`Sq9P4AzHO{do8UV!c2b?zf}{{DOP3oLIo+Cc zVo$1~xk;L(|DKXbqRSk1X8H&B-Dk^^U83~hQIbgE^FA{MhDYY--%WjYcF&jlGi$$j zt1&PvInlO9pXb4wbGKs;$Q^jvlJ+1%ogpjR=q@7z!-55N@7o&pomj}A5cTJ$rg-9E zCWe5mKSlos%x+?`{Hrc{w{QP*|3A-L)^a!;{AAA#>X9-u?X0;LUTmK&K4-4dUm@Q{Z+x^{k9_-@W<>1gYnlUk1a`#*VQm44{r z`E{?){z!{Wnj_7Y<6f5(!tCHED7e!>vUhrb%fglN)8F53zyH*k@8a|_{bT5w|*%kvuM$r6(9n>w@ZFbA(!Z3z0-X?$GZ4nN!NO;58V zMfmgO3=OL@9tlbd)=u6zZFHn_(?f<9$@A|*) z|BU|=|8HEd>Po<+l@1Yct*}62;XIwgYO<$RrsaA`nL5ciOZLR|M*B6&pmJI zJ%7K4#O?GQw{N?!ieCJ`cj^S=|J^K8^%u-KzI5Gd_0q#f&g`|{vNC4($E1xMpAMPJ z#Y8bp4g9FV-TJUWV3GK;wooOmZ9Lw}%~!atwF!QC^60roXx`LgM;3ZrKDOa-;6wr=!oa{rAtTnWC+*fMHfm4J!i!p9aGQ<)Y6&xp&Q~nafS**+?}t&l4lqXGD^Sd+r4pu;5Wv332OVQg#@l< z?Y?#J-qc{`54{g>Z(9|~ckji~=kDp-65h9O6+0KpG_jJ4A!KLR^et<~V>BysvDmB&LdKD&}&NjP}sN0a4*~C!AnlUjnw{U&n5a?pF75xbAHmb53*OF{ zcJSf$o*PA{uJN-nG(7lZJ6(FktMdOd4mSw1aI9eDYUoh-Ga>qiup>)1Ljb6bO1i4M zf={8K=6fLbhXac5HMmwOENW+T*l_fd{4?X9lTLL@yRtBRtp8s7*XGpgk4X-Ub$7n{ z>Rz>xmRWK2;kt~P3C@m159(j=hAGeb!@oD(e^W(8RW7U3veRaM{QMmE19`7{T+4ef zm0$hP|GWDg4(KZ|2po+!*><|3*Yet)RIRx+H=ghR>@2+XYI{X$Q`s!Pbhot!SF2_{ zTadzX^^!=+5|6J1g+Kp)-^a9O1=~g@M`f*lUlUyw1H!9ZFU@@Q@^Hz{-GWEfI`pjx z;Je4PTtY}eOX!G1^3s!5?hRh*Ry=2VZvSDdohj*}o8b|(YD087+p;+<4vva9b(7WuQS0mSO256*!BJ1w!FP*9MAY_^ITIXwImHDfPC7JkzHMmZbo!#UpOHa{ zfq`Mc`TZ4#_2Vt#CmhLUV_@iDWnpUYu&ApNzrgsXfl+}$tlNN*No$kEmv#S&c3(M~ z^pvHENkD^-gMqo}r!p(UjO{PKXWKnFbyng?)C*mv%1Wj|Ku4Q+;+?gU*s9_`sIH22?d28g^vGaU^pVNSZd)}W#>BX9zxF+0&0959OYMW3 z|8X-gFbJ>k*vufoG9jOXf#Jcb1}27vF4HXw7!();%pCS~v)mAoW;kF_Q_K9{F*ot& zxyRmz7!NQzFfsZvEZ|!B;hZpIext%RMg@Vq-aHmpM%CIsbAJbU>)OZbGcc7fE@fn3 zG1p+QR+>FKev|73{ds>6>o5Pz`>D#BjIm>8$X7M~$AJd|PbxcfU2?_qWskoS9f0u&{$6j(?7g~2h`Q+`nKf315p7UazPxGTS_a2u? z-)87Ou%Joqa@Nn6d5-?(#vgeZm=l>zn6tkyt1>W%N=m$A(%8Ykz~IBou%qH-S(Aytk zpZke*6$4kYFspHTqtdFX(`Bny&DV@+jel7a70AHqQNR#TAk8en@b9;2+xdy?{4%MV z{;d=D)>E}lGm~+B<8Nr{%jv+DI6wZG)2A1;-+wU_{dswl;X~Y9MzPJ;1h)P@Q{>nr z{NRyvLF51J1tAVID!CXvB+O;5u2HgEIB9a};iCU@?A%QMmClZyCNn8ymr2QUZqb0y zkdPx%-`m`6GQ=iob$2l+eR&Yu-DjSvVkN}#qE}x(@Q=k0S@C*){@K-C)rGkdjv@@A z3SZW;7>7^QDvLa^%xxQ6u;JuAQx@0qF%(H_rtYkrI&+wD zuzoTx8v_H&hc|}~fCj%AE;PJOu{qeqz|g?L(7$$0`N}h8f&3|7Q0e;Qwjeug@>f#=x+S!B4oPvEr}P1BN{7My7l* zhL#FtUWSefAO0^h+xqjVcr=43tHeR?Fb+W;b~bi~xYJiVyH6eUHc*-HBWwGP1uJ5| zc-<0W{ZVhXGc593Z)5@kLk%axhcDYNGBiZ)@5+gIK2LXUVB?csgSpx(1j`$@utglu z>99C6$8_Jc?UUE+Y_L19kFP<|@XNdq?jl7cyU7#FOz!XQVEA;Zb%n-~#r!uXpS+k+ zT)6!z``s%Oxg;&u{m4FMzUJ4KHn$1>PIB|Up1iZ8Ilf(G#$>sZm%GF}r}->tIr*MD zO|pjX@yd3=gex1rY*LySdf0EKb`jUIbMHMk75Eu=L(I1@32L2bX!JZ<8~9>(+q;GA z4hlbP1MdnkOYQoXARviKIU!ACbPcBX8 z(|F4;hnXiphk;?<>8rdgYj}GuY3%s0J?>T zSQrwPurM$@>Mvd>n!v{39XW;P;M1T}rc?GXGB7*=#l?$Nj0_BC?wqK(CJI_WK7oNj z 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 literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/ebwizardry/structures/obelisk_1.nbt b/src/main/resources/assets/ebwizardry/structures/obelisk_1.nbt new file mode 100644 index 0000000000000000000000000000000000000000..6fd0cde26cce23fa36df49e30b782891ebf1b306 GIT binary patch literal 615 zcmb2|=3sz;-f8EvZySglpP#F`(RSOr4c`B|rW$hHUMg~HuGckZ$y|NszIdU)Xs$_4 z*XDg&?*FOZqmG{&4%1Y?R!eSmcqC7v+1D;s%L_^HflUvA|{kR>wNC+xlFqY%TFJC@?I=(OX-Yj8I>n>+dCsa_PWeH zv_mXPn>XiIah2>r_Kg#~9+#F+b`|sq%W9VL78gjnaQ1G&vYOoK=S+65{bBs-bAI}{ z*06JH12&2JH0)fyJHIk)wNPVh?7i4+ulfH@-u3&-zO(D&>sr*d%$y)59(Ch+_x^t( z!ka^+^|pjh+T*7GGP(GdlyvgfsVGeIng5r+y~*xlRBP1fpcAeO|G88@ zlHh$LA)ipD-G4M4DSMo< zFV<^sl=&3BHf%*L>oS9bT-o0;wC;$0jLp5bIp*H~ O8LacJG9+^`FaQAGX&`j~ literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/ebwizardry/structures/obelisk_2.nbt b/src/main/resources/assets/ebwizardry/structures/obelisk_2.nbt new file mode 100644 index 0000000000000000000000000000000000000000..0b2ec08ffd6225bf4f89dc2b59be49d66d450d63 GIT binary patch literal 601 zcmb2|=3sz;-f52cvkgR!%Rf*#u%)y;_Lt_iuLhaBL#E!EyJ}5)R#x>)p9;@4O|m!p zBC2k=&zCju%oO_VDR|`1z5fS4-=86)z`W=Nw;IEPx|z0V6O^v|7>6+2K3Evod2{or zv-8(Ws%S5aagyiknX*i3cTcSvSHdF(wmH+>j~{PX{ruub!v}ry(!U!PG9)*%y!as@ zy_i8({;?9*jLX42uODiHR6EED9q3`2QOID-nQ*D$-;ECDYu7c^_!1Ue{`B&P#0!i0 zef@>^KG^Q=?_`#cR&h9f{DuVUi#@4D9u*6NPvo^;_`YR@z`2bXH@K%Rz4K>=ZeZru zNRbG`uXCKvcv-BLJU(+t@!dGT#yhjVe+g`UBdz<2dzoogRFH4tqOdIwHG(Cs`*ZUUX>ZNd3RS{K;7?uN2g3UG$plZ zdlRQXaXG)Pe^#KBxpUsjtw-!{=dPJtm$P*HbN{tp&#wtnytXH$Ca`1w#YQ`~X1inV zGyYCbFKUp?({pCyyCP*&$iUpky+b~Jt-#!eryoYFy?*ALS!VX^?(Q=cJz*4 Jo$ELm7yuoSBh>%^ literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/ebwizardry/structures/obelisk_3.nbt b/src/main/resources/assets/ebwizardry/structures/obelisk_3.nbt new file mode 100644 index 0000000000000000000000000000000000000000..8da474085603e27fb68b055f66a7ff07417a03fc GIT binary patch literal 609 zcmb2|=3sz;-f6!1w+(pOG`&4@_@m2jEZv{v%+7N|&$Y2^xzg)}61QU6EYpM*ZWHm~ z+Vo}1e7lqKp0iA+u}JtWY1h~EQklb?a-gTejf>%*`R6<@yk_3hXv_3)w_s_=Qcgw#rBWeG7! z{_Yo?ifTXmPd1)9v~0p%t-*Eiek((O5Vhh#sM_5aX1_waA|Qt^tnDRqm?)}`;@c`I?9Q7_i&o{Wxp P@P7t(zgJq{I2jlK%5)iN literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/ebwizardry/structures/obelisk_4.nbt b/src/main/resources/assets/ebwizardry/structures/obelisk_4.nbt new file mode 100644 index 0000000000000000000000000000000000000000..8353302767cdc5875b706cad9ccd3e6fa757ba5b GIT binary patch literal 660 zcmb2|=3sz;-f4#Uw+#eZ`;~IN^=_5Cm=u3e$+@wNlSyS}lZkVHNi5f?eHJb`7Zoyh zoV+qWE=WlBdT*_}!vw|J?|wB~XN`(3EA5Gb=#y6@9oeh<~C$F)7YJ7A_9J8B#*F+w*uTn-;fjud&dL(>K zCTJbob8Bn*p7-q%C$9wZq#a0TJCh#P6SH(i)4>z}XBeJX#-|z*eyuG!_Pk)<#<1BMRfi<_v5Qu=PIrEy!rO#cfVx6T$K5KYT8S^|1D)JwJ)>G zu@s)?_kT%b&!6Vl?8lRW7K_hNnQVSs|K5)WVUsr${aAfBtor3{zg>UtW^r41MQx2W z4ZeIP>v!~M00cA;_Zxdd*8csTx!oM<3L^(b+Zqdp&i(Woi(q*~q zxdhWP|6J3ykG-3{OEjN&Nj#Jh|9D#F%HF~mOwX)X&$O=%DO;`fY+bHESyub^Dj{c< zD^~aJPkG1oEiZI_Yp%reS$`e3Io{i+pvigs!@oq~2C+ SF5SKNi}v?{`~Rtr~9PqhJlWYR?1l@E7gm<6Zp4#!JO>qn_be2zBSES z_vMYhaoPU@$D4EWoEEo~%~w&rdE-*i^`!ef43k@wh1Apjd==>sHjbQLY?Z*0pptOu zT#AF8vm1jOlN+O24U54##mS5i-m!Y2f*2u*>k|YUCN=~%oOGPr@Hptej^a#Z-S4CkazwM7#z%+3nj z{aO63u$5;<$@1+v74OvIOy2A}JZFNIdD+WZV&SVl%{zPj@p-*{7uTKly1u(Xl5_g4 z^K-?sZPSIGr(aLs{n`AAt=iq{MW(wi@4vOy#WgfKZpNv5^Z$LmY@Ri(Dmv_#`>NBX zzb9mxF6V!}>e)=q{I{OTXVcQm+v>NkpQ88WtX|3Qa%t;@%JSK(%)jngB_90OyfSUF z?7bD9_MJzUUi-Fd&bk@*K9@w>PD#sq=bz@Cm-BgJq}22adfOKtzjJG~-dFGGH#X0< zvVEan`|MdpyhF8Gwc>k4WyZ_-Cp_W}l^HL87k{aprjl^z>@3$$osx_aoD!@vJ|uKJ zl`&>A5HjF0$UMOv@jc?4p)%uQ2H|gQ4Bw7T00k=NYq`_vX(|aK35RAKgKONdOeo^A zqA~+m@ip6N#b-DUcpT6;(6U$Xv}GD7)>~3- zw?pmUik~07b!Ntqr$^r&efLXtYy9?qI+YUhr@Izs>AdFXeFO zzMgq1>Fn1jE9YHo->O%c)xFbt^_;stcaME~|LjKQ@_n~`@7Cl!^Lw#mUUrh%Q=jSG zoj+&q*5n=k86`L+ zSV6qQ$zQvU$`}h7a2aHFaIdJ=c{XEWLtq1EwKGHY;`1H{G!C@vI{v6r5~Mufa)gbc zGJ`VXVg}(Xt;Sj3pvDAzk2nJp|K_IiY=&UN#D>5Gn^IkofbVw7jKW1C(b{P$3A17|w7kA;lc>4NTTau+ zmoMk1y{S9Hed=9_uvF@mT*;HircK)|)~?3rBW1WaZ-q*d(19flCzaGyf{ zO-NIir>M-J%($3AI7!UmjI$eq836PYkyQJGQr znKpZoMardjx03%J@wxTZaI&po@~KyyXEozD>!vT&_4L{LaL$!oMsCtV)9v-n3s(i} zW|jZhQ{AP`+57IxG~V+uL9U128OP|aEJ~ifF0*i}*87_^*1sP8GQZUu`LgPIqT8X? zZ`sd}MxCE=#(E$#RGu9tcC-G|)WcUG*(I?Ww?^Y`R>JJZE!E4Qbn*7%q1 zOuL^Nb@s*MU8^dyPVKbKTXWOr?XeH)j|{F;(D9dqU72BXD{t&DBHNVwr8#FYp4AM zjkdcJE;oO?Bp%oHoB#Kl)*bCVEI#{hC?y~5Vezq#OIb5xVgsjnl31sD8YpZ<5)S#w zcU!{P&KhFHXE+Xc9MCw>vQ@ERt6_>tf=I%lJ;xt)N^(lD&M;WMu_6f?-e*>_JS#Z? zRb1JBRK}ReK*)g0ATjqyQlBKF1g8Y+vB%Gy7(d&ks3bV`C4pTqpIPDj#*Oo4si)q* ze%`%RTj;cC^yz=~`y?*^IQ7EXY+uuv%p=-y#krnmv=8sA+WqC~?caM(oy^G!mw7qs z<$~OBqiw9&89$2lmfwgvdwS*S_Z~U1?`wY_p0&pQl=6Bch_u~t0B=-YgH%C=>_*N&Yi zyn3+HzV;k{`>Lgt_dNnL|7`sG>&-R)o=zj7(2q-ml~%n!bAM6YS&gepwPO})FIwj4 zJ1y#<2YepQwVUfi7&_v^X%-An;jlPUx0+^=W!7p&M)&pW?0WM3Kgebe1>&-!oG+5dZW zeEYHUkux^Q8Yn(={(ZMMUG`h% zYO?Q{U2{aA)+GINW#`-QR=@a)y5VkX%#B#eCfv6(JuW zefy$!j_+#zzn9p*y_&9kZ>GN82FGpu)1Eloadu-;%Q4B*JLhrW%V)#lLN_M0Wq+HW zZmqCTW>98a%phEDE^eI8lAw|xlJH1Ce8an#GjqU!S?$bFoqPfu#--06J?vrWVe*Lx z){{F24S3V32WIg}GD>htu+9MMf<{7hbN5VRP$Y2mq;H>Kv*jJg1y4F=cN+^C)bcgh z6c@jpy?4|5+tVMP5%2sNWWD_LfAJ2(-t}uMFKk<<5G?g_Y23?86L;vZS+{!o>Rna8 zH-uW=EPdIn9GrFQ#xM zGS%x}1^!443nj_X9_3629E2c9%! z_OWyvmVA|c?5Lv;+q%SaGoH+p3=He7_511dyC~|{q$5YH=1z{1e7;7x@ayAON(;@? z;#yye|BbfseDUI5-j>Uk17reUe~>Iz2wnGAiAQ(c^ry{b_xtv@{5aQU*}HaEgJkD~ zTkFqtPo0}3^gP`>{qEQ3SMf_9?p|Vg_v!Ak-GPZ(>z|+d(SEu9tg`G??%kTb*-D{L zz04JZjhFUo2fyspPXD*$Tb}L5?B(^_4vm3I83k2J>6~$QoC_kjNKe)1ei{B@NMs50IOYN zJ>58+B|#-YB;nD$2Sv{y!k=&EzvH`Fd&1+u5z|M{9`&%CDdTM@efF#>Z{F70czb#A zg`PUoZ&ly@Ghg4$WLMd@xZTT|&%E@||LPS!@5mX8yCwPIzTdyqEiW#5t!3iA?a~(W zZTXV7+f4av?!157AGWzj=$Ez7Y=K(qy8Y_6?^XOQS)6I?{^i~7(&Abv?{`>LsXxXIehJlWYuJO+i3@jG;Cvdjh(K6i6`mAZ-?FGxU zjeiIC|Fw?^C`*5JL381|$tfz?;a2ae-^>?ui~CD z@x#i$Z}vpYww!EXzuWHhx%&bCXMB0zd97r5{npzpT(OpM5pUo5|2Lg(vTAx-bk=Q` zRi{kN6@zV;^Jm9?JTqLX7_umfplK-`g`|iKH$NXNb=rlE*owaWD(JOy^ z=iN+cH_zHM`^ck966LXe;XdyxcU|RQI`{VP$u}ouhu5!}eog(#)3Pr!qHn(n-v6c3 zcK1sD{9j*Y&R$&0_;%)-);;Y#EIt(tM~-z#a?ZG0F>zy(8Gj5*EoG>pr+1Awm z)IRYfhH&u9ugdWmN2wzh83qgJSz1 j{M)wbXZ;m<+cSSbu)X~HZ?kR(|7Y}@UR&{7fPn!3?-+1P literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/ebwizardry/structures/shrine_6.nbt b/src/main/resources/assets/ebwizardry/structures/shrine_6.nbt new file mode 100644 index 0000000000000000000000000000000000000000..d699d08c485a46f9e0bde301bc5e0de835d953f2 GIT binary patch literal 745 zcmb2|=3sz;-s}GUw+$rNKA3mDHJkhG`G&*aG`B63Rnz0(EOY8%p4D)A%CnKF6BY4^E;ffmK}T_0v%4hUaYvUFYNEa|L0 zCX?@fJ@Mb@wB~N}(wr%Q*ua}eS6#MXU}(kyILXrOKNth zsqX5ZH~x6WRR|tddG~Lj+HKD>`aOl$k5;UF*({fT>i8kQw}(HbEX)qCUnPExJ!|vc z+Edr=e7&e&vq3!mPf7lsF9#02%e!>5@lLH9lUkn3orpOT8*cU;?>Q>TIb%!px1N)S zK|v+KI%A9V&NFi$A?TT`mvDFInK|IleBZ`!uh$M7$k*qdJ}k*8!8&8dvKYB@90xoO zXdF0VI`zP;Z%{LKyo*VLiI+E@J_8Ycc2i%7e{J>ri4C2_M|wdPzm;M5e5Uv79UJZ6 z`|9jY)lQ7i*;;J%XTH9h$*xV$;%)~x@?|cVUbR%)Jt-_ocGdRN0ekn}UpeQ^u1`lN zt~7bO^{v;jWeL5!{MW00uf4iv#*bfpM~;2pm%BfHa&G>fx?O^&&Is=Po%beY{?CK; iS<$~2UGu+q?FXmT$IlxsLcpT6;@MM7}!(=y~6a5UIE~m33s3eFa98zq&e>L6c07QX_JJYc>4KsfC zu=w!JVlmK6*wn#!ek0=tneLe;Nlta2Iy}FfnXoDANzp0sH>W&bdI=>bTdHrpa81hl z(XZoQQ=Rg^Z29zDfA?Jl&x{WlVL6qL)B~=(x$n%gu^sC|J&=gx?5)&basEf{rT%p>sN9o>-@9M{`yk8TV>^isgGA)efRQB{O8GR zU(c-Z%AGxLRnbA;=_}`5INrLhBIh)Fd6e~TncYjD-hcb;YH98Ecf0=9?2kK_KYO2B zTBL7@sqD=CCmWC6QYrl1=5OYyv#zIb`_qhbUmD%D|Hj%Kw%*>Ig_GbT0!Hh4P69N2R_sZWwqf_26QGnNfzzj|1Dn0#h@kFYUR zW?al5{LDnm{|qF^TP&v@nDb4NQ39mc;QhuK$!-j8Om2*7YkDKj7%DR;GcG<*QPzDV z`SZPWl?120q~xPLEN9f%9p)t`zn#5z)BD%YCm#~;d^%_D<7fYw43|9YHSN!t&1JNl z@qFdMsmdQ0=$c=>T^hW1@BLMC-fa4GbmGbxWw**ylcP7ZwH<%G_wKb<3uS))>N|4k z`@YQm(UWua_SEgXFlDB5)%UwMG~<69tlzY@Ht==u7DGG7bUXR=+w`_C|HsU6A*DK9 HkbwaJDt3cs literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/ebwizardry/structures/wizard_tower_0.nbt b/src/main/resources/assets/ebwizardry/structures/wizard_tower_0.nbt new file mode 100644 index 0000000000000000000000000000000000000000..903225608a14de846effba73dd71ec4452baaa76 GIT binary patch literal 2188 zcmb2|=3sz;rMG^_$J~uKvwj(kts;?s%LCPo3c%035tFK2u z&GHZbb0;^B$NjdaT6+Z2&ai`YO1@^>IYIDH&s%m7^&^}4DM-n-o)fJ-0>^SKCxVQU z-w>de(qfPoEd)}tTtf3f{XG#;oH%5OHXS#dH^$lsmQWyd-P+=d=6d+?i=4 zIWwEJN44knx<*e<<&-(ni(=nRZ77bDuI*deB6uib(Y&88|I9F&X7KrP+am?z?|)ey zDHz*-Rqkp&^XJNS4L+mdc=L|tp6|MxqJlkC%kv;~JG;$M*&$$@m;J?dTCWCiL}3p}pb2LJ5rQ*{z!=142?8G+a>26?|djyN8h`#E0VnfIdlJKh~1oesb(|Cn?t z;?NI6)}xNc>hqimCwxp6?rQFlpB*5R^5;kEBZbHI<_j%O{4nG@>UgZbP=n8?PR6Bh z!pFx7r(lCD&!htPH-gF=u816g>nsX zBc~aKdssk9epIuAQqr;e@1f~K03^C2*YgP|4IM8J={MVW{!p+RM{;M?pC5f$*WAuC zf^5(U?5|(fo^?$v#MsD5!u!hO=PJ+DzVQfd^`0HDdjdFh^yFOUlJJ(;9?Lvg$nAuM zxr^<)U#AZ2WtCLy+0PaTN{#<+If88aQEbQjca84~xs(=zX=~D1LEh=fujVUKRCe5K z;<@)-vGMwC&%QtXwe(lamfPRHzFu@!q_pz)r7iuhH{G+*IrAw0tAFZU^S7%zU9R6R zT9*9f&&oI5xfjKc$r(R6W*3@!dyCrNFW>#|pFa~?8gHKa^KWM9^PIFzwV#8wJuTyy zT=w+C=Py!ay7PXwCtg3wzx&bFoc~{*uW#eYHBMPO>z9Oq;md$K`}^!_v$ieu-2eNV z{C&Cq{})@oS$E-8aiziW`v13Oq&BU1wQo=U>VIEn|KD+0`L*1v>5H;rm+Y$0iuJf2 zyT5wXtD?(d<$tfo-nYyD^?chNTOD`X)_)%*etr0@`0dP^m^G!JWAa!3s=NC~X1B$8 zdk)VhhpgiRGL+4ieLgA{`Q%th-lr43>_;8lI3DL)fuc{MK5!u@O8=Z?0%vx0DNays zS5xlUe^6ccd4!Zf_lfrCkbbk%2gI#3&h2Qlb8%yG+it7;=t+xYHj}Bca*O0`wxY~p z!Jiv?i(azYF8u61`@+w~z8cfxz6fWD8wnXK{JknpLIjjJ)C}K?^S2gd3R}f#_$A%b zH{g=h&vkn1bgaMd#EYX=8$WViZSGO+`TxM`>UqxtM~*p$7#mGnaoqnxpuIAv_)6w{ zY+tZw)pwp9m%K~deaSlspKGok0fRkiWH%xY%SXBe3!*ttBD4lew&alVme zVvB)Uf}V2mq?HzyiGL2iEEb;iIa_%4_66Ir7x!1Y9XZMQINJ&A5m}4*TRERP9b@x( zQSs6>dEqu?<(7~9?*nab9eHNILN2$&{`Y5anK*gI_wI*I$75#)=%wTwX!#YXzlwXS ztfXSk?JrK-Z^&?hy%Eo1aMk{ELuYMxLzbHxM>6N+iEl4)zfbzCaRroSry11AwPv}g zsrCpQoAmVsYwN~JkyY%H+h4l2Z`>(%>gbV++``Uo`c^$>U!U8b%v0-jS|l3K}~K$-fOK)qb2U`XL_6-@%t={^}dd}7d=%w6Q zChpi)lqo!G{j29j8!azQ+1T>&^Zb>c)j4O}_{08H(a0CR*Z;{%+*G?!`}e+*>;Jx9 z(y7mwU3+ua@?$$E`fe`fpK89|_3gatbw%g1{}=pQuuY=w{yjU9x7$kg=d|rm{_}}9 zZ`RkU@Uq(A>26O?)M?#XwW4~m$lG=ub%FDU3#Z>S*&GA$aNmu-`~>jZb`3SrvEhKcu4%7rMvEn z#+L7vUnP5gZ%y@eTkY#7<+~PMEW7)q_Or0vE@ctjQ;rYM6`TqVV@nf&w-{bGp_z(LX-gtXz`QH4dH+PuY|Ku)ge*ZT<#O#Hl z&szRtzs>SyKa1VYe%bE*_sN<4&kwCX_4{1ISYx#8LOqHjZZTIyB7>`uF?Y~z&N3y8xl27kUiQTcaD~*zS?A88$JpOOT ztQm_|?GD|(YTL0l{~kPho%V6lTq)y!uaBh6PLsa(r2o#Fx(T`AWmg}{K0hYpcEaLb z@3}K4Vy-=I5Ioew|Fwth)k!6{;~QH94_R!Q$0Xq`q4?N`<8i;?3w=g64&h(fK3~L7 zwe~0%iyq)eJk;9xNa6ACM6Vgzi{?cu@fkTC`{?f0Ghb1;h4XLMBL(4OiEcg4Q@ADF zpJ_F0Y!Ng%*RtX{*PQ99Jp#w%ue<1_v>5!`p;)A--10H`&9sd4+@!Ax$}NQ{w#G?+ z6qH*|p81!0aHq0z%gM6+hj&g8Jk+w!9Yo1IZj3p>k=XaWY67>U;+czrpIN&ecUYWg z*~u{1+Q?~!f%pQD{2xPz(Z{EpXzdX=7H=NzVtcDcxcJTl!9x~{N`}^BZz1W#4W4Q72CAG4+6C8;$f&PB;uJcH^OVr7_a=gjocA$NhfmUd#>a;ag%c#(KQk9jkd(hAc+@eiCL>#feP&^S z0-w>tnSw_hj~&}7b>!VY@{4EeMT=_HUghP}XYNhk#yCw@SQz$;$aFSE_-Dl@x zg2#^URDYxZV!LrX?&k-2pyFSbLA>zW$MKei@lPK7a&qH%+);JN_~L}Z7S8i78hl2H z_Z$l+a25-9HTzVkITcRe{4Czp>@#D3fK19Enf6Bt!t**oOq-5J3c}AEr+Cl4V$-oM zI7KG0XwfqR{zcy|s+saHf`>)WXU$WsK90|3F-{g%JF^_*CU7_$sjPHr5+?_|M(1^b;rN`53e zfkYqoYfj{rRP>2pUQo5g^Xz+#>!t>M1`l`Ji?Gi$cs_6TmG6Zb;zpJ;v)Ou-d+gsq z(z-`@dgawolv{YkSo<`ftIF-*!?n zYcB5z&)xdw^6lKK|Env$=Ih?y_59!3$@8y2eZK1N?fdrMByTM{zbori?SV5l_U)*D zzqdAb+SHBr>%X6W|84*OqvbvNC101`n)!GA|Ku`tqsXhVU$3m&b^iXp^W_QqYV+=$ z4t=eB^=bA~=e}_7&&#ie#_HbswDEV^?XCIU@7AuBE1Uh5e_{R2_IrQ#blVyk%V*!) zbMP@w6|I|6|U6_q|c~Z&{9bYOL)Z^S7t>tP(#jZ2WWMzpblw zFZ-J#Gk~N5MMT&o70Y#2UOGvs@W7Qnl%wprpoOVR1f1fayoW#c4<&HC;P3)*{_dO zC2RDl_PF%yyVtw(&W}k^`3pW@dZxBf%@LeLS_)m(c((b78SdiM6?Er#tmI~IE%QA8 zLfZ+B#6#kHSIFfCWlM+jo9&wGEWHp^@);%TnYkYQ6+1gZFD2&4kz0}Z>%44@7gbH* zj89lxwZ(Jo!~ok{M}EcTfAd;9F+lIw3*Ly8U-?(DODg*OcvQJU|Cpe#^!XDJhd2^t z5{o|V`O>!GiWS#faZt%PV?&>lsd6$WxR|b59GxZG`pWT`e3fxb*4ox0!@@6ZJ7-*+ z{V?eDE}1#vM$-(OB$D;adzW6zd9L>I|5%{HFjYP2XVWm89IEnmYUj+x&1 zZQg6Q2I!?UIq%%E(|66{0KL5{^|tmo{axq#<}>f!k9ybQZ!NhN_+rnOXM3(laXxiY zGoCK}Bj~mKm3WOl`!8zyul!=4JKb!T{-Iy#8h#P~7eGS0vX}%QU4cIO(+yx z{C;m@Zu2bxNpP{~6LA}=%wm(=-j@bjw>f?_DExBl$d&XBtcAQ{N4}bZ$`ONyw;Vww zL5pEOIF^$|pE|jnu&DanZhc!O;Eg$Z%^wTHpUYyxW5a(&f6d8SX21RHvaG*m&4*4b ziu@hR@%d}?)BO+rKiU7_|LLFRzf=Ez{`7EX&h)AO6EC*g9$N2TaPiFZ*IBnsOH)Jo z{#@S_JGC@@)3O@Nec#`Gxp#Kgn)q$U_t#kbO}%HLfBSjX-xbMn-%Q?o3u*bj)Lcd8 zc7s`F8TC)lYORn{;qYEzNQZ&KkqlMt-iv4yVUaf!aK=3Bd+?lOC7FGU;e$!x4QD% z!`SxEY4^9Sw|+hA?0fB~dB303vaer#T+e0d*876NbIOjjT>F1k^4l){;MeDN`0UP^ z)tzR)WNO*hFEyurZ@bC!>@I)X{i#2;FKnCj`<=Y+?~vO2{D100-7&Wef584pN_7gqF@FF0K^iQe*gdg literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/ebwizardry/structures/wizard_tower_2.nbt b/src/main/resources/assets/ebwizardry/structures/wizard_tower_2.nbt new file mode 100644 index 0000000000000000000000000000000000000000..b19b6de4fef4f0f3b200fdb122e0a50fb54301bd GIT binary patch literal 2422 zcmb2|=3sz;t+##iAD<9pdob-pme;4}Hy-<#Sw1mWslI(WsqrpD^~^Vl9GiAZOmVs0 zlzM5wi_$c|pDz-nsW|`PxV5RrV z(8_4Bhh7SZ-5GO&BeA4Lp-54=Me_agN|t9gXGPea;7GKIJa1|MQa|&y?Xd^9CJG)( zx&8hjNcEvxi$N6MPX~|@?YkVo)NA&g69f;nTxUDg+9TlR?)b#Xjbm}L6NnNvGo8XM zso2veIT1_=D~TI9NysjD0co^4*8wuEWR5UM|BK&GSp)k`A0N4y2697S|Fs&=D>=T? zER=aA6?@cQU7TevU>YsFS`xym{e4QJT20d3=gqD)ov|QO{jUU1xL(TJqu$fkf8a@r zpwT(r!q{IY4pc=7SMOC;Zu#h9`}pr(ixiv0W4{|8DH!v8W_hGweDAz+SM!+)`|BEf zMvnu`JDPirX?9qg$e6<^$Ubx9?YR>JWKvAd^?<}J6(1=qF7)dJ$r>y18A&~#)6v|s zuTQ@t=Gu+#(|Qc%8L)z#9kbiC?7vor#jMxN2CRu+3R8RT>bnU}zUAM3rsYg2uaBd| zUUNI9$DE5Fvq>oS^xbEiEbMl|Vt&WZi|&4N7(X>$clDD1d71OKwNY}yp?kePeovBm z1a{g8vd`S`T*+9m$S}?8$t=Ob37plcM$29Fj?EF=d9KsqM2juo(@knyk1xEgX#{di z@eTHieo!vMVKNc2bm)twQ z-hW1Z$IpxH0>2kDT!)0LupKwQr2mW$krGE8)!r=E;4?}*?^-y4bAD@}Ov<5sJ&zQG zzom+>&)iVH*y2RX`9mND_3nieIDcDrHTzgFFMx?YoYU|~LHHb}#&pw_#Y|Q5&c}q8 zDP-|IXECwAw&WbA#&z}tu0vqARx&?zN^^R)i*1>Lk3~L@q`!o$`2mi^LzT%Vz>%xI zNUrurTyExeklu8#TyMd|4Ehj)J__!t{u^K}X>vI>7F%QqQz1pZ&D(AdYukm9Gr!9{L zpV7mflANGgRt<3@)|s!RB>W|0GoE;VD0fzynFx55*+B|B%$JpHQDym0dJRoc^2!>#`B`W3b9bmwRP z)!TBTrq}E1Q>U%e}8%hTBJcb8?y zi{15(zMJ=d@gch}>vvzcy?*;f_jgXoXJ=2Z+PUie^RxSd^*27Qzjd1b@`}j+5ogPT zZ`A!UN*qdDw zCU$hLou2!o3#4}OVYBL^MIdPr_x4|q&G6pTx1k``e$rDVkvx9(a34Wg((f7W_JAj+;GRcJBNNxs;L{ZFjFoNRdXK=do!@)cuH5`>(k08*Rp?z0y&k%2d)%2jZ>DdnTo?8B>r9JC zlh^aa{h!u`mM=BCRdda4w!LimjVXVxpT6C`DK_la(M9~V4d(d;7tcI@opsr?^r_FR zN82~WPAz@DX<3bp&G%1lcbm2T!s zS<(Hx;oQAP8NVl<{S)x*>5t0GrDua*J?c|?w)Lg<+I;iZMS0FYcNcA3^*;9BE&n?Y zcZ%nqe>-d2dhL%oH%d%pIajNN%J z-S(B=?PWZ6=gcarT z`s}lBi+}zTEsD4ld!SKu@1N|;_rmSJZU1Y(s%&%Ct24g*tLnf1*jL|dVfpLhx9I<@ NZI{B@zJxO{005tFth4|C literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/ebwizardry/structures/wizard_tower_3.nbt b/src/main/resources/assets/ebwizardry/structures/wizard_tower_3.nbt new file mode 100644 index 0000000000000000000000000000000000000000..1022822af7973055c5fbc444e9cd88494f228f79 GIT binary patch literal 1927 zcmb2|=3sz;t+#yhZ@USwJ(#+~x%TMB-=!K=FY+_0PpfK75P6|`cA>_sI3BO4+byX< z3NLq@TUo#K|CSg}=grxA_r*1|8ak3~=Sb?El#M*S)Q~&*^`FV!J%)ABTW&x9cfWP! z?nNhO-?@5B=AOs(-9^RG`n@y%>@_&KZ%wKCe%-SV*;me9Q@Gsr*D)bCj>p?0cl%bQ z8BO4pRP4F`%tbGy#lY%^2A|R8%MyMEB-+wm?3f^UXi18#c7je~i$SO5zGV+?OcXq% z(tiJ;#fcY{u7wj`CN(CzyKyYu7y#0I_hYlgi5FkHvfSJ_9-qJ3vqIhE@`)Jpv=#%+ z!2b1>d_G3^7 z2FgXPYJ1Ft4n-W|NDMl3rsMIa<96!D3`|Zs=!qPE9wo5T$#@F)(U0p>6AtZ6HA+bO zY`lv7=*-Dq*EGx&JQlxNAM6O@gcgIkYR(?jo(YBLIzN8Y_x>Wn{Vp{H?1yht3?~b@ zRdaPU_k0r(VV8WXsljJ-D>y(VWy|sf7AG?N9j`}ZB>iQIwLfvDqiT!zf@FT*HR1~_ zxRv}el0NT|-FaV~Sti)$zb-o`I5$8HBPW-5T z-efRe@bTk#r!U-$-;Io%W=vV({`=?*PtL`EnT|TT{bmKZfg9uoagZDIL2ig&V6m|C z>}QSZb54lPx?$5_q}vg*u=8uvMvH%2d3@H0FQ{@7e$AR(_zV=KX)PDy4AO!Q{dmhG zq1f}S$uOByIb}}qBDw!w?&qef_6WG0*FM$SBd~0CvjaGCOIaQ%EH+&@Yog$x70x>+ z2p%dawms3>BjC2b-|1_M+PCjVX9ylz;$r(t)^3%h$-_I@oXRbpomC}!6V5DYxw!AL z`NpqIQ@CeJ&dg@@@silTm*JR@+X;(w7u)vp4iDs9+&C6r*8*9nW*M8T!Dm#}dloYd zR=p{nz%40h;yqd9bz0uCpVw+0U*rF|e9f(}{`H%(CX2rNv~W${^>sJy=$v`<{Ly0V zS(~a%CUPChznv>yTlaic&TP|}p8b-~)b^fUy=qNQ?f28Ww+nwZ+OK!&)LvWLRO6X5 zZtklon0k9#V$R!J_5SP2uD{v0GqXH)&;8W?b-&)VzrW2BdNb|p=|>U%PhNsk?1##7emSK9u>H&h{U28 zpE(~EuBc4m`Q3e|`^3iYXN^87mRe2nmcAr%rKd;0O*-iQ8l}h0MGGygG#5Vx8E}^E zDTw->;B==MWc+spkon7QS3PrmBKKzY<`cFZMXmfYJhI|OMhS;z?Vbfr5S^9(9vlMa z`(N#ntJo#~CUYKj1eGg`<;wzXPk?gamwvqvexqpyPBW&gQLhO|SRt3v(j#o=BQV=o zx1$-9#3Jvv6i<;g*k~#I)T`sMlN;Na(;$%-2} zN&ID6mw%{Eky%Yfes1-}Ld9fG<(7-Av-fe@r~9${a^^&CHJ6d;0RG zQ(f85!^Q6XoZ6cI+nX!$_vde))K+gh_kTmCa`}hV>N_;Azn;5#_ND^06Gp#hgjR-` zsA+D#op--`dF}VzYj&*NUB0iPDm`}E_OHFSV@vb<*7CJ>`fKa8i^|`%-xqUf;%4n|)`#$L`{A-`$UWul3D&^M~u&pG;Nn%YS}*MBO{4d1%Yt z;6DM|4oAl1o&I!l0nf9&_uv12zbAIZCIlYr#p7RdF>VDH>)f{E=~FU zU(CJ#NyWRH%rC!L#l$LC$NmWkyZ+9%TK&(nRaW}lM|7;N`dO{NU732d`uB&`^$hFQ L&J^i(U|;|M{#doA literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/ebwizardry/structures/wizard_tower_chest_0.nbt b/src/main/resources/assets/ebwizardry/structures/wizard_tower_chest_0.nbt new file mode 100644 index 0000000000000000000000000000000000000000..d5591b4d9f48454d5f35f4f6aca806e17962ce47 GIT binary patch literal 2249 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 H!N33j*2K`c literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/ebwizardry/structures/wizard_tower_chest_3.nbt b/src/main/resources/assets/ebwizardry/structures/wizard_tower_chest_3.nbt new file mode 100644 index 0000000000000000000000000000000000000000..2fbe59525f63de20cb869a019e07fee70d2f1dba GIT binary patch literal 1986 zcmb2|=3sz;t+USNJ$4go^$v=Cwf^oq731!M3@4RYJj-sHFsU#yvCP$JI+$X{raD#k zkde2-%d%bJpS3;5~i8}5n=JkufA#93^r{-|?irqcCZ zLni}CLH~|Q#u+^cP3I~)5%I4!{uy8L^kE(=X>AH@( z)?~J8S!a0Gh92QKnBrn{`SdS|WTU2;aZ;BY&x9Q3e4&t5CF#DTdB)4sH6Zs&nO|`9 znbB_fP}KP2tr>zKQ)cueJagIabYJ|4#IZ9u2e@CdtXF*~YU~{6p)Rw!qqF#QN`vRq zdxmL_RcjfI)n{zri)U0*o^fFvgEEWot?UC4O@cwsXGzR2h*%UCQ7~5t6b_FrRv8{k zVOji@>7|0(Yt~DSJ=eIGG)t@%_h2`S(x1SWv?XqVshIJ~sD^9&NzYttW<3wQpR6|Z z`NVURE_BWe;oGi!{dY=(=iTJR6%)=i^`!I8usoPCPd?eGiPI{)g)hnEe7~WS!NOQ! zs}9cV=cJo{wn)q`;0V-bi8`77!AHwMRgiSna0R{Xe}3_dWVLg9rzNx`7%9o!9=GH@2BmXHK1+mbmQbxj%Pv=XLd0Ze49xGdukDo)UBaeY@`ODB2xA>#6_K>Tt7t zzY>H5kL+J^+pqTHgIP7x&38ub{(kh~vz*NaH=P4R_ZfY=tN*@k#*FJnV_#~2Km62i z*2yDh`v08_&AXm;^VZgSefR3De>dLT4xYYW?i2sIU$17bkDh&M`?Xg6^G(Ldw>kb- zK6~4I-!ggs|99KppZovc_DpTZwjVG2&iuUp-)Q;9D6!PX?^Z4P`Qh9B#NIQn_tu~4 z*3y{zvzdER;+cQn0;c3eKiz(Idugz3-t6P2?#`L_d#A_$x@mTM?K1t(lwP>?<9Jc{ zlyd3+?yp|G?q6Dxyz|e^-_N$!6c;@Ee6J<<`?|bW`sd&0&oan)&ar;JvW;ObdtKh) zYQyGT?|!d~e01;Jml>6h?&b9eHeGB3McLx71x#Q%`9``}r=d%n$MV%;wXMMd#z`#+Tg1N24DbBt80X>sn(-B=pxAOwQU3_X z!55|$%Igjqx^cLzcZ3uHUuUd7VtOMzPJNx@6H)u)23PctoL~?>e&;9)*xs+4m5Od0 zZu^B7RR}D;e|Z95lFmVngD+~$y4Vdt>E+9BIVj7>Xxjh*cE8#{lW`7!R_g}=pTmb^MA zae1T5UB|eNmqoULE@z?32 z0;qKDxuzz<4-v}65K2k0`DiS>@>a{E#F9tPwSs1UQ)iY_m5OfH**-b-OtAVGcdMvCIVJPi@jnk{9c%qzA35{t`lB;%K z@ThV8)2DN}e@nhURCi4LZ*R|@+P%APKEHadRs43?PUio&Zu@_jefHqhUj4b9G0)zA zUUlO1u`@Mw_vik8_VdnTMg8}$-%UP0&;Djbef;~o54Zg;$Vt{R+xO=49JAS9{(MpM zttl&;o!|ZG+>PbiqVN9vDCYJ3;MLFUiTN6eYD?G8`a2=&@#;po9ecJ;xcw(!ciFD2 z`{&+&zP)+cKHKA!b=M{TJiYng-Gu93&l=WSI&RWG^yPN*Zr*68-+N^9E$3|S-4$!T z_2>I}TPjuuAKSLK_2ZM~%+U;qG7d)>wW literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/ebwizardry/texts/handbook_en_gb.json b/src/main/resources/assets/ebwizardry/texts/handbook_en_gb.json index 8eddb4be..3b1dd848 100644 --- a/src/main/resources/assets/ebwizardry/texts/handbook_en_gb.json +++ b/src/main/resources/assets/ebwizardry/texts/handbook_en_gb.json @@ -1,11 +1,12 @@ { - "ruler_text": "--------------------", + "bookmark_start_section": "introduction", "colours": { "text": "#000000", "caption": "#666666", "hyperlink": "#601ba0", - "highlight": "#dd4c1d" + "highlight": "#dd4c1d", + "new_section": "#ee88f7" }, "images": { @@ -33,74 +34,196 @@ "width": 36, "height": 33, "texture_width": 48, - "texture_height": 48 + "texture_height": 48, + "border": false }, "magic_wand": { - "location": "ebwizardry:textures/items/wand_basic.png", + "location": "ebwizardry:textures/items/wand_novice.png", "caption": "A Magic Wand", "u": 0, "v": 0, "width": 64, - "height": 64 + "height": 64, + "border": false }, "crystal_flower": { "location": "ebwizardry:textures/gui/flower_picture.png", "caption": "A Crystal Flower", "u": 0, "v": 0, - "width": 64, - "height": 64 + "width": 48, + "height": 48 + }, + "wizard_tower": { + "location": "ebwizardry:textures/gui/tower_picture.png", + "caption": "A Wizard's Tower", + "u": 0, + "v": 0, + "width": 110, + "height": 110 + }, + "wizard_armour": { + "location": "ebwizardry:textures/gui/armour_picture.png", + "caption": "A Set Of Wizard Armour", + "u": 0, + "v": 0, + "width": 90, + "height": 90 + }, + "obelisk": { + "location": "ebwizardry:textures/gui/obelisk_picture.png", + "caption": "An Obelisk", + "u": 0, + "v": 0, + "width": 110, + "height": 67 + }, + "shrine": { + "location": "ebwizardry:textures/gui/shrine_picture.png", + "caption": "An Earth Shrine", + "u": 0, + "v": 0, + "width": 110, + "height": 67 + }, + "tiers": { + "location": "ebwizardry:textures/gui/tiers_picture.png", + "caption": "The 4 Tiers Of Wand", + "u": 0, + "v": 0, + "width": 96, + "height": 24, + "border": false + }, + "elements": { + "location": "ebwizardry:textures/gui/elements_picture.png", + "caption": "The 7 Arcane Elements", + "u": 0, + "v": 0, + "width": 106, + "height": 20, + "border": false } }, "recipes": { "arcane_workbench": { - "location": "ebwizardry:arcane_workbench" + "locations": [ "ebwizardry:arcane_workbench" ] }, "magic_wand": { - "location": "ebwizardry:magic_wand" + "locations": [ "ebwizardry:magic_wand" ] + }, + "novice_wands": { + "locations": [ + "ebwizardry:magic_wand", + "ebwizardry:wand_fire", + "ebwizardry:wand_ice", + "ebwizardry:wand_lightning", + "ebwizardry:wand_necromancy", + "ebwizardry:wand_earth", + "ebwizardry:wand_sorcery", + "ebwizardry:wand_healing" + ] }, "magic_missile_spell_book": { - "location": "ebwizardry:magic_missile_spell_book" + "locations": [ "ebwizardry:magic_missile_spell_book" ] }, "wizard_handbook": { - "location": "ebwizardry:wizard_handbook" + "locations": [ "ebwizardry:wizard_handbook" ] }, "crystal_flower_to_crystals": { - "location": "ebwizardry:crystal_flower_to_crystals" + "locations": [ "ebwizardry:crystal_flower_to_crystals" ] }, - "mana_flask": { - "location": "ebwizardry:mana_flask" + "crystal_blocks": { + "locations": [ + "ebwizardry:crystal_block", + "ebwizardry:crystal_block_fire", + "ebwizardry:crystal_block_ice", + "ebwizardry:crystal_block_lightning", + "ebwizardry:crystal_block_necromancy", + "ebwizardry:crystal_block_earth", + "ebwizardry:crystal_block_sorcery", + "ebwizardry:crystal_block_healing" + ] + }, + "crystal_blocks_to_crystals": { + "locations": [ + "ebwizardry:crystal_block_to_crystals", + "ebwizardry:crystal_block_to_crystals_fire", + "ebwizardry:crystal_block_to_crystals_ice", + "ebwizardry:crystal_block_to_crystals_lightning", + "ebwizardry:crystal_block_to_crystals_necromancy", + "ebwizardry:crystal_block_to_crystals_earth", + "ebwizardry:crystal_block_to_crystals_sorcery", + "ebwizardry:crystal_block_to_crystals_healing" + ] + }, + "crystal_shard": { + "locations": [ "ebwizardry:crystal_shard" ] + }, + "small_mana_flask": { + "locations": [ "ebwizardry:small_mana_flask" ] + }, + "medium_mana_flask": { + "locations": [ "ebwizardry:medium_mana_flask" ] + }, + "large_mana_flask": { + "locations": [ "ebwizardry:large_mana_flask" ] + }, + "runestone": { + "locations": [ + "ebwizardry:runestone_fire", + "ebwizardry:runestone_ice", + "ebwizardry:runestone_lightning", + "ebwizardry:runestone_necromancy", + "ebwizardry:runestone_earth", + "ebwizardry:runestone_sorcery", + "ebwizardry:runestone_healing" + ] + }, + "runestone_pedestal": { + "locations": [ + "ebwizardry:runestone_pedestal_fire", + "ebwizardry:runestone_pedestal_ice", + "ebwizardry:runestone_pedestal_lightning", + "ebwizardry:runestone_pedestal_necromancy", + "ebwizardry:runestone_pedestal_earth", + "ebwizardry:runestone_pedestal_sorcery", + "ebwizardry:runestone_pedestal_healing" + ] }, "transportation_stone": { - "location": "ebwizardry:transportation_stone" + "locations": [ "ebwizardry:transportation_stone" ] }, "magic_silk": { - "location": "ebwizardry:magic_silk" + "locations": [ "ebwizardry:magic_silk" ] }, "wizard_hat": { - "location": "ebwizardry:wizard_hat" + "locations": [ "ebwizardry:wizard_hat" ] }, "wizard_robe": { - "location": "ebwizardry:wizard_robe" + "locations": [ "ebwizardry:wizard_robe" ] }, "wizard_leggings": { - "location": "ebwizardry:wizard_leggings" + "locations": [ "ebwizardry:wizard_leggings" ] }, "wizard_boots": { - "location": "ebwizardry:wizard_boots" + "locations": [ "ebwizardry:wizard_boots" ] }, "blank_scroll": { - "location": "ebwizardry:blank_scroll" + "locations": [ "ebwizardry:blank_scroll" ] }, "firebomb": { - "location": "ebwizardry:firebomb" + "locations": [ "ebwizardry:firebomb" ] }, "poison_bomb": { - "location": "ebwizardry:poison_bomb" + "locations": [ "ebwizardry:poison_bomb" ] }, "smoke_bomb": { - "location": "ebwizardry:smoke_bomb" + "locations": [ "ebwizardry:smoke_bomb" ] + }, + "spark_bomb": { + "locations": [ "ebwizardry:spark_bomb" ] } }, @@ -146,13 +269,19 @@ "include_in_contents": "main_contents", "text": [ - "To get started with wizardry, you will need a few things:", + "To get started with wizardry, you will need:", - "- A magic wand, crafted with a gold nugget, a stick, and a magic crystal.", + "- A magic wand, crafted as shown:", + + "#recipe magic_wand", - "- An @arcane_workbench arcane workbench@, crafted with 3 stone, 1 lapis lazuli block, 2 magic crystals, 2 gold nuggets and 1 purple carpet.", + "- An @arcane_workbench arcane workbench@, crafted like so:", + + "#recipe arcane_workbench", - "- A @spells spell@ book. These can be found in chests, dropped as loot, purchased from wizards, or you can make a beginner's spell, magic missile, with a book and 4 magic crystals.", + "- A @spells spell@ book. These can be found in chests, dropped as loot, purchased from wizards, or you can make a beginner's spell, magic missile, as shown:", + + "#recipe magic_missile_spell_book", "You will also need a bunch more magic crystals to supply your wand with @mana@." ] @@ -172,7 +301,7 @@ "#image magic_crystal", - "It is widely accepted that mana cannot be created or destroyed, and that when a spell is cast, the mana it channels is simply dissipated into the surroundings. Indeed, this is how the vast majority of mana exists - spread thinly throughout the world. However, to be of any use, it must be concentrated, either naturally over thousands of years, as is the case with crystals underground, or artificially - an advanced subject covered later in this book. There also exist various ways of making spells more mana-efficient and recovering some of the mana dissipated during spellcasting." + "It is widely accepted that mana cannot be created or destroyed, and that when a spell is cast, the mana it channels is simply dissipated into the surroundings. Indeed, this is how the vast majority of mana exists - spread thinly throughout the world. However, to be of any use, it must be concentrated, either naturally over thousands of years, as is the case with crystals underground, or artificially - an advanced subject not covered in this book. There also exist various ways of making spells more mana-efficient and recovering some of the mana dissipated during spellcasting." ] }, @@ -190,7 +319,7 @@ "Most wands begin their life as a simple arrangement of a magic crystal of some sort attached to a wooden stick, with a gold nugget affixed to the other end. The crystal is, of course, the source of the wand's power, as it provides the focus necessary to channel @spells@. The rest of the wand is important too though, as it provides not only a means with which to hold the wand, but also a path through which @mana@ can be channelled and directed.", - "As more spells are cast with a wand, it grows more effective at channelling @spells@, and can therefore cast spells of greater power. This effect can be discerned from subtle changes that occur in the shape and appearance of the wand itself: as a wand grows more powerful, its crystal will become more vibrant, it may change in colour depending on its element, and after a while, the wood from which it is made will start to grow and twist into more complex shapes.", + "As more spells are cast with a wand, it grows more effective at channelling @spells@, and can therefore cast spells of greater power. This effect can be discerned from subtle changes that occur in the shape and appearance of the wand itself: as a wand grows more powerful, its crystal will become more vibrant, its colour may change depending on its @elements element@, and after a while, the wood from which it is made will start to grow and twist into more complex shapes.", "When holding a wand, a small heads-up display will show in the corner of the screen. This indicates the spell that is currently selected along with a pictorial representation of it, and, if the spell has been cast, a cooldown bar indicating the time until that spell can be cast again. It also shows the names of the next and previous spells bound to the wand. To switch between spells, use the #next_spell_key and #previous_spell_key keys (these can be changed in options -> controls). You can also switch spells by scrolling the mouse wheel while sneaking.", @@ -205,14 +334,16 @@ "ebwizardry:handbook/spells" ], "text": [ - + "A @wands wand@ is useless without spells to cast with it. Spells are recorded in two forms: in books, which are permanent, and in scrolls, which are temporary.", - "Spell books are of little use on their own; instead they are used to bind the spell they contain to @wands@. Spell books can be found throughout the world and it will not take long for you to come across one. When you do find one, you can mouse over the spell book to see basic information about the spell at a glance. You can also right-click whilst holding a spell book to read more detailed information about the spell.", + "Spell books are of little use on their own; instead they are used to bind the spell they contain to @wands@. Spell books can be found throughout the world and it will not take long for you to come across one. When you do find one, you can mouse over the spell book to see basic information about the spell at a glance. You can also right-click whilst holding a spell book to read more about it.", - "Scrolls, on the other hand, serve a different purpose: right-clicking whilst holding one will cast the spell that is bound to it, destroying the scroll in the process. Like spell books, scrolls can be found throughout the world, but you can also make them yourself by crafting a blank scroll from a piece of paper and some string. You can then bind a spell to the scroll using the @arcane_workbench arcane workbench@, but only if you have knowledge of that spell (see @enchanting_scrolls Enchanting Scrolls@). Scrolls are quite useful when you need to use a spell once or twice on a particular quest but don't want it to take up a slot on your @wands wand@. It should be noted, however, that scrolls are at best an inefficient method of casting spells.", + "Scrolls, on the other hand, serve a different purpose: right-clicking whilst holding one will cast the spell that is bound to it, destroying the scroll in the process. Like spell books, scrolls can be found throughout the world, but you can also make them yourself (see @enchanting_scrolls Enchanting Scrolls@).", - "To the untrained eye, the magical runes with which spells are written are unreadable. In order to identify a spell, you could, of course, cast it and see what happens - though doing so may cause unwanted side-effects, and many spells need certain conditions in order to work. A safer and more reliable option is to use a scroll of identification, which can be found in chests or purchased from a wizard. Right-clicking whilst holding one will identify the first unknown spell book or scroll on your hotbar, consuming the scroll of identification in the process." + "Scrolls are quite useful when you need to use a spell once or twice on a particular quest but don't want it to take up a slot on your @wands wand@. It should be noted, however, that they are an inefficient method of casting spells compared to using a wand.", + + "To the untrained eye, the magical runes with which spells are written are unreadable. In order to identify a spell, you could, of course, cast it and see what happens - though doing so may cause unwanted side-effects, and many spells need certain conditions in order to work. Futhermore, there is always a chance of misreading an unknown spell when casting, with potentially dangerous consequences depending on how powerful the spell is. A safer and more reliable option is to use a scroll of identification, which can be found in chests or purchased from a wizard. Right-clicking whilst holding one will identify the first unknown spell book or scroll on your hotbar, consuming the scroll of identification in the process." ] }, @@ -230,7 +361,11 @@ ], "text": [ - "The arcane workbench is a block similar in appearance to the enchantment table where you can charge, upgrade, and bind @spells@ to your @wands wand@. Simply place it anywhere and right click, and you will see something like this:", + "The arcane workbench is a block similar in appearance to the enchantment table where you can charge, upgrade, and bind @spells@ to your @wands wand@. It may be crafted as follows:", + + "#recipe arcane_workbench", + + "The following pages explain the various actions that may be performed in the arcane workbench.", "#image workbench" ], @@ -238,25 +373,34 @@ "binding_spells": { "title": "Binding Spells", "include_in_contents": "arcane_workbench_subsections", + "triggers": [ + "ebwizardry:handbook/arcane_workbench" + ], "text": [ - "To bind a spell to your wand, simply place your wand in the central slot of the workbench, then place the spell book in one of the surrounding slots and press apply. You will notice that the spell book is left untouched during this process - this is because the act of spell binding does not 'take' the spell from the spell book; rather, it attunes the wand to the spell. As such, you may change the spells bound to your wand as much as you wish by simply repeating the spell binding process. You can bind up to five spells to a wand at one time, though this number may be increased with attunement upgrades." + "To bind a @spells spell@ to your @wands wand@, simply place your wand in the central slot of the workbench, then place the spell book in one of the surrounding slots and press confirm. You will notice that the spell book is left untouched during this process - this is because the act of spell binding does not 'take' the spell from the spell book; rather, it attunes the wand to the spell. As such, you may change the spells bound to your wand as much as you wish by simply repeating the spell binding process. You can bind up to five spells to a wand at one time, though this number may be increased with attunement upgrades." ] }, "charging_wands": { "title": "Charging Wands", "include_in_contents": "arcane_workbench_subsections", + "triggers": [ + "ebwizardry:handbook/arcane_workbench" + ], "text": [ - "To charge your wand, place the wand in the central slot of the arcane workbench and place some magic crystals in the upper of the two slots on the left, and then press apply. Each crystal is worth #mana_per_crystal mana, and the wand will only take what it needs, so you can keep a supply of crystals in the workbench for when you need them. However, bear in mind that the wand can only take a whole number of crystals so if the wand needs, for example, 30 more mana, #mana_per_crystal_minus_30 mana will be lost when charging it." + "To charge your @wands wand@, place the wand in the central slot of the arcane workbench and place some magic crystals in the bottom-left slot, and then press confirm. Each crystal is worth #mana_per_crystal @mana@, and the wand will only take what it needs, so you can keep a supply of crystals in the workbench for when you need them. However, bear in mind that the wand can only take a whole number of crystals, so if the wand needs, for example, 30 more mana, #example_charging_loss mana will be lost when charging it." ] }, "upgrading_wands": { "title": "Upgrading Wands", "include_in_contents": "arcane_workbench_subsections", + "triggers": [ + "ebwizardry:handbook/tome_of_arcana" + ], "text": [ - "To upgrade your wand, you will need a tome of arcana of the appropriate tier (see @tiers Tiers@) or a special wand upgrade. Both of these can be found as loot or purchased from a wizard. To upgrade your wand, place it in the central slot and the upgrade in the lower of the two slots on the left, then press apply.", + "To upgrade your @wands wand@, you will need a tome of arcana of the appropriate @tiers tier@ or a special wand upgrade. Both of these can be found as loot or purchased from a wizard. To upgrade your wand, place it in the central slot and the upgrade in the top-right slot, then press confirm.", "Special wand upgrades improve a particular aspect of a wand. Each type of upgrade can stack up to three times, and the total number of upgrades that a wand can take depends on its tier. Upgrades cannot be removed." ] @@ -264,9 +408,16 @@ "enchanting_scrolls": { "title": "Enchanting Scrolls", "include_in_contents": "arcane_workbench_subsections", + "triggers": [ + "ebwizardry:handbook/scrolls" + ], "text": [ - "The arcane workbench can also be used to enchant spell scrolls. To do so, you will require a blank scroll, crafted from a piece of paper and some string, a spell book for your chosen spell, and enough magic crystals to provide mana to cast it. Place the crystals in the upper left-hand slot, the blank scroll in the central slot, and the spell book in the single slot that appears above it, then press apply to enchant the scroll." + "The arcane workbench can also be used to enchant @spells spell@ scrolls. To do so, you will require a blank scroll, crafted from a piece of paper and some string, a spell book for your chosen spell, and enough magic crystals to provide @mana@ to cast it.", + + "#recipe blank_scroll", + + "Place the crystals in the bottom-left slot, the blank scroll in the central slot, and the spell book in the single slot above it, then press confirm to enchant the scroll." ] } } @@ -275,11 +426,24 @@ "wizard_armour": { "title": "Wizard Armour", "include_in_contents": "main_contents", + "triggers": [ + "ebwizardry:arcane_initiate" + ], "text": [ - "As a wizard, you will need something to protect you from the creatures you fight. No ordinary armour will do though. To make the most of your spells, you will need wizard armour: hat, robes, leggings and boots. Unlike ordinary armour, these will not break. Instead, they use arcane energy to shield the wearer. This of course means that they must be charged with magic crystals, just like wands. Fortunately, these garments do not consume much mana. Charge them as you would a wand in the arcane workbench or with a mana flask, but be careful - if they run out of mana, you will find yourself defenceless.", + "As a wizard, you will need something to protect you from the creatures you fight. No ordinary armour will do though. To make the most of your spells, you will need wizard armour: hat, robes, leggings and boots. Unlike ordinary armour, these will not break. Instead, they use arcane energy to shield the wearer. This of course means that they must be charged with magic crystals, just like wands. Fortunately, these garments do not consume much @mana@. Charge them as you would a wand in the @arcane_workbench arcane workbench@ or with a @mana_flasks mana flask@, but be careful - if they run out of mana, you will find yourself defenceless.", - "You can obtain wizard armour by crafting it from magical silk, obtained by crafting string with a magic crystal.", + "#image wizard_armour", + + "You can obtain wizard armour by crafting it from magical silk:", + + "#recipe magic_silk", + "#recipe wizard_hat", + "#recipe wizard_robe", + "#recipe wizard_leggings", + "#recipe wizard_boots", + + "One may enchant wizard armour using a normal enchantment table, and due to the inherent properties of magical silk, it tends to be quite effective at holding enchantments. Of particular utility to a wizard are the Magic, Frost and Shock Protection enchantments, which may prove useful defending against other wielders of magic.", "Those wizards who devote themselves to the practice of one element sometimes wear special garments which grant bonuses for that element. Full sets of such garments are very sought after among wizards and are not easy to find.", @@ -296,6 +460,9 @@ "page_numbers": true, "separator": "." }, + "triggers": [ + "ebwizardry:handbook/on_subsection_unlock" + ], "text": [ "One cannot master the arcane just by staying at home - there is a world full of magic out there to explore! Ancient ruins, relics and mysterious beings good and bad await discovery - if you know where to look. The greatest wizards are also the most curious, and gain much of their knowledge and power through exploration of the environment around them, and experimenting with what they find.", @@ -311,57 +478,83 @@ ], "text": [ - "During your travels, you will probably come across curious glowing flowers growing in the wild from time to time. These distinctive blooms are known as crystal flowers, and they are strangely effective at concentrating mana - to this day, nobody is quite sure why. We do know, however, that they can be harvested and crafted to extract the mana as crystals, making them a rather useful above-ground source of mana. The amount of mana obtainable this way is limited, though, by the small size of the flowers and due to them only growing in small patches.", + "During your travels, you will probably come across curious glowing flowers growing in the wild from time to time. These distinctive blooms are known as crystal flowers, and they are strangely effective at concentrating @mana@ - to this day, nobody is quite sure why. We do know, however, that they can be harvested and crafted to extract the mana as crystals, making them a rather useful above-ground source of mana. The amount of mana obtainable this way is limited, though, by the small size of the flowers and due to them only growing in small patches.", - "#image crystal_flower" + "#image crystal_flower", + "#recipe crystal_flower_to_crystals" ] }, "wizard_towers": { "title": "Wizard Towers", "include_in_contents": "magical_world_subsections", + "triggers": [ + "ebwizardry:wizard_tower" + ], "text": [ - "Fear not - you are not the only practicioner of magic in this world. On your travels, you may well encounter a tall tower or two with a distinctive pointed roof. This is the residence of a fellow wizard. A life of solitude can make wizards a little grumpy at times, but they are usually friendly folk who are willing to share their knowledge with you - albeit for a price. Expect to pay precious metals and gems, and in return you will recieve many a great arcane wonder. If, however, it is a master spell you seek, you will need to speak to a specialist.", + "Fear not - you are not the only practicioner of magic in this world. On your travels, you may well encounter a tall tower or two with a distinctive pointed roof. This is the residence of a fellow wizard. A life of solitude can make wizards a little grumpy at times, but they are usually friendly folk who are willing to share their knowledge with you - albeit for a price. Expect to pay precious metals and gems, and in return you will recieve many a great arcane wonder.", + + "If, however, it is a @tiers master@ spell you seek, you will need to speak to a specialist.", + + "#image wizard_tower", "Unfortunately, there are a few wizards out there who do not welcome visitors. These wizards are typically outcasts, and are hostile to anyone crossing their path. Approach these individuals with caution, and be prepared to defend yourself against powerful magic. Defeat them however, and their knowledge is yours for the taking.", - "It should also be noted that no wizard will take kindly to being attacked or stolen from - and will readily take the law into their own hands." + "It should also be noted that no wizard will take kindly to being attacked or stolen from - and they will readily take the law into their own hands." ] }, "obelisks": { "title": "Obelisks", "include_in_contents": "magical_world_subsections", + "triggers": [ + "ebwizardry:handbook/obelisks" + ], "text": [ "Vestiges of ancient magic are scattered throughout the world, the most notable of which are carved stone structures which bear a great many symbols and runes. These ruins are all that remain of what appears to have been some kind of ancient civilisation. Whoever, or whatever, built them, they clearly had a considerable knowledge of magic, and used it to place protective enchantments over such locations that still persist to this day.", - "These stuctures fit broadly into two types. The first, and more common, of these are obelisks: tall spikes of carved stone, known as runestone, with an open structure at the bottom that usually contains minor arcane relics from the forgotten past. These structures are typically protected by an enchantment that summons hostile magical creatures should any human stray too close. Fend off these creatures and destroy their source, and the relics are yours." + "These stuctures fit broadly into two types. The first, and more common, of these are obelisks: tall spikes of carved stone, known as runestone, with an open structure at the bottom containing minor arcane relics from the forgotten past.", + + "#image obelisk", + + "These structures are typically protected by an enchantment that summons hostile @creatures magical creatures@ should any human stray too close. Fend off these creatures and destroy their source, and the relics are yours." ] }, "shrines": { "title": "Shrines", "include_in_contents": "magical_world_subsections", + "triggers": [ + "ebwizardry:visit_shrine" + ], "text": [ - "The second, and rarer, kind of structure is known as a shrine. These structures consist of a circle of runestone pillars surrounding a central platform, upon which sits a chest filled with ancient artefacts. This chest is typically protected by an arcane lock enchantment, preventing anyone except the owner from opening it. The entire structure is also protected by a containment field, which prevents anything that strays too close from escaping.", - + "The second, and rarer, kind of structure is known as a shrine. These structures consist of a circle of runestone pillars surrounding a central pedestal, upon which sits a chest filled with ancient @artefacts@. This chest is typically protected by an arcane lock enchantment, preventing anyone except the owner from opening it. The entire structure is also protected by a containment field, which prevents anything that strays too close from escaping.", + + "#image shrine", + "Due to their great arcane power and significance, not to mention the riches within, these structures are particularly attractive to any aspiring wizard - but be cautious. There are numerous reports of wizards becoming trapped within containment fields and slowly being driven insane, perhaps by claustrophobia. A growing number, however, believe such occurences to be a deliberate part of the shrine's protective magic, and that the wizards trapped within are in fact being controlled to protect the structure. A chilling prospect, surely, for anyone who dares to venture near..." ] }, "creatures": { "title": "Magical Creatures", "include_in_contents": "magical_world_subsections", + "triggers": [ + "ebwizardry:handbook/magical_creatures" + ], "text": [ - "Besides wizards, a multitude of other creatures also use magic. Many of these creatures are arcane in origin, and most can be summoned using certain magical spells. One may encounter these creatures guarding an obelisk, or perhaps a powerful summoner. Lesser arcane beings are even found occasionally in the wilderness." + "Besides wizards, a multitude of other creatures also use magic. Many of these creatures are arcane in origin, and most can be summoned using certain magical @spells spells@. One may encounter these creatures guarding an @obelisks obelisk@, or perhaps a powerful summoner. Lesser arcane beings are even found occasionally in the wilderness." ] }, "artefacts": { "title": "Artefacts", "include_in_contents": "magical_world_subsections", + "triggers": [ + "ebwizardry:artefact" + ], "text": [ - "When exploring a shrine, you may be lucky enough to uncover some kind of ancient magical artefact - an object capable of granting its wearer unique and powerful buffs and special powers. Three types are known to have been found: rings, which grant bonuses and effects to spells, amulets, which improve defensive abilities, and trinkets, which give utility effects. These artefacts appear to function only when worn appropriately; simply having them on one's person is insufficient." + "When exploring a @shrines shrine@, you may be lucky enough to uncover some kind of ancient magical artefact - an object capable of granting its wearer unique and powerful buffs and special powers. Three types are known to have been found: rings, which grant bonuses and effects to spells, amulets, which improve defensive abilities, and charms, which give utility effects. These artefacts appear to function only when worn appropriately; simply having them on one's person is insufficient." ] } } @@ -370,26 +563,40 @@ "tiers": { "title": "Tiers", "include_in_contents": "main_contents", + "triggers": [ + "ebwizardry:handbook/tome_of_arcana" + ], "text":[ - "Wands and spells come in four tiers: #colour_novicenovice#colour_reset, #colour_apprenticeapprentice#colour_reset, #colour_advancedadvanced #colour_resetand #colour_mastermaster#colour_reset. Each tier is more powerful than the last.", + "@wands Wands@ and @spells@ come in four tiers: #colour_novicenovice#colour_reset, #colour_apprenticeapprentice#colour_reset, #colour_advancedadvanced #colour_resetand #colour_mastermaster#colour_reset. Each tier is more powerful than the last.", + + "#image tiers", "#colour_noviceNovice #colour_resetwands are the ones that can be crafted. They hold up to #novice_max_charge mana, and can only cast novice spells. Novice spells are simple enough to be cast by anyone and they do not usually cost much mana. This does not necessarily mean that they are useless at higher tiers however; their low cost makes some novice spells useful even when you have access to master spells.", "#colour_apprenticeApprentice #colour_resetwands are the next tier up from novice wands. They hold up to #apprentice_max_charge mana and can cast novice and apprentice spells. Apprentice spells are a little more impressive than novice spells but usually cost more.", - "#colour_advancedAdvanced #colour_resetwands are quite rare and are much more powerful. They can cast all spells except master spells, and hold #advanced_max_charge mana. Advanced spells can grant superhuman powers such as invisibility and wreak havoc on enemies.", + "#colour_advancedAdvanced #colour_resetwands are quite rare and are much more powerful. They can cast all spells except master spells, and hold #advanced_max_charge mana. Advanced spells can grant superhuman powers such as invisibility and wreak havoc on foes.", - "#colour_masterMaster #colour_resetwands are the most powerful wands in existence. They hold up to #master_max_charge mana, and can cast any spell. Master spell books are very rare and the spells can cause complete devastation not only to enemies but even the world itself. Use with caution." + "#colour_masterMaster #colour_resetwands are the most powerful wands in existence. They hold up to #master_max_charge mana, and can cast any spell. Master spell books are very rare and the spells can cause complete devastation not only to enemies but even the world itself. Use with caution.", + + "To be upgraded to a higher tier, a wand must first become powerful enough to channel spells of that tier. Wands gain power as spells are cast with them. Spell variety, spell power, elemental effects and other external factors may all have an effect on how quickly a wand matures.", + + "Once a wand is sufficiently powerful, a tome of arcana provides the final catalyst needed to elevate the wand to the next tier (see @upgrading_wands Upgrading Wands@), and once this has happened, the maturing process can begin again for the next tier." ] }, "elements": { "title": "Elements", "include_in_contents": "main_contents", + "triggers": [ + "ebwizardry:handbook/elements" + ], "text": [ - "Spells belong to different elements, which describe the nature of the spell and also have perks when used with certain wands.", + "@spells Spells@ belong to different elements, which determine the nature of the spell and also grant perks when used with certain @wands@.", + + "#image elements", "#colour_fireFire#colour_reset \nPerhaps the most destructive element, fire concerns burning, lava, and explosions. A powerful pyromancer will unleash hell upon their enemies and probably set the world alight in the process. Most fire attack spells set fire to their target, causing ongoing damage over time. However, be wary that fire spells may have no effect on nether mobs.", @@ -397,7 +604,7 @@ "#colour_lightningLightning#colour_reset \nThis element concerns lightning, storms, and the weather. A powerful storm mage is a force to be reckoned with, and some posess the ability to call down lightning at will. Lightning spells often damage multiple enemies at once and usually seek their target, making them an effective attack against any mob... but beware of creepers.", - "#colour_necromancyNecromancy#colour_reset \nNecromancy is the element of darkness, chaos and the undead. Necromancers are mysterious and often regarded as evil, though this is usually not the case. Necromancy spells are commonly used to summon creatures to fight for you or even bend the will of your enemies.", + "#colour_necromancyNecromancy#colour_reset \nNecromancy is the element of darkness, chaos and the undead. Necromancers are mysterious and often regarded as evil, though this is usually not the case. Necromancy spells are commonly used to summon @creatures@ to fight for you or even bend the will of your enemies.", "#colour_earthEarth#colour_reset \nThe element of earth is focused on the natural world: animals, plants, the wind, and such like. Earth magic is diverse and takes a wide variety of forms, from poisoning enemies to unleashing the fury of the weather. Earth spells are a mixture of attack, defence and utility.", @@ -407,25 +614,10 @@ "The boundaries between the different elements are not always distinct, and some spells bear traits of elements other than their own.", - "If you are lucky, you may happen upon an elemental wand. These wands will allow you to cast spells of the right element for more potency than usual." + "If you are lucky, you may happen upon an elemental crystal. Elemental crystals are magic crystals that have absorbed elemental properties as they have grown - though the exact conditions required and mechanism by which this happens remain a mystery. We do know, however, that such crystals may be used to create elemental wands, which allow spells of the right element to be cast with more potency than usual." ] }, - - "growing_crystals": { - "title": "Growing Crystals", - "include_in_contents": "main_contents", - "text": [ - - "Magic crystals normally form naturally underground over thousands of years, by gradually drawing latent mana from the surrounding rock as they grow. Crystalline structures are very good at absorbing and holding mana, hence the mana is naturally drawn towards them. Given the right conditions, however, it is possible to greatly speed up this process. This has given rise to the advanced technique of crystal growing, which requires both great patience and attention to detail.", - - "In order to encourage crystal growth, one must begin with a crystal seed. The most effective seeds have proven to be crystal shards, obtained by simply shattering a magic crystal into pieces. A crystal seed must then be planted into some kind of substrate, usually rock, although other materials are also viable. Left alone, this would produce a sizeable crystal in hundreds of years, depending on the conditions.", - - "To reduce this length of time, several things can be done. Immersing the seed and substrate in mineral-rich water helps with crystal growth, but not with concentrating mana. To concentrate mana more quickly, two techniques can be employed: firstly, surrounding the growth site with lesser mana-gathering objects allows the crystal to draw from them, meaning the surrounding environment is constantly replenished with mana. Too many, however, and they begin to draw mana away from the growing crystal. Secondly, mana can be drawn through some materials better than others: air is very poor at this, whereas dense materials tend to be much better. Some wizards have taken to experimentation with exotic, magical, or even otherworldy materials to try and improve crystal growth. Some even claim to have altered the type of crystal that is formed in this way.", - - "If conditions are exactly right, it is even possible for crystals to grow far beyond their natural size. Such crystals are known as grand magic crystals, and besides containing a great quantity of mana, they have a few specific uses." - ] - }, - + "miscellaneous": { "title": "Miscellaneous", "include_in_contents": "main_contents", @@ -435,37 +627,57 @@ "page_numbers": true, "separator": "." }, + "triggers": [ + "ebwizardry:on_subsection_unlock" + ], "sections": { "mana_flasks": { "title": "Mana Flasks", "include_in_contents": "miscellaneous_subsections", + "triggers": [ + "ebwizardry:handbook/mana_flasks" + ], "text": [ "Arkendur's Arcane Supplies Co. - magical items for your every need!", - "Need to recharge your wand on the go? No problem! Mana can now be bottled.** Simply craft a mana flask with a glass bottle and eight magic crystals and take it with you. When you need to use it, simply craft it with your wand and it will restore some of the charge.*", + "Need to recharge your @wands wand@ on the go? No problem! @mana Mana@ can now be bottled. Simply craft a mana flask with a glass bottle and eight magic crystals and take it with you. When you need to use it, simply craft it with your wand and it will restore some of the charge. *", + + "#recipe medium_mana_flask", - "NEW! Introducing the brand-new large*** and small mana flasks - now you can choose a size of mana flask to meet your needs!", + "NEW! Introducing the brand-new small and large mana flasks - now you can choose a size of mana flask to meet your needs!", + + "#recipe small_mana_flask", + "#recipe large_mana_flask", - "* This process will consume the bottle.", - "** Some mana is lost during bottling.", - "*** Large mana flask requires grand magic crystals." + "* This process will destroy the bottle. Some mana is lost during bottling." ] }, "throwable_items": { "title": "Throwable Items", "include_in_contents": "miscellaneous_subsections", + "triggers": [ + "ebwizardry:handbook/throwables" + ], "text": [ - "Various spells conjure physical items, some of which can also be crafted directly. Firebombs, poison bombs, spark bombs and smoke bombs can all be crafted." + "Various @spells@ conjure physical items, some of which can also be crafted directly. Firebombs, poison bombs, spark bombs and smoke bombs can all be crafted:", + + "#recipe firebomb", + "#recipe poison_bomb", + "#recipe smoke_bomb", + "#recipe spark_bomb" ] }, "automated_casting": { "title": "Automated Casting", "include_in_contents": "miscellaneous_subsections", + "triggers": [ + "ebwizardry:enchant_scroll" + ], "text": [ - "Recent experimentation has revealed that it is possible to automate spell casting, to a degree, using nothing more than a simple dispenser. Nobody is quite sure why, but it would appear that the strange properties of redstone even extend to triggering the activation of spell scrolls. Placing a few into a dispenser and powering it ought to do the trick..." + "Recent experimentation has revealed that it is possible to automate @spells spell@ casting, to a degree, using nothing more than a simple dispenser. Nobody is quite sure why, but it would appear that the strange properties of redstone even extend to triggering the activation of spell scrolls. Placing a few into a dispenser and powering it ought to do the trick..." ] } } @@ -477,11 +689,18 @@ "text": [ "#recipe arcane_workbench", - "#recipe magic_wand", + "#recipe novice_wands", "#recipe magic_missile_spell_book", "#recipe wizard_handbook", "#recipe crystal_flower_to_crystals", - "#recipe mana_flask", + "#recipe crystal_blocks", + "#recipe crystal_blocks_to_crystals", + "#recipe crystal_shard", + "#recipe small_mana_flask", + "#recipe medium_mana_flask", + "#recipe large_mana_flask", + "#recipe runestone", + "#recipe runestone_pedestal", "#recipe transportation_stone", "#recipe magic_silk", "#recipe wizard_hat", @@ -491,7 +710,8 @@ "#recipe blank_scroll", "#recipe firebomb", "#recipe poison_bomb", - "#recipe smoke_bomb" + "#recipe smoke_bomb", + "#recipe spark_bomb" ] }, @@ -502,8 +722,6 @@ "Electroblob's Wizardry \nVersion #version \nFor Minecraft #mcversion", - "For more information, check out the @https://github.com/Electroblob77/Wizardry/wiki wiki@.", - "Designed, coded and textured by Electroblob", "Thanks to Minecraft Forge and MCP, without which this mod would not have been possible.", @@ -514,13 +732,17 @@ "Code:", - "- Corail31 \n- 12foo \n- Shadows-of-Fire", + "- Corail31 \n- 12foo \n- Shadows-of-Fire \n- Tora-B \n- Avatair \n- Aeronica", "Translations:", - "- Russian: VilagVil \n- Spanish and Mexican Spanish: MadWrist \n- Chinese: ZHENGLOC", + "- Spanish and Mexican Spanish: MadWrist \n- Russian: VilagVil, kellixon \n- French: Hahdrim \n- Brazilian Portuguese: lorrampi \n- Chinese: ZHENGLOC, dragon-evol \n-Korean: shejery, rewi_wire", - "Lightning ray sound effect from OhhWowProductions" + "Lightning ray sound effect from OhhWowProductions", + + "For more information, check out the @https://github.com/Electroblob77/Wizardry/wiki wiki@.", + + "Can't get enough wizardry? Join the @https://discord.gg/MTmMzMv Discord server@ for the latest news, discussions and extras!" ] } diff --git a/src/main/resources/assets/ebwizardry/texts/handbook_en_gb.txt b/src/main/resources/assets/ebwizardry/texts/handbook_en_gb.txt deleted file mode 100644 index b96617ab..00000000 --- a/src/main/resources/assets/ebwizardry/texts/handbook_en_gb.txt +++ /dev/null @@ -1,225 +0,0 @@ -PAGEBREAK -LINEBREAK - - - - -The Wizard's Handbook - - - -By Electroblob -PAGEBREAK -Introduction --------------------- - -Greetings, wizard! This book explains the many ways of the arcane and how to use them. - -Should you ever lose this book, you can get a new one by crafting a book with a magic crystal. -PAGEBREAK -Contents --------------------- -PAGEBREAK -SECTION Setting up -Setting up --------------------- -To get started with wizardry, you will need a few things: - -- A magic wand, crafted with a gold nugget, a stick, and a magic crystal. - -- An arcane workbench, crafted with 3 stone, 1 lapis lazuli block, 2 magic crystals, 2 gold nuggets and 1 purple carpet. - -- A spell book. These can be found in chests, dropped as loot, purchased from wizards, or you can make a beginner's spell, magic missile, with a book and 4 magic crystals. - -You will also need a bunch more magic crystals to supply your wand with mana. -PAGEBREAK -SECTION Mana -Mana --------------------- -Mana is the arcane energy that gives wizards their powers. It manifests itself in naturally occurring crystals, which can be found embedded in rocks underground. Wands can store mana within them, and this mana is channeled into the spells that you cast. Different spells cost different amounts of mana, depending on how powerful they are and how long they last. - -Mouse over a wand to see how much mana is stored in it. -IMAGE CRYSTAL -LINEBREAK - - - - - - - Magic - Crystal Ore Crystal -PAGEBREAK -SECTION Wands -Wands --------------------- -The wand is the implement of choice for a wizard. With it, you can cast any spell provided the wand can contain its power (see Tiers for a more in-depth explanation). Wands come in -various different varieties but you will almost certainly start with a basic magic wand. - -When holding a wand, a small heads-up display will show in the corner of the screen. This indicates the spell that is currently selected along with a pictorial representation of it, and, if the spell has been cast, a cooldown bar indicating the time until that spell can be cast again. -PAGEBREAK -SECTION Spells -Spells --------------------- -A wand is useless without spells to cast with it. Spells are recorded in two forms: in books, which are permanent, and in scrolls, which are temporary. - -Spell books are of little use on their own; instead they are used to bind the spell they contain to wands. Spell books can be found throughout the world and it will not take long for you to come across one. When you do find one, you can mouse over the spell book to see basic information about the spell at a glance. You can also right-click whilst holding a spell book to read more detailed information about the spell. - -Scrolls, on the other hand, serve a different purpose: right-clicking whilst holding one will cast the spell that is bound to it, destroying the scroll in the process. Like spell books, scrolls can be found throughout the world, but you can also make them yourself by crafting a blank scroll from a piece of paper and some string. You can then bind a spell to the scroll using the arcane workbench, but only if you have knowledge of that spell. Doing so will consume a number of magic crystals equal to the mana cost of the spell (rounded up to the nearest MANA_PER_CRYSTAL). - -To the untrained eye, the magical runes with which spells are written are unreadable. In order to identify a spell, you could, of course, cast it and see what happens - though doing so may cause unwanted side-effects, and many spells need certain conditions in order to work. A safer and more reliable option is to use a scroll of identification, which can be found in chests or purchased from a wizard. Right- -clicking whilst holding one will identify the first unknown spell book or scroll on your hotbar, consuming the scroll of identification. - -Scrolls are quite useful when you need to use a spell once or twice on a particular quest but don't want it to take up a slot on your wand. It should be noted, however, that scrolls are at best an inefficient method of casting spells. -PAGEBREAK -SECTION Arcane Workbench -The Arcane Workbench --------------------- -The arcane workbench is a block similar in appearance to the enchantment table where you can charge, upgrade, and bind spells to your wand. Simply place it anywhere and right click, and you will see a gui appear like the one to the right. -PAGEBREAK -IMAGE WORKBENCH -LINEBREAK - - - - - - - - - - - - - - The Arcane Workbench -PAGEBREAK -SECTION Binding Spells -Binding Spells --------------------- -To bind a spell to your wand, simply place your wand in the central slot of the workbench, then place the spell book in one of the surrounding slots and press apply. You can bind up to five spells to a wand at one time, though this may be increased with attunement upgrades. When holding a wand, you can switch between spells with the NEXT_SPELL_KEY and PREVIOUS_SPELL_KEY keys (these can be changed in options -> controls). You can also switch spells by scrolling the mouse wheel while sneaking. - -SECTION Charging Wands -Charging your wand --------------------- -To charge your wand, place the wand in the central slot of the arcane workbench and place some magic crystals in the upper of the two slots on the left, and then press apply. Each crystal is worth MANA_PER_CRYSTAL mana, and the wand will only take what it needs, so you can keep a supply of crystals in the workbench for when you need them. However, bear in mind that the wand can only take a whole number of crystals so if the wand needs, for example, 30 more mana, MANA_PER_CRYSTAL_MINUS_30 mana will be lost when charging it. All wands will take an exact number of crystals to charge if they are empty, unless they have a storage upgrade applied. - -SECTION Upgrading Wands -Upgrading your wand --------------------- -To upgrade your wand, you will need a tome of arcana of the appropriate tier (see Tiers) or a special wand upgrade. Both of these can be found as loot or purchased from a wizard. To upgrade your wand, place it in the central slot and the upgrade in the lower of the two slots on the left, then press apply. - -Special wand upgrades improve a particular aspect of a wand. Each type of upgrade can stack up to three times, and the total number of upgrades that a wand can take depends on its tier. Upgrades cannot be removed. -PAGEBREAK -SECTION Flowers and Flasks -Flowers and Flasks --------------------- -You will probably come across curious glowing flowers growing in the wild from time to time. These are crystal flowers, a naturally occurring source of mana. They can be harvested and crafted to extract the mana as crystals. - -Need to recharge your wand on the go? No problem! Mana can now be bottled. Simply craft a mana flask with a glass bottle and eight magic crystals and take it with you. When you need to use it, simply craft it with your wand and it will restore some of the charge. This process will consume the bottle. Some mana is lost during bottling. -PAGEBREAK -SECTION Tiers -Tiers --------------------- -Wands and spells come in four tiers: BASIC_COLOURnoviceRESET_COLOUR, APPRENTICE_COLOURapprenticeRESET_COLOUR, ADVANCED_COLOURadvanced RESET_COLOURand MASTER_COLOURmasterRESET_COLOUR. Each tier is more powerful than the last. - -BASIC_COLOURNovice RESET_COLOURwands are the ones that can be crafted. They hold up to BASIC_MAX_CHARGE mana, and can only cast novice spells. Novice spells are simple enough to be cast by anyone and they do not usually cost much mana. This does not necessarily mean that they are useless at higher tiers however; their low cost makes some novice spells useful even when you have access to master spells. - -APPRENTICE_COLOURApprentice RESET_COLOURwands are the next tier up from novice wands. They hold up to APPRENTICE_MAX_CHARGE mana and can cast novice and apprentice spells. Apprentice spells are a little more impressive than novice spells but usually cost more. - -ADVANCED_COLOURAdvanced RESET_COLOURwands are quite rare and are much more powerful. They can cast all spells except master spells, and hold ADVANCED_MAX_CHARGE mana. Advanced spells can grant superhuman powers such as invisibility and wreak havoc on enemies. - -MASTER_COLOURMaster RESET_COLOURwands are the most powerful wands in existence. They hold up to MASTER_MAX_CHARGE mana, and can cast any spell. Master spell books are very rare and the spells can cause complete devastation not only to enemies but even the world itself. Use with caution. -PAGEBREAK -SECTION Elements -Elements --------------------- -Spells belong to different elements, which describe the nature of the spell and also have perks when used with certain wands. - -FIRE_COLOURFire -Perhaps the most destructive element, fire concerns burning, lava, and explosions. A powerful pyromancer will unleash hell upon their enemies and probably set the world alight in the process. Most fire attack spells set fire to their target, causing ongoing damage over time. However, be wary that fire spells may have no effect on nether mobs. - -ICE_COLOURIce -The element of ice is made of all that is cold. Frost spells often slow enemies down or freeze them completely, and are especially effective on creatures of fire. Frost magic can prove equally useful outside of combat, such as freezing water to cross a river. - -LIGHTNING_COLOURLightning -This element concerns lightning, storms, and the weather. A powerful storm mage is a force to be reckoned with, and some posess the ability to call down lightning at will. Lightning spells often damage multiple enemies at once and usually seek their target, making them an effective attack against any mob... but beware of creepers. - -NECROMANCY_COLOURNecromancy -Necromancy is the element of darkness, chaos and the undead. Necromancers are mysterious and often regarded as evil, though this is usually not the case. Necromancy spells are commonly used to summon creatures to fight for you or even bend the will of your enemies. - -EARTH_COLOUREarth -The element of earth is focused on the natural world: animals, plants, the wind, and such like. Earth magic is diverse and takes a wide variety of forms, from poisoning enemies to unleashing the fury of the weather. Earth spells are a mixture of attack, defence and utility. - -SORCERY_COLOURSorcery -Sorcery is the element of force and change. Sorcerers manipulate light, gravity and even reality itself to fit their needs. Sorcery spells can be used, among other things, to grant their caster magical powers or move objects to their will. - -HEALING_COLOURHealing -The element of healing is concerned with defence and regeneration. Healers seek to protect themselves and their allies as much as possible and as such can be very difficult opponents. Though generally not used as an attack, the purifying light of some healing spells will do considerable damage to the undead. Healing spells are indispensable when in combat. - -The boundaries between the different elements are not always distinct, and some spells bear traits of elements other than their own. - -If you are lucky, you may happen upon an elemental wand. These wands will allow you to cast spells of the right element for more potency than usual. -PAGEBREAK -SECTION Wizard Armour -Wizard Armour --------------------- -As a wizard, you will need something to protect you from the creatures you fight. No ordinary armour will do though. To make the most of your spells, you will need wizard armour: hat, robes, leggings and boots. Unlike ordinary armour, these will not break. Instead, they use arcane energy to shield the wearer. This of course means that they must be charged with magic crystals, just like wands. Fortunately, these garments do not consume much mana. Charge them as you would a wand in the arcane workbench or with a mana flask, but be careful - if they run out of mana, you will find yourself defenceless. - -You can obtain wizard armour by crafting it from magical silk, obtained by crafting string with a magic crystal. - -Those wizards who devote themselves to the practice of one element sometimes wear special garments which grant bonuses for that element. Full sets of such garments are very sought after among wizards and are not easy to find. - -Legend speaks of an arcane seal used by the most powerful wizards to greatly improve their armour. -PAGEBREAK -SECTION Wizards and Towers -Wizards and Towers --------------------- -Fear not - you are not the only practicioner of magic in this world. On your travels, you may well encounter tall towers with distinctive pointed roofs. These are the residences of fellow wizards. A life of solitude can make wizards a little grumpy at times, but they are usually friendly folk who are willing to share their knowledge with you - albeit for a price. Expect to pay precious metals and gems, and in return you will recieve many a great arcane wonder. If, however, it is a master spell you seek, you will need to speak to a specialist. - -Unfortunately, there are a few wizards out there who do not welcome visitors. These wizards are typically outcasts, and are hostile to anyone crossing their path. Approach these individuals with caution, and be prepared to defend yourself against powerful magic. Defeat them however, and their knowledge is yours for the taking. -PAGEBREAK -SECTION Crafting Recipes -Crafting Recipes --------------------- -PAGEBREAK -PAGEBREAK -Crafting Recipes --------------------- -PAGEBREAK -PAGEBREAK -Crafting Recipes --------------------- -PAGEBREAK -PAGEBREAK -Crafting Recipes --------------------- -PAGEBREAK -PAGEBREAK -Credits --------------------- -Electroblob's Wizardry -Version VERSION -For Minecraft MCVERSION - -Designed, coded and textured by Electroblob - -Thanks to Minecraft Forge and MCP, without which this mod would not have been possible. - -Thanks also to the Minecraft modding community, which always has an answer to my modding problems! - -In addition, I'd like to thank the following individuals for their contributions to the mod: - -Code: - -- Corail31 -- 12foo -- Shadows-of-Fire -- HellFirePvP - -Translations: - -- Russian: VilagVil -- Spanish and Mexican Spanish: MadWrist -- Chinese: ZHENGLOC and dragon-evol - -Lightning ray sound effect from OhhWowProductions diff --git a/src/main/resources/assets/ebwizardry/texts/handbook_en_us.json b/src/main/resources/assets/ebwizardry/texts/handbook_en_us.json index 4c40250d..311a4c20 100644 --- a/src/main/resources/assets/ebwizardry/texts/handbook_en_us.json +++ b/src/main/resources/assets/ebwizardry/texts/handbook_en_us.json @@ -1,11 +1,12 @@ { - "ruler_text": "--------------------", + "bookmark_start_section": "introduction", "colours": { "text": "#000000", "caption": "#666666", "hyperlink": "#601ba0", - "highlight": "#dd4c1d" + "highlight": "#dd4c1d", + "new_section": "#ee88f7" }, "images": { @@ -33,74 +34,196 @@ "width": 36, "height": 33, "texture_width": 48, - "texture_height": 48 + "texture_height": 48, + "border": false }, "magic_wand": { - "location": "ebwizardry:textures/items/wand_basic.png", + "location": "ebwizardry:textures/items/wand_novice.png", "caption": "A Magic Wand", "u": 0, "v": 0, "width": 64, - "height": 64 + "height": 64, + "border": false }, "crystal_flower": { "location": "ebwizardry:textures/gui/flower_picture.png", "caption": "A Crystal Flower", "u": 0, "v": 0, - "width": 64, - "height": 64 + "width": 48, + "height": 48 + }, + "wizard_tower": { + "location": "ebwizardry:textures/gui/tower_picture.png", + "caption": "A Wizard's Tower", + "u": 0, + "v": 0, + "width": 110, + "height": 110 + }, + "wizard_armour": { + "location": "ebwizardry:textures/gui/armour_picture.png", + "caption": "A Set Of Wizard Armour", + "u": 0, + "v": 0, + "width": 90, + "height": 90 + }, + "obelisk": { + "location": "ebwizardry:textures/gui/obelisk_picture.png", + "caption": "An Obelisk", + "u": 0, + "v": 0, + "width": 110, + "height": 67 + }, + "shrine": { + "location": "ebwizardry:textures/gui/shrine_picture.png", + "caption": "An Earth Shrine", + "u": 0, + "v": 0, + "width": 110, + "height": 67 + }, + "tiers": { + "location": "ebwizardry:textures/gui/tiers_picture.png", + "caption": "The 4 Tiers Of Wand", + "u": 0, + "v": 0, + "width": 96, + "height": 24, + "border": false + }, + "elements": { + "location": "ebwizardry:textures/gui/elements_picture.png", + "caption": "The 7 Arcane Elements", + "u": 0, + "v": 0, + "width": 106, + "height": 20, + "border": false } }, "recipes": { "arcane_workbench": { - "location": "ebwizardry:arcane_workbench" + "locations": [ "ebwizardry:arcane_workbench" ] }, "magic_wand": { - "location": "ebwizardry:magic_wand" + "locations": [ "ebwizardry:magic_wand" ] + }, + "novice_wands": { + "locations": [ + "ebwizardry:magic_wand", + "ebwizardry:wand_fire", + "ebwizardry:wand_ice", + "ebwizardry:wand_lightning", + "ebwizardry:wand_necromancy", + "ebwizardry:wand_earth", + "ebwizardry:wand_sorcery", + "ebwizardry:wand_healing" + ] }, "magic_missile_spell_book": { - "location": "ebwizardry:magic_missile_spell_book" + "locations": [ "ebwizardry:magic_missile_spell_book" ] }, "wizard_handbook": { - "location": "ebwizardry:wizard_handbook" + "locations": [ "ebwizardry:wizard_handbook" ] }, "crystal_flower_to_crystals": { - "location": "ebwizardry:crystal_flower_to_crystals" + "locations": [ "ebwizardry:crystal_flower_to_crystals" ] }, - "mana_flask": { - "location": "ebwizardry:mana_flask" + "crystal_blocks": { + "locations": [ + "ebwizardry:crystal_block", + "ebwizardry:crystal_block_fire", + "ebwizardry:crystal_block_ice", + "ebwizardry:crystal_block_lightning", + "ebwizardry:crystal_block_necromancy", + "ebwizardry:crystal_block_earth", + "ebwizardry:crystal_block_sorcery", + "ebwizardry:crystal_block_healing" + ] + }, + "crystal_blocks_to_crystals": { + "locations": [ + "ebwizardry:crystal_block_to_crystals", + "ebwizardry:crystal_block_to_crystals_fire", + "ebwizardry:crystal_block_to_crystals_ice", + "ebwizardry:crystal_block_to_crystals_lightning", + "ebwizardry:crystal_block_to_crystals_necromancy", + "ebwizardry:crystal_block_to_crystals_earth", + "ebwizardry:crystal_block_to_crystals_sorcery", + "ebwizardry:crystal_block_to_crystals_healing" + ] + }, + "crystal_shard": { + "locations": [ "ebwizardry:crystal_shard" ] + }, + "small_mana_flask": { + "locations": [ "ebwizardry:small_mana_flask" ] + }, + "medium_mana_flask": { + "locations": [ "ebwizardry:medium_mana_flask" ] + }, + "large_mana_flask": { + "locations": [ "ebwizardry:large_mana_flask" ] + }, + "runestone": { + "locations": [ + "ebwizardry:runestone_fire", + "ebwizardry:runestone_ice", + "ebwizardry:runestone_lightning", + "ebwizardry:runestone_necromancy", + "ebwizardry:runestone_earth", + "ebwizardry:runestone_sorcery", + "ebwizardry:runestone_healing" + ] + }, + "runestone_pedestal": { + "locations": [ + "ebwizardry:runestone_pedestal_fire", + "ebwizardry:runestone_pedestal_ice", + "ebwizardry:runestone_pedestal_lightning", + "ebwizardry:runestone_pedestal_necromancy", + "ebwizardry:runestone_pedestal_earth", + "ebwizardry:runestone_pedestal_sorcery", + "ebwizardry:runestone_pedestal_healing" + ] }, "transportation_stone": { - "location": "ebwizardry:transportation_stone" + "locations": [ "ebwizardry:transportation_stone" ] }, "magic_silk": { - "location": "ebwizardry:magic_silk" + "locations": [ "ebwizardry:magic_silk" ] }, "wizard_hat": { - "location": "ebwizardry:wizard_hat" + "locations": [ "ebwizardry:wizard_hat" ] }, "wizard_robe": { - "location": "ebwizardry:wizard_robe" + "locations": [ "ebwizardry:wizard_robe" ] }, "wizard_leggings": { - "location": "ebwizardry:wizard_leggings" + "locations": [ "ebwizardry:wizard_leggings" ] }, "wizard_boots": { - "location": "ebwizardry:wizard_boots" + "locations": [ "ebwizardry:wizard_boots" ] }, "blank_scroll": { - "location": "ebwizardry:blank_scroll" + "locations": [ "ebwizardry:blank_scroll" ] }, "firebomb": { - "location": "ebwizardry:firebomb" + "locations": [ "ebwizardry:firebomb" ] }, "poison_bomb": { - "location": "ebwizardry:poison_bomb" + "locations": [ "ebwizardry:poison_bomb" ] }, "smoke_bomb": { - "location": "ebwizardry:smoke_bomb" + "locations": [ "ebwizardry:smoke_bomb" ] + }, + "spark_bomb": { + "locations": [ "ebwizardry:spark_bomb" ] } }, @@ -146,13 +269,19 @@ "include_in_contents": "main_contents", "text": [ - "To get started with wizardry, you will need a few things:", + "To get started with wizardry, you will need:", - "- A magic wand, crafted with a gold nugget, a stick, and a magic crystal.", + "- A magic wand, crafted as shown:", - "- An @arcane_workbench arcane workbench@, crafted with 3 stone, 1 lapis lazuli block, 2 magic crystals, 2 gold nuggets and 1 purple carpet.", + "#recipe magic_wand", - "- A @spells spell@ book. These can be found in chests, dropped as loot, purchased from wizards, or you can make a beginner's spell, magic missile, with a book and 4 magic crystals.", + "- An @arcane_workbench arcane workbench@, crafted like so:", + + "#recipe arcane_workbench", + + "- A @spells spell@ book. These can be found in chests, dropped as loot, purchased from wizards, or you can make a beginner's spell, magic missile, as shown:", + + "#recipe magic_missile_spell_book", "You will also need a bunch more magic crystals to supply your wand with @mana@." ] @@ -172,7 +301,7 @@ "#image magic_crystal", - "It is widely accepted that mana cannot be created or destroyed, and that when a spell is cast, the mana it channels is simply dissipated into the surroundings. Indeed, this is how the vast majority of mana exists - spread thinly throughout the world. However, to be of any use, it must be concentrated, either naturally over thousands of years, as is the case with crystals underground, or artificially - an advanced subject covered later in this book. There also exist various ways of making spells more mana-efficient and recovering some of the mana dissipated during spellcasting." + "It is widely accepted that mana cannot be created or destroyed, and that when a spell is cast, the mana it channels is simply dissipated into the surroundings. Indeed, this is how the vast majority of mana exists - spread thinly throughout the world. However, to be of any use, it must be concentrated, either naturally over thousands of years, as is the case with crystals underground, or artificially - an advanced subject not covered in this book. There also exist various ways of making spells more mana-efficient and recovering some of the mana dissipated during spellcasting." ] }, @@ -190,7 +319,7 @@ "Most wands begin their life as a simple arrangement of a magic crystal of some sort attached to a wooden stick, with a gold nugget affixed to the other end. The crystal is, of course, the source of the wand's power, as it provides the focus necessary to channel @spells@. The rest of the wand is important too though, as it provides not only a means with which to hold the wand, but also a path through which @mana@ can be channeled and directed.", - "As more spells are cast with a wand, it grows more effective at channeling @spells@, and can therefore cast spells of greater power. This effect can be discerned from subtle changes that occur in the shape and appearance of the wand itself: as a wand grows more powerful, its crystal will become more vibrant, it may change in color depending on its element, and after a while, the wood from which it is made will start to grow and twist into more complex shapes.", + "As more spells are cast with a wand, it grows more effective at channeling @spells@, and can therefore cast spells of greater power. This effect can be discerned from subtle changes that occur in the shape and appearance of the wand itself: as a wand grows more powerful, its crystal will become more vibrant, its colour may change depending on its @elements element@, and after a while, the wood from which it is made will start to grow and twist into more complex shapes.", "When holding a wand, a small heads-up display will show in the corner of the screen. This indicates the spell that is currently selected along with a pictorial representation of it, and, if the spell has been cast, a cooldown bar indicating the time until that spell can be cast again. It also shows the names of the next and previous spells bound to the wand. To switch between spells, use the #next_spell_key and #previous_spell_key keys (these can be changed in options -> controls). You can also switch spells by scrolling the mouse wheel while sneaking.", @@ -208,11 +337,13 @@ "A @wands wand@ is useless without spells to cast with it. Spells are recorded in two forms: in books, which are permanent, and in scrolls, which are temporary.", - "Spell books are of little use on their own; instead they are used to bind the spell they contain to @wands@. Spell books can be found throughout the world and it will not take long for you to come across one. When you do find one, you can mouse over the spell book to see basic information about the spell at a glance. You can also right-click whilst holding a spell book to read more detailed information about the spell.", + "Spell books are of little use on their own; instead they are used to bind the spell they contain to @wands@. Spell books can be found throughout the world and it will not take long for you to come across one. When you do find one, you can mouse over the spell book to see basic information about the spell at a glance. You can also right-click whilst holding a spell book to read more about it.", - "Scrolls, on the other hand, serve a different purpose: right-clicking whilst holding one will cast the spell that is bound to it, destroying the scroll in the process. Like spell books, scrolls can be found throughout the world, but you can also make them yourself by crafting a blank scroll from a piece of paper and some string. You can then bind a spell to the scroll using the @arcane_workbench arcane workbench@, but only if you have knowledge of that spell (see @enchanting_scrolls Enchanting Scrolls@). Scrolls are quite useful when you need to use a spell once or twice on a particular quest but don't want it to take up a slot on your @wands wand@. It should be noted, however, that scrolls are at best an inefficient method of casting spells.", + "Scrolls, on the other hand, serve a different purpose: right-clicking whilst holding one will cast the spell that is bound to it, destroying the scroll in the process. Like spell books, scrolls can be found throughout the world, but you can also make them yourself (see @enchanting_scrolls Enchanting Scrolls@).", - "To the untrained eye, the magical runes with which spells are written are unreadable. In order to identify a spell, you could, of course, cast it and see what happens - though doing so may cause unwanted side-effects, and many spells need certain conditions in order to work. A safer and more reliable option is to use a scroll of identification, which can be found in chests or purchased from a wizard. Right-clicking whilst holding one will identify the first unknown spell book or scroll on your hotbar, consuming the scroll of identification in the process." + "Scrolls are quite useful when you need to use a spell once or twice on a particular quest but don't want it to take up a slot on your @wands wand@. It should be noted, however, that they are an inefficient method of casting spells compared to using a wand.", + + "To the untrained eye, the magical runes with which spells are written are unreadable. In order to identify a spell, you could, of course, cast it and see what happens - though doing so may cause unwanted side-effects, and many spells need certain conditions in order to work. Futhermore, there is always a chance of misreading an unknown spell when casting, with potentially dangerous consequences depending on how powerful the spell is. A safer and more reliable option is to use a scroll of identification, which can be found in chests or purchased from a wizard. Right-clicking whilst holding one will identify the first unknown spell book or scroll on your hotbar, consuming the scroll of identification in the process." ] }, @@ -230,7 +361,11 @@ ], "text": [ - "The arcane workbench is a block similar in appearance to the enchantment table where you can charge, upgrade, and bind @spells@ to your @wands wand@. Simply place it anywhere and right click, and you will see something like this:", + "The arcane workbench is a block similar in appearance to the enchantment table where you can charge, upgrade, and bind @spells@ to your @wands wand@. It may be crafted as follows:", + + "#recipe arcane_workbench", + + "The following pages explain the various actions that may be performed in the arcane workbench.", "#image workbench" ], @@ -238,25 +373,34 @@ "binding_spells": { "title": "Binding Spells", "include_in_contents": "arcane_workbench_subsections", + "triggers": [ + "ebwizardry:handbook/arcane_workbench" + ], "text": [ - "To bind a spell to your wand, simply place your wand in the central slot of the workbench, then place the spell book in one of the surrounding slots and press apply. You will notice that the spell book is left untouched during this process - this is because the act of spell binding does not 'take' the spell from the spell book; rather, it attunes the wand to the spell. As such, you may change the spells bound to your wand as much as you wish by simply repeating the spell binding process. You can bind up to five spells to a wand at one time, though this number may be increased with attunement upgrades." + "To bind a @spells spell@ to your @wands wand@, simply place your wand in the central slot of the workbench, then place the spell book in one of the surrounding slots and press apply. You will notice that the spell book is left untouched during this process - this is because the act of spell binding does not 'take' the spell from the spell book; rather, it attunes the wand to the spell. As such, you may change the spells bound to your wand as much as you wish by simply repeating the spell binding process. You can bind up to five spells to a wand at one time, though this number may be increased with attunement upgrades." ] }, "charging_wands": { "title": "Charging Wands", "include_in_contents": "arcane_workbench_subsections", + "triggers": [ + "ebwizardry:handbook/arcane_workbench" + ], "text": [ - "To charge your wand, place the wand in the central slot of the arcane workbench and place some magic crystals in the upper of the two slots on the left, and then press apply. Each crystal is worth #mana_per_crystal mana, and the wand will only take what it needs, so you can keep a supply of crystals in the workbench for when you need them. However, bear in mind that the wand can only take a whole number of crystals so if the wand needs, for example, 30 more mana, #mana_per_crystal_minus_30 mana will be lost when charging it." + "To charge your @wands wand@, place the wand in the central slot of the arcane workbench and place some magic crystals in the bottom-left slot, and then press apply. Each crystal is worth #mana_per_crystal @mana@, and the wand will only take what it needs, so you can keep a supply of crystals in the workbench for when you need them. However, bear in mind that the wand can only take a whole number of crystals, so if the wand needs, for example, 30 more mana, #example_charging_loss mana will be lost when charging it." ] }, "upgrading_wands": { "title": "Upgrading Wands", "include_in_contents": "arcane_workbench_subsections", + "triggers": [ + "ebwizardry:handbook/tome_of_arcana" + ], "text": [ - "To upgrade your wand, you will need a tome of arcana of the appropriate tier (see @tiers Tiers@) or a special wand upgrade. Both of these can be found as loot or purchased from a wizard. To upgrade your wand, place it in the central slot and the upgrade in the lower of the two slots on the left, then press apply.", + "To upgrade your @wands wand@, you will need a tome of arcana of the appropriate @tiers tier@ or a special wand upgrade. Both of these can be found as loot or purchased from a wizard. To upgrade your wand, place it in the central slot and the upgrade in the top-right slot, then press apply.", "Special wand upgrades improve a particular aspect of a wand. Each type of upgrade can stack up to three times, and the total number of upgrades that a wand can take depends on its tier. Upgrades cannot be removed." ] @@ -264,9 +408,16 @@ "enchanting_scrolls": { "title": "Enchanting Scrolls", "include_in_contents": "arcane_workbench_subsections", + "triggers": [ + "ebwizardry:handbook/scrolls" + ], "text": [ - "The arcane workbench can also be used to enchant spell scrolls. To do so, you will require a blank scroll, crafted from a piece of paper and some string, a spell book for your chosen spell, and enough magic crystals to provide mana to cast it. Place the crystals in the upper left-hand slot, the blank scroll in the central slot, and the spell book in the single slot that appears above it, then press apply to enchant the scroll." + "The arcane workbench can also be used to enchant @spells spell@ scrolls. To do so, you will require a blank scroll, crafted from a piece of paper and some string, a spell book for your chosen spell, and enough magic crystals to provide @mana@ to cast it.", + + "#recipe blank_scroll", + + "Place the crystals in the bottom-left slot, the blank scroll in the central slot, and the spell book in the single slot above it, then press confirm to enchant the scroll." ] } } @@ -275,11 +426,24 @@ "wizard_armour": { "title": "Wizard Armor", "include_in_contents": "main_contents", + "triggers": [ + "ebwizardry:arcane_initiate" + ], "text": [ - "As a wizard, you will need something to protect you from the creatures you fight. No ordinary armor will do though. To make the most of your spells, you will need wizard armor: hat, robes, leggings and boots. Unlike ordinary armor, these will not break. Instead, they use arcane energy to shield the wearer. This of course means that they must be charged with magic crystals, just like wands. Fortunately, these garments do not consume much mana. Charge them as you would a wand in the arcane workbench or with a mana flask, but be careful - if they run out of mana, you will find yourself defenseless.", + "As a wizard, you will need something to protect you from the creatures you fight. No ordinary armor will do though. To make the most of your spells, you will need wizard armor: hat, robes, leggings and boots. Unlike ordinary armor, these will not break. Instead, they use arcane energy to shield the wearer. This of course means that they must be charged with magic crystals, just like wands. Fortunately, these garments do not consume much @mana@. Charge them as you would a wand in the @arcane_workbench arcane workbench@ or with a @mana_flasks mana flask@, but be careful - if they run out of mana, you will find yourself defenseless.", - "You can obtain wizard armor by crafting it from magical silk, obtained by crafting string with a magic crystal.", + "#image wizard_armour", + + "You can obtain wizard armor by crafting it from magical silk:", + + "#recipe magic_silk", + "#recipe wizard_hat", + "#recipe wizard_robe", + "#recipe wizard_leggings", + "#recipe wizard_boots", + + "One may enchant wizard armour using a normal enchantment table, and due to the inherent properties of magical silk, it tends to be quite effective at holding enchantments. Of particular utility to a wizard are the Magic, Frost and Shock Protection enchantments, which may prove useful defending against other wielders of magic.", "Those wizards who devote themselves to the practise of one element sometimes wear special garments which grant bonuses for that element. Full sets of such garments are very sought after among wizards and are not easy to find.", @@ -296,6 +460,9 @@ "page_numbers": true, "separator": "." }, + "triggers": [ + "ebwizardry:handbook/on_subsection_unlock" + ], "text": [ "One cannot master the arcane just by staying at home - there is a world full of magic out there to explore! Ancient ruins, relics and mysterious beings good and bad await discovery - if you know where to look. The greatest wizards are also the most curious, and gain much of their knowledge and power through exploration of the environment around them, and experimenting with what they find.", @@ -311,39 +478,59 @@ ], "text": [ - "During your travels, you will probably come across curious glowing flowers growing in the wild from time to time. These distinctive blooms are known as crystal flowers, and they are strangely effective at concentrating mana - to this day, nobody is quite sure why. We do know, however, that they can be harvested and crafted to extract the mana as crystals, making them a rather useful above-ground source of mana. The amount of mana obtainable this way is limited, though, by the small size of the flowers and due to them only growing in small patches.", + "During your travels, you will probably come across curious glowing flowers growing in the wild from time to time. These distinctive blooms are known as crystal flowers, and they are strangely effective at concentrating @mana@ - to this day, nobody is quite sure why. We do know, however, that they can be harvested and crafted to extract the mana as crystals, making them a rather useful above-ground source of mana. The amount of mana obtainable this way is limited, though, by the small size of the flowers and due to them only growing in small patches.", - "#image crystal_flower" + "#image crystal_flower", + "#recipe crystal_flower_to_crystals" ] }, "wizard_towers": { "title": "Wizard Towers", "include_in_contents": "magical_world_subsections", + "triggers": [ + "ebwizardry:wizard_tower" + ], "text": [ - "Fear not - you are not the only practicioner of magic in this world. On your travels, you may well encounter a tall tower or two with a distinctive pointed roof. This is the residence of a fellow wizard. A life of solitude can make wizards a little grumpy at times, but they are usually friendly folk who are willing to share their knowledge with you - albeit for a price. Expect to pay precious metals and gems, and in return you will recieve many a great arcane wonder. If, however, it is a master spell you seek, you will need to speak to a specialist.", + "Fear not - you are not the only practicioner of magic in this world. On your travels, you may well encounter a tall tower or two with a distinctive pointed roof. This is the residence of a fellow wizard. A life of solitude can make wizards a little grumpy at times, but they are usually friendly folk who are willing to share their knowledge with you - albeit for a price. Expect to pay precious metals and gems, and in return you will recieve many a great arcane wonder.", + + "If, however, it is a @tiers master@ spell you seek, you will need to speak to a specialist.", + + "#image wizard_tower", "Unfortunately, there are a few wizards out there who do not welcome visitors. These wizards are typically outcasts, and are hostile to anyone crossing their path. Approach these individuals with caution, and be prepared to defend yourself against powerful magic. Defeat them however, and their knowledge is yours for the taking.", - "It should also be noted that no wizard will take kindly to being attacked or stolen from - and will readily take the law into their own hands." + "It should also be noted that no wizard will take kindly to being attacked or stolen from - and they will readily take the law into their own hands." ] }, "obelisks": { "title": "Obelisks", "include_in_contents": "magical_world_subsections", + "triggers": [ + "ebwizardry:handbook/obelisks" + ], "text": [ "Vestiges of ancient magic are scattered throughout the world, the most notable of which are carved stone structures which bear a great many symbols and runes. These ruins are all that remain of what appears to have been some kind of ancient civilisation. Whoever, or whatever, built them, they clearly had a considerable knowledge of magic, and used it to place protective enchantments over such locations that still persist to this day.", - "These stuctures fit broadly into two types. The first, and more common, of these are obelisks: tall spikes of carved stone, known as runestone, with an open structure at the bottom that usually contains minor arcane relics from the forgotten past. These structures are typically protected by an enchantment that summons hostile magical creatures should any human stray too close. Fend off these creatures and destroy their source, and the relics are yours." + "These stuctures fit broadly into two types. The first, and more common, of these are obelisks: tall spikes of carved stone, known as runestone, with an open structure at the bottom containing minor arcane relics from the forgotten past.", + + "#image obelisk", + + "These structures are typically protected by an enchantment that summons hostile @creatures magical creatures@ should any human stray too close. Fend off these creatures and destroy their source, and the relics are yours." ] }, "shrines": { "title": "Shrines", "include_in_contents": "magical_world_subsections", + "triggers": [ + "ebwizardry:visit_shrine" + ], "text": [ - "The second, and rarer, kind of structure is known as a shrine. These structures consist of a circle of runestone pillars surrounding a central platform, upon which sits a chest filled with ancient artifacts. This chest is typically protected by an arcane lock enchantment, preventing anyone except the owner from opening it. The entire structure is also protected by a containment field, which prevents anything that strays too close from escaping.", + "The second, and rarer, kind of structure is known as a shrine. These structures consist of a circle of runestone pillars surrounding a central pedestal, upon which sits a chest filled with ancient @artefacts artifacts@. This chest is typically protected by an arcane lock enchantment, preventing anyone except the owner from opening it. The entire structure is also protected by a containment field, which prevents anything that strays too close from escaping.", + + "#image shrine", "Due to their great arcane power and significance, not to mention the riches within, these structures are particularly attractive to any aspiring wizard - but be cautious. There are numerous reports of wizards becoming trapped within containment fields and slowly being driven insane, perhaps by claustrophobia. A growing number, however, believe such occurences to be a deliberate part of the shrine's protective magic, and that the wizards trapped within are in fact being controlled to protect the structure. A chilling prospect, surely, for anyone who dares to venture near..." ] @@ -351,17 +538,23 @@ "creatures": { "title": "Magical Creatures", "include_in_contents": "magical_world_subsections", + "triggers": [ + "ebwizardry:handbook/magical_creatures" + ], "text": [ - "Besides wizards, a multitude of other creatures also use magic. Many of these creatures are arcane in origin, and most can be summoned using certain magical spells. One may encounter these creatures guarding an obelisk, or perhaps a powerful summoner. Lesser arcane beings are even found occasionally in the wilderness." + "Besides wizards, a multitude of other creatures also use magic. Many of these creatures are arcane in origin, and most can be summoned using certain magical @spells spells@. One may encounter these creatures guarding an @obelisks obelisk@, or perhaps a powerful summoner. Lesser arcane beings are even found occasionally in the wilderness." ] }, "artefacts": { "title": "Artifacts", "include_in_contents": "magical_world_subsections", + "triggers": [ + "ebwizardry:artefact" + ], "text": [ - "When exploring a shrine, you may be lucky enough to uncover some kind of ancient magical artifact - an object capable of granting its wearer unique and powerful buffs and special powers. Three types are known to have been found: rings, which grant bonuses and effects to spells, amulets, which improve defensive abilities, and trinkets, which give utility effects. These artifacts appear to function only when worn appropriately; simply having them on one's person is insufficient." + "When exploring a @shrines shrine@, you may be lucky enough to uncover some kind of ancient magical artifact - an object capable of granting its wearer unique and powerful buffs and special powers. Three types are known to have been found: rings, which grant bonuses and effects to spells, amulets, which improve defensive abilities, and charms, which give utility effects. These artifacts appear to function only when worn appropriately; simply having them on one's person is insufficient." ] } } @@ -370,26 +563,40 @@ "tiers": { "title": "Tiers", "include_in_contents": "main_contents", + "triggers": [ + "ebwizardry:handbook/tome_of_arcana" + ], "text":[ - "Wands and spells come in four tiers: #colour_novicenovice#colour_reset, #colour_apprenticeapprentice#colour_reset, #colour_advancedadvanced #colour_resetand #colour_mastermaster#colour_reset. Each tier is more powerful than the last.", + "@wands Wands@ and @spells@ come in four tiers: #colour_novicenovice#colour_reset, #colour_apprenticeapprentice#colour_reset, #colour_advancedadvanced #colour_resetand #colour_mastermaster#colour_reset. Each tier is more powerful than the last.", + + "#image tiers", "#colour_noviceNovice #colour_resetwands are the ones that can be crafted. They hold up to #novice_max_charge mana, and can only cast novice spells. Novice spells are simple enough to be cast by anyone and they do not usually cost much mana. This does not necessarily mean that they are useless at higher tiers however; their low cost makes some novice spells useful even when you have access to master spells.", "#colour_apprenticeApprentice #colour_resetwands are the next tier up from novice wands. They hold up to #apprentice_max_charge mana and can cast novice and apprentice spells. Apprentice spells are a little more impressive than novice spells but usually cost more.", - "#colour_advancedAdvanced #colour_resetwands are quite rare and are much more powerful. They can cast all spells except master spells, and hold #advanced_max_charge mana. Advanced spells can grant superhuman powers such as invisibility and wreak havoc on enemies.", + "#colour_advancedAdvanced #colour_resetwands are quite rare and are much more powerful. They can cast all spells except master spells, and hold #advanced_max_charge mana. Advanced spells can grant superhuman powers such as invisibility and wreak havoc on foes.", - "#colour_masterMaster #colour_resetwands are the most powerful wands in existence. They hold up to #master_max_charge mana, and can cast any spell. Master spell books are very rare and the spells can cause complete devastation not only to enemies but even the world itself. Use with caution." + "#colour_masterMaster #colour_resetwands are the most powerful wands in existence. They hold up to #master_max_charge mana, and can cast any spell. Master spell books are very rare and the spells can cause complete devastation not only to enemies but even the world itself. Use with caution.", + + "To be upgraded to a higher tier, a wand must first become powerful enough to channel spells of that tier. Wands gain power as spells are cast with them. Spell variety, spell power, elemental effects and other external factors may all have an effect on how quickly a wand matures.", + + "Once a wand is sufficiently powerful, a tome of arcana provides the final catalyst needed to elevate the wand to the next tier (see @upgrading_wands Upgrading Wands@), and once this has happened, the maturing process can begin again for the next tier." ] }, "elements": { "title": "Elements", "include_in_contents": "main_contents", + "triggers": [ + "ebwizardry:handbook/elements" + ], "text": [ - "Spells belong to different elements, which describe the nature of the spell and also have perks when used with certain wands.", + "@spells Spells@ belong to different elements, which determine the nature of the spell and also grant perks when used with certain @wands@.", + + "#image elements", "#colour_fireFire#colour_reset \nPerhaps the most destructive element, fire concerns burning, lava, and explosions. A powerful pyromancer will unleash hell upon their enemies and probably set the world alight in the process. Most fire attack spells set fire to their target, causing ongoing damage over time. However, be wary that fire spells may have no effect on nether mobs.", @@ -397,7 +604,7 @@ "#colour_lightningLightning#colour_reset \nThis element concerns lightning, storms, and the weather. A powerful storm mage is a force to be reckoned with, and some posess the ability to call down lightning at will. Lightning spells often damage multiple enemies at once and usually seek their target, making them an effective attack against any mob... but beware of creepers.", - "#colour_necromancyNecromancy#colour_reset \nNecromancy is the element of darkness, chaos and the undead. Necromancers are mysterious and often regarded as evil, though this is usually not the case. Necromancy spells are commonly used to summon creatures to fight for you or even bend the will of your enemies.", + "#colour_necromancyNecromancy#colour_reset \nNecromancy is the element of darkness, chaos and the undead. Necromancers are mysterious and often regarded as evil, though this is usually not the case. Necromancy spells are commonly used to summon @creatures@ to fight for you or even bend the will of your enemies.", "#colour_earthEarth#colour_reset \nThe element of earth is focused on the natural world: animals, plants, the wind, and such like. Earth magic is diverse and takes a wide variety of forms, from poisoning enemies to unleashing the fury of the weather. Earth spells are a mixture of attack, defense and utility.", @@ -407,22 +614,7 @@ "The boundaries between the different elements are not always distinct, and some spells bear traits of elements other than their own.", - "If you are lucky, you may happen upon an elemental wand. These wands will allow you to cast spells of the right element for more potency than usual." - ] - }, - - "growing_crystals": { - "title": "Growing Crystals", - "include_in_contents": "main_contents", - "text": [ - - "Magic crystals normally form naturally underground over thousands of years, by gradually drawing latent mana from the surrounding rock as they grow. Crystalline structures are very good at absorbing and holding mana, hence the mana is naturally drawn towards them. Given the right conditions, however, it is possible to greatly speed up this process. This has given rise to the advanced technique of crystal growing, which requires both great patience and attention to detail.", - - "In order to encourage crystal growth, one must begin with a crystal seed. The most effective seeds have proven to be crystal shards, obtained by simply shattering a magic crystal into pieces. A crystal seed must then be planted into some kind of substrate, usually rock, although other materials are also viable. Left alone, this would produce a sizeable crystal in hundreds of years, depending on the conditions.", - - "To reduce this length of time, several things can be done. Immersing the seed and substrate in mineral-rich water helps with crystal growth, but not with concentrating mana. To concentrate mana more quickly, two techniques can be employed: firstly, surrounding the growth site with lesser mana-gathering objects allows the crystal to draw from them, meaning the surrounding environment is constantly replenished with mana. Too many, however, and they begin to draw mana away from the growing crystal. Secondly, mana can be drawn through some materials better than others: air is very poor at this, whereas dense materials tend to be much better. Some wizards have taken to experimentation with exotic, magical, or even otherworldy materials to try and improve crystal growth. Some even claim to have altered the type of crystal that is formed in this way.", - - "If conditions are exactly right, it is even possible for crystals to grow far beyond their natural size. Such crystals are known as grand magic crystals, and besides containing a great quantity of mana, they have a few specific uses." + "If you are lucky, you may happen upon an elemental crystal. Elemental crystals are magic crystals that have absorbed elemental properties as they have grown - though the exact conditions required and mechanism by which this happens remain a mystery. We do know, however, that such crystals may be used to create elemental wands, which allow spells of the right element to be cast with more potency than usual." ] }, @@ -435,37 +627,57 @@ "page_numbers": true, "separator": "." }, + "triggers": [ + "ebwizardry:on_subsection_unlock" + ], "sections": { "mana_flasks": { "title": "Mana Flasks", "include_in_contents": "miscellaneous_subsections", + "triggers": [ + "ebwizardry:handbook/mana_flasks" + ], "text": [ "Arkendur's Arcane Supplies Co. - magical items for your every need!", - "Need to recharge your wand on the go? No problem! Mana can now be bottled.** Simply craft a mana flask with a glass bottle and eight magic crystals and take it with you. When you need to use it, simply craft it with your wand and it will restore some of the charge.*", + "Need to recharge your @wands wand@ on the go? No problem! @mana Mana@ can now be bottled. Simply craft a mana flask with a glass bottle and eight magic crystals and take it with you. When you need to use it, simply craft it with your wand and it will restore some of the charge. *", - "NEW! Introducing the brand-new large*** and small mana flasks - now you can choose a size of mana flask to meet your needs!", - - "* This process will consume the bottle.", - "** Some mana is lost during bottling.", - "*** Large mana flask requires grand magic crystals." + "#recipe medium_mana_flask", + + "NEW! Introducing the brand-new small and large mana flasks - now you can choose a size of mana flask to meet your needs!", + + "#recipe small_mana_flask", + "#recipe large_mana_flask", + + "* This process will destroy the bottle. Some mana is lost during bottling." ] }, "throwable_items": { "title": "Throwable Items", "include_in_contents": "miscellaneous_subsections", + "triggers": [ + "ebwizardry:handbook/throwables" + ], "text": [ - - "Various spells conjure physical items, some of which can also be crafted directly. Firebombs, poison bombs, spark bombs and smoke bombs can all be crafted." + + "Various @spells@ conjure physical items, some of which can also be crafted directly. Firebombs, poison bombs, spark bombs and smoke bombs can all be crafted:", + + "#recipe firebomb", + "#recipe poison_bomb", + "#recipe smoke_bomb", + "#recipe spark_bomb" ] }, "automated_casting": { "title": "Automated Casting", "include_in_contents": "miscellaneous_subsections", + "triggers": [ + "ebwizardry:enchant_scroll" + ], "text": [ - "Recent experimentation has revealed that it is possible to automate spell casting, to a degree, using nothing more than a simple dispenser. Nobody is quite sure why, but it would appear that the strange properties of redstone even extend to triggering the activation of spell scrolls. Placing a few into a dispenser and powering it ought to do the trick..." + "Recent experimentation has revealed that it is possible to automate @spells spell@ casting, to a degree, using nothing more than a simple dispenser. Nobody is quite sure why, but it would appear that the strange properties of redstone even extend to triggering the activation of spell scrolls. Placing a few into a dispenser and powering it ought to do the trick..." ] } } @@ -477,11 +689,18 @@ "text": [ "#recipe arcane_workbench", - "#recipe magic_wand", + "#recipe novice_wands", "#recipe magic_missile_spell_book", "#recipe wizard_handbook", "#recipe crystal_flower_to_crystals", - "#recipe mana_flask", + "#recipe crystal_blocks", + "#recipe crystal_blocks_to_crystals", + "#recipe crystal_shard", + "#recipe small_mana_flask", + "#recipe medium_mana_flask", + "#recipe large_mana_flask", + "#recipe runestone", + "#recipe runestone_pedestal", "#recipe transportation_stone", "#recipe magic_silk", "#recipe wizard_hat", @@ -491,7 +710,8 @@ "#recipe blank_scroll", "#recipe firebomb", "#recipe poison_bomb", - "#recipe smoke_bomb" + "#recipe smoke_bomb", + "#recipe spark_bomb" ] }, @@ -502,8 +722,6 @@ "Electroblob's Wizardry \nVersion #version \nFor Minecraft #mcversion", - "For more information, check out the @https://github.com/Electroblob77/Wizardry/wiki wiki@.", - "Designed, coded and textured by Electroblob", "Thanks to Minecraft Forge and MCP, without which this mod would not have been possible.", @@ -514,13 +732,17 @@ "Code:", - "- Corail31 \n- 12foo \n- Shadows-of-Fire", + "- Corail31 \n- 12foo \n- Shadows-of-Fire \n- Tora-B \n- Avatair \n- Aeronica", "Translations:", - "- Russian: VilagVil \n- Spanish and Mexican Spanish: MadWrist \n- Chinese: ZHENGLOC", + "- Spanish and Mexican Spanish: MadWrist \n- Russian: VilagVil, kellixon \n- French: Hahdrim \n- Brazilian Portuguese: lorrampi \n- Chinese: ZHENGLOC, dragon-evol \n-Korean: shejery, rewi_wire", - "Lightning ray sound effect from OhhWowProductions" + "Lightning ray sound effect from OhhWowProductions", + + "For more information, check out the @https://github.com/Electroblob77/Wizardry/wiki wiki@.", + + "Can't get enough wizardry? Join the @https://discord.gg/MTmMzMv Discord server@ for the latest news, discussions and extras!" ] } diff --git a/src/main/resources/assets/ebwizardry/texts/handbook_en_us.txt b/src/main/resources/assets/ebwizardry/texts/handbook_en_us.txt deleted file mode 100644 index 5cae001e..00000000 --- a/src/main/resources/assets/ebwizardry/texts/handbook_en_us.txt +++ /dev/null @@ -1,225 +0,0 @@ -PAGEBREAK -LINEBREAK - - - - -The Wizard's Handbook - - - -By Electroblob -PAGEBREAK -Introduction --------------------- - -Greetings, wizard! This book explains the many ways of the arcane and how to use them. - -Should you ever lose this book, you can get a new one by crafting a book with a magic crystal. -PAGEBREAK -Contents --------------------- -PAGEBREAK -SECTION Setting up -Setting up --------------------- -To get started with wizardry, you will need a few things: - -- A magic wand, crafted with a gold nugget, a stick, and a magic crystal. - -- An arcane workbench, crafted with 3 stone, 1 lapis lazuli block, 2 magic crystals, 2 gold nuggets and 1 purple carpet. - -- A spell book. These can be found in chests, dropped as loot, purchased from wizards, or you can make a beginner's spell, magic missile, with a book and 4 magic crystals. - -You will also need a bunch more magic crystals to supply your wand with mana. -PAGEBREAK -SECTION Mana -Mana --------------------- -Mana is the arcane energy that gives wizards their powers. It manifests itself in naturally occurring crystals, which can be found embedded in rocks underground. Wands can store mana within them, and this mana is channeled into the spells that you cast. Different spells cost different amounts of mana, depending on how powerful they are and how long they last. - -Mouse over a wand to see how much mana is stored in it. -IMAGE CRYSTAL -LINEBREAK - - - - - - - Magic - Crystal Ore Crystal -PAGEBREAK -SECTION Wands -Wands --------------------- -The wand is the implement of choice for a wizard. With it, you can cast any spell provided the wand can contain its power (see Tiers for a more in-depth explanation). Wands come in -various different varieties but you will almost certainly start with a basic magic wand. - -When holding a wand, a small heads-up display will show in the corner of the screen. This indicates the spell that is currently selected along with a pictorial representation of it, and, if the spell has been cast, a cooldown bar indicating the time until that spell can be cast again. -PAGEBREAK -SECTION Spells -Spells --------------------- -A wand is useless without spells to cast with it. Spells are recorded in two forms: in books, which are permanent, and in scrolls, which are temporary. - -Spell books are of little use on their own; instead they are used to bind the spell they contain to wands. Spell books can be found throughout the world and it will not take long for you to come across one. When you do find one, you can mouse over the spell book to see basic information about the spell at a glance. You can also right-click whilst holding a spell book to read more detailed information about the spell. - -Scrolls, on the other hand, serve a different purpose: right-clicking whilst holding one will cast the spell that is bound to it, destroying the scroll in the process. Like spell books, scrolls can be found throughout the world, but you can also make them yourself by crafting a blank scroll from a piece of paper and some string. You can then bind a spell to the scroll using the arcane workbench, but only if you have knowledge of that spell. Doing so will consume a number of magic crystals equal to the mana cost of the spell (rounded up to the nearest MANA_PER_CRYSTAL). - -To the untrained eye, the magical runes with which spells are written are unreadable. In order to identify a spell, you could, of course, cast it and see what happens - though doing so may cause unwanted side-effects, and many spells need certain conditions in order to work. A safer and more reliable option is to use a scroll of identification, which can be found in chests or purchased from a wizard. Right- -clicking whilst holding one will identify the first unknown spell book or scroll on your hotbar, consuming the scroll of identification. - -Scrolls are quite useful when you need to use a spell once or twice on a particular quest but don't want it to take up a slot on your wand. It should be noted, however, that scrolls are at best an inefficient method of casting spells. -PAGEBREAK -SECTION Arcane Workbench -The Arcane Workbench --------------------- -The arcane workbench is a block similar in appearance to the enchantment table where you can charge, upgrade, and bind spells to your wand. Simply place it anywhere and right click, and you will see a gui appear like the one to the right. -PAGEBREAK -IMAGE WORKBENCH -LINEBREAK - - - - - - - - - - - - - - The Arcane Workbench -PAGEBREAK -SECTION Binding Spells -Binding Spells --------------------- -To bind a spell to your wand, simply place your wand in the central slot of the workbench, then place the spell book in one of the surrounding slots and press apply. You can bind up to five spells to a wand at one time, though this may be increased with attunement upgrades. When holding a wand, you can switch between spells with the NEXT_SPELL_KEY and PREVIOUS_SPELL_KEY keys (these can be changed in options -> controls). You can also switch spells by scrolling the mouse wheel while sneaking. - -SECTION Charging Wands -Charging your wand --------------------- -To charge your wand, place the wand in the central slot of the arcane workbench and place some magic crystals in the upper of the two slots on the left, and then press apply. Each crystal is worth MANA_PER_CRYSTAL mana, and the wand will only take what it needs, so you can keep a supply of crystals in the workbench for when you need them. However, bear in mind that the wand can only take a whole number of crystals so if the wand needs, for example, 30 more mana, MANA_PER_CRYSTAL_MINUS_30 mana will be lost when charging it. All wands will take an exact number of crystals to charge if they are empty, unless they have a storage upgrade applied. - -SECTION Upgrading Wands -Upgrading your wand --------------------- -To upgrade your wand, you will need a tome of arcana of the appropriate tier (see Tiers) or a special wand upgrade. Both of these can be found as loot or purchased from a wizard. To upgrade your wand, place it in the central slot and the upgrade in the lower of the two slots on the left, then press apply. - -Special wand upgrades improve a particular aspect of a wand. Each type of upgrade can stack up to three times, and the total number of upgrades that a wand can take depends on its tier. Upgrades cannot be removed. -PAGEBREAK -SECTION Flowers and Flasks -Flowers and Flasks --------------------- -You will probably come across curious glowing flowers growing in the wild from time to time. These are crystal flowers, a naturally occurring source of mana. They can be harvested and crafted to extract the mana as crystals. - -Need to recharge your wand on the go? No problem! Mana can now be bottled. Simply craft a mana flask with a glass bottle and eight magic crystals and take it with you. When you need to use it, simply craft it with your wand and it will restore some of the charge. This process will consume the bottle. Some mana is lost during bottling. -PAGEBREAK -SECTION Tiers -Tiers --------------------- -Wands and spells come in four tiers: BASIC_COLOURnoviceRESET_COLOUR, APPRENTICE_COLOURapprenticeRESET_COLOUR, ADVANCED_COLOURadvanced RESET_COLOURand MASTER_COLOURmasterRESET_COLOUR. Each tier is more powerful than the last. - -BASIC_COLOURNovice RESET_COLOURwands are the ones that can be crafted. They hold up to BASIC_MAX_CHARGE mana, and can only cast novice spells. Novice spells are simple enough to be cast by anyone and they do not usually cost much mana. This does not necessarily mean that they are useless at higher tiers however; their low cost makes some novice spells useful even when you have access to master spells. - -APPRENTICE_COLOURApprentice RESET_COLOURwands are the next tier up from novice wands. They hold up to APPRENTICE_MAX_CHARGE mana and can cast novice and apprentice spells. Apprentice spells are a little more impressive than novice spells but usually cost more. - -ADVANCED_COLOURAdvanced RESET_COLOURwands are quite rare and are much more powerful. They can cast all spells except master spells, and hold ADVANCED_MAX_CHARGE mana. Advanced spells can grant superhuman powers such as invisibility and wreak havoc on enemies. - -MASTER_COLOURMaster RESET_COLOURwands are the most powerful wands in existence. They hold up to MASTER_MAX_CHARGE mana, and can cast any spell. Master spell books are very rare and the spells can cause complete devastation not only to enemies but even the world itself. Use with caution. -PAGEBREAK -SECTION Elements -Elements --------------------- -Spells belong to different elements, which describe the nature of the spell and also have perks when used with certain wands. - -FIRE_COLOURFire -Perhaps the most destructive element, fire concerns burning, lava, and explosions. A powerful pyromancer will unleash hell upon their enemies and probably set the world alight in the process. Most fire attack spells set fire to their target, causing ongoing damage over time. However, be wary that fire spells may have no effect on nether mobs. - -ICE_COLOURIce -The element of ice is made of all that is cold. Frost spells often slow enemies down or freeze them completely, and are especially effective on creatures of fire. Frost magic can prove equally useful outside of combat, such as freezing water to cross a river. - -LIGHTNING_COLOURLightning -This element concerns lightning, storms, and the weather. A powerful storm mage is a force to be reckoned with, and some posess the ability to call down lightning at will. Lightning spells often damage multiple enemies at once and usually seek their target, making them an effective attack against any mob... but beware of creepers. - -NECROMANCY_COLOURNecromancy -Necromancy is the element of darkness, chaos and the undead. Necromancers are mysterious and often regarded as evil, though this is usually not the case. Necromancy spells are commonly used to summon creatures to fight for you or even bend the will of your enemies. - -EARTH_COLOUREarth -The element of earth is focused on the natural world: animals, plants, the wind, and such like. Earth magic is diverse and takes a wide variety of forms, from poisoning enemies to unleashing the fury of the weather. Earth spells are a mixture of attack, defense and utility. - -SORCERY_COLOURSorcery -Sorcery is the element of force and change. Sorcerers manipulate light, gravity and even reality itself to fit their needs. Sorcery spells can be used, among other things, to grant their caster magical powers or move objects to their will. - -HEALING_COLOURHealing -The element of healing is concerned with defense and regeneration. Healers seek to protect themselves and their allies as much as possible and as such can be very difficult opponents. Though generally not used as an attack, the purifying light of some healing spells will do considerable damage to the undead. Healing spells are indispensable when in combat. - -The boundaries between the different elements are not always distinct, and some spells bear traits of elements other than their own. - -If you are lucky, you may happen upon an elemental wand. These wands will allow you to cast spells of the right element for more potency than usual. -PAGEBREAK -SECTION Wizard Armor -Wizard Armor --------------------- -As a wizard, you will need something to protect you from the creatures you fight. No ordinary armor will do though. To make the most of your spells, you will need wizard armor: hat, robes, leggings and boots. Unlike ordinary armor, these will not break. Instead, they use arcane energy to shield the wearer. This of course means that they must be charged with magic crystals, just like wands. Fortunately, these garments do not consume much mana. Charge them as you would a wand in the arcane workbench or with a mana flask, but be careful - if they run out of mana, you will find yourself defenseless. - -You can obtain wizard armor by crafting it from magical silk, obtained by crafting string with a magic crystal. - -Those wizards who devote themselves to the practice of one element sometimes wear special garments which grant bonuses for that element. Full sets of such garments are very sought after among wizards and are not easy to find. - -Legend speaks of an arcane seal used by the most powerful wizards to greatly improve their armor. -PAGEBREAK -SECTION Wizards and Towers -Wizards and Towers --------------------- -Fear not - you are not the only practicioner of magic in this world. On your travels, you may well encounter tall towers with distinctive pointed roofs. These are the residences of fellow wizards. A life of solitude can make wizards a little grumpy at times, but they are usually friendly folk who are willing to share their knowledge with you - albeit for a price. Expect to pay precious metals and gems, and in return you will recieve many a great arcane wonder. If, however, it is a master spell you seek, you will need to speak to a specialist. - -Unfortunately, there are a few wizards out there who do not welcome visitors. These wizards are typically outcasts, and are hostile to anyone crossing their path. Approach these individuals with caution, and be prepared to defend yourself against powerful magic. Defeat them however, and their knowledge is yours for the taking. -PAGEBREAK -SECTION Crafting Recipes -Crafting Recipes --------------------- -PAGEBREAK -PAGEBREAK -Crafting Recipes --------------------- -PAGEBREAK -PAGEBREAK -Crafting Recipes --------------------- -PAGEBREAK -PAGEBREAK -Crafting Recipes --------------------- -PAGEBREAK -PAGEBREAK -Credits --------------------- -Electroblob's Wizardry -Version VERSION -For Minecraft MCVERSION - -Designed, coded and textured by Electroblob - -Thanks to Minecraft Forge and MCP, without which this mod would not have been possible. - -Thanks also to the Minecraft modding community, which always has an answer to my modding problems! - -In addition, I'd like to thank the following individuals for their contributions to the mod: - -Code: - -- Corail31 -- 12foo -- Shadows-of-Fire -- HellFirePvP - -Translations: - -- Russian: VilagVil -- Spanish and Mexican Spanish: MadWrist -- Chinese: ZHENGLOC and dragon-evol - -Lightning ray sound effect from OhhWowProductions diff --git a/src/main/resources/assets/ebwizardry/texts/handbook_es_es.txt b/src/main/resources/assets/ebwizardry/texts/handbook_es_es.txt index 90cea3cd..237a026e 100644 --- a/src/main/resources/assets/ebwizardry/texts/handbook_es_es.txt +++ b/src/main/resources/assets/ebwizardry/texts/handbook_es_es.txt @@ -173,7 +173,7 @@ Niveles Las varitas y los hechizos vienen en cuatro niveles: BASIC_COLOURBasicoRESET_COLOUR, APPRENTICE_COLOURAprendizRESET_COLOUR, ADVANCED_COLOURAvanzadoRESET_COLOUR y MASTER_COLOURMaestroRESET_COLOUR. Cada nivel es mejor que el anterior. Las varitas BASIC_COLOURBasico RESET_COLOURson las que pueden ser crafteadas. Almacenan -BASIC_MAX_CHARGE mana, y solo pueden lanzar hechizos basicos. Hechizos basicos son suficientemente simples para ser lanzados por cualquiera y no usan mucho mana. Esto +BASIC_MAX_CHARGE mana, y solo pueden lanzar hechizos basicos. Hechizos basicos son suficientemente simples para ser lanzados por cualquiera y no usan mucho mana. Esto no significa que son inservibles en niveles mas altos, sin embargo; su costo pequeno hace que algunos hechizos basicos sean utiles cuando tienes acceso a hechizos maestros. diff --git a/src/main/resources/assets/ebwizardry/texts/handbook_es_mx.txt b/src/main/resources/assets/ebwizardry/texts/handbook_es_mx.txt index 90cea3cd..237a026e 100644 --- a/src/main/resources/assets/ebwizardry/texts/handbook_es_mx.txt +++ b/src/main/resources/assets/ebwizardry/texts/handbook_es_mx.txt @@ -173,7 +173,7 @@ Niveles Las varitas y los hechizos vienen en cuatro niveles: BASIC_COLOURBasicoRESET_COLOUR, APPRENTICE_COLOURAprendizRESET_COLOUR, ADVANCED_COLOURAvanzadoRESET_COLOUR y MASTER_COLOURMaestroRESET_COLOUR. Cada nivel es mejor que el anterior. Las varitas BASIC_COLOURBasico RESET_COLOURson las que pueden ser crafteadas. Almacenan -BASIC_MAX_CHARGE mana, y solo pueden lanzar hechizos basicos. Hechizos basicos son suficientemente simples para ser lanzados por cualquiera y no usan mucho mana. Esto +BASIC_MAX_CHARGE mana, y solo pueden lanzar hechizos basicos. Hechizos basicos son suficientemente simples para ser lanzados por cualquiera y no usan mucho mana. Esto no significa que son inservibles en niveles mas altos, sin embargo; su costo pequeno hace que algunos hechizos basicos sean utiles cuando tienes acceso a hechizos maestros. diff --git a/src/main/resources/assets/ebwizardry/texts/handbook_ko_kr.txt b/src/main/resources/assets/ebwizardry/texts/handbook_ko_kr.txt new file mode 100644 index 00000000..6071ff5a --- /dev/null +++ b/src/main/resources/assets/ebwizardry/texts/handbook_ko_kr.txt @@ -0,0 +1,239 @@ +PAGEBREAK +LINEBREAK + + + + +마법사의 안내서 + + + +By Electroblob +PAGEBREAK +소개 +-------------------- + +안녕하신가 마법사 친구! 이 책에서는 마법과 그 사용법을 다룬다네. + +만약 이 책을 잃어버려도 슬퍼하지 말게. 책과 마법 수정으로 다시 만들 수 있으니 말이야. +PAGEBREAK +목차 +-------------------- +PAGEBREAK +SECTION 시작하는 법 +Setting up +-------------------- +마도의 길을 걷기 위해선 몇가지 도구가 필요하다네. + +- 마법 지팡이, 금 조각과 막대기, 마법 수정 각 1개를 작업대에 대각선으로 놓아 시작의 지팡이를 만들 수 있네. + +- 아케인 작업대, 작업대에 돌 3개를 아래에 두고 그 위로 청금석 블록과 보라색 카펫을 쌓아 올리게, 마지막으로 양 끝을 마법 수정 - 금 조각 순으로 쌓으면 되네. + +- 주문서. 이건 상자에서 찾거나 마법사와 거래하는 수 밖에 없네, 그래도 가장 기본적인 주문은 책 주위를 마법 수정 4개로 둘러싸 만들 수 있지. + +그리고 마법 수정은 마나를 충전하는데 쓰이니 많이 필요할 걸세. +PAGEBREAK +SECTION 마나 +마나 +-------------------- +마나는 우리에게 힘을 주는 신비한 에너지일세. 보통은 지하에서 결정체로 나타나지. 마법 수정 한개에는 100의 마나가 담겨 있네. + +우리는 마나를 지팡이에 저장해서 주문을 사용하고, 주문마다 그 위력이나 지속력에 따라 사용하는 마력의 양이 다르다네. + +지팡이에 마우스를 올리면 남은 마력의 양을 알 수 있네. +PAGEBREAK +IMAGE CRYSTAL +LINEBREAK + + + + + 수정 광석 마법 수정 +PAGEBREAK +SECTION 지팡이 +지팡이 +-------------------- +지팡이는 마법사의 무기일세. 지팡이가 감당하는 한에서는 어떠한 주문이라도 쓸 수 있지. + +지팡이에는 많은 종류가 있지만 대부분이 처음에는 시작의 지팡이를 사용할 걸세. + +지팡이를 들고 있다면 화면 구석에 작은 창이 나타날 게야. 거기 있는 그림이 지금 대기중인 주문이고 그 옆의 막대기가 다 차야먄 그 주문을 다시 쓸 수 있네. +PAGEBREAK +SECTION 주문 +주문 +-------------------- +주문 없는 지팡이는 물 없는 호수와도 같지. 주문은 두가지 형태로 기록되는데, 첫 번째는 영구적인 주문서이고 두 번째는 일시적인 두루마리라네. + +주문서는 아케인 작업대를 이용해 지팡이에 주문을 저장하는데 쓰이네. 이건 잠시 뒤에 설명하지. 주문서는 전 세계 어디서든 찾을 수 있네. 주문서를 찾으면 간단한 정보를 훑어볼 수 있고, 책을 펴 보면 자세한 정보를 얻을 수 있네. + +두루마리는 좀 다르다네. 단 한번만 사용할 수 있지. 두루마리도 세계 어디서든 찾을 수 있지만 종이 한 장과 실을 사용해 직접 만들 수도 있네. 그리고 아케인 작업대에서 알고 있는 주문을 각인하면 되네. 이때 마법 수정으로 마력을 주입해야 하니 주의하게. + +대부분의 마법의 문자들은 배우지 않은 사람은 읽을 수 없네. 주문을 써봐서 알아내는 방법도 있지만 위험하지. 이럴때는 지식의 두루마리를 사용하는게 좋네. 이 두루마리는 마법사와 거래하거나 여러 유적을 찾아보면 있을 걸세. + +두루마리는 한두번 사용해야 하지만 지팡이의 공간이 부족할때 쓸만한 수단이네. 하지만 두루마리는 몹시 비 효율적이라는 걸 기억하게. +PAGEBREAK +SECTION 아케인 작업대 +아케인 작업대 +-------------------- +아케인 작업대는 겉보기에는 인챈트 테이블과 비슷하게 생겼네. 마법사는 여기서 지팡이를 강화하고 주문을 저장하지. 사용하려 하면 다음과 같은 화면이 나올 걸세. +PAGEBREAK +IMAGE WORKBENCH +LINEBREAK + + + + + + + + + + + + + + 아케인 작업대 +PAGEBREAK +SECTION 주문 저장 +주문 저장 +-------------------- +지팡이에 주문을 넣으려면 아케인 작업대에 지팡이를 올리고 주변에 주문서를 두면 된다네. 한번에 최대 5개의 주문을 저장할 수 있지만 지팡이를 개조하면 최대 8개의 주문을 저장할 수 있네. + +지팡이를 든 채로 주문을 바꾸려면 쉬프트-휠을 쓰거나 지정된 키를 쓰면 되네. + +SECTION 지팡이 충전 +지팡이 충전 +-------------------- +마법을 쓰다 보면 지팡이의 마력이 부족하기 마련이지. 지팡이를 충전하려면 아케인 작업대에 지팡이를 올리고 왼쪽 칸에 마법 수정을 올리면 되네. 그러면 100의 마력을 충전하지. + +SECTION 지팡이 강화 +지팡이 강화 +-------------------- +마법사가 지팡이를 강화하는 방법에는 두가지 종류가 있지. + +첫 번째는 등급에 맞는 마도서를 찾아 지팡이 자체의 격을 높이는 걸세. +두 번째는 특수한 도구를 사용하여 지팡이의 효율을 높일 수 있네. 마도서와 도구들 모두 유적이나 마법사에게서 얻을 수 있네. + +특수한 개조는 지팡이의 어느 한쪽 능력을 높혀주지. 같은 개조는 3번까지 중첩할 수 있고 최대한 개조할 수 있는 횟수는 얼마나 중첩했느냐에 따라 다르네. 또한 한번 개조된 지팡이는 되돌릴 수 없네. +PAGEBREAK +SECTION 꽃과 플라스크 +꽃과 플라스크 +-------------------- +전에 마법 수정은 지하 암석에서 얻을 수 있다는 말 기억하나? 사실 마법 수정을 얻는 방법에는 한가지가 더 있네. 지상의 꽃들은 가끔씩 마력을 띄고있는 경우가 있어. 이러한 꽃들에게서 마력을 추출하면 마법 수정을 만들 수 있네. + +혹여 이동중에 마력을 충전해야 하나? 문제 없네. 마력은 병에 담을 수도 있다네. 유리병 한개에 8개의 마력 수정을 두르면 마나 플라스크가 완성되네. 언제든 지팡이와 이를 조합하여 700의 마력을 회복할 수 있네. +PAGEBREAK +SECTION 등급 +등급 +-------------------- +지팡이와 주문들은 4개의 등급으로 나뉜다네 : BASIC_COLOUR초보자RESET_COLOUR, APPRENTICE_COLOUR견습생RESET_COLOUR, ADVANCED_COLOUR숙련자 RESET_COLOUR그리고 MASTER_COLOUR대가RESET_COLOUR. + +BASIC_COLOUR초보자RESET_COLOUR가 사용하는 시작의 지팡이는 BASIC_MAX_CHARGE 마력을 지니고 있네. 초보자 주문들은 금방 익힐 수 있을 정도로 간단하고 사용하는 마력이 적어. 하지만 그렇다고 해서 높은 수준에서 쓸모없지는 않다네. 특유의 저마력으로 대가들 조차 유용하게 사용하지. + +APPRENTICE_COLOUR견습생RESET_COLOUR들의 지팡이는 초보자들의 다음 지팡이지. APPRENTICE_MAX_CHARGE 마력을 지녔고 초보와 견습 주문을 외울 수 있네. 여기엔 유용하고 적당한 주문들이 많이 있지. + +ADVANCED_COLOUR숙련자RESET_COLOUR가 된 마법사는 몹시 강력하다네. 그들의 지팡이는 ADVANCED_MAX_CHARGE 마력을 지니고 대가의 주문을 제외한 모든 주문을 외울 수 있어. 이 등급의 주문들은 적을 직접 파괴하고 초인적인 힘을 줄 걸세. + +MASTER_COLOUR대가RESET_COLOUR의 지팡이는 현존하는 최강의 지팡이라네. MASTER_MAX_CHARGE 마력을 지니고 모든 주문을 사용할 수 있지. 이 단계의 주문은 몹시 드묾어서 찾아보기도 힘들지만 그 여파는 엄청날 걸세. 주의하게나. +PAGEBREAK +SECTION 원소 +원소 +-------------------- +거의 모든 주문들에는 각자의 속성이 존재하네. 이에 알맞는 지팡이를 사용하면 높은 효율을 보일 수 있지. + +FIRE_COLOUR화염 +아마도 가장 파괴적인 속성이 아닐까 하는군. 강력한 화염술사는 적을 불태우고 자연을 파괴하네. 화염 주문들은 불꽃을 내뿜고 지속되는 고통을 야기하네. + +ICE_COLOUR빙결 +서리와 얼음, 그리고 모든 차가운 것을 포함하는 속성일세. 적들을 얼려 둔하게 만들 수 있지. 아니면 아예 얼음에 가두는건 어떤가? + +LIGHTNING_COLOUR전격 +위험하기로는 이만한 속성도 없을 걸세. 번개와 폭풍을 다루는 속성이네. 강력한 폭풍술사는 무시무시한 번개를 마음대로 다루지. 이 주문들은 동시에 여러 적을 상대하기에 알맞네. + +NECROMANCY_COLOUR사령 +사령술은 어둠과 혼돈, 언데드를 부리는 마법일세. 보통은 사악한 이미지가 많다마는 꼭 그런것도 아닐세. 이들은 자신을 도울 친구들을 부르고 적들의 의지를 꺽어버리는데 능숙해. + +EARTH_COLOUR자연 +자연은 매우 다양한 요소의 집합체이지. 동물과 식물, 하늘과 대지. 자연의 마법은 그 유형이 몹시 다양하다네. 아무렴 모든 것은 자연의 일부니까 말이야. + +SORCERY_COLOUR신비 +이 신비한 힘은 자세히 밝혀진게 적네. 빛부터 중력, 공간까지 뭐 하나 쉽게 설명할 수 없는 요소를 두루 다루지. 그래도 확실히 편리하기는 하다는군. + +HEALING_COLOUR치유 +치유의 힘은 자네를 보호하고 다시 일으켜 세울 게야. 대부분의 주문이 생명의 보호와 유지에 몰려있고 공격 능력은 매우 낮아. 하지만 일부 언데드에게는 치명적일 수 있네. + +물론 이 모든 속성들이 엄격히 구분되는 것은 아니네. 어떤 주문들은 다른 속성의 힘을 쓰기도 하지. + +운이 좋다면 원소가 깃든 지팡이를 얻을지도 모르지. 이 지팡이들은 맞는 힘에게 강력한 조력이 될게야. +PAGEBREAK +SECTION 마법사의 방어구 +마법사의 방어구 +-------------------- +마법사로서 싸워 나가려면 그에 걸맞는 갑옷이 필요하지. 오래전부터 전해지던 마법사의 방어구는 평범한 갑옷과는 다르다네. 이 방어구들은 마력이 존재하는 한 찢어지거나 파괴되지 않을 걸세. + +마법 수정에 4개의 실을 둘러 마법 천을 짤 수 있네. 이 천들을 이용하면 마법사의 방어구가 완성되지. + +간혹 특정한 분야에 전문화된 마법사는 그 분야에 도움을 주는 더욱 특별한 옷을 찾아다닌다네. 물론 이런 방어구는 몹시 드묾지. + +전설에 의하면 특수한 마법으로 이 방어구들을 더욱 강화할 수 있다더군. 믿거나 말거나 말이야. +PAGEBREAK +SECTION 마법사와 탑 +마법사와 탑 +-------------------- +두려워 말게 어린 마법사여. 이 넓은 세상에 어디 마법사가 자네 하나겠나? + +세상을 떠돌다 보면 뾰족한 탑에 사는 고독한 마법사들을 보게 될 걸세. 이들은 홀로 지식을 탐구하는 이들이지. + +자네가 원한다면 대가를 내고 그들의 지식을 배울 수 있네. 물론, 그 반대도 가능하지. 단지 이들은 좀 너무 혼자 있어서 그런지 꽤나 괘팍하다네. 절대 이들의 집에선 아무것도 부수지 말게. + +그리고 불행하게도 너무 오래 혼자인 마법사들은 세상을 배척하게 되기도 하지. 이들은 옛 향수에 빠져서는 모든 이들에게 적대적이지. + +이들은 위험한 존재일세. 하지만 이들을 무찌른다면, 그의 지식은 자네 것일세. +PAGEBREAK +PAGEBREAK +SECTION 조합법 +조합법 +-------------------- +PAGEBREAK +PAGEBREAK +조합법 +-------------------- +PAGEBREAK +PAGEBREAK +조합법 +-------------------- +PAGEBREAK +PAGEBREAK +조합법 +-------------------- +PAGEBREAK +PAGEBREAK +마치며 +-------------------- +Electroblob's Wizardry +Version VERSION +For Minecraft MCVERSION + +디자인, 코드 및 텍스쳐 by Electroblob + +마인크래프트 포지와 MCP에게 감사합니다. 이들이 없었다면 이 모드는 완성되지 못했을 겁니다. + +또한 마인크래프트 모딩 커뮤니티에게도 감사합니다. 문제가 생기면 늘 대답을 해줬어요! + +마지막으로, 모드에 도움을 준 아래의 각 개인들에게 감사합니다. + +코드: + +- Corail31 +- 12foo +- Shadows-of-Fire +- HellFirePvP + +번역: + +- 러시아어: VilagVil +- 스페인어와 멕시코 스페인어: MadWrist +- 중국어: ZHENGLOC and dragon-evol +- 한국어: rewi_wire + +번개 광선의 음향 효과: OhhWowProductions diff --git a/src/main/resources/assets/ebwizardry/textures/armour/invisible_armour.png b/src/main/resources/assets/ebwizardry/textures/armour/invisible_armour.png deleted file mode 100644 index 892b9537a21e50551194322f4d148dfdddd39f2b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2411 zcmeAS@N?(olHy`uVBq!ia0y~yU~m9o4mJh`hEb}-In zU|`@Z@Q5sCVBi)8VMc~ob0ioT7}!fZeO=ifGI0tDiOQW+7GhxF_~Gf|7*cWTZFF>w zOt|E~XGLY#cE_#XURIVIq`tIsqwH?4rN>y0iacd>-C{b$tB-}%iG?+=`N^K8i?l?( zGBPRDN1CzgeGeU%OR$eRRIUeE-%q7)5MxwP|7&b&GE z?#N>On>(0`Hw%_-~SPBH|AkpdaRnSZrhVT%fJ6y`{d7d{WA+Dvd8!Pnx!&s z?8x}r9WLvFrK)`{8kBxoBEG}l54h07RR-11t6I)a`BO}`s zST^q3*HqhS@$9)iBg4F1AJQ{cvAJG8aIit6;{lJuMV^Ms3$m;ZO=5AqJ~3Q`r9+eP z(C2^>S!3?myal{PQX;XgaaR|vIB>H1SK+H0i7m`FPLo=G%S#_G-v8b`VB$u7!Q(%E z-v01YKE}cOwpk%E6ur!z7f{w{a$Huv-o&n|H_2|0QzbWA;?RcH6t z>{BJH&G|^C2bGKr3$mV73oB1>+rY4{K3`(hvZfD8Z1=v$@sz!9op%4gr(05C##-N0 zZV5gJwfWy3UXcGkmZ9PPxtJrh@-{7BeMP0EBabL4-HMJ@WSM1Hn#p*1{eD*0a78Yq zlEV$FGBcD|Dt()my`Hd{DQa==L#9X0Bp=0pS~F_bw`GS4zkz2ywOuWK{9V@7T-izU$G2P|?%b*$fR=d%DE`|7`o} zy>vobvh8+Lmun|1Uo#%JPda};e(v_;oa@i;4GR4G;NTHgon@O}bhK@laW3i6g?6uX z{&&AB{W{j(^@_(n+M;LXM9(k1{8vraW!yMY8!UED_NKz>zkL}m?#|}9T3zu}ylqp~ z_e7!9yv%&1^Vt|uo~pJixqCxYdV^q0^xSRF7;Zc>FAo2h|1;_C%<|7)Yo2j=Y&d(& zM6_*^x1xY$fXnhHK@t0`Lhmtc`V>?e#Z|@>t-zrEn8Beb_kqWmn)6H7{B(H2(7`Rs zFu^OPA#2A)w$-I!yVo?V5QwnSnv=_TaOOnMGd(_Gd-vtnoQOIbYECMcMCT?J--A%+hz>1LO76h<-%l^E zzv)w+6LI8ImDpQdMV7AzHcgI_^Wy`cJGdF&nk^??EJepP2k9$kTaYw_ZnKc**l zt6lHaocz+4^|3np$F=PuE{CtWHi^99>*J03Zg*NkwCl6lhf?khJei)>#UTP`?aaE` z-rm|8bHFe@_|Ch7E5Z$)s0$RaI;vmV#TaDy;nSk{Io8?L<^TQ#ZDgLi*pfl|hsD{s zbZ^IXJ)_Ydz>GHnofxogYC8RePTU(_b{WZl=|H7J; z3X?qjl9f{z)fY$S$DX~RtFta8Ah_JEE{`+R=1**a;xeJH2biDvN17EL>9tf3sALRV zI_)sm)$H?C{ZH55=NE}8-WDj(@Zvk$itYN-g||Ij9AEY1*VL&V4f{X)bu%i@W))#Q z^?V;kAH$P7EL*0>ZCWeNbw-=NZjXSUxX`+joDS2vUo-mg{+xSzRbq-=}oE%x8|xn_fZs! zbSREq|2)y_?9Y$?v+lH~wspJ2{FPwXk+G$t%})B|7In4{Q(dZ~ONFOwW++qn+@Ey) z`@a-JH_80}$JS3gWB+PbU$>j%yjr%#_`b(IXW(#OWG<~h=WT;WWYNJl(b@ z`l*rMTj`TaGXG6VIozbgquHRAI)^pz#3ozmHD;2ZChxdnUG+v<-YNb|^0Vq+;i;QF z)?bMF;uZIbvFU5VJr8<*W zZ&-5I?22|Ne$$Zse1%Bu*|`gg7Kd>!cx#ZgYl`MJwg~U%9&5ffn12#W*zKHGaXsynr$PfCtOlkY;a_15#tK7f?Y;SPChwA9Mo z`W)-3Qpxq_0uTQ`?)hta!keql!@T0>SVwOw-eOUHZPDV!=)=(td#&8pT<}qxF=L~$ n!-bVEgAVu351PB~Kco2dUy3?5yjvL<7#KWV{an^LB{Ts5Xe@i@ diff --git a/src/main/resources/assets/ebwizardry/textures/armour/legendary_wizard_armour.png b/src/main/resources/assets/ebwizardry/textures/armour/legendary_wizard_armour.png new file mode 100644 index 0000000000000000000000000000000000000000..71917bbb7c21c13060bbb21a6fd247806196b750 GIT binary patch literal 12450 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 Slo=Qp7(8A5T-G@yGywoVLe$3q literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/ebwizardry/textures/armour/legendary_wizard_armour_earth.png b/src/main/resources/assets/ebwizardry/textures/armour/legendary_wizard_armour_earth.png new file mode 100644 index 0000000000000000000000000000000000000000..81ed19477216aebb5c0f64f9e0cf1faf386ffcb0 GIT binary patch literal 13287 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 I=akR{0F=AJA^-pY literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/ebwizardry/textures/armour/legendary_wizard_armour_earth_legs.png b/src/main/resources/assets/ebwizardry/textures/armour/legendary_wizard_armour_earth_legs.png new file mode 100644 index 0000000000000000000000000000000000000000..c7c4fb3eab1cf92abeb5c2a8f34ea4d69972ac9c GIT binary patch literal 1726 zcmeAS@N?(olHy`uVBq!ia0y~yU~phyU{K&-V_;xdG`FsWfq|91DkP#LD6w3jpeR2r zGbdG{q_QAYA+;hije()!*4yytN!sc>f73-HowyY_ryceVz3Dh@K6Ba|$^P_r$}3O# z?>f!9R!nG)vWm>J`1-0J%;KV6ik+#ttHjrZ1a*qet+~4{+B^K#`P!wQIp51aQQTMC zAz&D_Z|^IcU!p~oJR6cbZ@E`)sC)Ay`9)2I@rl!)Kb3v?WO(GG+VanGrzFEK?|wQ* z{Et7tIBam-G@^@l)u}p_+50D3-_6t z!(5-cv>6P0kKUicLtB4#EvNu9xpdZ^m16FeF!%Ed_vRAz(J`nprGLJ4NkG*n0j zm2BaM1K;GWbb4$~t(dIll(|eZc==hI(`))7ioZR1^y=Bo?(5ds?N|HPTof+8zuB#Q z>(Pi?Ro@bLlQx?RZ@JW|bM8Qd56iJ!!-j^w?#>=kUh(aPr!Shbg*)!6WP>-y{K zEMiU4Gf#M0B&y16DJgk=sa;{G#iWq-rw=0&#Ai?c+>q`b_v*F6Lc1=XE2V7emqnY; zesf{IBs=M1$5y@17Pbep`y{({d_Ud2U>X$dw2hG|VeOQbmJ$g^oG$%A`fP5URk(Gtt;YdkA{l|i;B&M z=(gOJo&^W&e3Xq&U0)@3H>~8h!G{?eKD=R8*w8FpKGSzYuB>-5z-*KL;5)3~_4@IX8VkD0TNNjSTQ90OL2j?lJfOC2ZL^Cz)@>^%)&`+${eivVueM<&H+n-;+ve z*kH&Y9aQpT%3?u7k3Bp4yOh_iU3_A9%!b|9SDUTj6YETAEd9ruwsgPtltm&h85kJY zlDyqr7)~%eWnk#%=h9C&xNJXev z@NrhkoMpxvdoL1-i1p}OCCpFx@aN*qJ&&UTUgqY%UG_43tL6GFkE1TU zTy}Xnzsup!XQjIeIUihoQt|J_p&5SWc8o>R?ul#eFmB4LVai}HsbxQ5Z=EW*(8HXe z;n5E!vkwa{r8~xba)~K!TqRv!QI)=ZkMo}w3}zn;rueKbx&3Rea!T{2IQ6>eTWy$p mC#qR~^9-wwS=XE2B|LG@BG0!aF8vG)3=E#GelF{r5}E*BJ0&*& literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/ebwizardry/textures/armour/legendary_wizard_armour_fire.png b/src/main/resources/assets/ebwizardry/textures/armour/legendary_wizard_armour_fire.png new file mode 100644 index 0000000000000000000000000000000000000000..972abbc6fa75aa6d48bad7500e1faf892ae06fd2 GIT binary patch literal 13116 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 AFaQ7m literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/ebwizardry/textures/armour/legendary_wizard_armour_fire_legs.png b/src/main/resources/assets/ebwizardry/textures/armour/legendary_wizard_armour_fire_legs.png new file mode 100644 index 0000000000000000000000000000000000000000..a66695791418aa99c98b79f028ddf0f37b5fdcf6 GIT binary patch literal 1703 zcmeAS@N?(olHy`uVBq!ia0y~yU~phyU{K&-V_;xdG`FsWfq~_FRY*ihP-3}4K~a8M zW=^U?No7H*LTW{38UsVct+(OPleE=&{-%pYGC6S^EIQ&Gded>*eCBr>k3XJSovpU= zl>aQF3t5UsEQKCy`1kAbVfl&`S)7quriFPOnH-&W^1{lG-|j?p{k-!0`NXsDN{|i zn(%2>iho+NAf0X9gRBPAHjBHp3yt%wKl84dQ7L31d{83sh&Sha&ibHtZFkCF2;~~Q z=GFc&wT$6V@7X)+7P2~>(D!-zpxSH43`NGVU&2%(WPreNM=&2w_cFf#ZBKeg0HPvfb!kAGtMFSVZ?TK4XKf?m!my=QTizgxCuK6iQOeBs=o-prKa$Jkm! zbwh8bU+Ta8!Jqd}{tJ8aE#)jZTeY6)#I>t?0M5`J%kG z+1j(#UC*)(&)9$D$3oX>a!VubS#5k_6PsmNW2jY^nOk+RlK1%03g1trHKi%`L4}q3 zuKw;>Yi2c1a;@^gG(R)(O=UVMg@xDR3RGMqA4PPRmo*#C;4{D7>t4P!x_7srr}LrJ zf;kRBuD>>z-aZg%AO6vZYhA@&)0%=evUi;&FU!hpS!XhLVb^aa&P}&+w%+TF7K~EO zD+%_$F?-j##C03GYlXLay^RTbu&;n~1LIM>w!N8~vd%Hz>y=){y5XPP!4Jk6@e_IN zo4<+P{9v1r|FOCEcPi(@>clUqY{nDLZ`(Nkneo-Pd&?b*Qrs6vi#23jTevy>y@h^J z=_+sA=to@B{KYGqf{!dusEt$8`^@jWCGh~uQs<3{`exhhDtot>UKg4ZV8gZDwmw$o z*rmJdDk^V+vW~pf@1H2ZzRn|V#@B_%S5!W`wCDYvW0o6!9Jv_69I5zqby0pjP$fN-2ra$Y%A75;VJH}MN#WRctMYY*4Q z{Bb+}zk6kax`N{+8?O@+aycALAKt9_y5{-b%#YR2lWn{LIDbFA`MW(_eouYbzl|pz z*ED=TUapf^{eR_qg{&{86XvY*2#H}WJJRftqTcs0S5dBC>urKW+U75{$2E)<9Ueuo zZ9BirYQwV0|8`i`-(zzTa1#2T_m6EZ%c3fE;|q)o3=C{Z-tI08CmA9c_}@*jtY%EalYaqsQ)y?sp% zBCY2oBBx4hZaFgl*r9Vjgv$1{@^62i@+Q|rZG|D5N^ru$Ud_F5SPz=vdKGr!;4$T`ViIv}(40 zPSEk*ZpXN#xA{ZH9mbIDc8q(NSM6hdao$hq`-JBYex1txCD6w{*=|zdBB76G*hB99 zSYa=`{!iPFtBi*}esJ}fT@vgb&>V7JSbnN4ldIrKiHBzc<`q_&?bFa(t~oFL>%qP8 Q3=9kmp00i_>zopr0C2q^RR910 literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/ebwizardry/textures/armour/legendary_wizard_armour_healing.png b/src/main/resources/assets/ebwizardry/textures/armour/legendary_wizard_armour_healing.png new file mode 100644 index 0000000000000000000000000000000000000000..5d4c2faecdbbd8074a6e6b0711c09bc971bdc1be GIT binary patch literal 14008 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 HDWM4f)LU5b literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/ebwizardry/textures/armour/legendary_wizard_armour_healing_legs.png b/src/main/resources/assets/ebwizardry/textures/armour/legendary_wizard_armour_healing_legs.png new file mode 100644 index 0000000000000000000000000000000000000000..da815502e7eb131d8dac21c47ea3dd90a1b9077c GIT binary patch literal 2067 zcmeAS@N?(olHy`uVBq!ia0y~yU~phyU{K&-V_;xdG`FsWfq^ZoDkP#LD6w3jpeR2r zGbdG{q_QAYA+;hije()!*4yyNO;0uW{-%p=W#Lw2Ih{B`DT{sYAG1XTR$B zr)j;eSF)v~k1cQ0|3B|un#at%HMJ{a_1m z`)o$LB=Yy!ueSZn{_AONqur#8x_AD&f5H&c)9izjn78GdX{?~Rp^DtO+weNOt>i@|ZWGN0?(VyjH|H(cL$ z@SW6oo_{>9yIvVDtULJPrTS0HGWLc2QWv9*>*W}-t7`YyB|P6Zd-vUIy+Ms3zWssM zl^<;}C}i@oJFS&>)c?Y@;_^GZYI+U(4n8}wSE%%q!|jz9mO1*B-Rl+$(Yd+l(cI6c zYJN#&zpMP{%b53R&4P6Gya!p0rf%hRFP+lw*L{obXsFFSbjC-(E#l+hxpmimmcN^> z@Vy{*5yR%Y5svF+_&7|Pc2*>baVXXsOl^L@^K$pK@7f)y1{&s)v=kJkNL#HtTM@5mEHV9^@Phs zZ+cC=((|U(lq+v-;COh7D@(vZVYNu(|BTEJ3l()#J3U0Fs>QlJjaqdjYO7nH)TyYD zEvvFFuUlNG?HiSQE9!ObmphW0K2>jLRlVNZ-{{Nk!oNmthT*X@lhbD!y}oiYZGQ5> z+OWt?uP$8;i%))jR{G)o*Vne(epf9a8FR9$Gc-8+TCPRS*_++n;o@<-d&Ziq;aW}B|Sk$oawO?&w+)-1!bmMs_exFZ(cQSax#ig z<}5N}O-|S#ky=<)`2E}+{Yvkke?s{`t)B%2eBYm-$6Cr?Z2#$-@U?FiqOJUnf~}1& zkMUTKB`PTyDnnF zb0xXc)$4R!+x;J!N+=ffKiaZk-|ai<_kG`=`n`*FTemRRt-W`SwZ{Hm6?h@>);qa* zvC|gsIq~4~$A5P#w`N>@nOc*hEV4|*_{gUtt1iX#2FIIjPuo*%ekIODYwf$x>6hoM zYP)lJ^Sj2b*zfc1nd#2XI$>$GUcip=^|K@UvOoV;zO}gGSoM!{Z}*m(C>XosJ$rk0 z!dkay&pa$@BW0C!kJcUZ+}bO-B0XWnwxuRpcNGT8-Dcl3Rk2th-Pirwq2%1}mgV!k zZtq;awJ=HXqY?KRDbd|hUz=n~AMa$)R8cg27^wZ}#I~*J#{9l%3-)D;dq#b`=W+aO zVD&>|71^&_U5x$a*8iGoSITgOcPaBB#w*8``NuDf4m4o%UmDK6<&B|I# z#TDOOPhM-fo84`q{lW1v+o@%T|9iF17pP!cu}`ajJ*P;u!_nc*$voMWMPjx2-q-x{ zqIDgrvpK(AKOHCUuUjP zcd=L4oZ2mV^!Ou|9byT$1ihIHnigJeo59@*Qs0+m6>=?AqpW zJzp=?*HjBh!T5ryg6~51lMI^x=uYy0*Z?7>S>0bIu8|XNIx9N{c9Bi+bY5ZFB7<^&_bR*wH4vp?1b7ka-x@xW?6U57YdoxAfn)$Gm6l`mDk$1mqtu&Mf&{tcC+?<&W97BVm}uqAoByDFdh=n3au}Rpp2Bgy#$ljCP(bjv*QM z-cB>jJLDkX`d`V+MZ40+%2N?y{`a8{Je!{b*q<~+bYs#023a%TR8U-@A zmpiz$10xdZ;@Q^>YI6k(SjS22d?B7EBsUV_V40@ z#mvXDqy8pe;yvUR^ND%tmVI~UZ>;`jGuM~lv8j#5veI37N+Hdw=B=rl_Lgf&>kU0c jzSl=y7iHE){b7C<+%KNnz&4$Mfq}u()z4*}Q$iB}id@%Z literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/ebwizardry/textures/armour/legendary_wizard_armour_ice.png b/src/main/resources/assets/ebwizardry/textures/armour/legendary_wizard_armour_ice.png new file mode 100644 index 0000000000000000000000000000000000000000..2ee99037c7916363fadf7054ef05b92eecf92e35 GIT binary patch literal 14111 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 Mr>mdKI;Vst0KQ2zRR910 literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/ebwizardry/textures/armour/legendary_wizard_armour_lightning.png b/src/main/resources/assets/ebwizardry/textures/armour/legendary_wizard_armour_lightning.png new file mode 100644 index 0000000000000000000000000000000000000000..abd9333fe6df7c68f240d3a49f389efbf261ed7a GIT binary patch literal 12621 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 literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/ebwizardry/textures/armour/legendary_wizard_armour_lightning_legs.png b/src/main/resources/assets/ebwizardry/textures/armour/legendary_wizard_armour_lightning_legs.png new file mode 100644 index 0000000000000000000000000000000000000000..2ce2af0cc141f7b4052aa8536f85df60cc74fffa GIT binary patch literal 1749 zcmeAS@N?(olHy`uVBq!ia0y~yU~phyU{K&-V_;xdG`FsWfq_-KDkP#LD6w3jpeR2r zGbdG{q_QAYA+;hije()!*4yyNNl!F*{yrBeX5n7g`gnupqI`qn^VwgXirTeGc~_Ov zv-CF}%^L+C*?MYR{`K2^$^L@Cz3W1b#H@bRy822`vGeiu$G>L0)OudIuBiUd@7*7# z#M`Ct7)I6Yd9~}Q^s%R;4k1}7|^9z7yHZ&!F?#DS^OQI`H^t6MILm)V@2_M2z-mp63` z=l36Ym$jW`f4fp_755AFo_B?l&Tq8l*t@kOZr9Jh>=&O4*(Zt{+9uhSUGHMj^!>hU zUG&kHjvJW0>@II}I_!U8dvW-kK3%>ByMt-RZG}QlIasf_u*A*r^_FHfADzln=h>f6 z)Et|md)dqfwwsI@t2ZJZsy`+P!8QdDxyFcyl9R_b+Ex@v5)7 zb~eUOo@l+~OW#zf&EOIdoxo!#v13Yv$IDG~dO0kteq?U2DLyI7Gr?ot6s9`{N(VPR z-)r_vLiVQ4Ps5%oOiC?Nd9NrmID~03{onZL!$LJ3)y|HtPVcG9*0{Qc`j+=)9SigE zIeTVpRPnb*k6t}{cQyL#)QN|dWNi)Ed+nB#SZ=^wgWZmcw$8Kueraj;_IG=~nLV&u z%p+-)^JB&0vo@7Vf0p}sUrwK!d$CD-?WUBMo1U&-C-!0M0}aK6i4Ox8+eYq=tUWJP zoAB=Xnu}*|rLB>%tWM=UoTjgpv0V7(oW_kY96h(w82ILzr%w;otTf(kxjV}(z=JJY zW%eA;*@gxYVyT=}Mc+@|(XaFls_WkVN3=LI_jBswB|Bj zCeAJ-%`$EKo80-H_wz2#*ZL8Ev3^}fI!m`|-iZgcQZaEH>+HRG+kWpS^xGS+{>x(POS7dfR=vnyW!soS458vnITCR^&KGiYd+qU??jEAn( zQ;waFJAHIVCeM*y2LfZQKR3MO$nP>;q-Pe(`1*EvFxmI{a2IzE~wbc&qH=O_Q$MjJXZQm|t3u9C zFS+>BU;O{hR4xOa!!R`2q~)q?lAY{M_PKHKuNZfG$G>=A^+r2HdYZ}0*GFSqW;TRe zvR3$-=bAjf;mCUitIrGtH*PaDIBk6LbK<)5YRQZYVdWWj1nYiXw@TO?#TRfo{vz?E0? zdw#y$=+9ufIa0URy5Uv*bcTD3p0^plq`O;1Tbz?(D6k4sG)kTECGGSyEy43K3!0A2 z|IGaHr1gS SuaJR(fx*+&&t;ucLK6VN084NH literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/ebwizardry/textures/armour/legendary_wizard_armour_necromancy.png b/src/main/resources/assets/ebwizardry/textures/armour/legendary_wizard_armour_necromancy.png new file mode 100644 index 0000000000000000000000000000000000000000..f90e785c186fad065b074f186f14b60078a3e5db GIT binary patch literal 12490 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 literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/ebwizardry/textures/armour/legendary_wizard_armour_necromancy_legs.png b/src/main/resources/assets/ebwizardry/textures/armour/legendary_wizard_armour_necromancy_legs.png new file mode 100644 index 0000000000000000000000000000000000000000..ebb496be24a7fbdd3bafbc09d2f168fd1ec9406b GIT binary patch literal 1926 zcmeAS@N?(olHy`uVBq!ia0y~yU~phyU{K&-V_;xdG`FsWfr0gCRY*ihP-3}4K~a8M zW=^U?No7H*LTW{38UsVct+(Nko8GAL{7n~)Y-+u5plC+ORN0iDmKXNb-k*DKO2||7 zvaP+29EE)#Ulamupl;OlE2 zZBe+vs5(Eh>-GoXEpP9LZcpxJUf{psW?{d}RHF-gS|%$4FIc^IWLBHDXVb&EpHI~M znxlK&=7%F=URTb7bhWY#h6kh;TifR@+?;3onzv|;4dagK z>s@5KEFW=j-5yziw47((go6}X9vute+xOhhKPrB`uTHb0rGd5CjdlM5F1E(icJrU- zvE1pk>+sB+dt3~H*Tf{8dD!$+#e#O}q$@M^@zqJ`oR2ADXI7b{zLded$792r%JsdL zZtiB@btTGM8#oeEnN2wqCWLk!s9$4Ivx3vxQ)yAsqoAdl*@1zfm**~?wNX?!*tmH0 zwK;ot?AW!l`fFHm>Jo#MQM#e)w{B~5l@2jKlQ$t_?elYcOJ3euTfKfS?~d~t&TV|s zcCRvw{pWG~UwQe`m&o+!Ef2g_>qPF#`MGK}YmKgjmq$iK#gz>IYk6V!H@Ur^@!KxD zWb-yjZTE9=k0*|ipd-%oc$;K{^YgPepN4qdJCl2E-7GCRSmA}$wmipd3d&m8rU1ILG;zb`6Gu$5@`|`*k zsrkUCX?x!qzubQR<$SFl@fYjYWu&uotLB|}U@H|9$Fa`do44)vPK9|cJ9~BK?>-P; z>eQsN)@!wZ&6k>WG0WeDO^hwsQ=7fFbxvAk*{VBTJazxBUeOO_J2&y>_u{KvwhtO? zVsBNPz1wAU&S0(b6;~N`%|}XUb-7>L)@*M(nH8gc`;pb8H2u_Ty9z#RTeeR$L(@M#Ev0L12RqEVbED&Rj&9h-_hZ{6y#s%JZ`*u1 zB$6k^Y?pEs%)h8a_PB7189LW`mV{J%yLPkg*!4@* z>BT?1_kX#1+0N>gyLt2ErTlSjdhM!Lx(?Udm0eoTDtXRghtOjmk?dODr7stsxATtT z-YUFDfU#k-vGyF{d7WYc>P{S242<+viMHHIUbklFtjJ|uxlB){6|eFsO_k}|8Kqus zal0cf@FLS42}YKT$A>r;YwWSHa;`tX?SFIM!+BO|N(XP=?6f}LWgJpIN1~-biEo2f zyJ7b6^b+Gk$;OfI>n7aP@>%vI!7ACXIWWBR^wKR|TNNT7ttec<8+n!4tS@mx;p@s9 z94nqVO}rP}{(6e&qSJ4+G)x~<&pB9hys%f+;oqN+FFyYY2~2;``DBiaWB010Jx)x0 za*>_>76%NTv`luAnp5|@!F~Uh&Z@F-o)(`8EMe>!hyG6t-NSW8p@qBXWT0i91*3tG z*tYgPOuiod)w^#mvMjr3ykRSs*7H4LUVC~k81c$}5S$^^mf>7_rBr?SHCD?r196wqE;UE;8qH$wwi_eg*~xwj^(N7lxG# zdl~+xd^i%uz`(#+;1OBOz`!jG!i)^F=14FwFtC?+`ns||W@Y1LvbM_NzRJMB=;Z0* z7?N@C?ex8QhYUno`xV!91h{-`3Xo{fRrct4yZA#v?Ub_jw-`A~8K(06;Z#&|)tK8M z#?Kj27clIl@D{wTy(4w3TWd_HtANMZ$c&E1OX+!7jH4%3l2V+Vc}{V5{Hx+gpw2H*C)9GI&|#9FlnH zWA1i#i&w4BuQ7bw%|4^#HP?ix>=DrnrN`4h@4dzxa`zY01okO+nXk;BYZ0aV$eV$o zT<&0nuvP5^siVuC?tE(4Wmc!i^lg6s^39wHdpg-wGv~hBIr~dVhEUko>__62>m9=0 p@F{Lvo%~38S?NwwJMB6Kx0BO~-KOP6GB7YOc)I$ztaD0e0sy@zg6{wT literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/ebwizardry/textures/armour/legendary_wizard_armour_sorcery.png b/src/main/resources/assets/ebwizardry/textures/armour/legendary_wizard_armour_sorcery.png new file mode 100644 index 0000000000000000000000000000000000000000..1d9a9f7cd929ab35ab1bd03ef558745546a5e4e8 GIT binary patch literal 13352 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 literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/ebwizardry/textures/armour/wizard_armour.png b/src/main/resources/assets/ebwizardry/textures/armour/wizard_armour.png index 4f391e29e8ff65faf776bfa2697522e05da67981..7a5d974e1613d224219f5b35c8169326dba2a769 100644 GIT binary patch literal 11798 zcmeAS@N?(olHy`uVBq!ia0y~yU~m9o4mJh`hEe@iDHFP{4;=Ecv0ubbk^%l&@k{`1Zwzt7t5=a)=AbE5m6wdeleco^0=pCQ8?71ANm-h3BeEpex{eS=eRK{oIx31e7UU|E#)RI-<^n~YM z%-=4`StM9$PWb98mEpK0aPkepCypnB|cH#$I z?pSYr~^x|E8 zW?c)VUr&tJDK-{_aZLPia-o2;?k@?S9>b$D-fK3h&Ufn4Tso&EQ1`b?(HYI>F-2$B z{t)ugS@|T$OLy(ASB)DYg3m6S7L}cSXG`JBW6P!AXRO`*uKLBs<@2gvZr$$qqsQQp zhjPEstBlLO_MZP|rkQO%V|9B|cR*C)(Wzl^saLO>ZQS;k&-&e#&w9JxefxIn@zwWn zo9%7BpO4$zfBnhEf_u~V?>Tnba=%_8t9qc_;bgrCn|V(enQom-58tS0QR!#5dzG^0 zqQlu{rz|g@O0F=_dHrZx{{7m@ck+MJl76iJ^X%U2 zww32@{w-rwz9#$JjbBo`Z(e=tS2_7*=KF@qUoY1B>+Jin&Gq=F>TQ=l{_DIRrL()Y z?A@+y@~?kw-1q;@>Yv}u|K%=j74_ATQvN2hto%^cFB_|Ev(~MD@`|S=>z(DJz&&l^ z*}XekZybt?U<qaY|*S5b6bDwP68mrsZ$6fwq^?mPGwi_N^xBB<%>Yv-v z^VaX4vUl0t9f@B9%2!pZ?@!j=dR;KqFwncl`kUGJ8M`gqze?}BJ=62@hV^Ru17|;) zxApze|Cevs=KkAw_eD#}Tf5YpDVyGhEELJ_~x+K{grq21+Bx~Y>f>|0vFkQ)CvMmHvO7C- zSJQJQKk@jDS^xhiJg#(g=w}vs_)+!7rswCbuJ6cys62W04@(Z7>l{gCj9$|uB2D%k zfAwZjl2DKLf&MM4I$5T-vxa_~_RVK+;-fj!d%s^h!Ek4rr&6w=rOdv_;B|AKL{#}d zbF!OxC-RO`?;obWJimjWbB;*T3HNP&HDJ|IF zpgVVOh5C#+OVSUl+5GllnHpF4o2@HqKFfCY-Q8sIKqct9iT|&F^^b0xD$odjVi#{& zyzzVYjO4vy`co$-X3o9xv&-tUXjy4gLrIRb=jNpEC%ClMnEc!oqjGYY(}H;i3hpe^ zJ}YuzgMF}ibaMQZO|eoP*6b7Ztgz+GxtU|w|1h0%n-y1s{I{KZHocDtl74e@&CKhZ z#i3QI3F0w4O4iKZl;2Jk+{9wQ>-H?`%o*VHL*ucR$%zVUS%SC0RsKBp;X&Mfi`>If*i z#;LdAyl_>Vp?iUdj$OEZ${!9E!Rw4)w>hvKXVR3;x%k{_tGvqV54Ne7nQm|YFlWcf z-%$pIJJ%gQQuScARMS^jQ_Zwxo!+8rm7sP!xd~a

    6O=(jz}?l@uoHdUD$HHabmu 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 L`njxgN@xNAS>?eV delta 2532 zcmbOh(< zOBZp8d}U{8ap^F~n#kqi(GWFdii9R>2+JX+Ct(X4-YzMOniOIY^QYAAcUARo!#_9r z&%Aqk@9ocX^&gies%Y=Fet+id@2_Wm3m%eiUixw0+xcrfK2%)KUUKQr_VaxUXSQGH z@SP?ixU%KRpV?j>J3`$K`~A8){olhX`5VRNk2c-=!X!{IyZ=9T!cwz+Wos*{6Av7i zx4U-VtL^O!d8`|_rIu`dt`L2e`A_H6&)Db4jIp{;?T`j z(hxD#P`x`-n6+5nSzMuW($jjSWdS*}mK8O=<25?q5-_nr(BZPFfj~fDi$-U~ugkv$ zC#Q;tur87~dgqXiS?Z-7H9wgc9vr#3-{E@6id}q6Y@SmbBo@5lQLr+(>ku<-p%k0f zsxA&wRR>naRf!32P6Y|aG`qBCWoTrwh45N@aggVGf48&3#ldIV#}AjCfBclM|0NJA znsaK2VaYSUnt$x+7jNxj{MgZOxVrq&1?JiS(;3wgQVu@XH%gk_b!=GndO_2L6fp({ zpO!=e7bTJTZ}u~13v233>3Y$zRcUjb@)8fO^tf74h7JD@##TH(#k!|7S1fSmB2%HG zIdy#dC2HB1PU3P@=wo1UWMRnI^>bgFaJ`3d1jEbMUCx(H100?Hv)}8#dwbV{>0*Yq z_We8ewDHd5b7A4t|M#)f=0>?b!-MkV=N~S#mn9^69)6U>xU!|CZ<|@iM6sTj9ZeU_ z@3&=TOmN|3OTJJdo2}vMd3~WY+mxn`Z7Ib&8ou19oz2J~o0~gh-h6iBt_vozLQ@ZR zv~90n{*U{x0Ruz&e><*;vkq+gv5wJIw^7hxk&(vI3%yEq72)b-xxR-lnE0GO&&=@b zlT_Tl=c>=$pU&vpd$-)o^_s_?uMN!drO)5z$CMrC%=g>lx9SRi%=`YdbBS8v4(Ud1 zD`Oa!m)Gog)R^|JR&uZNZ&0#c_uhW@CgEh}!!Km(Z$0mg?oeMBF*jhx#bi&x`_eZR z*8e@1@@DUB9@8q8r{X?yi*MWeUTtTz-X_b)ATlMp@QHi>;6TvF ztc?F(e-t^#9LWFQwxi)S-?kY&?&gccdN%Nvl;m^Dt~GR@9H)5WR{dMqThCXk-YcmT z-|$`Qse0$uc^{n~ynOR_^*yGyA--i!CoDWCc7<6og=;#@B>dK0S_Hl)`} zYZkM|HOHP$ImM^CerMse`dl|y-rK}f-nEPU)lT}FgZ2m%kAKwz592}>*kgRU%$RRUT)2^`kLvB z+Gp*5Yk$4+Nafj3ud;I;`}O-)$!yl;wP$#mc6`6{mGeGt-@SUxg3o=|B$gEyoXWAU z|HD+ulDwNkfHOVKgjFQn=gIe)&8!c3+d}l>R&X`#d@aoPxaym0_ebV)b8Mq-?6-+t z^YQMDG^6cHl3rZMt9flGdh*96B}aCj?eh2E-uZ2_cw4|8bH^3Y4e1`|cg@_)dQm88 zamt;wvBz0$K9@H7GAwpH7%;=3qvV^+7iPuy7?1iTzqOgT_~XQCE6XejFMWOY_pjH+ zX4~}V3^flPo0k8+{loIoU1GnpH z$}7Yl%v@a-PWyXZdjI?pT2=CA zw}Rn1p|2;DpY88TdgS3O*ImDxAS;ngD6+SDyP49#2qyp{O7j)t3Rc^?(3qXdw#u8 zUsG_)Ye$U|23yYU1gsMaheC;T=Ua* zE}Q4l1Dhf*1TS}tKf!e3m+?A{zJ@pNOl(uRHlAUMx>e1@ADpSz^I!jXZAF@g(!+A{j@mR@3{xp1iRIj--JIA+rXdaUK=c|zSiug z|!-k1s0s1qH_6a|^YB&AR=BFinOJ=Y5>9x-7 z(5?eTG0TFUuXxFSFgQfuR0u^IEf?M--*F6+4EKl9}*N9o(? SYR(J{3=E#GelF{r5}E*!)7kC- diff --git a/src/main/resources/assets/ebwizardry/textures/armour/wizard_armour_earth.png b/src/main/resources/assets/ebwizardry/textures/armour/wizard_armour_earth.png index 46ec5132632457348b85b1a2a742676b8aeb1a2d..3baa618438723c2c7898ab525d6c86c7e173e16e 100644 GIT binary patch literal 11486 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 delta 2771 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 diff --git a/src/main/resources/assets/ebwizardry/textures/armour/wizard_armour_earth_legs.png b/src/main/resources/assets/ebwizardry/textures/armour/wizard_armour_earth_legs.png index d6ef5a393d03b13ae8f01146b6fbd16e046965ad..e1e6fad04a95c31f7b94097b1c0962e256ddd0f5 100644 GIT binary patch delta 1504 zcmZ3bAzaZ{A&^Ri6}oTcSna{mW**f5+cXtUK(w_gP5fmao_J zVzyqN$1YW6yYBexbyf48ulg>qFaB3>o%D$pS{2ier+<#FTQI-=zWRx^ozJrCCzZaw z7=6+9!?F!;rhd=bKIdMSSKXJ(f9L+P&A+lg=lMTTORaf_5gw{>f=C=#H+?t#I>=D6NT51(~i6yi6P^ zS5JMAU&$pe6|+MvEl+37oyskjvL0WXwPo(&wtA73hc3CeEIoZ;QE24su2p5Sw%?mX zj_ob=jIDm3oN$rxD)VM`m18q1r$wrtH%oo>rdVgk`BmNF(VI%Xn(9Oww(K{ZoRW37 zZSvu%d#tL93%|Zoevlowh|Qgwvsdo%$y;Y%X=i_F-1&a9n|b!^ja5&c%r!0P-m`MS zT)&E9wqr%A^#*#g87)fg&58Be`t0nTXK!A41hyJSDBpV`k$dbwLg^`)FHhdh-TD60 zv>pFM@_$C3S?YUt|G}7BSMHvvefF07TF#uVAU;QHF7svKoGNAEhI~UCrRGAYx;b1z?4jbW^`&s==--F$33bjAnv`t<0>(tjR^_RcYxwgq~Tg>zI z?DNvL04BRVg0tN-LN9OMdcEd_53l3D-pcz|)E}`Op8jJ^(&LbVmJ=%`s>j&tyxweD zeZ{EdgT(_nuOYi7%O?#5fw%~@(X{qA;~@K31{Jfgcc&CI#?mgz*T3N|5r zxzkF|w%D~!l8r9Bp|CA-qLo|mk-EFu_dE0&taK)Xe8|uZNIzS1Go*j-FPksXug~1J za@M-)aF^x&5!tO9-#xQ4{CC2-R_?&OJhe5MKKI0Yx){@orrk9>a4_1tYjueH%K90M z{5k7W*IrF4mnmo4CLA|gW5dkGoV<-moW7Y4mu^zxJSQ&ik$$}TqyAn8-nbvmdK0$s z*OW9m@lTNzb*?wKcgdf9MgOHFsj|#_y!EMUG3%HXM;HgVq?~%OZMBnv(q{H9AurDb z#=n)!-2wK>tyay* zbLlZKFmM)lL>4nJa0`PlBg3pY5)2Fs Z>?NMQuI!Il*?3IE8*=89Y>f6}1OOrr$v*%9 delta 68 zcmdnZw~~2+vIPTMlDE4HgB*hp1Bdym+zkv244efXk;M!Q+`=Ht$S`Y;1Oo#Ddx@v7 WEBgaRW*$?f4GFnTo8PkfF#-Sqx(}oP diff --git a/src/main/resources/assets/ebwizardry/textures/armour/wizard_armour_fire.png b/src/main/resources/assets/ebwizardry/textures/armour/wizard_armour_fire.png index 5040c8666433f6991419092c28a3767d315723f1..47b1556dc1b63669a623222b03d82b1cb378f865 100644 GIT binary patch literal 12095 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 delta 2800 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 diff --git a/src/main/resources/assets/ebwizardry/textures/armour/wizard_armour_healing.png b/src/main/resources/assets/ebwizardry/textures/armour/wizard_armour_healing.png index 866fd4861571d99ccf8f40db825d3d52116fd21b..5a1c4b510c2d9482eeea00ab6950ab2e0b665fcf 100644 GIT binary patch literal 12777 zcmeAS@N?(olHy`uVBq!ia0y~yU~m9o4mJh`hE=LGd}`y7ijVX4_uZK)|Ect!_5HU`zwiHT|Nl?t z{r!9L?$z(8Jo)kN-1x^e>(=j)v%5E8p81V$UrQ(dDxUx6&WoRiU$^=B@B8_1r=Goe z(f7)`cKc_4+Oz(b|Lw|u?=S5;`uoxQ{l8lb+#a}=&#tz5t@p3Dsw z+Eu&%QOv*CvS)uEn?KxJ|4VK6YP%uhHwcpYml--r@I~ZVUa|qxAdZ6aD%f zcjvA@|G#$9-6-Ytrsvi5u^l^(o)?VI^KHYj>+zc2RF>yQ11;#={p>(7W;JIQBk z{&=-l_nX_T(^b|vTTh?+yZ81vp})58k9`0AZu{-^sng#TeP1iGUVrzyma4Ww$=K2@ z&nkY_tv~wi`Lw@#@{IlErfKJ&KCAQo$H&yV>W}}QzOG%oHD%YexSzV(*Gf+_M7EhM zuiweldgJQ}lboOL^go}>Tj$?ZnqiP*m~IxazAW!z)87rc+rPfqp%-({=3UO^ioAx7 zin0X5h%MX0x9Hu-SYLAgWYm)x7yVP8ZvR~F%xu; zc~$S0UN7V~FZeI$Zlv6A^lFQ6@T|Hv$@E#3(;~&UZM*YHd(DnZr&h1|b?w&TtLvjS z-#7VQzV@bj_N5v3uP^0a`?1JteRRY@&k5%)+<2=i<$sBRP1oNo{@U;8S(DGLD|#&Q z&@J1{!}73Ka>fP!>h{$8yMAA|6aO`>>3?|D?*B_Hm9PH&e__tVS8`|nUb(FwC0*(+ zvRza~e~OR(b_O%ORpslLjy$&xy83;ULg_yJX)#fA{Hi+{dAd$dwfitbE&xr zr1`at+XHUDS$*r~o36}_LVxZk&%73$%ba-rX*RF9cK*q}*{_f9%{p=VO5FG0=S8(~ z_osc+-#2@I+=th4`S$EhJdB3lt{E(Q7-Y^X*t>h<_lJfTLJU_=x*)nsTXo4R=damH zlS2*G&I{6AIlp}2mTQw-P~`uo>EPj~-(&C0!3>77gj z!+pjLTb5nd-?;JIQTbC*zf%vt_MX^t;a0(qF2Tt7!U={KQ)k-oUD>!QTe#!RJaZ?H zTUmY8_YSVL2=894pgi*~&&K{sccfIm&AgO#GMr_Wn)!?>A5D+W_vMddb$dd-NSE!) z@mzhs?P$N$wKLyJ-yc}(e)vcCyj{0!y`IMvPPXjprvm+woz(MZ{de+*gHt8>g=d{q*eN zhlrfIn4C|Csv?UDjn^98_{WplCpUMtac_rW?`_t_+t1&do}GPTnf#ryo_jm?Z+7L2 z&W@cK{k!sPgW3(vpk23})|K`Kq{|)Cza8Ypb~)}(?d$cMdpo_J_C+}y7K={0>2d1( zlc>Xw)tp|f+|+n4IwI|@uX1zO@@;u{x8&aL^Y7!`teQ8YQFu+|)EToT%dqV(QV!EO z@v~2-D{^~uW`eKkhXr#SoTrCx5@tC2W^pBt{C3Y<=QVEmdoJGHx<&m*=Q)8(R~H=D z?A^;&zIn^`yXTs=9KR*D;_F8vz8^OhJU#1K))brAa^tK)_WhIu34>#Aip85M7quVOn>(6eic>yFFku2<7P z#DAi%PW)Wx_n_`GiAxGk8ZPdru~{J^~-nGM~U$&Fuu)PEx&qJ zQU00f71s(gcrITPJ(H8d7Rc7Ed|&7AW{o*h8!D=68n1qApTp`?$!)(ZdCSzRCQAx> zt`$U1p6~wC(nVZ)4Wr4eD4|8?q;7cXM_1i?zb7(6B*^#3>AE)=W)k5=*7=_oBngH5 zez-_((e!s%`@aE=vomjcv+?=Q1 za{@klOx=6xR7V#(|Hky^4aa#U&!v4~{_@Nu>-!DG?~;+_87$RDj>w%2Of6RQ+avZ^ zKEm{4y5_Tln#|ZA=`ST}xhH<@alG^Fx|Z5TM$SXC^MVg;aPE6K!AYejv3+f`j8{Xz z$xju*ulwI7%n9VX@FQFHq?6wP`2c0fH_fTxb?Wz3dHe$Q_6G265xA0CRkZa_%aU6R z>J!AnHwQ0b;5~kdt^S|GA;kk7UuUs+zlb=U64d*{G3F%urzd|VDSngMemKpVHTtN7 z!LvhJo%eU{lshh@b6i;BW7DF5t><>RWlKm!Trw8enb*2q_u-TdrPXf_Ftf1v$hk-- z{Qa=+?u;n^&6W1r){5%6!rc0TiAu)j&)!fjpUYIktmblqNpJR1!3(dQE{cCrv!3p} zb;S#|_Z%GpjErSB>STm8!<)=bE;0<};59vw7u;xeSi+s#IJM_-%RT8tftUa;7A?z` zdn|iWqqcttci201-{V^Wo6K%IBs<6Kn0WU*Us1epRoDNAniCyrdX@R-C73UHFkfZ< zQ--ZO50<#>;N4rvuA#Ev>Z{g!+Yeo@eX!1Q!{wVL>^3S1s}n{37|Qjfc!V8ZWAm0v zZ=p_Dp-Ai&zYQ{5?}{<9`Fv3*Q_~VFT(23gT%r(_zRg>}nc0Ue?cJsp{>AFo^8J0~ zV*iQz<^DT(d!hO7vgBJq1=BYwro>J>lkhhFMCzfP7gMV{cXpgvv8Q2C67#MLb!smj zdA1x_@`PitRG3fG{Q{!`8SdO$K{L-LR2$p#?KJ#whjaQN&d*<%?RVR_?dJQTxWs2g zzWSo86Sdd%7E8b5b~_#a=}G9NiHfs#_Q|WpGz#?hRo>_E*!@`Cpe%6x#rIkp6d$&3 z%#}eyleOWgQZZMo@o5QV8Kfy3g zfl)|t-_O|!%0kT{l|j$gj;KBmj1D_+q;i{v)4UzgMqP5Z`K%SICZ*{*Ij*~1cGoo{ z>tn#9`0Z3C1n8SLP&N z^?q^jnozX4!LqW#NX714?q{#psGH_K?kaUUBeV1R$CA{@oYp(D&%EqP5;$_<&?)&t z=eRxQmTbMdi(}@&;{qEB%Kvk&3GQUjE?UR!*pTA-Oke@8ZzcOThW0xtN9=Cs-{v)5 zu;t*RG*wm=+4TapO*IE!ssDSkps6fk1MesC@&qLZG1Wu7cMj=)$l7W0XYZADHL4T+ z7q@L{E(At7 z#RJZ3=CV3APCqzp(xwZCT#tlIXbqiUeBckeM=^JPhs%@D2}gU%*YJKf51OGp;lfwv z0~|M1Ev8;N!QCg8<{D9C!@-gxV9$P-qx_aE&*9zLMH9cQI4aQ3XB)Stkn5?7J%i9S zmg%Z1JA))P3JCglTmE2q{cVGf*#0TbPb)q%1+w0ox41KIj-XFNJs+#$6ZKc2Q@%G? zA8{*;jo4yjQm5t=vqn%+Ow}{;$LUo)P1QRL`d2qNl&gMxT=bvWp&o9XETGA8I8SG{k z_CkpBlnE=NGxsD9p+5h*3!&c*J{5hi@a#kz>$d@Om}UB7(^EO8e$YA`KFf8LAy3NT z$*wDkSj^it?&90r?bPh`X0H0C-*ulFA`6vLJbS{l4(@$ew%y>2#u1;Imtm#xP8MlMp&`&^#Hu!Zl8x}L>Nhj7DXRiF3T8NdI@)G6w)v+`hhi0%nd!;gE_s(m(8 zczj`%7rgm`V|R+?F9l_19`e)8~n^=BjllSaN@}(7!k7;8Tx7XP66P zMT1to{}sm<&GbgM<3NziyM;Evd7JjktTxqQiB5DE=lpUnKw4*iP3*t>Vfp_y{F&={ zOy-Hzss0mh7X`O%*jvA6&;Mt6QMv|7{z^vHYfdHZ;X5;LLh^?>b9eIEKHx}{sGT1p zof0*Dh2@HeyyHjc#6|iVsZlGqd0|+3CmX*rRecK3zIdpk_tMlrFJ=3 z=FR$+n$6FGbe)n7wIrL#gY+~mEnPfVgIMsel|baqSvS#{j}@k zOuaa@sJ69pnRK&`ADFN@poXEXNqC0Dl>df8FJc9rfBLkiCgEH{M1^?6tms#_e=V#J zR%HwNTQR9EeAd-@j}m?b$xK<%WV}IpMdFvKdoH}aaXIv{2IqCvq6xecr6M-ud|Bwg z`q^bs*)HdB=JM|CF-P*Uetx|2@pZ7{?ydJ{GoN`m!LeQ`aQ7E|$tO2Tmuy`vJHOlG z$Gd>Jj8hlMzu$6bZNOAX&wUMMGt|0|zj}AIN9&V=>VM`L7n_gjs$8F?@_f(?PwK5vSyKI+a}8n((s%2Q96?c^iHIXd%n zJG8&=NM6fts`0e#Zylfa@xBO&8~!=k{CgSuXZbGIne`TJMp?XO-PTgsL4 z+<(?xy~$;lSUw-jn&qXKpxUjJ(xmrto*-iv+nED#3#NRw`%&m{a{R?fZy4o+*G+Zd;OdD3gYq~w0Q(9?ffhgS9lY&I(Xt`c-LKUctz z-`8W+(uN3@-e->kE>73b6En<_nZfjgC#T<9SjFO?+1lV{u{H5ws>l4Z5Bf~D_cpAL zIBh<`LgJwAaUa)4<-}MEqe#|eYI`L-O%9cnHoGg|)pSWXcX|G$bKx_ESuaOwWCzqJ zSI1p8xyt|UkMkT$UPFnvlmCoOPtN!BK0I&EEt#V;w|Sp-bjh-xVzDA4b?s~ZH;?&^ zzJ30Zws4(+RasW~^Y-$$Ix(Atzxv??U$K*+DcS`&UxSs}7qps-OWsU~DR_`| z^0QJ?t3YG~@59Ljwo_}gR_>YeCh~(*RS=u^>B1Gyjy_%PGW(2$YbCey)+1Za1~krd z4tRd~){0k66(@NUKCndPt?tiopbjUKV7J6_Ph{wSXcXYU|%0wUJ$F2U-)#Xb$d^L5zS4rw5+yP zJs>o>o}JU8+M{mf&X*^r&dVyby4dBx+B$9W*kx6#tl<5v!mK1?T6A4nj(11pRJq^l-fg

    X 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 delta 2765 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 E0DcB3q5uE@ diff --git a/src/main/resources/assets/ebwizardry/textures/armour/wizard_armour_ice.png b/src/main/resources/assets/ebwizardry/textures/armour/wizard_armour_ice.png index 3e25a69c53cb59df1927574deea7935e644c57c6..ffda7c9231df47516af0c786fa637b64e00b38cd 100644 GIT binary patch literal 12968 zcmeAS@N?(olHy`uVBq!ia0y~yU~m9o4mJh`hEyT0;$>pl6J7=u^m8uRac zzxv(DaL)C=zw@u(JOA~|+roSQlQw$S?ECqBfAB#G?axU(dT(AlK6-!qJE2I&oQP%c)xRD4x7PNbN$c)+-+905OYdF(`%n7qnXUWQ zpQyk4^EiJO|Jz^x_UCV_o)E&X@@X#Sc0bKi~m z$L60>_UqaA;n{=pCHsChY?Yt?=hI#Ly4%-Zs(bq+wja7Kkk;`ns#kT3!C6hu`ai;4 z?;`cWYz#j}J$d?Jr&#{?+_L>Iwaeq?m9w2cYBT@Gary7d#sA0utBHG2DY9!G%bzWx zuerD!rYW9(nSZa<`OoKDCbMhb_Wu?$zixiq&1S~gGgH~$T(_7makKttn2Ejnz3J

    x*w%N^^@5=vG-UwgGmr4x_k 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 R4+8@OgQu&X%Q~loCIFo^hNS=i delta 2749 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 diff --git a/src/main/resources/assets/ebwizardry/textures/armour/wizard_armour_ice_legs.png b/src/main/resources/assets/ebwizardry/textures/armour/wizard_armour_ice_legs.png index a62eef4e06307deb513531102ff39a1382064393..f18ace7519bec1972391ee14d52b149667bf6814 100644 GIT binary patch delta 1603 zcmZ3;Je7Zfay{#ds*s41pu}>8f};Gi%$!t(lFEWqh1817GzNx>TW`aoC%s+8`!`)g zvZ+;|=^=wt=uF49`KoU&-`)MYChD^K~qxphp;NkMmS*{%P-mM^b=aH`~Kh)eX_ zt#LcN^lka~Y($`^` zzsvr(&#zg2F1>#Ib@SUhYj?h{kKP@qr4xF2@s+O~7WoNt3{>Z*if(_TUU9v+{0^^{ zp2XdTXGiu5m7dzLEm(1}qu=kIZn3_IPv^P}pHKaHK`Q%QrEGxLohOlu{i=BmNsOj! zmiyB|j_-czGiUpo<4?;P3P6&9L%tJEZKspo3n=4#GOP9Sr@wX#- z(kJ-v6lSjeG=sGUE#av_WKLc9*2n7F}RAf`RbRcm>Ik=E0PYJ{I9~NKK#Ic z*1zXjUEKoiUlNh5`PFcm`{38LCFwijg^x@Qx%az^^~KUv_3O^D`goRzon;X}$~9^3 z?yD8rLb1nRuei2)y{q& z7ckFD{r%qDCv5ALi$9xAFOEOCoMU@zP0`gfv*inG7EeEN%xiViroD&jx|Dj(E&Q%5 z(YQ+g{z;YHbNMgmnsb!Qujg`hFP_!?E^1?9s`T32K8v{M%GpzT&up3g^=wpmQLK>q zw_DRMU3pb}z09!apn<#6!Nqc4&u+*vo0I?6iaB$2tV{PyLFPL5wKg4$LP8N74pp&Y z-3v43dx?b^Y%x>ua7cb*r(U%D!n*D9K3^uheP5-#hR65v!8Ht0JzE+l)h?MgeneSVJD>^tXevxHRvn_Yt09q!C< z{@|45H=o0qFK2@vgZuHNeJi=AG&uY?8>OM@z4(Z(Yg(8@ylyY!mIo%apH@kqun5sV zaP>hf4_Crg4px>s{&N4>6+fA#EaGzyueW~w#WrQJR{3sbrmJTzM!fscv@^X&BeFy7apS^%kDkr4({VDy|(s@@%>7-!rR5A6&F7k@)k}izr+_G`0d6`hO5u# za$9BA%j~$9bc0y#4Xk&yb>I8*^Tx^keJ>Xu`dI%lOwv)xs(!WMoRp+X z>Was2w7pjO5E(6+d0y+z8xF_lw*T!-OPcqpO;VD&WXEk~J1_ZMyyr(%^?&G85k@W*pj^6T^Lp}>}B|$^5IAr0|NtRfk$L90|U1(2s1Lwnj^u$ az`$PO>Fdh=n3avkLiEt}O(7ej-53G9&I*wL delta 43 zcmbQrzmR!?vH$~HlDE4HgB*hp1Bdym+zpe}+2pt$Ff#KPDIM{@-MiVJ&5aQN?$Zml diff --git a/src/main/resources/assets/ebwizardry/textures/armour/wizard_armour_lightning.png b/src/main/resources/assets/ebwizardry/textures/armour/wizard_armour_lightning.png index 29cf575539f9b1898ecaa4060287f158b4b479fd..f8c5ae62b1dc8bd05f3e2b38e378f8e7c81d6f52 100644 GIT binary patch literal 11578 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 delta 2755 zcmdlL^;mR*vH$~HlDE4HgB*hp1Bdym+zpf4mE`IlFfxfVsI|>a5M*HBD)4l145_&F zHoCeeBwX_U+}|^1&V4!e=ET(Y>v~(K9M`*jDPRHHkp{yf+f=r+sYT_gM)fMN{ae)1 zWv1xZWXQJk_7=6Z>otxkd3SM!GXG)^+!U6RDqgvDQ}gaO-FI)^ludhP*H?eXa(eOm zJJsoJGh3Jbs8>xnZ~J_A`MdAG?>&#uWN6Aoo33fD0F4H4Fl7=!e90blfOR5zP{;u7|)GO&lIOe z{=LWWAdjOg&L!$v-h%Q^th@Y6CRk@NemPXg#Nfu*_Bp&r!Dz#dddr>w2N$#Y;N7vd zk^!O-o0rHPeynBU?5?7sJp20Et*yn)X$6`csvJt6R&{w8bbMde)4b}yAGOL?ERLR2 z5?-X~h_Eucu&v;F^2y35l9%Db-+a4v`P_QO5Y`T!n&+*)6+gNCAMD%3U=+!_b5Gvd z&ZeI_&f*H4K?hxZ0wm5)sV{1D-Q3I|s@Tmkg<;mZ#wG_b*N#aY)A#KVe3&3GGlp-G z#Gw;6O3(P3JUTV?Ged*C{D18d-}Y6n6&6fz;cQ`A<;S?l`7*CdljDlE#yzW)6lQar zXkxf(aN(-4A?qcDiwmWsKFwkbWj0%zclcZBX#q|S4)*4XPfN@G{7R8_%Hpdp7Vgcc z|6Nz}b?V~|zuCPW4hO!Kp5BmIDjmZ6%$SE)VcBbgM&ELQ1uv~q9A_knF))O*BnGfB z8QJZx;j>$I#BkdAMT#=6Np8YR9Axt6TQD-*`0>Ll=B;Hv|GHRr4Gm=}j)zrMEbUh7 zmF9;lavWiD5O85=ST_55sfm0>YbmBi0u8F$AV{6~H@M2)k64Nt& zCJG7}KiAX=>p*@CReUI^W13G z2?1Qb*8|m0pLlIma@avnd6Au&X^cZv*-;w?2j^PbHaB<2UL6zPb`^HV&NlwvzY-p ze=`i$B;Q^1d%4SXk2${?&(~bLw|{^6(@N>Xt;O$uJ$oCuHhx>I{alOYeIabd$%$W< z8oh}4q#!7bl>F@ z-hAqh6cYY7ZHq{K7Lyty!@Ns>JsBK4Ivx4kC%*Gnn(Y_)dd~x!_@jCUOl+=pT(?>u zE2qH5bpCjA@$Ke>>(i27+$wrA?S1^6efM_7^SS39I{i?Ct^Cd52Ys~@4hObOk+}5t zq>`Ok{A2|QzH=KM9dI#=-1h&|7X^5uXO%P^*s^;^t?j3m-md34HTZY!Vi2x)@JNBNA(H)jkQ~dr^&8@>xP4}C zzVyrSo6*#m_?nOR%`V$+2t0Hlf{pj0LEAB-8=u=9CR%?GyY#1M(Tk-`rG?pRWPdCS z{dv}Ehxp0w`ZpF;T|UgMAw1)GvRJ**ubrYPLEDe~2rBuWJpJN@Ef=DsrA{-fRQWb% zUi$9m2iz`y*tU1+&e?w*mis!G$$3h-oaJ-o^EJMlkSLQclw)KtVU}E+gLm%Ei8mfz z4rSc%`NDP&9VKPcg-T)*V;OJ!nH;QO^kHv$Si-$UX1D*wDOeh*&U%p1c;zsdJp*`WwZMYhuHNQ0;Hykm$yH! z%iCS{Z(sb|1J_nqB?(_Sd*|kzujh5PoV`4M-^*BbgM)j$PL%B5`HrQD^PR|z?0r(7 ziW}eMrX9$(-LR^rUi?9;eyH{R9Gi1NY)(}RE(bf9y+0nTd2(TH$`E?XBGl{5mAO-wMmt}X_{r!o<96q*4F~_sK0UKA#qaecrML6ztt+p5ZI8Z| zr@^!`B%$P3%g2Ys`y4l1Gx>5?z46e+IlWvA9&vZ4PY=CvOK48y!V~WMH~vgJ<)xxv z^Ql9X;cN;+XzQ=3>zhwB)GT5CW&Qq!ag<}l*O$xB=qwPET9+*ApclSJ{=k`gy??H$ zb!S-R_V#+mJU@{+HFTC=U0u!f+^+hlLz-Q&D;gP#_iYqZkz<#Y0Gaejnwf#^4(s`+ zIt@2oZmBuKvhf7dvn_gGYb5t?E&B66EJ#tGCr~8Z-fZ`-2tj`7%OR(X**M~M-doSN zq5Czst;h?w>r9*AL=$ zb4T#{?XR|eqqakS>gE3F$+>%+v^1~iw7$LfCga(epIgFtE@VmocI zZEp%<*C!j*)z@8O)Oh-N>5sc-qC8C$-%i?kr())|pQd&H*8Ny7`*hC7%8yq4=Vo#n zXe(?yynL@xitBUMz0u_pqil|QGEYAzcJ`{~J9*bT9=oGw%i9-*Rfw{zE^1a-8}|DT zJHMi8+r)cv;rD*5N$Xx7^KX@Zn^)kE+v^4P&xt$ncb=q*kZ;hpdPf(J&PXTTcQ?|l zndj`QU%vI(lk(FXIdNLgS+;7;3XFVEEap@rHsNq!%4N;#kMp;injLQ_U^|#&#d?yr zR^K;t(az|zOm#(NGoG!UUcT){QuQw{y+5R)tx=V>#T12>G?O3KF`fxRr}8-es1sg`@hxq?SJ$< zfBo$9@fC4gHN5BhEB9Y7kMrMuFW{c}j*ov!gP&E;|8?)h-=oKQo9Dgx`E2jHedb*M zD(~*KpZ#s$`s4bSEB|vpz4z$zqxV-d^J?Hhh5?@}UXmh&7YmHhU z_ntTQ#~-~bzFm8-WU9LU@u~L;jgMRZ`;lE&_3{7n_s@IJ1-`OMfBihlP;Wg;ibU6( ze^0fTKD9ZjKC=5aOTRLCKZ}{b!IJ4ajSl7=FXm4AslEMBZ}Ed&DT^yl-<`%2dwS#De;zewKYz|tqvjoWXuOyKnUT4nZL^IhEQ$@Ot; zQ5-H@mLg8hjDl+fY0jDw9vqz-L2Qcsz2*8B(8iK=CgY3)_av1&#%obFJJef_J^RGOy-k7H`&}Tp1;mmTt2h; zjMeQor`K=L_&+t=aP_)vzshEZ+$vl?xBO=5_PhK$%MNv_&#gJNa{1hUl3UGJ-Cz8y zuKSL?``NvL!ABnLUH7L;N`LyNLT+^n&n`*9&ld$hF5;MQA^7HtLcG< zcqgn1$j&;3c`c>Fy3#=3j?$2aV*-)H4@F8j*c>YTM_wjH~ps&cx#c82Be z87rq-R3u1ie%<)|WgdTdk>!<2JM~Q#$$fTWulN4ksDA!|d*SKgzn_-R4)LG=moH(y z!S=toCI7#z{^>9NCwJD$kMWthQ{&q1-##PsC@FNhT0u;{_N3*Ns*602bUfH=u}to~ zp3mlq37e;!)8d_0Ug>1+W|*iqy+-}kw&fNa_dOH&fA=XF-L>w}tNg$pf3|*C!}{gV zCZ3M4TYuQ&PKNQ%Ste^NuSFETXOc5)3rOoZzO3lMf|4-lu4x`wQ#QHH^tLx=n)d0* z_Qsr3E&D$FzENIwQ*ZM*pXI?y4}$3=#@8n(F>K&PtGc@_nlgBSnkl9@`)!`i5^$cD#U(v4H0Q>B02@soR=cGI%1 z`1Rfhg|v&#v#X7z6%=;J9(yFY{Fl*TU8QLA8MYCI_1_-tRFU33W0skIziWckPtTYg z-=z|qZ>FC)Hc8lUx4HO^z0967H3X+EcNMpNe^KV!6`4mjZqI!fIdf9gjm;*TE*tK% z(rCQPx2n~VcORQrrlg1bg3E8d`S?$`%h~F#eZpI)xF9uNOSN3d@YKPVYYu{n@-G*0xGXmSw9;fsx9l?v=S(9ac&=W+^B$ zTWK0KKda~pV&K|1*W_^Ahmvo*PPcfj`Vqh#xNOs*TUR;w@7S!-Vydk1|xbd?x>GTz?ogO=< zutsfNlX!h=vzBFsNci=8llVTbxx0L4VoXb8>IAnsqZR926tpi|NIpo>J+S{we*bS) zv&x%x3AcpIStM<=85+-6Hk`|h40^7AsN_WZ6zBT+lfJKYoF=A|5l}2F!uj=>?A;zW zLvfuu@{S>sQiIoN$Ook_ z;#o$6O>uK)vo^|o;;>QOd*HR_*)su}mP$T7*|%2gC_FQ5)q~lmrB{A_F-2{<$OnVu zv^KqWz1xE}B_FCw2KTwUPRNwR z=S%u=nkvU%`ncABIn&|5er82qF0ZSfr#%+99@wWDY|J??{>A>-sPZG3VMP-vn__+b zvZ?tOr`!MJ)#Cf-s>jw6v~$J-!D^l7C)c?bsvJ1_Nlkq6A)xRdf%yuyfW1wH9EAInOIS=gUbJ(|YrVcd^afTQfI*ZF$D$I^zLzoQ>vsh93h$b{bDG)3}bAQc$a@k z@?6aa68(%U6DCwo{M_u_X{I5}xO2wAUePNPZ=BA`bZpr2+?Anmx`4vcyI+&+qjEwg zBgyL*k> zo{kHv4yn8mKJuvTymlI6VOO-^-33anr&o7ytV+4t&CMjf)n;|u%*1T2Z0oi6diXge zNi%3V&36+mK`Ie$h)5$V)h$0t83(61=wK78x@>gGHS?(BEBj?5C^;xI5aJyIvPo9)MyXCLnr zn7`I~*|MgmigVTSmheoG$ZMeo7p^p4c=~`*|C?(KpQb6OUfo-?==+47g8afM!Fs~7 z0#=#a9g2H2jWX^wnmcpfkekT(y_?}{?h==_=)j|vc~(=-mnam@{172M-?C^jOHRyj z(@C6@ce`El;OLs_dHHdfrs1Cx3mJaio%XKp#laU2HakTo$)4H9|J~FhbV(4qTir~> z!eh)+*+SGfgW_6iRe046cIx^~$ZYziyjQ0-Z=UzAy>pV}f)4gQR{Z#((@II*_=kW% ztnKDY3)Q@11kXp79uHc+?9KY(qfK*e7)7-$U9g8u?C?~cy|-K~6}%-MPgD8pw@!-n zpy=jueKvR7%tb4u)7DJkx)IwF6s5T7Nl<>?aw*Rhvf2|)Xdhl0b9|G9^4%QYnOU84 ztBn`${(8!3!q&*JpwvTqHXX8*Yi-I3mUj5J-1EfbYcq1UNJSiCT6nnM{NpO~2k9~aLR4@1BU!^Z_N@nAU;ZkHFC=O*`fULI?Wf#_p5E1{igt8Ll?#n16Ywlz3q zi?}*hO)$;e$x+z6Q#UVxol93bz_}sFL-!Y}#LmBtvz|>h6--*f=i%9@{7hrp#F-Jz zg+{+_xlTK4q~=~W>5*yL^zdByX7jbp28Vq)|K5MDxa09u$D{m`iXq1jov@sF@S1ji zK(X2px3pPt>|zVAZs!QPw&}2VnEmm**2#O`ZNKzT%d27goABkaoOU5IFI-HP>pJ5c zp4IiQ$%?W3TT~HGuIBY^r!%|1wgpY!5x;5C9A$H+^J1%|_Y`bY4T!w+G+^$DepO$s z(>)(MJWA#r3JTo)$fV%AS@Jp|10#FA?niO!15$eJ73D?V&1J}CG%_))J$vPL0RMz; zfz=W*1r|~c9(tKM4ofW5HdQMgHF7fRyP)}Ox70(|Rj&_J?obJwHvQJ)MybiaU%hnG zxPNTAhW&y1>-!m3NX(bNp8Io&tK%1zPxr(RuS%HqZqlk;V7j<*u^ryF-2NxuaD!?l?GY4{txW z@%?FGIaQVB+@&c=*K=Jp-M5ur=%2nsF*@{T@Y>DntNNUO{mptk_f+&T-@L$IrAe#g z{`@%9_1bl-;kz4h$;Xm>|7aDPJn;J0r2WE?QAlWZlSNpq^fON@?Y$pP2-`Nkp3pSm zKxOoXEEmN@N&EdF0Y6eR_Sbc;W7u2x>cT5-yARPpGIk%{RBE-ce>ko^C#~Cyab5eH z$M@&my3RV|Z(@k+;rGn58Q)zK-;w=RXu*`GD;il`8=L|*1&Meym&~`m`+LFJ_g=OP(OzJ+&8>pH{fdBYO4B?akBV z{`!kKMSOpGK_IK-@#c`JXH-{4J9b`?U7D=!y6w2GX#MpE4D*e=8|$~V=I?D|;|pYu z>}}b#-pz7W@yvrfO{))0Uy@LECS|3v_$C*zmL>0^4oOWsxuCE+rt7n#O6;6Tmm-9> zKI)O0nbj%7eQ#O!)Be93^{1%kA51jO5wy&b;+P{)_G*h3|1#;vj|49WaSG2mr)Rh~ zrFu{8$`9WP?RM+SUI?ErcrMM1{6*HzkndGT{@KEkq zm#wdNpZq+R>4bCWWYInBoEeejHw+G{#J1^qNuWuaB<0;d0&z_mfnUimxnWm|jad_Fu zxTuB7-FmSc=8D;;o9C-DJ{DT_Vb(I68U{B5wvV}oRery;UOZ*Op7m8TKVRoHNU~LZ zv5_f1>>>$2<8b@%Q{-%S{CQust7HwN}jDWnQ`l8@1vIY z)kK%x3tZzc)oQQM;)AxlR=Ex*&2PEsn9V%vA>iT^FwMa2W_Ie)yH_WE(z*4FBSJIa zScIhdv^5iRg)Uy;agweKP~`Mhx^8uqXP>Om>*BtjMkn`Ou4=GtEK2)!Tx!Y3=(NA~)ZDyB2qV zu}uHLisvo|kKTT1bU!LqH#&FW7MTV)2iCs^eHNaZt|)UA*4o(dPmG#bo9#XOh?2sy z32p9cWmp5P1Nm2PopWsI5+!A3`BwfT4mUCm*x5^M*3#FKl(XYgX(CeKld@s;_}3*?x%M4?M}bh(Y~S zApZpESF+nZ+#i-cDZb?<#~JuxOMlW#-`~~#zfWi}M)KdN@@%QPnI6O8^(C#YYxnwJ ztAs!Aw)q)2m!mDK?AG4b=fhTSQ^<);IyGf-#F4FDVhf@)n4hua1VwxPJuRRAbMdhw z^DTp~ehfZ$XPJD0=brp?kKVq1exg1+V?VzPZ)N$zZ#>`lB#-`iu6wcg^vdnqLu8B^ zxc*cwShv65sNOC+BDc&h*FGRo^pgSO z)_MA_EIgN8hts~1*`v_$p@-v?-R(WDjB{k;T%L7mIjBB&VzM@X?J+~TSH|>*xqd)6@rpW zm**{sHOZBi@!Zz@DMI7O*W-2!+I<!a3PRGqZ)zUyzAe4 zt(-Bd&C*U*R$2XG;KR(7P4gxzPna}oyQH#b!G_JZ9#~$ID8Ewu#p&4g0LFTseS74+ z8CPf>)SJRo-E+@eKs9wAkIPl&rRigyh|KD z9!%w1+iWmFw^nx99CkIkB}#8QpHFp8ublSsJHv~h%U#=pH}Yv7UN!yeM`<>;g)K^7 z!o5u_r-j`9qw_F#r7mX}^J}NQGiKe9DmboXdyPRfTu#M>ElO5$(GriPYxj93sQ5~U z#7&XeIyLK%$Zn=TS*6L0Om*3ztgE?~x*a-hV0qj~J@=8G@Ug$lt-ko`WXrR5EX!oGR&h(bl(?{JT9&h~S?8^4p(FR3?W7m= zR415S6?gxxZ28&Q@0*>~s~TB>^eu%;f@`#Yr?<{#DZC|W{3-}B??p84A(6Hipk|2Rjjit(ekjM2WrvsG6&I?fb(ve&)jk;=;I2jUinqJEbQ z?dA#CSoLq3Y;ZF}!t`8gnZ?=j#`O*+A)BsTaNXF<=5SfB)b;ZEPqUI7_orRgE2z6w zRDEw>`;>VhRpR_!4Sti_SFZNgElixhw&p{}rXEpwsYAKXUvH@Y@QeN6vz>c?t&^Wy z+rVznI_n)@`1E^4pU!2R*t2fqmu)Mhx36=YEC0Fji8|-XD=te{KU|vE{ovF~m+8CO zIahTY7D+1kyR=KPbl#=A-;?69zPH|faOqfdaow34S2X^zNZg#%pUunAaq8Lg*M(Ph z+}!F`%5pMVus(C$x{yD6(%3#+je4+X!|etBi_;de+n>FsY2&VaYjbx;pVkTEgsbIS zH$J_2;Cs>12k#uFox83XUixTHvjOkx-4C|*u`(Ma)s|Ot<-+ONriBC9^zJU5*8Fr<@D<=7royQQ12#^2MM-zIu5N%hBM??fM)TfcrEsg$3> ztGsUc>Xdu7TysvS-uSUaVs4as?XC55mAhWt6KdMK{n4ydkE^|YTAsOI`RI^4gYnyFV`1WBZlM5WY$CiRGOQ z7vJt#WRf3r!1(!Ey2DBlGJv`MB3s8|vR}JXe1IRL$)jt0sqf zSlwE0Yuq%wWR3#Y@lG`-jl=xkwyV0oOPX_LbNJl4JFENrOA|Y}^>Tx@h3766Kge5Xb#8G?bhX29_>r4PO3#dJ;t_Eb)96_nl7o? z|IPd(Q~k0s(PIJJ1rE1^j|WC?b5NXDgH7RH8wm6-%Y+;H>l5_{byr) z*yr#jCpks+fJIgjHgh#6m|vOhR&T{1$NnqSxy@eUce9GSuwpj9eC(U|D-D0zEN7lN zPp6}4mtDPZU&u50GE3__yS9kFEamw${cCIG-M0(PY6V)(T$21UcmCp*|Et!gYOHu) z_G{kdjF~@cbH2V@^31r{|H{S}zT2FtieKINd(`VnM^_*$ucg2=Gx;nYtZt0@1GgGSyPF+&%@_PL)I%dkEf0DeRhfmDj;&|hr zh0~gJ1*?l^FQk3*pWA7&a`WoSjiTOa>97AVeRo}F@#e4QA!Q@EWhU`G=624Dq-3s4 zoGSayajVKqshaC%bL`xfiqv))WSM*RbVzs$7t7@FK49ADxVdWgJ2gIz!1ot_TFkK6Nn?}WAgi43ggx16bSpDoyZ&-F{1 zUHzXQoPQaV^i#ww;H%S-kG4}jzxLsqmO3@xyas?B!n8-JdDE6bn6d)2#z(JlXe z>3*BYi-~)Frm7!0!xgZ5{;zP4&8yg?4GcFtx#T;oVEzLBqLr7bR(}kBJ*&OWxzs=S z;=Wg63Uf={e#gGq_xq)j$tKrlo>%tQSw$Cr4aoX;(OE9_euzPcS5f?xjeIXM%5`3S zjyQZM{#nmo^_TTuoGve|@%p~7CNTUupX-`m3O_8rpIOUy>UZ81|D)b7legJ*EP0nM z5OiY-Yfj&XobNf8Y#Hm$*C#uzEm-)xW25`~9LE(apZ}cDz{0TNTj(*i1*^=zZ{f7# zJ9|e&W&e!FM@tR<6detqhbmGCTT zu&$T2d0+G0>Zhw{ZHeyoL&6hGjig_9-@I_rUG`F-vHpvKUt2HSGIb0$U286sU3~dR zjljp70dHQ0hrhAf#Wr^_Yws;Hi?_=b8=bDN;dpOw>RXn?-0aJWM|1@KKRn|9>Q>kf zeU6~zH{X;j`X!<Xtn< zo8Y1MtUh3`n>?HL#tI14-?iy0WWg+Z8+Vb&Z81_lQ95>H=O z_Q$NOTr5^RXI0lRFmO%rba4!+xb-%=K1VuS_Wz#W53Q{|bJa61U$S`nB4W2`Hh1>2 zm8n7M3p-o;>;oJPG*%s2;^Ek|ZiP>(uv3G{Mo(8}-5}Kz4c7)2RhHcCTuXd2UJ0aR zER4EVk{v!PBKOX*-rE-Me%5_z|GVz}x%Y22Pu9?U>>2jB{C;`e{qw*7{ixYruG;r_ z!L=Rx-%d7Vop)#DA;0`?3SCaxidHHR=mN=yJ=EF$8q+Oeo>X0-W+b=jhN@pk+SKYqU4f7nP@Vj3$G`y`D< zi-tr?hK&hPW>F%nZMn|oJT6a+m^LXK*pS=fdq%g}#6w478|U3Ei8BuDbFbd`|Kr4z+CDUDriP?Kc4@8hY=H7_E%r*$;^?ax2H&%HWvhQ|HFW{g2) zva1Si%CgLu#u_OwZ6+&2gYuzmvMx$S`|e!t{kBad@1>Mgvi60oR;-$nj&xp+XJ>d* znZ#}+{QTp?E4(YZdPD_9&C}99{GP~Da<@T2K%Bu*fRSNY=s&qshDbg!hpOtRgebKX zN2mL>-xHo6lZ&Wgy!_K9EzNh$+gC0w1|Qq^|K;}oV#mVpe7yrM6-I-+^s39^j zXYz%a9u7TQ9-aBg*|Vpfvn^MtdT;OV#o9@(DvwSdW?iye?j8ff3m+AOx#tgWG@Y@G z)idmYfbjHnX^FSZ7#@6i!Qrw~<_6dH+$lV=e2glQjXI|{_)bRfM@l1qaf%c`d ze=p`3Hb=WYc<|hQ+ZVkD@7ZfUZoc>H?_2Zz4+M9ZlWUp<$XsUiNHq(Hwy zF7K|-k+#i$g8i#niunI>&TcP%oNb$5{jA=2qinLX`o_lr{pt4R!O=GRi=XaY>>bX% zMO#~X()+Fw<&U?88*SOX6<-f)j>geD?>x&U94sHa!0|$E&aU;zdknl7 z5`tfwz50L0m#4#h$LBRQ_f9#g1~N2g9f>hua461GRxArSnRzZZM%Qn`uB! zu2@!Z^3+ayKl28L>1RKuFv@KE#?au-`9Hu@WR-yPy;F{x^LBsc+{nD){hEbEsdo1q zEPecUTwFM5MfzcpziBCvs;jPrO?kd{p~8kDodw;u_ybyJuxEyLJlwF4on7hp#5~!O z6`k_ezE_x?x|_qRy5iF+f#O)TT;5&F&lfY!Q#ECE@QHkTtkE)e)4Isd6Z|`5V^SJ~`efB)sR)DfzB>pHfO}M&g^@aVy z!IR}=H9YRB9$k68NLl~be?xtSw%)xL=G#e0}*txyWrmtss$loNw!k|zjbfHM0NN7`jAJf5IYTSMq;vTE!GBm6{%E@qGRs=so z#gy-t{qG%n`SSmVnf?>IAHRR}B74{2C`SFQnPnG~c}v!9c_+xkutxNUsA`c=pW)+; zY*yu8o9(Z&CDgvzSGn^*`Ti}JUMGJPu?jz8P`jGv%2{oBrF%uoxv$K;)$uagHT;=- zeP_ts;+z*MX8iA;o%<+qHC|n>@gXK7j7 zGxwT3nwcGaHC*GR!+tmi3*#F1_cCgXYI*{VCahW!tOn)G_D75U}n(%m@c9i6bn z^aan!;|4izzJB40+`clTd)@AkugsGso?{JF@Zm{d{J#5eLxswQ;}Rw-R&IW}F-@FP zSjJN-RbYpsK@J;7GGi~Bqdh}i_L*0bL96QzByXtHKHh7{x$*GCE4+VCn4M(4!uvOd z?L_dLw9eJf>tdJ2tW}t?y{P4_{E?;KX8mQ}zsGA)W3NQ7$jLqOJpq$8OXT$XhUe%j z>TP`-@MX&B7=Bm(%2~Q~m99NXdRwdQx*|NAKc3v|x5rb=!{4&+lr`Jr^w+22p0aNU za4azV#q0fVT7<3B(?8F957arAzyJJH?8a_;x6OaqI*&id2z?>H^$|;I>eR1(4rdfT zN`(ovv48NppRc>;ozeT9&Q5PWd}Dq!^>C!EaK+!WtnSqn9bZ*=CQNz87LfSe@%6H6 zx$|o7bBN}xkXd$prIOw1La7M(TW>#w@vRd0Y@@sAR9@EIHs7_kZTQ3ge!9XHB6PIz zM4?QF%=a^%XQvz%VcDg&I(?4XHESF154$_W99pGIXDVpvTv4!;(CEk>7*{3L<3;Of77d84AU^9+ecH))fg*XOP$KG|%Sr2UR zxiCLdLosWIrqp~J?zL>$tAlx`F=iCiMu>A{b+t`ge_cd0BJDcI$;7FzyGkajU7PF{ z)9}45LZZ@Mcu7iU6i4Do&$UVFPre2mov>@+{0(AH%zrD0FYvme6tzX?nW^i|N1eAt zQg_q_JNC@W3fTB~-md=loB!PBKjviW8hPOu_hOIj(~Q|aUcQ`qlG*9P8--o5{j>gy Zf495$Z_+{59SjT%44$rjF6*2UngE#Z5a9p- delta 2793 zcmbOc_Ca)lay z)s*Kef5^sl89b>%JY1ogEKLhUJ3uKux#O~y)Vo8<`u<$i(xFPa0 z1ILcTFaI;>Tx)iBtG{Bc&Gsdy=0f_lJ;n?>WSe3Qm9$@9zYzVCDLu_^LUcCcM`IR- zH8woY^)eNVHdIxzczLwU+P&`X!G$_2_;TKOBqW8kC(i89GP*M7<(jQ)Ic^_R)t{!& zapI-bqK5|m>N3Sb*x%((%vR^{TEudCOY%Yu4h18JQiszsPpo2Nc;H?if46J?n_G;l zm|fWRZBLe-_xDTMmFuk&LU}VRFGmWq{*Iic=^(UpPxp-l2J>zeHKryubWLz&@?tn_ z;^3&zt>of)b>$2Ra?hFqH z6`5m;{l7m7ug_{{3WnG;g8@V_$fmG%4Z+A9Nus>|XkhGgm_(mB! zV_T+^Sc}wV28IPnI^9YllRmC2J-b7D+L01JSFKA8UnYrpEL4fB|Ln`)a9z1xx}frf z%s=BIUatr@XODwhXL|mrdSFy!Dcj^A!@%Om!XUA%HugAU5Vx4at?BNGGuTob5AFJX zxBJ|-rv}BFCC;Z9SSBY#TD49{c(A?xpR`w_JhJV{ygOKIWIY5?pYZ=Otp#_h)3vU^R-o;z?VoJ>5iiRW_A$A#bZj<)@t zogm3}%vh4)z>}WF>;DQ5{=86dp?7XB_nF(} z>woQeUH|Lj7tWZOr;;*lnzVx>W#0Ypc);yz^F=D`d)~qH>HFW#`v3Go6wkLW$%nU3 z-+eEA)ziQ0zE?i~qMzrh8IwEf@{w|P^Ap+inKqx^<+iQzJ^G9L>ZveuwvsJx*%(r` z3c4Kf{xI)}mH6SSCmGXu8?tNtWRKNv6%G}z+pt`Ib@g_JdWJ`bmuoPjoZ-}1!pE?H zLr`2oYp%OfPRn%vrJr|9l2uaGRao77XU4QCVhMr_4>XhgZa7W0(r{vtEM{6|`F@T1 z5w`Lb*uHUatdrr=btweYd1Ye@V95H{+0jZ-_^a*bAF2|J`#!( zRC+Oye}TJQ!up9;)o1HZPoKZuOQ5G^x>FA{wNVU|JN?0{sG^fR-JmY z*bhMucP%l#XZv|k@XxO^@9vPf78AHPk~>(<;QVo&C($#%rUY(3@+0WWO#V2BRZGuC zO3y#X6nwbiUB&9x^J-(aJ$!4E@x!h-E$4vhg2#N`Q62029Kzl_ICiXaV&Zfjo+W9z zKHj-IJ>$M;sc!z8-Qk|x}0*xhwM&kGUqEiq?y{2~OzAmwP z_q$=e`(ju5d08C^HC*S+Zl8{yB6~VPkE!L<>Kji~7Wg%s@MKRjJKpdhb~5{_H3}9h z`>gAm;!pDJY+++>qhGs@l0vcQfeM7#@_|`1K;Uy9RS&TF!zM4LNol%Y!CO zJ;o&N5Lc0AxxD<=v_sdtzA-)Jc+cvzx1eR3cEp;@*v9H9!hil$wOqFDcMOw?JtWRO zi~E*<c3{!slnrmB4pU)l3y zL_MryFs`=eii*}*WNduyhSmAfzByr$OJ6>Heti4gWh<0pbe@T2<(!$9pT*><=6L*= zg1i;a&U~H&Gxk52^^D<&-}0xUbDb??ny_&kEvgNWE!eEvu>AS_`d16S*KVF}ba2LlwbpS9&f8yg{QFM%qs5bb;R3(z z=7a3W{IAWY(R69o%nIiFr+%60<*GZcTqL<*&Yyh~oH~|VR@gY>?{vTEXW!pT^mW`{`HJA&wu1xWYl>2dFhY8XKuYeqpxW8>yuIL=j=a! zaz9?~D?0b1>!X$X^J)J*jc*Fu$LTnQl_YG6z2m>?9N&`mI-|&pT-T z;A`C45!oQTN5&x2vUS4i)BKF4&GB2luVxlXN`Cu4tEZOt*l%9JWq<#u>Af`Gy)pJq z{DJdp6q5ZMmVOR+xhLB%s-tt-j_JQrIqw~xxtew7r0Yu*!`>O4F{*mP%+L^5`})yt z2h|0vY>xfhQ?|@d(mR~aYZlgWBI)e^iz4ga7U?M1)pTtV&iVFe&(G?zO&Z>vem)Ow zrI*P+*3M|ppTv4$fu+90?W2EH&))MsbLHp0{R(MMjM*dKOrDv=9Om`9&i##YXJBAp@O1TaS?83{1ORJ}ITQc@ diff --git a/src/main/resources/assets/ebwizardry/textures/armour/wizard_armour_sorcery.png b/src/main/resources/assets/ebwizardry/textures/armour/wizard_armour_sorcery.png index d5e31f09eb1f8bbc2018a837b5de9a0e3d056ed0..b8b1c69559d50a2ea1b0f660477237bab7bf358a 100644 GIT binary patch literal 11818 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 delta 2760 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 uH*e0tGv818tYs{YuD!+erZ!IOv%TY%JTnPXU3 zJ*4TDef7yxJ-=%L+@BuwTkUvQMI*Jor1Y2ijkjx?%`fk>y;Xnmxup6T2lpqE0l!X2 zO?@ezrf_lh+~>weZ|cw7{q)TIAA(7i^XK=rOB_9&G9&wblk=DbjNYx0x!wprH%{BLay zbILA_k2T`+vYgdzHO(lip#F}+(w;oN>BrA6dUss3kX6Uf`3uu5>2*Fbk zK?&P=dR3`^CTFu|tzE9Snaf-IjQ4kzBPLcm>)OQ|3TDr`webCp7kc?uWFr{s9j#ON zA`*gb%O!2DIjt)>hqW$DGN^jjW_@D@l|whgCMPm7K8?_^4vWh^&m+tHL*-0N_eE)r z4O@2^m~Id(Y!EJym#($pkI(&@ckCjQK-ip$1qa!fbdq&G9iQDG;}y0>F?;Ridu-CV zMUQ$mpR;`bOLFR-ipOiq@BMzT*x#{noC}4k z)GL;3dFgAm`R3W&I_~H@L2kcNCg+yjd_E!B&sALW#=oPY{;E?Vf}VDTtXg*K)vEOi zkIj-QTI*?i*6ex>x9+wrD|}b=U-{wk&en9^6)QvIKYx0q&fJq%+##>N&6wFRSK>&m zdPB>#`nfZ?a(do9u`(7lHEX@P;Mlgqns+)I7pz>9`}pWPw|Bbco1UrX{pyk_E&0!G z`Raw*&h$L}6;n;_X&5nljlE$SdZ}Q8sqkdJA6hbB_xk*Ox@CIhY~NP}8~uHEciQcU zFR3iS>QFZ6%$R2L-T^}^_eat(reXwxrQ&}}7Eat$YfqzxUg=2!3XJMKQih=4y2}jERMat{Tdg8fFJ{dv9rsuS9a$M>or+d zUhDd7vv5_xX-nm(p4D1W*&cBR^;c?zl&ZJ}^fNcie3Rs4&pEmwG$N0<|^TNDa(O0j|>-Z;mWc%^rDP<-X*`I_TT zHq5QwY019eq<6;;o>{-8ytl;Ldgr}m7yr6k3GLuId p)jYGYL$2CbTKRUAwEPKQmk;bLlb`S8dfUJN0-mmZF6*2UngA_Ml?wm> delta 693 zcmaFQ^^|pjvH$~HlDE4H!+(Y)49q3*H@;5xWRa_X#KFy{%2ea!puxbvROIR67-Dfc zbn@9el~5kH^I!Ltu3oi!vY*l1nH!{!Fddn9ch4yg8>{G6j|SY z@F-sU*_4ZQXX~&2ls*2p?cu+s2T>`uiw?VlrtW$xxP9^NKRwSJF3CRr$LQ&+aGOuj z__)up$GiQn*aSCUxbD8>T*+-g-L{|axC;B~of%HqEPQyRqK4NqVBdjVVwrq4XX7uv zR({kc5q*H$G<}ck#F&X{TO+bL4=#!n&nXp&>hQKa#=D}R^rQ9c`m?$pf6AQtaGtH! ztvk{x*){vnw@xSjhf<20HZe0r(Zy3 z72Cm!<&7p=I;_^1Dac0u7kpgLGmZ1PQEvTTrjFy+O>C4WFP`R69QoqB{|d3JuNjMJzB{?Rsl#!z>(vR~N3B*=Y!J2#og*D^d4jRW<0;GDeoR~TQrJ!UQgOY1 zm#&D$LdR8$O{N7z#b|e&ox{h)wq%-*m#}K|ugxt}O=s|xn>LB(7%r*o_Z421DrqG8 z_|&3^*Mn+7tHQY_?A8AKWD=+8(sai(K&Y>-xB{lSMt$xhCjTFzx~#o>~>9HU|?YIboFyt I=akR{08>Rv)&Kwi diff --git a/src/main/resources/assets/ebwizardry/textures/blocks/arcane_workbench_side.png b/src/main/resources/assets/ebwizardry/textures/blocks/arcane_workbench_side.png index 15941b3c4acd82b3f3e63c8a3239f7033c43703d..9050fa299c21ad5a8ac059f8b97722689890ace6 100644 GIT binary patch delta 2171 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 diff --git a/src/main/resources/assets/ebwizardry/textures/blocks/arcane_workbench_top.png b/src/main/resources/assets/ebwizardry/textures/blocks/arcane_workbench_top.png index 4bb07810093f4c7177ed097daf93079c0de7b933..69e7e0b77c45c0c1bf3ec315ec1e7aee5bd4dd40 100644 GIT binary patch delta 2328 zcmbQlx=3h(ay{GBs*s41pu}>8f};Gi%$!t(lFEWqh1817GzNx>TWiCkH)*T${7Dy$ zWMbkxSX2>~${txai}6_h32_l`no&*O=X3o`S+H?6OP|qfBnMtnqxa`#5CT2{A5+1w7p!4 z{08a8M-6{{(ko^NI+(M(PrLrQFbnsBFV{CUcz+bNd0na+Bd8bFaPL6c!BAe+B8O^$ z;Ke@8ze?AKBr5HGCsO`=)#vLGUtUdGEv{*!FXiXxZ=7)CC)YKbw!699vA>sP@Ane4 zHg8&@tf9Q-N6}3GX8WCauE}REEam)okgIH`WP?Gnk$Jr$t5Zgf&(lNScby5YzjH%9 z$yQlSR?XUPYLHP8sbp`6V(Toa*?lC2wXl9f?!Ognq)f^$l;~aHH zI_2|X8JSfcNzG);+rzJ*zH6uXHI3L!es`qYG8qLQHHQZ@voJ-TY5Eb^*RfD1?nZ}) zz*G&-q7RMDEdnNIq^4fgUY!web%kf~m->l|j|i9^n~~(FS2@MNQ*ouI;nFF_W@iKD zZnSb%dj6fIGVuerOwT-bVi zUX@(O)`#r;l8G-mlzVG7Z;Px=?Y%eSw`um4$k{y~RhRQ$Ggwm z3IpTYdbM;jq0O_;_@2ut^57~==uMe)Im3vJZRh04j^^e3&+1Oj7W@~!XXpDF#*=sb zZ?-gEdHYQ5)3?moy7B5=`#EMsS{QDvTd<*b!lv#G?a_0;b6i~aTJvX8vjDee_p8hw zyY5x_o?XQxu}A9&uiq4|CC{H6Pz=UUw0dh%Ga@eelAj zm9BQH94^)rOkmo4J%`0k&wpy0%5o{yn0r$rXJx&beqqK*j)Q;MQrNG*o7Q&Gg740C zHO21E>F0Z_Hi=!4sJ*zf%*XA>^&&BL>wtR?&zatB-CY$IH)Fv{?`Y#Ui{Gl|eBV(2 z)O6ww{`rrdEm0SL$GWv%ZGnJ6&pa6U_}xyE~M^`lqBmNsm;sCIdI*wkBJ zjrg0hBNbomd7Cq#U}5vt%ru`9{~kBGq;%XWlWBVGcrDNMj_l^tTu}-2?0VO;aqrk( zS;Y2#mptLorJci+v~&7iZ&%hMGq*bA+^}6}7pI@#dyi@U^{@bY-k(F=Ki9^8b9qxWgY){WPKJtxBfCWot`WJgD(|DU-UPp&D$a8a z3)GpLytmuOGzRf!YQH+VFkybLeV1(g%IPj%?949WUH`wfom;pjLh;G7M~S~~U!AsA zJ?zTjZJeuZZJ4=FoH^K2e)Ykl*}H}9l#XZZE}pi#v|4&gTl*F7#g;K!lb0{>;eXHP ze)IT`BNvnRtM_*NPZcaUZ|+u^c*soYa$lJ%*P$){Li`?OFPQNwx8;t@zPt8|6YLH& zWPYy?5&gN>?#DQPrkJ${I_bT4dcnTAo<&QbEYX_+O2j%Z2`D4#$PA&H1j`w(s{8omBm{MJF1Yh#zL>yWd$ z{31LrOFrq@;yG%T5%pIp`@ZZ@X3y<)KD^(#J3M3I^Xv?_ROLr$YB{$nm$B-;zhD?> z)g>|Qa$c&|tW#TdzCQWjL~Z_Bt@~Fl^h{?rm7l>`&3&2GH)0;+uLc&M`}=&VKjp5F z*F8$cL917#P@+yxmj-O#Z^@^zEUB3y9Oo4hLoqdji%8H>tBg* zu4;OC#q6`Q6z^p=hpTsD97RRCtS%>yV>tAQcFw2?pXYUpnzueuw zSaK7T-)nt1C&$TPHf5UAx~3<6iL2CZ9ayDS_IJnR!!xe@l?oNs(VxNcr|I_2{Y|#~ zJ)UzvZj6c6eIO*G!e?`6zwaGJhTI1ieZ=0>s{Q*eWgNL|+4r>{|DKr>Gbb|T_w>VW zF8{Rmu&EdR-lYG^dCRP(&*^@G8E#5B$E-W$x{DnBf4`Y`d*5TTHPf?u?z~w3x?qZM zqnwgai^uW9Yrd%zoY9Rs+wk8b#P>(N!_^jRa|OW_VN?HkOgfPua#8VNk(KMx-N&A} zHSzZgTe~ HDWM4f7FJu{ delta 634 zcmZ1^G>LVBay4nJa0`PlBg3pY5)2Fs>?NMQ zuI!IExcOAMS*QKzVPIgA_jGX#u{gbS^66~hK#^nhp7}zO6E!Zkugsj>!Mc_Ig6rKY zy-gu21(~v9IdTJ=cC7f{punMb)K^QH6HUb(+|^o*sk0&zR?{hZTAnm$Yj6$W6K!BFo?@R?@1qXA;X?C66a1 z=ErLtl}<4%DhzMjSzjWx{ldaM3FTKp<}UOu6j-oiQQ5wqxA|WEmAf}}xnYmhk+^#8 ztZ%wUFZs<|%JqXOP9QD(Y2uZz28Q?pr(fJ%K4nPNz?2T#;qf_oQI=MbT9=ezBOQsAg(yI2R_!P+xN5%r0Nn zwXfSeH?2_g-gM)`<186f!L5dqbWZrLw8%a1^hf;3Y3yD~r!FMyVdI{`x=r}D+{627 z>x3Jmis~)ceu)YHukL*)k^DIN+7Fe|`x)P^e_kBuywl*jyWr^~XP<07{M;a{?qjW8 ze{s??+k4EiEYemx&2}AMm$x(5dY!Xf@$NGxZzndn&$6gl(|PB*jgs)Eg46XAPPX>{ zDcSYbUFqbZf6S9~&g^VdeXo_8-1}}`?HUz_DP5vUrx+eQaak~T)w0PmODE3`GA|2l v@R>b()w0Fe-FLj}A01q5RdQZvKjXy3#{VYuKk;B-U|{fc^>bP0l+XkK^ED;A diff --git a/src/main/resources/assets/ebwizardry/textures/blocks/crystal_block_earth.png b/src/main/resources/assets/ebwizardry/textures/blocks/crystal_block_earth.png new file mode 100644 index 0000000000000000000000000000000000000000..cf587dc108e15ce01f7b8b85a5be662795acb2ed GIT binary patch literal 2864 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 literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/ebwizardry/textures/blocks/crystal_block_fire.png b/src/main/resources/assets/ebwizardry/textures/blocks/crystal_block_fire.png new file mode 100644 index 0000000000000000000000000000000000000000..10940157553ba61bd0c00f8514d4ce40c7aadd67 GIT binary patch literal 704 zcmeAS@N?(olHy`uVBq!ia0y~yU=RRd4mJh`2Kmqb6B!s7*pj^6T^JY`Rxtc$){4+# zU|`@Z@Q5sCVBi)8VMc~ob0ioT7}!fZeO=ifad7hqiWqNU>tkSG^7V9a46!&JJ9&S$ zh@;4H`<=Ian*^^XO=#X>#^%)2u`F0XN95+I8$T9rjLFeyN=V(E@KC-WM|MM?#}R|M zix}4y{o4_vGUwtE!%oXJ~ICFeDWSUib; z&0N%Qd-J=EzhYV*&zbY!`s3;i{k50o3G*4usANA;-dyq6?y7jI3`5%jgU}YSB~yjc z;vU6uSzYuET@)_bx>D(7ztFSAM{LCp#7MTwJYf7AFu!vF03yeaIEj^`a? z#*;ZcJLHnYjM?I>S&vUU9isBcFC%r^0zKt3lU&woG91||@Y!$C_9=U3I`uI>C=c7m zrgGVk$KluBD=X91ZsT_Nq}H}DXEW!EZB4ZX-Ip%ym26^8JLtADOirnA3uf)5(2yIob z5t58H^Yxf_bcVms-_XeTlOZzOf=@W_3S?s6BPhRjk-&84GkcEgnc8t%@z?T0vp4jH z-oBZ8UB9?DPkw=;PuiCKn$<~a$E3eseBE{Hn;y@Nb6f3CG@HMA+{fBsXti^vIMb1% zd7Yk)JWVgo&)C9V^7mwKSn0Z)@c;eA>z`JuZApyx?~!?~Z+L;@+Mm~)q6`cS44$rj JF6*2UngClfFc1I$ literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/ebwizardry/textures/blocks/crystal_block_healing.png b/src/main/resources/assets/ebwizardry/textures/blocks/crystal_block_healing.png new file mode 100644 index 0000000000000000000000000000000000000000..d20fb9f072d2e423a25505a5aa3b8c07e2d65c04 GIT binary patch literal 740 zcmeAS@N?(olHy`uVBq!ia0y~yU=RRd4mJh`2Kmqb6B!s7*pj^6T^JY`Rxtc$){4+# zU|`@Z@Q5sCVBi)8VMc~ob0ioT7}!fZeO=ifad7jRs0m)P+`z!VROspA7-Dfcce1a) zaG*%r{F##yrH;?)Ncw58WYK{Q8@N}LWiRTK&sn?L?3cKQ$xHsiwbNoFg<@w2lyzu+ zRL-yOaGepde6nOAv-(f@UjK`i^4!Wo_ zpFVTx)@ebGqX*`GXJpvl<-g~8OUveHm)&!Y+>AeVt8LoWJC@}W%sFEF9Z!2-Q4Zg% z&|Fj|l)l{K$1xd}2E7eM#w_QK2r$j^J;2J>_{^SxVJG*RKRgekizDneXE1ZlInU-8 zoBrRoZCyZ*ecMCE9RK%x3wCbr*_$M=&$vDG?4nqYgqfRHBwMk!D%}k)$?87O={orV zm%or?N=)Nxr@a{qjs{0O)48>iecpS|gnFX@_hTFPiv|2D&3Zq7Ax}@EmV!gH3**9U zO&Q~MnTAtAZ41@~N1od7YpsvVj+~HFJSUrimO7O@nphrOc3aiN@%7&RA}zPQ84LPe z%1E)@U2HY6(a!62YTKdODc81j-1GZ)*$KB9u1DW~DzmUtq`i$_Gxv|eCHZAr zcDa5@lgia-Onzn^Tm42{AYrzp-|?U;+-$Ep{8Bc|zm(ScB19@z#qsN7lSMC2zyE&l zl+Kk#sVic}Eo#9xT$?Xd&3tj!rvQKiS7{YDM3wV*%C4$J@CWbpy^H4?J90@Bgtqc$Ju3 w*Pqpu`LFzDyq4wL*2o)QFhO$Pjq~wcZ7gCnv$lIOFfcH9y85}Sb4q9e0573Mxc~qF literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/ebwizardry/textures/blocks/crystal_block_ice.png b/src/main/resources/assets/ebwizardry/textures/blocks/crystal_block_ice.png new file mode 100644 index 0000000000000000000000000000000000000000..230ffdc26a80db4a4f51c5768765491e57003566 GIT binary patch literal 876 zcmeAS@N?(olHy`uVBq!ia0y~yU=RRd4mJh`2Kmqb6B!s7*pj^6T^JY`Rxtc$){4+# zU|`@Z@Q5sCVBi)8VMc~ob0ioT7}!fZeO=ifad7i7>g}&Oo6Eq!^wZPDF~s6@?!>$P z!R0c??DrS*-JR3Ob!d&QX>Q7F)53F%rW!LW!X!`XU8!d0`PYB*KeJM}_qN$bx4*b> zPiJX@W2cL|cNFc^Nncbr$y$>^uR=yAXJ6|s)`$9G;FU_9mi${|TI-{qLTB$@Jon|76hppNLbk}w z6K4JL_P&?imVC%~DSA6p^sLsT8@fhiJLN@wJpOmLnZxu%N>_<|Q}0}@$I5k1=S!Bk zRdamV$+3P(K~|~R_SHSS-#%YICBzW4!neai!sfr}L-o}@J>Nc8Xr8;0!N31rcN3F( z%>2intv=2z5sZvma_!sAb}f5{nE%$Dt7hHVwYMQ-qRJ=J3k;0E%A{Hjow=)iHud7C z`Rt1v@158*Pgi)3%%a~Kd#*hWx%KAACR4R_yau)PGiOh>Pk3KcxFRT9Dtu})N7USi zZGIn?KTPYD!ZP8BIw?6j$3=<6hspees z__O(R#e)71hq(7`kWYK}(rRXwWac%GCt5ynADg*sIAje1M40wnF1ZzIwoR%h_FZb- zM^(|Iet$irXYP&N#kYOZiK#mTB_3RSz1?G>lJCV7gD2l6+_`=9d6AiYRKdqTk`9N1 zay=9UW+Z4vtU6YnZnGv=jghrb-$=jy_h-cjA(6&sUoLpOS9qvumHf($2uZ^xV_MF~s6@>Ewgi zGN}^B>hFI)yDWS1T+>N%Jk#cuUJ~P9eWOV?Cunu=T1A%C>b$J2PNM#CqK_`_chqk> zW-Fo}EiiG0Y1ZruE+$Fg+oj9P(u9S#Pf9c1oV(f3_;Y1MPt}LLwjcKCpa1>1^5~g6 zrn#x|uF8xD_j?NpCH`5jR}<OAY_{_ias(O1uKINDsklZ>uv-4tAQm21 z4=*;6^yxbuU)$)W|ERLGZr$3A-jg_3*-g(zwVu2v$aVeHpJ!nQt@yZlIGVSao#f>$ zO8lZCAMJ-Cg``xoSgV zi-uFyJ1ucH|4k2AOv17vX6gvC-H+Svm+fv;@`cmpxavylKfLiute#gNPTt9teBSnO z(Oa|ITi?&DN}l7i@{DhKbL*#EIWM;btZAo~+)XZ1%#vSO;$fZn>DyBAndR0YbL=JT z|C`89Up1rTaqW*2hSTb9F4(#8)Y9q4PTVLHU*wVOa)^Pqb*EA9uES4$KCUtQY?_gw z=;&~uSwS&_z2?hZuIQ<$7PdT6JV_^Pk|xW)QO&pQQ%d=BC$pt*qLc8%AMee%m`h)X z2$UJ_`TcN>o>=z+MqV{L#>`7w7(TpYKQP5kreT3TuXVz^A2<4WKZ_p>wQG_&+pv^@ Pfq}u()z4*}Q$iB}+9h}a literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/ebwizardry/textures/blocks/crystal_block_necromancy.png b/src/main/resources/assets/ebwizardry/textures/blocks/crystal_block_necromancy.png new file mode 100644 index 0000000000000000000000000000000000000000..2db8bb8f5b633cda4e15062c7ca78aee2191c9b5 GIT binary patch literal 858 zcmeAS@N?(olHy`uVBq!ia0y~yU=RRd4mJh`2Kmqb6B!s7*pj^6T^JY`Rxtc$){4+# zU|`@Z@Q5sCVBi)8VMc~ob0ioT7}!fZeO=ifad7jh3kCM}OlM$VdhY4s7-DhScd~!R z>{6Ly_V@4qR(pGLvdPNKf2Nt2%u-(ps4_dww3@4NuS`hN!?yCvn}y=63Mpp$p4d# z5eJ$yI3Cyp$QwwAFl(H;9{;B=e%+ECTlan3&(Q7i?}$&Y0}G?Y>_dIa82dA)bXXV_ zvu?Bg{y{%yeO&d-1%*d?w?1EyzwKp9ZkKlEt=+X};xF&1{j7C+E93EA#`fjbOXkl# zxaIha?rRSmE7@2pFfbw7-IXCpS2j&i@@6F-!NMfJ{@r1;exF&o$GyWUl&W%D(@6ty=%n+3DXc znSUK;yuN<#p)6J3fY+DvcqA6~T>LER!gHKoPVn0;i5eTFH&=hH;9_7i(71p1UvI*W zZmuJzjD3zg?B+-k5q;R)e=Xx0TZO}R!v_UBjG%7NEPpNS@*$#2_p;s1r(3VDPwI7@6R@|M{g2?yFHCzU*K%o}Z?NKdWi08t zIrKGS+tC|FKZ|4x`=)Ap9@@ZqPhyYZ&62(x#m3EirB#hv8Cw<@sz~Y^l~=aasCItV z+5MH7Z?|lL+|7`AKa(bf8LLd!O<2VD)$RWxooWAG^1XCvl&||a?^SjF$CGKRr`g2Hv=fPqPK6SC|V;l=OJ}wXX!~7-A{$QlY RK2V-v@O1TaS?83{1OQ7BjSK() literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/ebwizardry/textures/blocks/crystal_block_sorcery.png b/src/main/resources/assets/ebwizardry/textures/blocks/crystal_block_sorcery.png new file mode 100644 index 0000000000000000000000000000000000000000..e416e570ed3d6b5084f3eba1e0af1a6917feefa2 GIT binary patch literal 806 zcmeAS@N?(olHy`uVBq!ia0y~yU=RRd4mJh`2Kmqb6B!s7*pj^6T^JY`Rxtc$){4+# zU|`@Z@Q5sCVBi)8VMc~ob0ioT7}!fZeO=ifad7imYZQLts9<1V+U)7#7-DhSchcGX zDWw9(?Tz=hFOP2B#U{PT^!2)E1D7UF_q~$}3>udlXl(A~{KEg?!QE!{!>oRB784ez z=q_z^S=_1rknPHi43nmua`9VSD%um$cI%(F+b_xIZ+K27P4DyEnsmFOy4s8VzBLVs z4NOjgf(HW+{GZ~K3EAbzPl zF8%XvHqVV`cb2>oel~6YLzkxtZu07fFERS@H~jp@_4ixyvvj-UZ`;pX#@#*M`oUfC z!GSxURI7UV!fu|fd9C;N8{4AVMK;G=8$6r*4R?Q1ZN4U4v3iDg&F!xjUus>+esb^O zk1r}w^A9<6P>+cl4YH1zXe!h+={6nFbw6ELRo_kT#kHn>3 zsOq}ny<=JcL!ok;uF3fV@gt&-B;=>@Z@zNl!O8Q!7p8X?zvfUr?t4&Cb6=i?DBg3r89McP%-aa|=_WjFy?>B6=YK`iD&^AH1VBOZ)4U2;UW;+}>tX(qO z-!Vw+`nwCcYYlho=PUFmP|i85d*H)4E4`+d4BPEEH8M^;om@O;=iVb5Psy$DZIVAy z%JE8}VCzP&viI_O^L|aa8Gr8KCDl)B1U}3#-d;0x?XlQDZ#l)}?xa+_SJZ2o@MzHk zKI@>gdVBBkWYLxKO(C8KZiL=Hd+}6ufPQn@oH=#kuh<3rIXCjKD7feJ%qZD#N-;*J z*ZIkZ{^xr?A2#YzmZ+34xV5o!_CuA9enlYzw+CGwejN()i~=j0pHDmMrW>k|slmX& Oz~JfX=d#Wzp$PzH&28-f literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/ebwizardry/textures/blocks/obsidian_crust_0.png b/src/main/resources/assets/ebwizardry/textures/blocks/obsidian_crust_0.png new file mode 100644 index 0000000000000000000000000000000000000000..0e33184a67d4e7d89babc67b620d24a41d1f5462 GIT binary patch literal 884 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 literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/ebwizardry/textures/blocks/runestone_earth_1.png b/src/main/resources/assets/ebwizardry/textures/blocks/runestone_earth_1.png new file mode 100644 index 0000000000000000000000000000000000000000..707aa8e9e5cd651c0e948d5e5d01ab64938945f2 GIT binary patch literal 742 zcmeAS@N?(olHy`uVBq!ia0y~yU=RRd4mJh`2Kmqb6B!s7*pj^6T^Rl|7&0&>b{;;& zz`(#+;1OBOz`!jG!i)^F=14FwFtC?+`ns||E7-DhScJl5% znNR@-|Ep`?&HH%f-KO1cN($~1CJH+-ZR+U!!9StZCFvhi=K-f8uS59`4HG7AXgPRq z?#G<-o2z&I4io%R;k{}}+^XZ6Kc77Q?(7sWXS%sGm#|#i+~D=)Gc?1+i+8EydF&S^nf zUm4e&Y-CsAoy0Y(rRw^}C+~}E8f*@%IaTvH@$ee06{lEU?O7N7O!%-Cp{vFZV zYrY>>wXa=u;)R29#h=+9-vl20l-J*FF#pDk@@N9Lw)w=c1c;1~^b!39<+_TGVR`9UcG^JSx@x6O|t4-!hvoPaY%XfXM ztO*h_XJhTRF+~K~urAdUd@Rawa8kgu&do6bj4Uo3H<{lSZ@Aa*I?K%XXvVJ|)uko} zl?(WH>0PdH3z6KUEcC_lLZ)fah360UzSiuwzxCQ_d zRccS36p{bU=I;azab{;;& zz`(#+;1OBOz`!jG!i)^F=14FwFtC?+`ns||I21VsW&gQ-I zKKh)`KVR~FtHkYv6otR5&w$0Eq4}V^AlTl;R zhxd19t@5y`ct1&8KRrV8!}r^5cI=)k4PVpF|9}29hqZxyM{}R*o(fB5hsmm4DpyjS zLNvG!C+oawS9ny?`Fo)yQ*dg%ghA)Whd0<~wH%%hD42G7+A6OKx!LRWwble|vi>_^ z<`l2Z?AgT+7(JVpG^s7TS!VP1wNXuj&4DeaY<{hnni(1}mGesFWf_b45@yzKSFEZy zP*nQh_WkvbkDo6IaS`o(aB{uadHFD-_;&?@=hV%<#l~Ja;<@MQyA$8*?;P`wSDC55 z?TlEoSU2zb=hAZZH%?r)FE6YvKKJ0<7B8Ng7hhJMjZ9T|Ah_l5#DW6(ROzA%{C+Gl zX9~-8G#L&*$awebqjrPp(cpktLWa8>IHt91@`-uU#G#> zbu^c9$~9JBD4luDc+sf|vJ)4aZ@hN(gya0?@A=vDYW7Ubuj|YxbHBHi&*Zl9>)7*` z?bkoPIlXny+_f8)usFr4uF*MF?O?NDosfM^U(NU1p%%7zesW&(?AJWa+vgx~Xl~kd z#smgU&d`}B9?nn+do6o@-!7r^ZK{d_&)$b|G%>pdsVyz6OuMnqRzW?cpMAN(LD{&! zn^jg$=xX`lk$mo8$)p!m%T1QvEL$+SG>{we#O!Ucq!&Q^>RR>^}9Y zYzJTLuD-**(m>TZ=k~nKry}yKH?bdnkaK%pnswF(dGWUVfW1y#+zbp144$rjF6*2U FngA@yO2GgC literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/ebwizardry/textures/blocks/runestone_earth_2.png b/src/main/resources/assets/ebwizardry/textures/blocks/runestone_earth_2.png new file mode 100644 index 0000000000000000000000000000000000000000..685fb30739499f1f99a035d413c54d0e8f364a12 GIT binary patch literal 732 zcmeAS@N?(olHy`uVBq!ia0y~yU=RRd4mJh`2Kmqb6B!s7*pj^6T^Rl|7&0&>b{;;& zz`(#+;1OBOz`!jG!i)^F=14FwFtC?+`ns||7-DhScJkS- zm{5V^^`Xn(xu5^ylQiQ^4X0qaU4y`cJ+0p1kF0lmkQH$}_`N`NM}cIEgUL*v^t5+h zuD{*)e2$j*c4OA9EA{_{{_)!P=gs8_0wT}vf6tZ@UNW_foh*Xt>T>PZIDDr5U6>$L{AdRA)dzR)@)@h9FE>oRD7{v-gMqWiVT#v%t;2FT zYZ}>Ac;A)JeE+}h)Ky8Jb_bEV%8MVqr8!?$Q)2q+z`U-V`SiUDS2Nv1U0It>`Ny07 z`Eb-D7&A=(OC^_1Ck_lHDGis5s%`(2}gRL`9_h z+-{eZeRK82eRgiJpH?Yq|LJZ#_bPqOogW_7ovzdIIV#xreEydf?zp)@GOL5lh_~e8S(ztN3QektokD_3mVDXtIBjd1v7e91B#voQ z93o0MvuA%3oS@PqJf$F{C1%dwl$y`(6TUV%&sEgADp_`Ujg*4w!ffH4R&%w23s+f- zr|a&oy}P(!mH^-N)r{U=_ob$%x4k{iTy)6PpHEFdK+Z&q=e6u3<5S0F=6vtev|g)u zxXkHl&!aOj>T@I4JKmSb{;;& zz`(#+;1OBOz`!jG!i)^F=14FwFtC?+`ns||AFt=hGVIWYa0nn2PqrU^<5-!v&IACZ&Tz%C%<@upc&h`CKLXoB zufGnvTikc{fmrTI<^S92qUS&D_P2L*3Yb%WFE_(yM_tv?4;v2qRQ^gi8Y0`E#+iRF z_r0-K9(ow^EcDNj?e%(#esxXae*eB)=GdVS8NrHgh5kDpT-7|f(dy|< zt_^R5_wU^?<+0{stvkFk^Z#Wm{;WEgBTUQQHvdW84PnI)ev|7D67Bg7MgP^+9{>GY z_BFrtyEeg(eerQ6pAM&2XU<-bnf6-Aab2U{u9?j-%q|;LR05Tnrc8wQXcFq{n$TT5qi216|B0%T8_x+$eZ})Tvy6AbqzhX+W9Irz zU1@Q3?&;Li>*K#JYM3R!Xa1Ve+v~nmxc6bc$AXrRXQ{Ibb8zrWiME}U`zZM|m{0H5 zktuVpO-VFgnB`WOwr=vdHP;us=W#!|)2?nY*ObrRDx%xkeWD~-9>^8XW9`+vnrNOj rZEoTI*(>CxJbH8N%!b+dALOrSWhNSQ>a;U3Ffe$!`njxgN@xNA&eumr literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/ebwizardry/textures/blocks/runestone_earth_3.png b/src/main/resources/assets/ebwizardry/textures/blocks/runestone_earth_3.png new file mode 100644 index 0000000000000000000000000000000000000000..5a23e576091b394b6484992282475ea2b27bda42 GIT binary patch literal 727 zcmeAS@N?(olHy`uVBq!ia0y~yU=RRd4mJh`2Kmqb6B!s7*pj^6T^Rl|7&0&>b{;;& zz`(#+;1OBOz`!jG!i)^F=14FwFtC?+`ns||E)GNLE-+SM`PfNSGyFTXCD!4v8dbX?VzTo1b;@YDDybU5P-(NHP za_#w%bM*FYT|@3an=>U>3%f8_*nG3OT7TP?;aLKk)z%N+%D5ZaBs?4=o;9qP5PYO2 zORD>^o&2B6%dgH|;Z?8Y^6}+E8>`c;MS7ye$9aRocy7p^YpMM5%IM+I$dsjT73EeZ z^Eu94C}GL!W#|-kY~!Z?79TF(KW`b8D%ldh|Ky#wR(4y|*NIKsG1qXFmYxDrTHlE+ zH_xtmcy@Kqici13_lYno9lEN-B(Q$IZsu-biyeon%8#5mY5CwCPx8};g$u$SSFbZH z?~O^0c)g|N^InN%)tRhETo&i#ArA>8_{;90xzJBN>WqRY+gWJ{f>yt>=tO}~1|w$&0j<#*pyE3Xg;c1XKpp|i-S$F0xnHt&jK z9)@c1?VbOk=DG?Ss+rp@4P-qf)4AYKvb~Uf&aIcn5_Lpp3jYkbyYa&xqvHP-PZfKn heh#qY6K(j<$Y2s_a`9l84FdxMgQu&X%Q~loCIE;~JkbCE literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/ebwizardry/textures/blocks/runestone_earth_3_overlay.png b/src/main/resources/assets/ebwizardry/textures/blocks/runestone_earth_3_overlay.png new file mode 100644 index 0000000000000000000000000000000000000000..c4087bc965b93322548841ecdbf07a25910ff340 GIT binary patch literal 730 zcmeAS@N?(olHy`uVBq!ia0y~yU=RRd4mJh`2Kmqb6B!s7*pj^6T^Rl|7&0&>b{;;& zz`(#+;1OBOz`!jG!i)^F=14FwFtC?+`ns||AM^EH>>`oM8WQT%A**LN;f+v8%=7O`z!l=Cg2 zU97_4Qo;(qlbum>L#7nw&W*@fj zWU$-4^TBd`cEP!K&Mo8EU>_1!Q`gvDT)tnqQ$W##KPTtlx5FOkhtkR){kEUi`lMw$ zvzOv_hv0|Lrz@WRE%#kBNK_&^;d9=jgq&cmS-^0YhIts3 z&M)WG-D$&kN%ZL5pWnXM?l`=Aw{HG)>%9M!{R~Y?T34Rgd|9r^+AyVMor=?guja*? zs+;R>2q>yNwAoZ7qov6?ZAzq}n0VV;e)lImt1Z@C`#ZB*ePx2BV)|W{Gd_}T%V%tQ z$sTfc#knJ;v)<(E&M0j&zWAe1I&{IjaHW+WcF21cHzzDQZ#z#+bM_^fUx!b)rrUgB mKHD5M_n*P0m+TDx*ef=q`i9=wQp&)b{;;& zz`(#+;1OBOz`!jG!i)^F=14FwFtC?+`ns||aDeUOgQqZDUD0X}I zy|3@yl$49M&&=^$J89SJ<*Q$5|9o?~KQ<VAD8sV^Hmg}5J{2)Gv`MUJx^R^- zaN#1LHDArX%FFX)hhygJ6YR@%cisJZq9t33hqcY~{+%_QQ;W)XFB5w4`;e!( z+N#By?(nQQ=3#c@+fRdeL36fsN_cra-O#HwVfj=Jtu@;_e>{6zwCCf*!kG)I)Mv*& r`?BI$*bP0l+XkK@)=JK literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/ebwizardry/textures/blocks/runestone_earth_4_overlay.png b/src/main/resources/assets/ebwizardry/textures/blocks/runestone_earth_4_overlay.png new file mode 100644 index 0000000000000000000000000000000000000000..000189caa6dcc9d9f04225c0d20e0025186ff990 GIT binary patch literal 739 zcmeAS@N?(olHy`uVBq!ia0y~yU=RRd4mJh`2Kmqb6B!s7*pj^6T^Rl|7&0&>b{;;& zz`(#+;1OBOz`!jG!i)^F=14FwFtC?+`ns||68>Y zZ}E2KyM5ooHoi#ovRZ8wx@uLim)*}F&PP~}?%20;ao3@ri-XN>&y$$yzM3`IkYSa= zpW0&gVAgZ@ZJ++UIxB+v&(HI1A#)U%4&1#h`~UdquVM_v2F!CcZT3eoFHmG#rBG7p z5VB%*$4?)xn}zla_GY^8Ttds7-Htv#GGorJAT{GNy&-dw+*V96|I5O$LYYfb{8p5q z!}p_x?F;<0+8%K@#cCUBndg72`TIro|BFXF#>*{OMB{SV#Bx>E@msIb3N|bw6 z=AzV7tfGmZd`>Y63OKk#Y$;q9t!w?KV2_s8-w8jSZC@H+v%x9Upm>pml!zeXoSb9L zY7@E_@{7r;`_74e9HRI@wZZzg;peySwf{f-95wInMm4shJV^lzMP^%kGUZqcn2&E{ z3ctQR=3mvT`}XUe-0Z#{^Ka9K@8_qR_%g7UFPtG9T)6Ffry7@@0@HUZ!Np29Z{B&k zqo(Saza96d>u1FRA3SIek$F4oCi_Z@sa&VmJzK6H{^{!Zi`B(t&WXU6LU65e+rxzG-q3b{;;& zz`(#+;1OBOz`!jG!i)^F=14FwFtC?+`ns||v`$PZhkM2=)F%k4q7gl{~mzpo#sGIc{oZEYJS^ZJoVQ zS#I7u#sHSQ$y`o{%o=xuTx>hGWA=mzN6y~J<=ZE>zu+wsw@#v?+oc92%Wy$?m8P3V zef2`b3#)BDr0Q@8H$@&@<9YiATW)_FQ|k&XqivCE?z*hqy0zhjQJFBy+ccM$_YW?) zDi{e1=w38SF8#bE?uNEm7srGEZkA#{qvFN0Z#OtQbzJq8F^&{jlNXg>zFEy%%}r$4 zt{HFr?UjXCj>{a`bi1A{MV`BtgLQrJ-g&AETk?#Uc(TR&pKsT_$Dn!Rxl?KVuLz}; zt9Y;b_7(D)>r9k6cE~?j@!q}r6Isos>wQxG9?D|i)Z=mGY}C=S5gTT!HZ4Cr^MVIg z{?5L$1vh1mEpT2Fy2ke6)HN^8pZ&8jPU8FWGQi2>(8%W(&XJ) gESkS{?T>nKKh0ljXITX^FfcH9y85}Sb4q9e00V6bb^rhX literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/ebwizardry/textures/blocks/runestone_fire_1.png b/src/main/resources/assets/ebwizardry/textures/blocks/runestone_fire_1.png new file mode 100644 index 0000000000000000000000000000000000000000..71eda33ef8c65e80b760eb428ec4363cb33a5f5e GIT binary patch literal 712 zcmeAS@N?(olHy`uVBq!ia0y~yU=RRd4mJh`2Kmqb6B!s7*pj^6T^Rl|7&0&>b{;;& zz`(#+;1OBOz`!jG!i)^F=14FwFtC?+`ns||YmM&cyUZgJ|>?-VjWPd`^As6A^iy!i3EfP;mk@We%rnz@o-JMJG=GA_y zlAPleW1q10>mK=Uhr{o4cvp06-_3iohy646wcobA(%;jIy}mG{6yJMW))VwB%kJ^l zvy*I;3in0^i>MScl(jQ6Fp1sfWoqF#V8{@6Ux%^4-_I<4j+DWU$6hb>X98LTi7OrSvJCm8UBJktQlrwklBy?0=Tgb(MbjrVJ!uwKWm>c^|IBW`Y=1FH3@N}+Le8H3>U^Y8AHDQrU z>g}z}zs}#cy*T^oq&J+La_64!iCpg?G5xaS|99ULCfunsnf>|UW8KgV@2%fGWwYO= ztH#{9?c1K)Yfe7%cy#!f$xunXs-R0aqXGMo|JeygMmf^XX1&gnE zb;?;=hjyMnyGK{Ha%1FtQ3J2HhQ|Nwx7R-GzSwg0rGwG()yGzb^_8ypp}ySBf6eTJ SO8E>73=E#GelF{r5}E*B%QiXy literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/ebwizardry/textures/blocks/runestone_fire_1_overlay.png b/src/main/resources/assets/ebwizardry/textures/blocks/runestone_fire_1_overlay.png new file mode 100644 index 0000000000000000000000000000000000000000..5a373e2360787c4404fa788cfff68ece29a27e07 GIT binary patch literal 713 zcmeAS@N?(olHy`uVBq!ia0y~yU=RRd4mJh`2Kmqb6B!s7*pj^6T^Rl|7&0&>b{;;& zz`(#+;1OBOz`!jG!i)^F=14FwFtC?+`ns||ieDS`?ViMBMv$L*?W7!*&ivT2WxL%+VL@C=b|GF4rb5q-|dS$6|;8Q zo_(>C(^b})e-~jrDbsMbj=!N{_FFbaCzb~i4D0i+Gwe`TpKa{VD>3IuTNi@_%R&dC zg%1vMhHg^-=6uliaqnIx_O=x=rzVzO_tUp%WH@|Q!|=lOQ+I?LKQwbSdIazCqQTEMYmR|UQ>nz7A3 zyVA%YaM7l>y9NIq&!6|{S)T8=7MA{S?R$6bPc+aI_x_h1ZQ${)W>?I|cYm2fFYwtu z->FzzS9WgS`@-gRVc(AP89NKbYMR{id^Y3AvxUg=d6^UV3B=V#A&pTj>5W*(c%cyZdi%{7O1|8tlsp_JjBXq@`Nelb{;;& zz`(#+;1OBOz`!jG!i)^F=14FwFtC?+`ns||{T{i}+1<@Tq)X-N^$>|)T=j%#EHGV=`c(8xb!e1J`Hn}-H>z>_00(~iC6zWdJZ zdC0~Mk{{Q5hkm{PWOjPIg-}3o*zRc>hrTAAd{(d^=;6bsO(~KM8mErm?Xz-`)7PuK zen%ji>HTfqlf4RD2iCo2C`j0wTX>+5CxE4){46iSD#y-6KF+L6lOqBP7&bNUeE4pL z^#6l<1WYeHZRwhC*7y9NoqECXf?59<90VL)SB7+G^(-~G+VC*rJ?CN0cW0cI?D)9S zdV@53*m~=Eb`>7ha)J+Q6og$Po1eaEGUo2G-m3A)?ei*i^O;sGe>@-br}=)qRwLe;6ltSw&5eTO45{@r{m z{P^)|<(m(los43R5f0T9UZJWW8Tap-YRiG&-}vli8$5F| zbiU)6cO;S{WRZ&bw!;&j{hs$xOiov<=J#pV{r~?muJw=9ynABLx=ho6J2P54!oEJS zQ|Mn-ysmyu;CcUzf4AH(w%z??_xyPqC96c1pJzVFHG83bVEyMm+W%jFYg@rsynM#T zl#Ndg=XLK6&R$TVxa!l7tdpzm24p{&;Jz-Y_1kgfM@;W{mMR>m+Rkdsr0~dvbBE>X zZ++bYh2~nJ+a5P~@rcaPQ(x3pt-ahZNoz@v$Fzx?gIRayKeOvSQo7qxTVcs0LBW6h swSG1$((mxeI!@Wh;jH=PX~@TVMqRP^HH#dUf>I-cr>mdKI;Vst0Fo6&0RR91 literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/ebwizardry/textures/blocks/runestone_fire_2_overlay.png b/src/main/resources/assets/ebwizardry/textures/blocks/runestone_fire_2_overlay.png new file mode 100644 index 0000000000000000000000000000000000000000..f32c33c322b256e9a4507297d828a81646f2831b GIT binary patch literal 743 zcmeAS@N?(olHy`uVBq!ia0y~yU=RRd4mJh`2Kmqb6B!s7*pj^6T^Rl|7&0&>b{;;& zz`(#+;1OBOz`!jG!i)^F=14FwFtC?+`ns||y z8CL;Uf0wk-{mXXezL}_+%s46h4->!lJ&7=n6ZNOe53nh2^Ekmh!Sq{2*UWWwJ65eW zGH!C+u6}J{$Bx2xQ{T_4S>&&Et*x_bq1Cz5o}7gDwW;CObF!KJIKuU8I%Dw3S8W@M-(~LQW5ItJ&xK zN)#`gq4-Y4{E-feR^TM*+YdcH2fu%;YZJBh$G`78|9rh~y~VC_X^C?8u4Pvp3X{c@ zqOMM^Znl}Fx8qN$+Sf-ZxA}kDPT$NO_ve?7nREZ6FO>?BiN;^lU)tOKpH-iq-yvmC z-X-ZDmVNK-wjI`6*}B9RY4uOfUU!RkD;r;Bilp|T=bu&YS}bBZ9>k&ark&ATxkDf% zK%{)RZP^)T*FxsTe$9nK%&f~#cdmFS_teDAr!|D@q*0Mt=!V}Z?=E}Hn0Gn#`GcA+ ypQT>MESF5IoKs-_O{9F2Wc!qib{;;& zz`(#+;1OBOz`!jG!i)^F=14FwFtC?+`ns||dqlV~E9R-^pkD zq(eno_7|Vqn_F#jMuo*pF-YtoYlIRL_XGj$iadcNPMu91NBr9=)VAH0+rIn#-sc-$ zC@zv)uw>PGuQI#EBktkT_uSf} zS}IZhX4{kkACZQCB}@tpv;X!nG#y}cWvJL%$=$F@({swwRDp;kKFSO$80Gw29z6V` z-tQLlIE33Xscg=nmscdR99=s(1Xc*Ha0ol>BAIp2IbzjDsrxu` zPU7-xeQOc0H&IDNFz=lEwUy51zvUPLQ!}QXEjVwl?{8E6g~h$2;jhW3@86aEJSReI2wOKjQ-xep@8tOVcfk!Fvpuk7!i8l+~^^s0Aj>MZjwMO&XJrM4vG zOkLyj#QPJ zu1i}34l^Ef{lKxMWwX98!!k4L^~U?_>yC@t*B_d{`>xLu4!;YTi*_mtPAMo!brW0K za`{l8=$m~X&gReGWGffY=*R2w@tMPfD-H>%oM-Po`s*N)IMpcr|F5R&@ADX+-jTZA zts4LL)12GCnOAvzJXR+2tde=gfkQ^RO&mL3S5KQ(FlVad^RS(^ax30lnGunZG}B0a zNe|z1V<9F%pS6w_s&g($J#-Y%F;NukIB?5I&@U|2zITPnV!_Yrt}-li-QdF+zHp1% z$1a-*SwDWK%bjxBbu(99O2BJ%2gm>G3&rG0wci~RRy%d2Wus}ES^S^)#^(X|w{DUy RVPIfj@O1TaS?83{1OQouFZ%!h literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/ebwizardry/textures/blocks/runestone_fire_3_overlay.png b/src/main/resources/assets/ebwizardry/textures/blocks/runestone_fire_3_overlay.png new file mode 100644 index 0000000000000000000000000000000000000000..c5ecfe2110749c61ade8f8b38d09e8a983eb7b0f GIT binary patch literal 714 zcmeAS@N?(olHy`uVBq!ia0y~yU=RRd4mJh`2Kmqb6B!s7*pj^6T^Rl|7&0&>b{;;& zz`(#+;1OBOz`!jG!i)^F=14FwFtC?+`ns||gM(B~>?R{mxf88tg%Vm4F z#4f>m_qV8Te@+H(Xlehk{Qjh~KmNR$b@rjd^J9lkYkP$-Y_iP%H81j1O=|k0Y(e91FOGUGu)Xx`E2A8KAvYg7b`NXQV{V_5~v?aP^0+Z?{WTaKYPJ!9(Eg5&k)`>Q@Z5NuRDm?!n~`|-ej`8uz% z<7XnC-u%ga{WSNxXaoP5QccGVu5r2+So7_vD_kz2z0{}0rT3Ut>6VNiPm2z^zB4#- zLu;<|D@B8EsZX9Q4~+l&=S0j*Jyjm%pOxK0joUAs6E%=Akg+~kb^r6T_C@dOE7M+I z7TmqUL^707BGJvGB5;GYFvH2qmX%jOKEM9{>)G}3H}2nlTRD-LCF$8ru|`i3)_p#m z=jJS0pjlvkDfZ!0`S@GUHXP?on|EMN24lw?PM&F+kMHLE6BIZe@vQHCU47d6{CtMz zSER0gX1)LK+m*a`-*#B5O3f~`c+5M2=h@1|o*p0ey^mbtBcK!f=!%wkyRB){s?MG1 zVmlvCzVq<#%a)T4Nm;xiBCJbIMVvZzru!V?30vvRWmR5wxg*-oq~zHx;RKUT*K;k> zOHI8(-qfvht1&5#SG)A+-nt#)&zp_rT8kEH2#Z&qduwt*C5xp!=!Tyb{;;& zz`(#+;1OBOz`!jG!i)^F=14FwFtC?+`ns||HXlrjSE@;g_u&ZoKa(c=ua2*3z)$;&mr&CLx}*9@B>`x7-hM2CgN%UdAx%mdRb&hV5c87OlW`?ZHi&@f^ zYdI->vZ1r?m#qmb@x9CT{L)oe(6)GyifD&Igkr-gA--96j-+N>9^BuN6)J# z6?k;U@Z4eve){(P`JK1lGaO{KX^J^?b4uexjpI=Qf|oA-{C9r32g|c#@vBwK-}61W zG9gqmjl+pk-9KoN;L;Xle$|D(JEY5Z%R1U@VG>C%SbVXi)!1|9oh^%xH*p9E&XCmd z>Rlk{$f$RI=4$qijgo!o=lS*HkDq-tZ%t>g?h3Vev2lf$*Uot2^VNZ4-nsQV@2+uN zF!9JfzL;lhZ~NU<&P|bZRN8U3Or<5uFHF%hY3Eyxrp`2_Ic`(W7C5P@_dE#Tjucji zV0k>JP_#?(sP?B1nuq15@6=|lytr1LQ)G1q$N%f=#O7@g4qMLbIptu>WXZjA)&J?w Y3JiZe=~b^O0|Nttr>mdKI;Vst02fFzn*aa+ literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/ebwizardry/textures/blocks/runestone_fire_4_overlay.png b/src/main/resources/assets/ebwizardry/textures/blocks/runestone_fire_4_overlay.png new file mode 100644 index 0000000000000000000000000000000000000000..3f98c9fb9c2bd3d91a806ec33b3881f846a3e20d GIT binary patch literal 715 zcmeAS@N?(olHy`uVBq!ia0y~yU=RRd4mJh`2Kmqb6B!s7*pj^6T^Rl|7&0&>b{;;& zz`(#+;1OBOz`!jG!i)^F=14FwFtC?+`ns||dS~EA!q0DQkFR5$_CetPn&~OVcJt#m-pG4-XUDv=nt_Zbp8eS!cX|1l^v{y{^6yUC zc9x%Jb#*jiPuP2#QQ<+^R+k0=MhmtBx7({3?o6J1R&qHXkK4}0iVUk1L_Cy4YUTte zS0{yY=UK(dh^Wk|)xDEv?s4#M-Qi6#l2>kAcgkl|Yr7^N=E0?jpP1iO}iT@ zQ*P2YJ1~0j>6zVk<{yajU8cjIp20P%W%kG8=H^L^G0nY3H4TN=FYgRqTsYC{+Ea&l zzQ=gBZdl*iR$(^l)7N|>me9u8lkYe<*(5dWUfdw$n74GUQi4zM`QOV$x7*7vRa8(d z%DkXH!|MLue}~>}lRm)FJmG}v!BspxXDqKY&78=0@O%9}lgSwuf4u(Kxcj>G(<>A2 zYOYO`aCMxw#3kJ?Fd^OZg|J}n?z3zQH;X=CaW=8?H({MTb{;;& zz`(#+;1OBOz`!jG!i)^F=14FwFtC?+`ns||UvY&DLyH~4T zWqp75R(f+3!;c>?o1QM1v#;vh&!_s+nu}^aHAQJNJeqnwe&0pbr(a(O->bK9X56<< ze`c~a(~cdxEdN};U(YZ>`^lV-j~FWcKU~w;mglf{gA{YEdIv`wPlILJnVuM}8;=>j z3S24vK4HQfWro?Bi{ltPZWZ0Qr9vqp>?XWmMZG}bBnG#2hs|}}aY(Kf$(1btEEJhqjdAYlwQ^YLdoAtMl1nx>)_;9DQE8WiJhPI4`T^5Z z47Jx|zCW^fby$)8`u59u?A0zd5vuOatcR2gjx+fM=(Cizi}G`yzoD(}Z&AyMy=vv$gh?aLH9zeQKZ{-x(l3GqYyvn2)Jo)9(TpQvZD%P{rW!o@R^Z;5?+ z$Ma447W@0__dC{If4+Me*UCqKlLZgFy*n-Ze3jn1_l4{39-8m_Brj{te@6e+@-I{h TG*cKD7#KWV{an^LB{Ts519&2A literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/ebwizardry/textures/blocks/runestone_healing_1.png b/src/main/resources/assets/ebwizardry/textures/blocks/runestone_healing_1.png new file mode 100644 index 0000000000000000000000000000000000000000..40d6daaafc2fd34847357fa9bd6c8539a4cd4e26 GIT binary patch literal 838 zcmeAS@N?(olHy`uVBq!ia0y~yU=RRd4mJh`2Kmqb6B!s7*pj^6T^Rl|7&0&>b{;;& zz`(#+;1OBOz`!jG!i)^F=14FwFtC?+`ns||&zpP9nN3kuB( zoE9zUJWwPes3NX6N1%GoX8C)u>+Q>It&QI|C!N`~`{>2J&*xP4?b!co+4ply8@^gB zj0@E{7r*r8yWsU&>(1D97xOVlYRvny+k1tmw|BSAtvhavHodofJ_)f*C}F#7c`utW zK}I5(V+q59i_gk-hO~!%TvLYVe*{^dyhx3|NGOx<*>S8@@1w>AHD+` zrY;NF6!c~8RdYSgWi1Kp0ixD^-Woy*RQ+DVejrd zxphdU@VkT}%f0Flh0fi|X<4%#Y@M!G$M>N1h_&}6`QptRoi^T1UtjF-si6DpTQTk4 z)V65DCf~wUi{Izqnd~1$XPz?x6Uo%N6zw{?)_f*vDNj%(vy=9Eu3@mrHs#t zaM7sjZ)gGcPlg+iKK$)1;| zEMKd5x;J&5{r&^D((iw~{_4EVjXMvUuYTWfZJxKlq|@ReL9Sa@wixh4?ubgS{Tlx7 zPxb8W`zpkfd9Kgfed5^N`x)iz74JQbz4K>Gi@)*XpRD|Q8@dwai_M6uL~#IZJ49 zJznWL=~_b56s;o`5_6xmM9p=*8L+x7Lf^x<+j4cIK$2GYiH3iHeO-^Anfw>&Q?OuX x literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/ebwizardry/textures/blocks/runestone_healing_1_overlay.png b/src/main/resources/assets/ebwizardry/textures/blocks/runestone_healing_1_overlay.png new file mode 100644 index 0000000000000000000000000000000000000000..8f4700e7dc4e4a638106902ab2964658d07fc373 GIT binary patch literal 841 zcmeAS@N?(olHy`uVBq!ia0y~yU=RRd4mJh`2Kmqb6B!s7*pj^6T^Rl|7&0&>b{;;& zz`(#+;1OBOz`!jG!i)^F=14FwFtC?+`ns||6)jDV~E9R*U7u{ zV?qUv)fd0BESHa*tYMK5S=Zn>U##jMgNDWm4bMiFBN7543W^t%8Yd)63-Izvu!st= z`nu@2b13gzu)+Dw>)NWfKem2*cdz=LWLNf^ysnF9-v53kz0>@^kyH`GzneJ$t0UBo z=Lh7!4O|_uuHVj;gONcvQtsbw-#0p!FHc^xHa~$;PF0sJ^CHWIjQ8W583oZbdO3+ck5X^DIM8DD(0U3!CY zLKSwRw|2-!-Hg2Ah?5$b$rQLFCmoCS@`7uRK9E~>TZ|2F1{+OG5Z|CoAe!e{u zOZo%_Lqw$|C;9bHTy;1{otNQ=%acmKy|*8qyENzCoSBEBPV>vxD}TRkHZyj|;>XF0 zS7@E%Qoh<0R`>sn>#NbY}Fd%TrrZfBtLMf6{tef2CpD+G~o6ELuxfe9-zT zF`rNG&Rn_Or(QieKdGdzv17@-wAG~@D<)jIeMWEJ%Ja6?oKZ7uPB5AMnDXs0D5r4m#PFj0bX`P*dl55K1j*lAy zrPk`5vur!8xT?#r?S|yHz96^t$7Vcy$ru@CbNQu$a*M-(32F1Hip8HRZPHmBQpD0~ zu`MNTb{;;& zz`(#+;1OBOz`!jG!i)^F=14FwFtC?+`ns||~YXE~i!y=K6BYYx%T055X zFH&$7(F+Q&*f@9Z?cK+u->%z#duKq+xnm$GZ``IJvw*{siB zn|`f+KKs2p*zxn&7v!CCwWb00pX-GRf;c4Thl8o?Y+@-r8&zW6+ z=gH#l{*Mi1dXAO2N!tJWX)C{ep5x9XX_Cx_ZlAOi4o>Cye>&5&RYKX(a?kfWyZ#to zH_r=bN&dI*d&Av>BI2($r?t9kx(2#lncVCB@n~GTgiTmNxxv$0&qVWTYiIL^`!Q}X zpHukvoK^q(f3DlFt9uGYGWm&%;#(@IDGbgcTM z(wP|Na;fbg>y3La72J~7&Uqr-rIoaG;VPR<=ganIE=K9-9eA_jh}u@$)2Aky>Dp;+ zI`r7DLu08}&lIzs_^BSd@7ii|1+ey1GBa7s5?ixpuS>p(yQXU#o7(0{nPIcv)z9%Q Wo)tXDb{;;& zz`(#+;1OBOz`!jG!i)^F=14FwFtC?+`ns||*UjU zF|H!6;d}FTuivHE!XnuGwBdyQ2k8z+JI21Zj zMkg8?C*OEiekV8Q%H4hIS6T6_dwa%fRjuFJ&FA&LrhLs-VPp7Ld3E{KEjqe!OU&n7 z$cj1_|D!`fnc-GM-2R)&h0~rsRgK$o=NQwQlC~$Qx=b(n`Ocl2`;LJ@{$O?gMXm;M z{q3)p>18JME}Ls5Ce(XPYB6iWo-Z97b}kdj`6HOmNi91rdh54PL*z3s$2hUs?FR zA75k`5C5xhDxdT5@q7CdQ#C}9Dzopr08ol^f&c&j literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/ebwizardry/textures/blocks/runestone_healing_3.png b/src/main/resources/assets/ebwizardry/textures/blocks/runestone_healing_3.png new file mode 100644 index 0000000000000000000000000000000000000000..d7784e67f1b0d9e6e3facf534983e4938ba7d2e1 GIT binary patch literal 724 zcmeAS@N?(olHy`uVBq!ia0y~yU=RRd4mJh`2Kmqb6B!s7*pj^6T^Rl|7&0&>b{;;& zz`(#+;1OBOz`!jG!i)^F=14FwFtC?+`ns||XnTF0 zdAGGs+1jwLD}&?bPPcPYLz|zAOB}erTKbrUIOCf5y|(khr(b7y!ep5~hl}C-y!bPV_PsP*uEXYkU1L?( zWv&Af##_Tag)FGcN#NUK`OaR&LCbc_)UQ>ilRmsSeN~DfuzhCX&u8=A*ZrEe zet*=XIm*w^{3<)%zyHsH>8FohiTbFf!)9;&Jf84S}*j(_wh-+o(B zNo0Eex8$A{fsCAIi&q73Zw)&Za$%D4`g^_Z371U-k2`pE&N04MJ!_fbGn@V(?cWB9 zN-ZIQ_jO-HDL?Jp_dfIXv~{)z&j<(>otqMr@mIZrW0h6E!l`Cq=eqx2Z&%gT`RNKT zS7&}~vFXpBp6j!%gS;%B3ru_*%hA}ip;G=?03*9bU*@c}v9bFPR{LKsb>HxMHm_3C z%tXGna~8k1I39l2H|5!dKf7l~h7`8U=rCM#sFVdQ&MBb@0QRFty#N3J literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/ebwizardry/textures/blocks/runestone_healing_3_overlay.png b/src/main/resources/assets/ebwizardry/textures/blocks/runestone_healing_3_overlay.png new file mode 100644 index 0000000000000000000000000000000000000000..53767af66aa2f605ade4f341319f2faf9f534bec GIT binary patch literal 724 zcmeAS@N?(olHy`uVBq!ia0y~yU=RRd4mJh`2Kmqb6B!s7*pj^6T^Rl|7&0&>b{;;& zz`(#+;1OBOz`!jG!i)^F=14FwFtC?+`ns||*TX} zF|Gow`&X^oSO3jHWDbX0%LgwT#{L6*Dsn7lIu+t!Yc`!=isW0+V_P<<@KHm$(f0a0 z^KNUOvbAAfR|dz=op!(OUt5$K!@r7+&$gJ)(~&PMEk2!@Z(~#KqshupdTf6E-X$N8 zU0&{A@$C;2^N;G%!xGPx8osXHe*E*RPf`sr3eS6j86VvI+#Pwv-1ga&qYqw6xrP=- zF-jyayXG~I>qkiJ@#4o&j?^(Wo z;dy%%luUdNAI&;!ayDkq{G)L(_mq?@o*OJ*6PF*!BUigKido^6fwA8GJD>0R-@m?o zf7GKn%FoaIDm&i4|4+dF7`tWHy37*|f80DM-Y@1;%C>mblpu*)^WK(quVR`Iv?$7* zgHbS1Uc39Caj4_&%k4H6hCU0YG<6(cslBhPbS28rxTxzmTkUIx4#UNkeeSz<-{lir zxT9u^e6mW5L$a}aXlvAptwzh5rpZ)(&9h;ey{yxMEy(N1oR9Y|oA4SwubdKfvz=2= zaY@&&Jjd%&n*LvE{cmq8dCQsB)-j=Y*%YVO_Kq$AS1VZp<>p9y`n~>sQC*#%uJCeo z=EoMB{`~2=KHECT%i_7f#K*B5ja?fm<(~yGvTO8Z&RQEAyZ>Od|MgP$4X0O_zOrcF!Y2v3vQ- e-+$lyT7TEUtia~yBMk-y1_n=8KbLh*2~7ZzAwin} literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/ebwizardry/textures/blocks/runestone_healing_4.png b/src/main/resources/assets/ebwizardry/textures/blocks/runestone_healing_4.png new file mode 100644 index 0000000000000000000000000000000000000000..4bd763973725f408e060fafdee0beca4168e424d GIT binary patch literal 813 zcmeAS@N?(olHy`uVBq!ia0y~yU=RRd4mJh`2Kmqb6B!s7*pj^6T^Rl|7&0&>b{;;& zz`(#+;1OBOz`!jG!i)^F=14FwFtC?+`ns||=w9C`QF~s7u>tx^j zXjhT8`7^DJzsFq{IWQY( zOzm=6WY+uU$F0oASJnz0-&ejb;?9!DvpVPIe7AjXt^iyVW-H#kh17T-Nl0$NB{g0HJfMW%=o5+-DmYKjs-WYE6U%$`^H$nIHy=8 zh+)IWFOhdcX3I?Vh~o84Qwj1Cl4P6_)+eESj=dwDNsDo<5MRIUrJY<2i#wG~r8HH~ zHBS+0apG{CCbj9xgypkryk}0Cm$oj8efivAT>+SQD1pKe{$ox@OxS%iDXIlX{LwObl8yb-~pOTbp;@ z6tlb5RXOkR-t_NR70vhWKl#|Y|3~dhMQ-i*K%V1YBMvO-+9D+-&uWx?uHfMuCr^#j zlji>Gck5~U-f?7AKq(G&(ez2mb!B|W-14z>uw53oO|5zcvSUd>FxO+zw_H) ze!YK@#GB1^_+K>Cf zcH5YHZ{J>i$TQ);Z=`dnm{-$QxwWQ86XvUUb{OunF7KYsQ1Sj`u&Z)#j7|Q8rxh(* zzZ%I-=gZce${lj;;a+zy4#k9?L+u{ZB-eDC1bO~X=$dls0h5euxJ2yZ$Vhi(^B)>B zrpT3VVq4xaugSb7df~3S_f9TmFq@!~?#i(E@Fef|sUp9VTLgSoADF$k>#*nBU-kR) X5)2w-(&sZUFfe$!`njxgN@xNA`+0DG literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/ebwizardry/textures/blocks/runestone_healing_4_overlay.png b/src/main/resources/assets/ebwizardry/textures/blocks/runestone_healing_4_overlay.png new file mode 100644 index 0000000000000000000000000000000000000000..73287db93892f2d5c5d242b5688200482c9a8097 GIT binary patch literal 821 zcmeAS@N?(olHy`uVBq!ia0y~yU=RRd4mJh`2Kmqb6B!s7*pj^6T^Rl|7&0&>b{;;& zz`(#+;1OBOz`!jG!i)^F=14FwFtC?+`ns||tx^j zXjhT8`7^D*pWb>^%cNt=s!y|ju;$#jxX9_YhJx4{fozeBUzAtmLHg^S<)A<*V(t<&_RHf4Kj-DJ^eDQRcLJ z2_DAgXJTsR3otQQ8RhJMG2uwt&!5^kHnnYxH(v712rCtI*jWDI-MzbSnIAA&Jnz`T zl<@fF=3SX{p3LyLoOL9n(=FR~32Q^WaOf^6pJ#r3%k!clCic> zZp*a=JYJfcOccF^KbfeV4^msYeCF(12Q#0WglR0@aBWdY?q}DJvyv>1Rr_-=3LcE= z?lieO-F=Ic;jYWN3;|Y$qP%Avl>%E2%ffSb{e- za?@q`!rGU?KZ~DEjLOcx^l!WK?|Z9u{kp5Z>9YJ)r%V=yP|Gc=m!;n~m)X2wkH&wS zAFj6dD$YH+>$-DWN$j;-vu%EU4F7ucR8z^fdrem=eR2=5gm3&_kL`nS9{i>`iU2bf$1*+ZM_M^L*=E#35K&{!UDv@x#5z%iG-2 zc2w9oPJb+T?b_**7^^i~L-Yb7+rP`LRcvvXBvB)b{;;& zz`(#+;1OBOz`!jG!i)^F=14FwFtC?+`ns||o0({rT&Swx0QPkzG&TeDVHv+m>PT(Vp&b zag)=m%a^CueEt)CWwU(Undi@+%Y3UoVyP8NP2QVa~ika`gIHw zE=io)w8W%sp?ro|aZ*o!Mv%pXV=Pu5|92WD^*(+7+C1aRmYZ_lIyiQpyZp`e?mvbG zJ(JIym=vD$@HcMze5KTvL;2Fa-O8;UBC6ZAFr>_tY@fL8^OBt^*1_u<@M@k#PY|9y@G zE$1%5*ogxe`%iA1S6hK31y*n=IgV0*R5mhEfszu zpsbQn?VovO%DLa{`dlx{b%V^c*A(;oZ4jBYLP^u@+2$?*U#wE+1T#6lQJIb*_Al%zDZ8 ziK}L9zWJx|%pB#4^JXm1u7=#4A?&+1~#0uy$>&+`~Ub{)NI&w_uhuv+wc7SEZ4vv_sVd(sn8cs1_lNOPgg&ebxsLQ E0620}zW@LL literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/ebwizardry/textures/blocks/runestone_ice_1.png b/src/main/resources/assets/ebwizardry/textures/blocks/runestone_ice_1.png new file mode 100644 index 0000000000000000000000000000000000000000..9c1455fe84038896e9ef2bd5ad4788e4df338281 GIT binary patch literal 860 zcmeAS@N?(olHy`uVBq!ia0y~yU=RRd4mJh`2Kmqb6B!s7*pj^6T^Rl|7&0&>b{;;& zz`(#+;1OBOz`!jG!i)^F=14FwFtC?+`ns||7}QOV~EA+(8;#> zGNBT!^M9Ml&;Gk1=eStW0Vk&84vyZ8yb7~KN;-_37BPq{_elMyuJK8G!leL3S3y>; zi8`}yaF)HPczfjAy6d~ko(Q}@^XAOn;`St0mgP2AtIz$G`S|&LeMnT}^jTNi>xI}A z-|NObT~ORGNwJ&zy+MsB%YthwHg4PHw)$p5V&cTz`|mpc+4ONmRAgkLiOizK9Tps! zW_pQpoo9Eb>|{7#eSCkGskBVVZiW{ZBn}y%Po1nzv!Ic zj0SOaTa~07wZ)2T{ohqx;{rlOGiN>M?z#MqlgU5wNr2TPlf`lClXE+L&Yk;sEit6y ziq!P}6)j67dM|igwzWD|TRr#PL%|@g7KW9kZ`E)6#LaWGtJ`IKPKkwYLSoN^CWXG2 zWxHQUoBzz&-TSYu^WFmgOdc<3HU0Ap3is#L3$H3X7T_f!TA1)c{`-Xce-CVJHk&)-7cn7>HQ zyZh+YKfCDLw^1gh4zVvvG^RA>Lp39jX;zYi%F{@3RZdvnh&IO5iHr2b{;;& zz`(#+;1OBOz`!jG!i)^F=14FwFtC?+`ns||f#=Huu0^$SEpf;Rv9;QvVB z$=;)@WlH!0j8Y08%C@ae>C~zq! z=8#ppnV@G8qr+2~|EsR%6kK@Aw7@x;JySs;`Ak&g-Tju8&S5~t9{PFUfMYn*3Lz|%!SChrE z+iw@;-}y2>cYEu#UuJ%o5ZN9w=~U#ib!R^QycYlH`gi*e zdmZJAUr*b=ZNL7uZQD5yaZFfJ+2!ND_@kzqu(oGl#JAhk9Eufp@;)E^wJX5e{LgV| z=|}&X*>7xGvPNc#=sC+J+HP}7tQelSI_4WBBvsy&x2yNd;PIbl`}p$N+>7^aFTR

    VNPcQD1sQEkfe@bd-&erb%`;KrnYIDVeKD51Ivi!2GTs^-6 zhf>tUhoQ5I>K_Zrr_Q`__wG_L_XOE<;R*+)ss?E_MR}~gno#zQ_lakHLpW1()tapm z!W%a4c7McruJX{1HbW`ds|=1Z?o+lY_32-HDWjAf*mBk=ZjX(+!ND1&@fTN_U$`m} z9X*9ZGr&vn$c);xDtrHFR^|SE_?mB$&f$!&`ybAk_ibi%_PoW-e8)J>TqrQ~v8exP c&hVeX`a|x9LyBpJ3=9kmp00i_>zopr0O34~oB#j- literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/ebwizardry/textures/blocks/runestone_ice_2.png b/src/main/resources/assets/ebwizardry/textures/blocks/runestone_ice_2.png new file mode 100644 index 0000000000000000000000000000000000000000..1822ef74bacc48b984ad0ff77bbbdcbf75305b56 GIT binary patch literal 829 zcmeAS@N?(olHy`uVBq!ia0y~yU=RRd4mJh`2Kmqb6B!s7*pj^6T^Rl|7&0&>b{;;& zz`(#+;1OBOz`!jG!i)^F=14FwFtC?+`ns||6E97V~EA+(8;^= zVnQWa_t#qgJ~L-$gz)jcRu2UMV@1W16Sj{cC#(?caCa!_V2W!r(q(Fy5ESvTb;1e8 zg(`f;eX`9wkBjYpI~gi9g|2%RpZ)Up(d+j2I-?vX%-UVO`-{-&uP>!#&hZ6aGP+wc zw`L;q1^I6`ckVu1VUki@e9HWOefN&Pm-p`2yVrN_^A{#dr$-z++@n`DWsAsBONN7% z|E^Y;JSnhacZg2ja4o5KVQ$p1!#vMrG#p=KHSsGj|DRgicSPk+kZS_v`MbWM_BBO>^u~V3aR7rx+VuY%`ltVUPOxVy>Bs)*RL7 zHRCkfykpy8Q(mjn8Ly>8OrEnA8O)ooL^JoY($q({uCCrwp5OnMo&SKP*|qB*=hq+P z&%giZSxFb4;N|TP5}zJo*=Z!Thv5i!WA{Y&e!0sgyc~_b{;;& zz`(#+;1OBOz`!jG!i)^F=14FwFtC?+`ns||71vFV~EA+(8;^= zVnQWa_t#qgJ~L-$gz)jcRu2UMV@1W16Sj{cC#(?caCa!_V2W!r(q(Fy5ESvTb;1e8 zg(`f;eX`9wkBjYpI~gi9g|2%RpZ)Up(d+j29JM)uip%q-$0hBwt8G4fQ_(AG+3fX` z^@|vO9k#PBFPG?V%gOWm`RsST;P(1m$G?3uE1kFa@|3tFNq*y9F9I(Gi9BaudHy5( z@x=*;f66fA_8yGtHf`IMDamgBFph2{j^k^TFZl%tAv&u;b`m= zT*^DSJDcG|`1(COg*O9_b@WfXd2!A~b@}6eHv1oadwtze>C5JZK|$f7xtA}5ifW6y zndG*|#KtCX+QlWfNFYM9^ITw=tVKVcu2t2mMF-j)dL|xO*03bUD<$&!>DO+HrzF+Y zH2r(<_s6?;`y%R}8ht#y{z&=t{9|j^>Q+Uv88)%h9I$LJ$vyiqhppkmJe%{HDP5by z7Mt8sxpC&vExzj}FLV~K%?`LQNBqRW3a3fSw)l33bY+LH|8#G!?Z*EP7%h$;`(^d- zv;GnO{QF(z%Y#cgX6$3-*A`bhG4!#|FEf^9I&ka}2vJorP zw^7$}e6H-8p!ozd}ejsnR4Vyb%rXZ@9v&;D(C(DE?WPt);H5w#kKhAf4S#hzO+o&i+}k2 qu;ek0bH#@%;|jiAzt8Z8`Q!Rn`CZTJ*D^3LFnGH9xvXb{;;& zz`(#+;1OBOz`!jG!i)^F=14FwFtC?+`ns||Hc-OEW?gkSETkBHPgnLP(9tlYQ`Cp<2l zbeg4Mhw$dl3GH#)4<9?$uzuf8_YY6k@2;z^p6xnm!5URA-o1X^r>=V>dR*3Kkb3?j zd~aU+#~ii>qp0MbgBiY&Q@&W~&M8)4o|WYoY_1^nPy4ydLcX7$pGY`vFuCm7#AA~> zX_7d%-Z?#snj#J%C8n+<$54?I%hb*m-Fj;l8mfG$`?<+fXU}GB?V#|7F=wCF^xe7h z_{ zDsDQOBqadp{pm#{@QUzbM&V zp}2A3(o8iba z=6QQsEG%sgpKe(7jirH)*Kx&9ZT$~&y9&D(-(Ooe2XY#8}YF$x2%g+aF+!|7O zE;aOG*CN%|`xah*7o;|Q$<0ZEvhEt18C^w^v0Q!r=L4YkcS{wT7Rd7aSN&`F>Eyticd&+u?|P=Zor-BAVx1_n=8KbLh*2~7Yz6l%@@ literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/ebwizardry/textures/blocks/runestone_ice_3_overlay.png b/src/main/resources/assets/ebwizardry/textures/blocks/runestone_ice_3_overlay.png new file mode 100644 index 0000000000000000000000000000000000000000..503b6a63a33d812b5f96105d7ff8ecc64a185631 GIT binary patch literal 843 zcmeAS@N?(olHy`uVBq!ia0y~yU=RRd4mJh`2Kmqb6B!s7*pj^6T^Rl|7&0&>b{;;& zz`(#+;1OBOz`!jG!i)^F=14FwFtC?+`ns||_M&6v^f@yNks z_nBvS>YO&*wY9xlyIa3oQ1Hs8u+XK!kGkK#TP$i4^!dTV^G7B=J^N3(M@@OkmM_=i z)%W@^dRTGZ=HK?R)OyYO?>}G7uI|vUznhqy-Ca3r(Ol&|oxOhDT30kOPj1p?kb3_! zd~aU+#S*TDZO0PU9+h&Aobts=chC0)EWW18S4vOd{Xg~lyb~^eDr;I?bk5|=Tja99 z$M{pyxt}jB+5Pz(9D5dMJPUDc%*xsn>9_mtvQ=3rW&h?Z`;?LTG1c{%_MY`S_v~=U z&1tdzYiIrY_mRRLlSu-{J=R*@s6O-QYv_~w-}{*pS{S4ku1&R)3%>i;AVjW=ZTA+t ze_%$e`H#;2xz>XWZ@_AT=V_i%Gu98HvTBgZ@4U|p|Q@WWcPNTCo-vlkGkjF zy~}9F5+JlZxhA6{)M;A!8{YOEHlL%jaF3Qo&;NyFSlY(eVLTAE#ZiYVU*{rMKLbnlNL`l{_;(qKR#!|Q%kqi z|7D-QdDAjIe&^W=lYzopr0QVVy As{jB1 literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/ebwizardry/textures/blocks/runestone_ice_4.png b/src/main/resources/assets/ebwizardry/textures/blocks/runestone_ice_4.png new file mode 100644 index 0000000000000000000000000000000000000000..765defc9833a8d4daecffe2b84e6f75ff7c56973 GIT binary patch literal 862 zcmeAS@N?(olHy`uVBq!ia0y~yU=RRd4mJh`2Kmqb6B!s7*pj^6T^Rl|7&0&>b{;;& zz`(#+;1OBOz`!jG!i)^F=14FwFtC?+`ns||nHp!eA)m!@Tl*HW?AJZkwwZvxq@b1a`!>#9AqIiR?(^T=O z7#GiSiRH3fTTCt(9e-cVucx;3{JY9Yzt7EmzU%1u?()T90!yCV`&<8FGw1bX_m+gM zUzl>}$`es3eQ5>}FV<=Ab%W(J3@t5>-kEDJuz$^(V@sE+TJ^G7`M%uD`83GB@{31e z=GLl54`kLavk6$VZ998|Uyq`vkWli8U6N0O?9W*SG}&YeJFB>~JIs-^c)sD-r#}hu ze_!2uV`5QRcIMzeIj_uP?(P$g2^G7G*|>S-Bz?5Ikh4`&tXt-Z++7_@Ezo)BgSvcIjE65pZn5mc)t@9)`-FmsmR(8y0?2khhI^eEp~8rJ4CZO47Ui zS6QoUj{kV>>vjj15A*iiO)E%g$eX6DJ=L&HTeM?>8Yg%8|3w9_)#SsJPuZ^Y3$|o!?XD@@c%7XLj-E zCj&Fzle;9txTb9N@tO1d*eR>+`{%i>IKi&1eJ3));m)k5f3v2x|9>}W`!1e7p2h6! zUF*4pnD`7l4_$kwH($E>^Sqy}tY^;na`f4-d)zxzVa7GSn#E4Z9>qu3F1Pho(esFEc~MR@NyT`6SYS;8z%}Ws#NwgEV-|C!|7Do zTf?_$lNU}@tab{;;& zz`(#+;1OBOz`!jG!i)^F=14FwFtC?+`ns||m+ag zIjItD>%ae~hg;9LMDYe&r>Wvm zF)p6v63b<|wwPQnI{v@H*|!hF!|n zwr!8RdE>zUACqV7w-a3-yR)l5VY0}CExUA6R$qSUYB=kKt(@aL?mgc#R&p3NnPseW z^qdl=z$jmEPBHe{!v%5gA2PaWi(1*&=>OaIv8*QKcmLt#?KfV&{PFSCt{s1$EA9NA zGM7)|#XPf%M?V>u`JUV*8OAkbtB=o|=f_U%+VS^miHO#xgQvQ7Y~IkY!&LhI`mm#i z>&s6@$FjM%U2JAPdYzS%k$r|rVs`oT^Sy%Ss-KCA85o-@ADr0kaPL*n{pw5EN)1~z zpI-U!=m`rW%k;-fQ%aMW6;&5MKlkz7tyvR-zD*DpI`vfO@nhi^&4-t}sGg`j!r3@c zNKvJ-r(wx`wHr>S(%u@rO`E)MqGHXnm#<$hkE?IdS)y6F`|Rh*$!j)pEG;w)(3^I_ z<_`{11bG^7ng=_l^n=ZFK j+;Z{Bk0-1Q|C!BpC*gTe~DWM4f-`kuj literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/ebwizardry/textures/blocks/runestone_lightning_0.png b/src/main/resources/assets/ebwizardry/textures/blocks/runestone_lightning_0.png new file mode 100644 index 0000000000000000000000000000000000000000..e6cec3783e769e44906ee29353792ec29f660e41 GIT binary patch literal 629 zcmeAS@N?(olHy`uVBq!ia0y~yU=RRd4mJh`2Kmqb6B!s7*pj^6T^Rl|7&0&>b{;;& zz`(#+;1OBOz`!jG!i)^F=14FwFtC?+`ns||NeM;abIxy$gHKT|ce;?fP|-x4rj&+dkD^#CG8IW#Rvi z&cA)@vuTBn3v0vQuci!V&lnhIcvW4vz2HQpde|zi2CWI-7fH67J}$Ai;C26Cs$FG^)WW2N{g3( zpi1(HgWN>^nWISB-YJn!nzw3_g6#ql|YS}v-Q#^+b`H?I)r zRz7uP$pkH<$zpPQWanKlT)>iT6g|m_>srAXp3ubD;`qxooSPm~Qo)Qc|+8v-4AD>X2H@uVnxA z!o`m~A`4w!FVdQ&MBb@0IPNt@&Et; literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/ebwizardry/textures/blocks/runestone_lightning_1.png b/src/main/resources/assets/ebwizardry/textures/blocks/runestone_lightning_1.png new file mode 100644 index 0000000000000000000000000000000000000000..b6e4f88968bc2bcc8c09154731ee06dd5e44a149 GIT binary patch literal 747 zcmeAS@N?(olHy`uVBq!ia0y~yU=RRd4mJh`2Kmqb6B!s7*pj^6T^Rl|7&0&>b{;;& zz`(#+;1OBOz`!jG!i)^F=14FwFtC?+`ns||juz@M)P3Pnr zdE0Ln-mhLAv87XE<&sJ3UR|+#E?4>OzI7LkJ~GOc|9j5tMB>!ms=+_U`OrWS#R@;=hgj{T>aB@cX!FS zucPtOz$-{KMD$(Xu?FcD<=|e&k3kZ0avXt<$3((>o28~qk$c(QlrGJ@b{;;& zz`(#+;1OBOz`!jG!i)^F=14FwFtC?+`ns||+>#nMb6oOdR^{C2}|pGFG*ttDdpL> zvy);sThzB-eX1Jxs_Sc3>(rhMh6VTE{`kKpKYzJ*VF9x!L)i4`!WkTly%R061q4^! zcp#D1HnnB9>}h$&wHAtOpDrvuab-iHi;G6shBplVwiwldlWO~(x`*}C_NB(@&%+L5?O2=8AiznVa>-&}B$FbaBO;>3FW8l%Ev^Uke z=KuTDzkmOPx1Z#l)?Cm^vRtfabL!&H%dAP04db{LHU9fI@9z2f-<#$2pS(M7Z&4!q z_t!j|zR7pytbE2h&G^&F)8Siky`|V>mdEGc_*?Y$jPWd`66I|j9h&F&SL?og%loLW zGA$y%bLEsyZvh+0&6k7k{eS4BlN#{j``hSU_rw3aSv`GIoNnh?o+Er-# zE_}<-!LVrJF0Lty<^9i{t9bu9d{e%8%d;2TP82$@%(-zU!_V(R`(K0Fh1RO7cVq<@ z?%lU&$zc`GsR5xotfiRq1p0hT*^YWA)>J6Cu+9vMFy+k(2&!75&owWXYl2pLoj-?q z@rTaFna#et1(S}fEs&^M^|NPT?#85ulRbauEu3xhga1%}jgjHo$N&Zg1_n=8KbLh* G2~7atN=Zrp literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/ebwizardry/textures/blocks/runestone_lightning_2.png b/src/main/resources/assets/ebwizardry/textures/blocks/runestone_lightning_2.png new file mode 100644 index 0000000000000000000000000000000000000000..cf4e902926ae5e29b08ef8b33e99b1a49f65a67b GIT binary patch literal 735 zcmeAS@N?(olHy`uVBq!ia0y~yU=RRd4mJh`2Kmqb6B!s7*pj^6T^Rl|7&0&>b{;;& zz`(#+;1OBOz`!jG!i)^F=14FwFtC?+`ns||`D!D83M}lzkm7i_s*%* zCSz-hO*%I>?f+l?RXzw2O8 zQ9ZWKU1h_+59;mnr|+;om8*_6IGGrUV6?cB{Xm9D4NV-Sj>GUg}Oc^r`>;$NO?0 zb24I$=lMSoIVgL&RiSZ`@vK==7hO)W9lUw|d4;BMbFdn}?KI<~JtYr!h%VyFYYn;X z5xP|TdZ5f{* zKWUeBTOQ@%*t2W@^4hAV00}?cuTNDk&Apwz+R7kP$1vc`jdTAUog6|t11;7~^AOtO zutwem3d6Q_&L&PXUWA3ZYD_3rd;WjwC!4>W9T(>Nzew9!)~5=%Q`BFv46T?{EeC6Kcn>F0-J=RD?!PZ!PC{xWt~$(699Q7NUs0@ literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/ebwizardry/textures/blocks/runestone_lightning_2_overlay.png b/src/main/resources/assets/ebwizardry/textures/blocks/runestone_lightning_2_overlay.png new file mode 100644 index 0000000000000000000000000000000000000000..f862c84c28e6bb44bb59605d567edf33aada4e85 GIT binary patch literal 742 zcmeAS@N?(olHy`uVBq!ia0y~yU=RRd4mJh`2Kmqb6B!s7*pj^6T^Rl|7&0&>b{;;& zz`(#+;1OBOz`!jG!i)^F=14FwFtC?+`ns||$>|d_XmwSIpFL_$)lqpk`ZlFf9Z<@01XbhxNBtn>71>2Lo2Df35Pf;ox^+ZFu@tmtk6v(o&XX6?!3I!awc=t0^%x za7=i=3^KxB(tDX4qi4%^zt8;b{SUO={hOl{WzFMA=2 zg~v9$w)j&dZsxEhU{=HA1<$^4hO~y;@0NBgZB-i&%#(Y^;Gt!rANT3!ZgVG= zRZU@{moptgZ`AyleE0n84i1-=s*N)wb@cRJY`?31YInbOhl0|DDH@f}4CeY>I93y+ z8PYv%;qBz^&BdP#4Chuc9Q(_s&#K>=;#OSQI?FI;`wOQPx28=Il4I4EJe_(?LiATV z`>*)$hrNNmt#vKe-`7t#+rB@*xFq%i#{>tPg7P&_4sCdUVb`-azl`JlehDi`|9kxX zk^Jw1I}>~lm)J~L%_2DEO$XOJx4zQpc%%}% z$RhOeg3{R9Usg66l}@?~(|VqZhTaykT%6{j`k8I%h5YRdC(Q5ffBN|T{|P}!GHfo- zUnX^~*59ABJL=I=hC|)6rGFiF7f84HV)Fd?l5YJt<1e;KP1Ad_oLKJ6eYin6(b{;;& zz`(#+;1OBOz`!jG!i)^F=14FwFtC?+`ns||*TY2 z(xC!w{-JmGKS=EmNIKZXZpgtacYglc zLjT)$Yu~Tcxh0tuy2>@Q_W9~b`uqMJJIc_q`>1M^zDGYT52sjCDu z=Xq)-zuRHW@J^w9nX0u|PwnLe>)Mm*OXxylhPEH zv-#Y+&Putsan2QVTCjH~Te(Y%#q8dMbanL;8p6iP{wg%wr;IP zJOSc1=_gM8nZEzWm$Tj)jDiPWH*_~xJo3|IJ*#=yl>L6_M2*L4!4*G0YnQzi^-+8q z<;7H_xV)*mM`)F2Z(G+Sqsfzl|)hvHJ3oPwZ^#ZXcJp s#jd7){EeBkOK* literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/ebwizardry/textures/blocks/runestone_lightning_3_overlay.png b/src/main/resources/assets/ebwizardry/textures/blocks/runestone_lightning_3_overlay.png new file mode 100644 index 0000000000000000000000000000000000000000..2fd6dfaa18051a942a5cb881f9f37ee40909ab4d GIT binary patch literal 745 zcmeAS@N?(olHy`uVBq!ia0y~yU=RRd4mJh`2Kmqb6B!s7*pj^6T^Rl|7&0&>b{;;& zz`(#+;1OBOz`!jG!i)^F=14FwFtC?+`ns||*TY2 zGNC+f{coeU@2Z|LGsVO)P)vhMNPC+G2j{{MENd#*Z)|vASs|&^60zZtqf|@Vym|9| z{L4#2!>{hWuCt0WE;8=MzjNuQkI&!h#^X@2eV3c|<3EokrEPX}e(>cHXQc;221m}d z>n#z5b%iIhcB*8E?ucLe!9*#GVasjZ|3?p3*{UA>_^5-6Vf9m?hJ>^kk}OM?_=qYU zHP%c$BU{dXK=#RvEh)#F3Nxgxe2tJ{bEy3BysOY-hj`JsDTJ< zS@B`_?DHH_CS8zLWVy9Fy1?C~qx&dJSz%e5kCCDAC!ZZZz6sylyZ0l%-u%7omH)5L zFR{P>`{ic-la|4{X;Y?LIQpk0%WS^I6ee~@pM@ei5^vv^_o>~H<-S~EY<KYw!>FSh>@ zu}0%@N0{i2$;T$D>&I<~UVqY3`CZGdq#NZ|)YV@seA~DDRfoltrd1P;3x4b{;;& zz`(#+;1OBOz`!jG!i)^F=14FwFtC?+`ns||SSPGn&j!?7-DhSb#ipK zOsK%|`sJ@mzAu@6w>Mjk>7LM|#p{zEd6#_L%wf0ULDzgQ5fNs`4@cK4bO}i~n;35{ zzPa;DiGTV0;#2MS*8E?-XhGNirKfBw{xcVIJ&5pK=CN$fyt@md)(gJ3wA=0bhKb>k z?dzK&^V8?dyPIev_gM9_j=HeU7mGlKS8u0<@0fMAO-XVZk2+t&$qJr^@X!#^JrkT% zK3lp;r6u*xWK3XtSC!e-R`oO>wBuyy=GP3z|7E#$xOsHGyO4Ns1IszfNs>Q$1gf{3 z*qGvxW7X5rxqNL|&i=VU`p+UHN~}ZYygHyFDaQ0@O4dFVeeaaLvzQk=l9;>i*xqjU zEB@2I`1U@tG-OG-|JcPMBs!?W;`xcwMF!h!ED!P;akjVJoL^t?fA#S@vZsOW$y3w?wPnoW}=hBsc83<#nB8$);;}Da`w~v^gW+%I$v5Zed}%8jqfYI zyLhfRkzh3;$-zlxixOXaPsQuc?QizipM3RmhPmC}3E!q$#%^`q)2`uccdj69$&?8a zO1Y(TcNd$y*1q@Wk>Kw4{~mt28Gq;ZC*g1QaYDQKJO$a0OfY!P#(8svLya4kV0@25 z%h@NY-}nFP_|>kt`F{Q5gXYiQ%-8c+)bV|V_#DSD5s!K4=Hcm@LbKS;8m)TTv|V5B zvQ1>tw2JSKWU7?E*&4ddI-92O_ukLrWj`OqhfLj;Td1@|;Dc-9QkTlA*}t+{8Qs&@ z2kSojap&?|>8{1fPXf%ZFVC{zDdc-U^~QIHMR#)p-v@?%J8fBMc}OT@-o-a%9bHM9 zmt^@m!V8*rSI&DZ)FQy~@c$AWo_ZyvEnnsK&pMxH(-FJl=eF<{uWc7kPM&p^P2KBC h--WGTa@h~mGqx8P&M1E1%)r3F;OXk;vd$@?2>?}FXJP;V literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/ebwizardry/textures/blocks/runestone_lightning_4_overlay.png b/src/main/resources/assets/ebwizardry/textures/blocks/runestone_lightning_4_overlay.png new file mode 100644 index 0000000000000000000000000000000000000000..d739791ce478abb3f2c6e27fe656c7ef16a42d83 GIT binary patch literal 783 zcmeAS@N?(olHy`uVBq!ia0y~yU=RRd4mJh`2Kmqb6B!s7*pj^6T^Rl|7&0&>b{;;& zz`(#+;1OBOz`!jG!i)^F=14FwFtC?+`ns||*Tv# zGNA&;>qDQHoPVQpvp4$y>wcj}OSdOI@-6uo$)X=paCEs4>rn@RJs(9?7O|K)o;~yC z&6{)QzLfZv&kug;x;`r0)lu~S`bodv@9k${cvxiR+&bkpI*);{OYbws&LyR12{%7vNXYt`BPrKa=wdoA<&RxlXYS~DxO32-Pngy^Jp zMLfE(VRH2yS%&fnvlmaBE5N*al~ZhfTP!=r?bY5vWs@ZDt~F`H7;PG=pDo$5Va zcVy1`wkPj!yOnkL*X)_s#kp;G_o%X{v@mvB&J)sV%-XnQj?aawPnjAP9QyG=^xZtW zDZf5m`n^nTimIh*(S7ArZ&sO3Gg5N0oXK;@kB@Icqgv*5ga3cc-_`!~Ftb0mXV&=- zb2tq*?TxtbZ_AhHOC)i>e=o6fBxK*zw`G|^38t*?{>ZpIL$F(@VgDkpkRBFiPPy#KlDrUW?nIAS+pQ3 z?!&d0%9(Qdckfm_|Kjpu?w#*X=47s0&wkb{;;& zz`(#+;1OBOz`!jG!i)^F=14FwFtC?+`ns||s3Kp#r5D8^su_m6&BhvtYkee>Ma zVQ^EHVb|T7pE&`-Ce!n{J4;d% z#@oBIUPmzMS=GK%tO8R`v~?t;J!#LZIC_%Gd+JR`&WH8 zI9KR$w5ma6v9Cg{^lK@(Drx;wJLi75d;7K4=T#4qWuGa3zdY^xW$RU5+{t}2r-?KC aV+`0XA+GV=z?p%8fx*+&&t;ucLK6T;&GVuF literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/ebwizardry/textures/blocks/runestone_necromancy_1.png b/src/main/resources/assets/ebwizardry/textures/blocks/runestone_necromancy_1.png new file mode 100644 index 0000000000000000000000000000000000000000..f9172656fc22a2af67ceb82377d159013dcbfab7 GIT binary patch literal 703 zcmeAS@N?(olHy`uVBq!ia0y~yU=RRd4mJh`2Kmqb6B!s7*pj^6T^Rl|7&0&>b{;;& zz`(#+;1OBOz`!jG!i)^F=14FwFtC?+`ns||T6a$W2>{@8wng!yZ0zsHSBPGuE(f97&f+GuMxA?Q(A?eV{d z#V1X?VfVk=-Pwh~;<>W^E!k}hE-W4lpJ)GW*Dt=D(za@mhFtHIOIvsBI^X&~*k!@0 zp06&SW>}l8S9v+}l*>xxRh^fNR=;aguy~ek)@^;~w#`keMJ%@@IyqRDx++f>o*(z$ zce$oW}5?YU9p#YDy;gJr^zf&g+Ey{Pkt3o$ktO9>~f`r-4Nk#Z~JUIw-AE!wXZnKtE5*1241y{cpK>b*YrqAr=Q5lYW1_^=h{#IzWQ&h-Q^x?`P6u??uoBH^VwXc%)ZLo|NAX#;i4^^#>rYUQ};U* zpR*8HH$zgb{;;& zz`(#+;1OBOz`!jG!i)^F=14FwFtC?+`ns||(dJbUQNw=-Y-!&1{& z+)Q%?%Jy{heBV38Jie}7%f;MI_P^WF9lP%qX|YezGGAT2%bY=|^X|uqQ-r>6kCv0O zpU`vU-A{QNDU?)qbY7e~m{ zOMWW-sY&16CY^~%&(dC@mNkEe8I(Z@=E3 zbm5GC{=MU6pSyzk|NJ`p`^Fmc8GIca`l;tLvP=GdVrl3|$eJOwms86td%_hxwltsK z1A>BX(aa0BuRi zDEwUgr{ss@uJThM8TTYEHS8{)G0#JB>gN~(U!G~1aX00^tb{;;& zz`(#+;1OBOz`!jG!i)^F=14FwFtC?+`ns||S$o-s1R+s+96w= zQ@(q5Z0L55s%t`XcAVS$d``8O-M*hoRypY&+xDMb^zq!UrpGrP4&50M7pTPiz+(14 z#`5P`wP*hx&c0J%_S@V=w}XS>@RiSE{dd_KqO?6&pP7H>U;lhzUfZfg8iCyJ>eQZh z%=}@0B`PrVSj~~e=Y+jeeCF2fU%HXiQt0(JDOb&{XH)_g9outLDr;3m;*x7!3uKlv z+wc9+T_+QG8|5?>FgQ4K}P|Z1Mm9N+ztZaJlfKNk}sP z_OuwaAg?vEyz34!_FuSZ`>X8B|!_uNB%dhzV`SCD6L~51R_TT!IZ?^5Q zQgb^})7jx59lIc@cp^if;?yIPxcBX?Z=J#->N9si&`fKF2fG~3il?t!=BLNmaL?%e z{{Px(eXB0rXj;0yL&JsT`0{P1PCuW2?d&_b(52GVQqc-ZF|jcVjq-1mMYAYoDJad5 zTyC;4O6OzdEDi^!%sq~-E4OZXUEaabEBUVPidWZyuWcb*X>RskSNxJW7Qz;i^Umtv zp{NO7nypc%bi{4{^E%G_)L}2T?KzLvlVaujk7lsx-7>vb{;;& zz`(#+;1OBOz`!jG!i)^F=14FwFtC?+`ns||22Bo^z1k_J{JYuD|pukbYzdi_?~MoWq5fWf<;+vR?nG6*sX9k^5c|3j7BtTO?jB1acb3bJZe z|1SAse-}r{R2x|jxz9&l2`}q>Tj!jtJ6SyJu4z}$;&TdtHZ}Khcmtb4PP(u(6-ku; z`SIxdjpvLPS?}lBPk)=}y>jNO%|}v;Ihl6<@ksanQuv*v;M)D_hp)}&bFNHC<5~Lr z-A(zz?+^0}zyJBZBW9g|pj9-}g4IW#)_qhzJt?M4W;rKQ z)6K6BZ_JOpyXUXnQaMAeu`Kd^osX(4<9c`)&Ov z8}CmrNle;tetJRqmWyJdvzu8uxR#2E#e6vXce&D5hlb2UoK2R@44%U>}kdpYQ?U}KEYs!X%wHOyMZ z76nnS9h#!F17G`y+x~A`&=Y*jXO^%=M}fuMiz*L8+9qYr>Z^VCaYab^u}LRWzdev& Y>g1VIlaN1^fq{X+)78&qol`;+0Bz<#761SM literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/ebwizardry/textures/blocks/runestone_necromancy_3.png b/src/main/resources/assets/ebwizardry/textures/blocks/runestone_necromancy_3.png new file mode 100644 index 0000000000000000000000000000000000000000..6de4425d4a1ca62a17ccb030d37d1a465cb59bed GIT binary patch literal 685 zcmeAS@N?(olHy`uVBq!ia0y~yU=RRd4mJh`2Kmqb6B!s7*pj^6T^Rl|7&0&>b{;;& zz`(#+;1OBOz`!jG!i)^F=14FwFtC?+`ns||}2me z8FvAf__|%yZOVcFa(E;RQYw-USjQh@|KM1{ARYBe?N-La*BmXrSss4pzbrSp+%3j= zbEEbGrGTGCUUk3TJr8Q-dVKkZxz@4MhqcdL<_v$DRqmU@e4y~%vFJNyf zR{Z?~e`I3^L%~eb{;;& zz`(#+;1OBOz`!jG!i)^F=14FwFtC?+`ns||h}_%h~h5>KaGdjQ#J&NdO{X=@Lw`=>oOB&vu`+9cy*(+xQLPb=y3%-jNp1;%bfA%V;(9FLr zX}Nt9WhXZVTW?yYEqQd0iQj4EnVnsis*jf{C>2PXEnW~9%Hh@DdO|duz0ox7Uj6Tl zac}v*yqRG!QC9Hb#=C|$<@Q$ZVRvweSoHDV-Q%;CbuKmEG^v(n2k#EPEp;v~0)lF{ znHRL*UH$)!nu^}JgvV()jjN02y#M*(U4K>a4<;kY8kJ3pFPj+hGIOP<&g@#Dv}lLb zQIGTI5|jnG*Uk^T+AA&FU%EI(X@$m&q*ZG+8vL3UpI0|&_hZ>?9T8?Vw|~~Xlcs*Y z#9(0f;^gxa)n{zx$gQ}g5-WCR?wPl9X1-XUtmPIKAkrax_2teFudnaF{`9D7-ub%* z$#Ku8i^jO$si|q4G4;(N;fW$g8zxWXF;h(XQ}%!Jna@sPMOAsL|9m*xf9GEO;#G5= z9lL!!{!>YvlJ<@pu?0EqM#91FuG!uiAHT#^au@+!9Z>*$!PD3zW7!U!-5}9PsR(!Q_XLA?LTewiHz7 sJeQp;q1Klht!*^(x?8k4+kb}5_rqD=aoQ*{FfcH9y85}Sb4q9e0Af8h-2eap literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/ebwizardry/textures/blocks/runestone_necromancy_4.png b/src/main/resources/assets/ebwizardry/textures/blocks/runestone_necromancy_4.png new file mode 100644 index 0000000000000000000000000000000000000000..406c0b17f03914ad15a38a74604a4ef82bdcf292 GIT binary patch literal 723 zcmeAS@N?(olHy`uVBq!ia0y~yU=RRd4mJh`2Kmqb6B!s7*pj^6T^Rl|7&0&>b{;;& zz`(#+;1OBOz`!jG!i)^F=14FwFtC?+`ns||?qE-IN^hV4)>Y! z=kEN!9qU? zVbP{Nr;fgwBhj&@e7@oN4i1Lg_|Lqzvv?bJH(MC|-5D|0-#3|Kg;rP6yiP;86DM<& z{_(%-TXkt^TZUcfnQ0wS20Y9stGW#AeV)9Vk?JxvM>#;qxv{@5&FYSJcv!^eu|NZ!&?O*p}`s1UbXLtn< z7A9#31iG|DM)>Txef@pa-OzT^GeYO5y^2ff+j*P1`DL6p4>Yd zzbCJ(=dnkbyQ`(0)v~wNtMX1?mR=t*jkV|4{OS8Iev{SmGg>THcErX{Yd1&hG!^L^ zrq;I>K010nzhY0N$Atq&pV^+z-}`L+U*%c*e!gov?O|QQ(6jUS-IJAEeLDo55AM6E ztmM%#LpqJEVdlctX)9RHeE#ynO;Ab8i+7311wK(%4Gyl)NqwvQ6fX%`TGu|1H-B!? zHuLd2k&Q?0X0&&uo5u@#9S-~#XTK;*OJ@1cSz#bWuTOJ_OkI^7F@^h5_+p@u8qbgHdvECAqnY&Q-EM28L+ft(l$Osqqcg3?QrKz1yX=t1DsJV!Z literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/ebwizardry/textures/blocks/runestone_necromancy_4_overlay.png b/src/main/resources/assets/ebwizardry/textures/blocks/runestone_necromancy_4_overlay.png new file mode 100644 index 0000000000000000000000000000000000000000..7428d44d4fd855e9c011bb60e911297cfff0bde7 GIT binary patch literal 727 zcmeAS@N?(olHy`uVBq!ia0y~yU=RRd4mJh`2Kmqb6B!s7*pj^6T^Rl|7&0&>b{;;& zz`(#+;1OBOz`!jG!i)^F=14FwFtC?+`ns||S1Z_IiyrJFI%!aXgiNeMcN~g3q<~5o#u$tNM9G>vy ze98U!yX;dp?{IeSn!c?+b$+qV{JXz}LO%%IFwGC(oU{J@g=e!?oVxj`DM^@N;)!iH z1(Kg6)waJrD{3fkQ|?|;oPZ$1u6+;x-?$#la7Xq?U`;tR0yd9F>>)a5QxkoT(N|Y<<^n&d|Y8nepT2C;k8L=C6O!&R_ra^Hug4 z(n?K_k4z8DZZ=#xO&2))pt#gt%u*q%~barm)Re)|j`#Q&CW4T4v{}b845kDocL0 z)R%`_w9S0{Zb`($yb|ZLr`gxrhO{lVxo$9w^x_le?b+EOQ?0hIStWXT z?Y+Lw7mvoC;Vn5i|{xxFfcH9y85}Sb4q9e0C^}yU;qFB literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/ebwizardry/textures/blocks/runestone_pedestal_earth.png b/src/main/resources/assets/ebwizardry/textures/blocks/runestone_pedestal_earth.png new file mode 100644 index 0000000000000000000000000000000000000000..cb5c70b31938172e4c0bcd8c8b117caf5ba0f48f GIT binary patch literal 737 zcmeAS@N?(olHy`uVBq!ia0y~yU=RRd4mJh`2Kmqb6B!s7*pj^6T^RZq;uwy)-(0zq zfq{Xuz$3Dlfq`2Xgc%uT&5>YWU|=ut^mS!_%+ABlCdB1yc%6ZPDbLfzF~s7u>15j? z6<2}Q{bx?SdU?_7cXLv!l0f-^14j-Vy`7y+6I-HUH2Xe#>DPBy0>t%Z9!pOQ`V!h-#yg@r9at3SLo%) zvpqTfet&O${(R2zS?pH%+-9nG4XbL7F7FZ@jL!KDfN>n#``y#LP? zK7IYhC3kY>{djtQ-oD^($*D=l^X2bdxU=)7$-VleGuH0hov(2q?f03wIh_J|X8txj z!nZ{Gf*&vOUlQ?{@pikoTstSrHhyM*ePOHVZVFqTt=SZGD`=WedIJS<|yMNIL&~)s{*HZeu1#mMrcf^(#>? zd?v(!Gk;2e~EPq72x&rx8j&_N@)`VugUC* znaagPSW%OBw|oX? z(}kxl+3`voo~_;Gwq>=uohM(CnZ$MZ%@wg3Um7k%1w4DouA_PIQsBySr#CK|{{Fni z(ns%liVsiH;d?#v+MKVaJd(O29D-C2om^J3?8dXY{*DPDJNHW8c)R@Q$*KP4)_uiC vtDgVLOQ@ewQ9kYG^ItOyS50~LhyUyEn*Wo(-n+)Yz`)??>gTe~DWM4fdDl)F literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/ebwizardry/textures/blocks/runestone_pedestal_earth_overlay.png b/src/main/resources/assets/ebwizardry/textures/blocks/runestone_pedestal_earth_overlay.png new file mode 100644 index 0000000000000000000000000000000000000000..8974ca8c204708e3c70580a0317514e9b5d403bd GIT binary patch literal 6570 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 KelF{r5}E);#Mo#6 literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/ebwizardry/textures/blocks/runestone_pedestal_healing.png b/src/main/resources/assets/ebwizardry/textures/blocks/runestone_pedestal_healing.png new file mode 100644 index 0000000000000000000000000000000000000000..96799d5fdedab3f35e35392a65f1ff11e493d05e GIT binary patch literal 769 zcmeAS@N?(olHy`uVBq!ia0y~yU=RRd4mJh`2Kmqb6B!s7*pj^6T^RZq;uwy)-(0zq zfq{Xuz$3Dlfq`2Xgc%uT&5>YWU|=ut^mS!_%+ABl!#(9>;amm=ran&>#}JFtsu#WU zWI{z69{!(Go%dBaknMz9U$1iH8+OA)VV_M5Z8?k!JvgQvWKr`l=$c{R;@~v>?$wno zM~?KrTUCADmgmQ|4=4TOYlYG{gDW=Pyr{Ip!hYdTANzZSWqaH{&pQ3qV|8n{dVgS{ z7I#}>`=3v5E?3;#ulA?G{m`TdTMdsg1uJOj9x(Y}(Bcr18F%wval5IJ+SC_eYjhY3 z_Rkm4yuczTu)x%yR84$|65t4eB^LzWDteY2S6_@?#sQW(em7mwl z4AzT2W(zA1E>SH0sdna?%NxN$B^C~srup;#9$3Hs@43tC_b<4{oOa6Q{-sj>21$(@ zpY!*#d;a-Y^x)BA&{(jy6wz*@8h4{@`dZa{GE3BxO`GtPP-uM!&g}e z6`$t?EPh}8Pwsu=%)>E}nrCrTWvzu9BnV8FvX{jsUlb+?RTdpCIWUJ^>{>~O#0 zv4z24k!Y6Y3XTg7)(#s!UUlGBT4(NkeRRZS zwHOW_E^W*3S$8FhQ>3%$S)OB@jl#+xrNvyUuXfFu{)XQ;IMiXs&by1RZ9LPp0=wpXj9O8uw%pC=@#D*^+ireYq5Dx_5?gTS zDt0C92`$wDtCf}hzxPsy9b-#9G@V? zKMv<+>amt>t?uraFsZQeYuCT8ywijxR9t*-;bW|MFzxrW#G1pCAGiN0{n_{N?z~5x b{~5%XYLewebITYQ7#KWV{an^LB{Ts51-4a2 literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/ebwizardry/textures/blocks/runestone_pedestal_healing_overlay.png b/src/main/resources/assets/ebwizardry/textures/blocks/runestone_pedestal_healing_overlay.png new file mode 100644 index 0000000000000000000000000000000000000000..8d7b3ed056017b7637ebc0b747b3e201e91d6dd4 GIT binary patch literal 6610 zcmeAS@N?(olHy`uVBq!ia0y~yU=RRd4mJh`2Kmqb6B!uTzEy=plmsP~D-;yvr)B1( zDwI?fq$;FVWTr7NRNPt{9z98CHSeEv(Kse2nXI{47M%TY-G2E`_J1YWmE zLYjYYE6-j2A^nY+)BcFv+W#vIX8V5o{hoWb*l9p)T zWmGtHi}9d9Goy4Tv+JglJ6%|0SpSH)yt}cRi%o;&`bnRH!!nM2JGPqL^W2gfTaYfb zmeqwt#EZ#PLt(9Ampm#m}x)B-m?Gk=CI{ zsvc8Rlp?*#W?nqx)Mq(U$MSj5hK$D7P20J3yjHF&`f7S5B6#Yo?92)NpLMs~2%0=C z`sKP}_n+TyOn!N(SihNViOC-h?CxL2P%qo9Lrp?Jbb!M~8wJBHUueqrI?B6`o zplf2ub+?!DXV36^xog2yzeA6BdMy1DY;@VeilgR4D!#v)lvkLx**TDf{hEeOk(KVT z0}JGz99nYxZu`#tPtUUakN^1WpKx(n;P?Lt=X738*}4DIH}-2)H?6tyo5Do(e02Ry zw$1CF{ODCj-J+XoHy*Gm{nWT8;r*S(0(-yYYTl4Mwasan;hXjqbp;#McW=4&_~Xt~ zC*CJ!&eY6fw#Ygz`1ICwrGt~p|5_=1P5yW+lKt$~dB<-sy;u{G5x9Sz(v!_@Y#$%D z$XCwzZBSOLc-ms)j~Cm7^Jic8cvCq=@I>Vmg=?QryvR1FDtx}>aT~(|CcDQS*0qw& z>*DUjIyPBmD@_qz@{DI^fBI+ZHP(eMH#G6^%89)ZyWJblK0B4|kF@Najjw;$oxkC9 zr^{yBLN)eU>+%RJSDmK_u5JUuNek zZ+GQ}J0&mO@aVKyXr*h?S;^2ZS+%Yk4={DLu2qjc{b~(QPKU*oj8FFzHH_5HKV$!P zSvs#ZDH+AcuCVR9ND9(8j@|M@L)XG5Zv5{ZM&s_^9dTwp9Q?9w_ zblFaScSO<-jnuh1A2JT*a$J}_Z9@OIX?uKMS{#<-SX+1RoJ*v$h|GjPUbhqC$^!fx zZydZledeM&Z0EAfk56!CQ%v{Kd$gc*`itc(%>j;$uz zuWH`;z4x1MKiwr7;ui_Z6cTzmGAd#`fB`kC)^FJBa0{O!Pt_~)l% zw{Bk~epb|8aa~lHK zlK%}}YguWiDnN{h89lwV!HN{TKYZv3fUm%jIQaKbZM@n|HABoK=l8VNd-1aPKl^ zgIS+^<#^*huU+vpFf=ylS9WK{b9W`vPq%(ux_bRmpN9XPnWg%xkD51@oMTFh5S!Vz zjyt2>{>eFhldgMOw{QRc@o@H^UxAljuT|UgQR>0c1Z&Uvr$V1TI3DC3zB4cPrd0Qq zMtSqKH7oDG^o^E$!CUvIrc<7?;%e*9a}Ex-=HEJI<#=aqgyP2S-Rn>2W#8~$$I*UV z)A04NSwH4hzPeX*D%|zc-5#+&Lf`d@GEeEB41M%iO>#|H_f_*h>B{xp>MyKkf6F;` zcJ|IQ*P}Mn?-icDTlLT4x4(IJS^9NJt)I6@Htir+?32|qS@+kga~xQI$n~J^kF%wQ z8-4!F`F3h~?Syl;7auZ<3(zsM{neB`C?*Jxar)p`yEHp)~Wwo ztHQv*kc_nk%q%EL2GxMJT?cs&7;rHE_qix|Ai{T(-^u0sZFcR?a?R@9u#s=~_29A` z!D(|JJSfSkJK9r}a`~q4OG(QozMZ~aPlBwsUU8Rr7Jm0FtC57r{ldvxf*Bb2Lo!1m zN+NuHtdjF{^%7I^lT!66atjzhz{b9!ATc>RwL~E)H9a%WR_Xoj{Yna%DYi=CroINg z16w1-Ypui3%0DIeEoa6}C!XbFK1 z^!3Zj%k|2Q_413-^$jg8E%gnI^o@*ki&D~bi!1X=5-W7`ij_e|K+JGSElw`VEGWs$ z&r<-InV6JcT4JlD#HFC105u#Gw5}B;a0@_uu<^wuDf*rTCCMfgxdpBjCHh7N1{S&o zM!H6p`pEh#atnNY;kxsRp`n(i=v~r#I+1zA66a3A(aKG`a!A1 z`K3k4sjg+Ic_qromKNlc79-nPTAT_J0=qjWB~8B~7h*HA9(PaQ0Jt7dFs5hb7Jzkt zR3ocQNrtN{C@snXt4T@LPt8fqP0cGQ);H8MMDb8XZUI~aR_}lf2M3guOMY@G$P`Z( zTP2VKtWxrmGgGX# zCLtN&UzC}inU|P@>?)8^DVZr&7M6y|7RiRjx+$qf2D&CDNk+OB$;nB&siu}j<_5+l zW@+X|V52|*YvmZ=X{%(UXMhk1$Vn_o%P-2cRSM6{OUW-UMo5KZ=B5UhB!Ys?(A3Px z(!|8X%*e#R(%2Ho#IV$&;>`R!kg0|SdS+nVDalrD`9-;jCALbLxryni`UQFEV2O&{ z0xRdD)WnkfqLBRj99t!jqZEwv3=P1ULBR%;tX(TgtbFp56G7PltT;8r4xAIf`OPUY zT_4P~(Z{D4!=&Jh{PH}oMo6B+V-7+o+!V*6lJfkbZ2uzvq^#8B68z?1Qw%pLC^bE^ zxTL7klYpnt)Y(ANrAKCQNq$i!lKsJ{g%BRZTREBFpi)o(XJ4ztWKbyDDitS|rKW(R zKmjI|oROH9o|k-< z#3UPi9O{ttgOgo8LG8%OAiACN3o45;(=$r^%k%JBk3}KG1fR_0)VyN6b|Wi+1Pf9H zV#fsysvs9PJ1!f2a4iO^(I8;~s!?c(p{b9SRwyWpT0&Czjt19gaFG-OBq<(EU8BK8 zQV5Wwcr7yJB3=C{Z-tI08{S0voN8N9(+{wVez**oC zSiA`K7! z&#BJ)svO96!mY1YIr0s=VWP0lCWf{g#)Tdn(+;wzc^GufFmQ2jntu1{%9bNX`roap zK5xtOW7~(5{_(X}-F=$-S=u)Ew}K1X)_#XZl8tS@Cfd~`B7WX`Fk#2bqH zZGKOg{x|y&e}#$;XQXtnjsfeUOH4k@{LUOMQ=d(JYhNCroE+4dcl4AH!}s5u6PbJk z7#X9OgVT!~XI-ATVZMxXo9^t7ZO)rJ* ze!8){zt6z?%U{*`wLdF$ba&W>Jdi!V|99XW?b`iMzkF<;A$dE|#c{_jDT#Y~)UUkw zJ#YW<>V#(o;n(IeWk;#BeT+AI%&Wk2_`uVO-g8?8XBFz}1TEgu5~=h^&{Rm5p(mp? zic5>h$chAQSjW7GC6*C<-HS?j%H8Kug?DR=1Io~PQj%=eLlPW@X-`L?b^=e@S$L? zqSR#Vtzk^Aix%vRo*>Tev1-bR6^F96Dm_>IefUg>s6bxc_Z6i&o0T+;<-di9&1g6B zH(qNwHzdf*rFhxPSy!_N=)3|MfJ7KOIcLnzF6~J_VLYWU|=ut^mS!_%+ABlA^lcp$zKKrrg@$&jv*GObtj$8 ziw+fO-Cujo?)rBtP2-TIOsQ8cbaBWvGb)7E3RUQ`**LS$Rho5d<=Z1Grc9czma8Ii z{oBs(Z#GLFdA#)NYSsOFD;|1^20s0o(scFI_xAQDQ9rBAlK($wDCF2P^Zd*0Guj=r zS|=Z6`uX>%x4oUE;%?dxnc6;tJGW_v6#4+0CVX}6=$lpCfzBGSo_Ad=ETvbs?M4w zhDJLkyL4z?%H4-j20t{t}aPHTllRI)J3MjCYm6fk_I6HHp$f0XGC7K&&3mLi{GW*rMF8PW{P2BpGmXFi^ zl$RgZU@$NS1kCaYFh$8l9k?D+R%;)gFMh2OO`E)08B)w^0K z_|UGtq+@>9CvH=AH%{uwxsw^JWWrljRplk%n4DrXzqqv0GpIGH(st&CTR9oGr~NEB swcp&l=I0B+%a4=o?%sQJ_`v@L?Y8i5t3$RjFfcH9y85}Sb4q9e08F`OT>t<8 literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/ebwizardry/textures/blocks/runestone_pedestal_ice_overlay.png b/src/main/resources/assets/ebwizardry/textures/blocks/runestone_pedestal_ice_overlay.png new file mode 100644 index 0000000000000000000000000000000000000000..b2c4faad19f834a1afd58411aca1528a9db7660b GIT binary patch literal 6510 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 S{msC@z~JfX=d#Wzp$P!!9zkvZ literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/ebwizardry/textures/blocks/runestone_pedestal_lightning_overlay.png b/src/main/resources/assets/ebwizardry/textures/blocks/runestone_pedestal_lightning_overlay.png new file mode 100644 index 0000000000000000000000000000000000000000..02c27b7b7e6141d056e771c0cf3ad78e5a955bcc GIT binary patch literal 6497 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 AW&i*H literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/ebwizardry/textures/blocks/runestone_pedestal_necromancy.png b/src/main/resources/assets/ebwizardry/textures/blocks/runestone_pedestal_necromancy.png new file mode 100644 index 0000000000000000000000000000000000000000..90b51c8851fd2ffacd916d67c96703e7cbec62a1 GIT binary patch literal 713 zcmeAS@N?(olHy`uVBq!ia0y~yU=RRd4mJh`2Kmqb6B!s7*pj^6T^RZq;uwy)-(0zq zfq{Xuz$3Dlfq`2Xgc%uT&5>YWU|=ut^mS!_%+ABl#S)}*x{HB)@ybp`)rr2{P}Bl&F*~@XS!Iq zYKKbOnstSFoZ#sSvypWa5L9C7?v;`hS-HUTsxrr#-@Jm2ERG&6|9|bu@8Ae!Uw6CH zO5b?)*_>@g+t{boJ-*S`!tN{^`HPp|d8>n3#|5v&x81IK{e8Il{)%?5oK81Y1EC2a zb#wNst3AIy-Tub+xsL96r+bfo?5w?iu;th3FOq6MUVl=TpKlkqwP@D4KVQzim)SP) zwq2t5kIKJ3Eyc6W+w}Th3EHVA%vCUR{fzexMf1+BF$>H|c&&Z>TSJd$iosgr?D>uf zQE9t$Grr5Jd@N`yI!g0^d2T5RtVY7c&aUqZSQ$zp!zzoPxVGV=r%0i7O4_A@;Tc~+R7P&xF`AS!pur5V?Rf7R5e zeYTSjbYV#``rcV65g5qww6I30@vhmK-aYB9*UGmpV(sqhGU9V@Gu!Zvdv-3%xze3M zA(mGJ1ry&}&udHj_4gb{l;k@drO0Pf3oU}SHXR6Hw~^ugegDJD53FD3zie6c=;aC# zv-=xNPB|`UUVb^bzW%<~qzH+-))Qs_e)zz+*)MIwEvKtqm)$li%bmN?m$BEGZ;sM; z-ssFNMgi+jiwZg}EtsjFQ?}bW^Fvu}>U(Ww<>fzHexJJ`S2_2e+U1w`eu`ITb~fGc T<>+Q$U|{fc^>bP0l+XkK3nV&T literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/ebwizardry/textures/blocks/runestone_pedestal_necromancy_overlay.png b/src/main/resources/assets/ebwizardry/textures/blocks/runestone_pedestal_necromancy_overlay.png new file mode 100644 index 0000000000000000000000000000000000000000..da450fb8a30d0e775487031db53f0579124229b4 GIT binary patch literal 6436 zcmeAS@N?(olHy`uVBq!ia0y~yU=RRd4mJh`2Kmqb6B!uTnyNw~N`ey06$*;-(=u~X z6-p`#QWa7wGSe6sDsHWf$nN`W!S`o<@EJiD+m(-BaK7RF_9J+b#!b)fH3xLe+|>DW zgHu8$mPCF1|1W*T{trfKSx;-8OmMnTvGd8KlNO14<9|=y68-*@>-@?5yLXB6_=wFf ztLKfqmVV=Jv2#h1{`@l0)jtvoOKiHGt;@|UCYI{-t+`n?>Alv;+M9bXO|+Mu-o5+B z@7>)Diz_A81}=-4~e@assFbw<6fwL?c6ze@vJL>`{VWB9LunAyMHrPydflD(iP9txrvF4Q_Aj& z6}bGVoO8TXMW#nY+aW(;^Me&#LXrv=CjuAyH2?awCPZ+N@m-f1so>sNvuzhug2grS z&*7JXzC z+`y4+WPX1mSIY$fpTCF7WnV3o{;PDY$#H)|n#zpQn|fW#-J{Ds=4?Edz5L5G>!WIX z41(XjakS}3Twt8E%)x3=qyVEko4w>j>DNAt%un`aE@9iT(X2tntT_LUaOPUmdpX8Y z+#Me@rf_5hI4GR9K;P9J3%UdrN^(!7bVR-b+ zG}&rCnVFV_erl0h4CXs^X%%{DrsvFhX!ZDAkEo@1a8BXT=>bU(CwZ-#;9q+6dO-5i zSy_3@Znk~OU+8*u$I@xmr5-DHzpH++vDn|1KO^_X!#4TEBL|gxYa)fi>?0TJKl^t^ ziZgq%;r44s+f8RA+vsI%6SlWxPCh0m(LcHI<{Y*3Stl)xXU?AUG9^IdUW4hU$#dK$ z8ydW@lC*zO^xfdQ`@JdU|GUgT`=43qdG~*_rRhrHXLX;xacAqU?@SVR+{~rE>=vKN zHb+hAbIX3*jGd$2UYKg_ue>WN$6$i{(HW^srPUL!o36?ByFTa2ro;ok_Uutzck%t| zC)5Y}Ir6H=y?+~P zbNS}!IlKE0vUQqj=yNPk*NHwDZ}WS){*g7)TxR%ho1}a!aPm?6M?d+RU%1=E?n!(t zI8*{VjHW?PnQeg5d!UAY~i8}43A<;!z_I-@n*$B0p&IpBlUiY1fp z#H|*{oNOBKBF?mHt8CGEr~QVTLa(Xk1-i`gt$e!r%gs&M9}ivq_F$9kMc)0+dV6;n zhL(mr>Z_i7ar1O*y}IfmR67M z!UChVfB&MArOaA<*SY5zsxM%<_UFK&XNKM1w>m0bTh;&VsDW+Pngm zH=zo*cVyh&WxGUqr^FH`mwun+#v2NAukV@_`@*%s+WdRXhBTLEyJ$ZX+iP_Vhh-11 zuf8(HUG~P>Z+ccz7XqjLag?9C%PiTMAu%KHpRV%SB@PSvRhIq`@e*b{d#s@MPtymM zUUl22ugu#r^MwMcVi|5{e4i0j{fYV3BD?2HehJps9I(6Fk>|W}d4m7xj~`7M6)vnj zmKLYur(CD{Rmm!^^;pP>Rx4*k&jrsozv}H>WFYj)Aef? z%BwQXlHE3U&X>3Q|GnH_vX0Bh=3<|Cu4%)zFXw{$AO6am^iAX7w>7&<6knQz?t1lS z>y0apu8%lh3qDAHk~DjvXkee_+Yni|JytQDT|GVXu3k8knX%}Gu>bt7wSSK!OA7?7 zKhdtco^P6;w#vnit5pOgYUZEZl9P2cc0yQ;kI-9#=gJA3*B(DEnRR*P&7*J37iB$& zT=9^-J6pdr_}0`m%hrGDLWeH72LXrgr2>ZTqbKr4DaXKV;Y$Wk@ad*V}EHeYJ;o z&7H=x+b?tY%$mJ7-2Zvnv~=~Bz3m&FOiG&~UfMeQsh(dq`PB1>Mdgwe-)%B%jUV5% zl&$jrbAIyzTjT$N9TRu9wf96nE)U{c?>hJF+HV1$FU!?DEeO`0zw&E=(>IQvZ(cvE zFSurKy+r>1B~7#HW#1*7x3^B zXQ!4ZB&DWj=GiK}-@RW+Av48RDcsc8z_-9TH6zobswg$M$}c3jDm&RSMakZd%cjDr zBDWwnwIorYA~z?m*s8)-32d%aUa=KOSYJs2tfVB{Rw=?aK*2e`C{@8k&qU8a*R>+E z%t*m6W&?6cnI_gTmFdq6BUM zhz~ZtxFkj2v!Eo|q$0P#wW37d$iTot*T6{E$Wk9!e?@MAuPm&XYryIqu;Ji0+w{a)4DzesX4t6_{ycVUcELYM!ENl$d0o zYhr9Y=Te}mReMtnV$zT)zCoC z3@nk7Y~_|;l$%&$tCX3Wn4YR%ke3dYsK_m_axO|uEXgkl$k(=&@piYh$`cnVFO4J2K9WEPj?7gZwJADmhU z;X%BWlL-zg1qE>SwMt9|g`%xeabj6&3OEWBU{c8$iFxU%DYi<`Oac?n#FAc94O0y* zQj(K&P14LQbWM!Rk|9Yx(IhP`)xg5i!py`F)%4>0w370~qEyH9)VvZ~CHKtS0&qMl zXh4&hCaU`Kj8sq>GBC8%H89sTGzu{^vobWbGBi+v#I}NsKB#1b`PK$hcKG^QA%}+z zsBE$F1SPoO(t?7V%+w-C$bi#LaB3mMBpZDk>X7tzf%E z7}%1$-CY>^8R8g@y5C&6lYxPOv%n*=n1O*?7=#%aX3ddcU|?V`@$_|Nf6UIq&(C$@ zvCs(y2BvUN7sn8b)3%eWC#i(;xb}aEOH2K#-Zq0%spG)GjAqxwb5RORJa2BY=t(D- zI+%Ywx#mobzkE;D2GzUTbG3iIdo7-|Qe^F(xVV!%c6Rkj$`=Pgg)qA~rc)1K=h zM-89dZrW4x**5>WxzS{gVA*Hq3@s@I{&U zBz^t*6x)y_e-o|7i499WJ^s`@=b3q3?N8h2>>jJa=zJSL|1H-JwEQ~#CvwKa^{408 z)ckU}dMeZI^X2XPpC-=Vu~l;Sf%CW1I}7|y&s_epGfL}vsT-r-Y0=MYD$jqONi#m` z_HAFGjNAmxPM&AEiLbdi&b)ToF8cPKgAjkZ4!e$ZsP@ktk277^f)tDm%|pKMg)=x@ z&sA2^h&sU{xU^b*cF<{u&u%*&KMavwk-8vbVfAwZn+0-p{X7mrjvEZzWDSjv87(q% zP!sHHH@wogkmt;8&RRRW$(8aw97;?^k-yHE_^r@r`eb1{(P6V}vGV)Kgn3Z=K4sZY+*nFA~aE>g1BK_hDwnvit9Q5;Pvqbya!2$*|XbRhWRp>yGy1 z#Q)NEvilbOGoBw1Y9l-K&^zmCZk8M+A4;mWeE+^yrL*)q1)par^DNp3U1|Yp>1k@tHGC_+4*i i#go#1vwfCVKaW2$XM%BL{MY@UAs$axKbLh*2~7Yr(%3!# literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/ebwizardry/textures/blocks/runestone_pedestal_sorcery.png b/src/main/resources/assets/ebwizardry/textures/blocks/runestone_pedestal_sorcery.png new file mode 100644 index 0000000000000000000000000000000000000000..4747ba9ed535b08889f5fcfc0af466204c62f88f GIT binary patch literal 709 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 literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/ebwizardry/textures/blocks/runestone_sorcery_0.png b/src/main/resources/assets/ebwizardry/textures/blocks/runestone_sorcery_0.png new file mode 100644 index 0000000000000000000000000000000000000000..973f908d9781910617ed67fef5b1f911444a2e0a GIT binary patch literal 521 zcmeAS@N?(olHy`uVBq!ia0y~yU=RRd4mJh`2Kmqb6B!s7*pj^6T^Rl|7&0&>b{;;& zz`(#+;1OBOz`!jG!i)^F=14FwFtC?+`ns||6P_}#FsyXM= z=bcwyb?Rk_(o&X&RYrZvzLyK^=1aCUu2>bbKKx9N029MylZS?V$_z_IyfiIt81OK# zgt~@i-WC&Fm?`C@$uJ{Q_ltGI9OG4|HtD$R_t9LqYRQzWO{ z!H#v=OP>k3v;=Xbx%G%Lhpye(f4q6$d(Q8_YcC5iEfsO%_^P9{WQx|R{oNe3_w!4S zKc4viX#V8V*#E!GjCZZO-E;r__mbG~mCL8B;*Wdq=?-`3S~d3h8#_W))qQix*HQX< zZn@yup6|b7&;HW=HMh_Fqxp29TiaYi4L9#H*#GYN9K+4O{&8R0_V(HV{_W!=HO?UU*K7;ecOW(O!cFle^CD`jr?f%?^ zo;`8v-^QP?+^pm6d&ctdrJ6PSCl_7&Y$N{Xv%2|D|Ufq{X+)78&qol`;+06Y8UJ^%m! literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/ebwizardry/textures/blocks/runestone_sorcery_1.png b/src/main/resources/assets/ebwizardry/textures/blocks/runestone_sorcery_1.png new file mode 100644 index 0000000000000000000000000000000000000000..d9e317f4553b14ec1df5e57e8e7a014d7eab1637 GIT binary patch literal 636 zcmeAS@N?(olHy`uVBq!ia0y~yU=RRd4mJh`2Kmqb6B!s7*pj^6T^Rl|7&0&>b{;;& zz`(#+;1OBOz`!jG!i)^F=14FwFtC?+`ns||g|92C;RXH!e6keSyuY=jRfyk2RE|+%Dd#1Uw(gI z=Q8zuoKg_Z*|-V|6cEO2EJJSfo|)Me4fsmSnP&TPBBa)x`=E-j~@I+?_MtL+c! zTKAem(MMNjy7!*%!KIIH8%~t7*H~(BjN!sIU9HfdWQ@7`9bc>(bwB-G7YbD!hYo{z)`fAMPdhNOJr;KL7sw7c)2BUalin>=)|$ z?VsJzxy4t$8qCa)@s&BgCOmuJACJsf?-xurHPuh=Fuu4$_?X1A&z6CgO)j%^ZCbEN zRI%lx!Qw}Y{U@m`d|$mtW6`?TiQ;>{$LLLe`SHg6jN7+8E8nXhT9(;yEO+b{;;& zz`(#+;1OBOz`!jG!i)^F=14FwFtC?+`ns||}1E{ zTLuEH`=_Qz3Z*s7{MYd1N?Du3Wk0^Z|BuhBdMW=Pgx%Wg#0?hjR|mJMmE=cxzJI%~ zR(tkYHbKS*PoJ``HGTbc*5i*I*JeE}I%&Yekg?WMhA$=ZSk>ON{r8i%ToZ9^{4Tdt zgyEd!G7A|#h9eT4hH9Js*6}x7idww&SX6h%gj7jGH-$9Sr3Co@s z@N{roe?3(qIV*8vgn*OBRo{GdCDU2~!8KbMzSQ=w-nMb&{Kdt5OP{pGYP!Z=Ka*x0 z5*nJU@1?qN&-VnK+p&tv4^Mv)Gn-*bPzT56n>jZ6V%+!Ii~E+<_1s=RHRP(czx}#P zS3oALEmb=4xklvQyLWvy=O|Fhb{;;& zz`(#+;1OBOz`!jG!i)^F=14FwFtC?+`ns||Bv zEB`I6yZZk7+#s%oj}<)~7hZpj(3{@D(ca!Jk<1_Vy&SRA@Jl$<81Xe{k`Eb&~1;o7YYFRB@QFDoeJY>!sD zZ*ok)RdDy+zD+t8qu4|0A~ju?Up^=y%;#Df%bsy9%4{}o_a9|J&9vLC6^!dxdAB4V zpM9{$=KRUebHY})TG`r`>IZI#%H`wxw)6MTuF2o)Ev&4#LZ$?rNi*JZZO!#;hDCYX zrCq!yv1If1_xIQA3j6b`*6rsn_P1r$7d})i$@B^heX)11?Ijc5MWU_;jpQe!N{Vmy zf8u{Xa&1_~+K)}$9y6}rOI|ACrTOjq_nkX*RvdeN=l=c6|ErEC-CM5F6Hp0-(A zPEJlDrZ3{Txs1F#JD2Aq0aZ^S1yNT=%YQwAQk^p0a~bz0ZvD}=PwMl-H~N*KiEEeY zoK6>K*mCViVNX!k_Uqa%DmR|ZS)8fmc3D%YDM+g(Z}(lbPjyw*&p!YBzf?`*eRE2W zqVMGoTT>(L(idh*ZM&T-kvEIY|E$De@8z?W9b6o@{<@1@ZrzRLXRoJiUU>OsOZMV5A%wh$-SPtEFUv4Ffe$!`njxgN@xNA1!g7^ literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/ebwizardry/textures/blocks/runestone_sorcery_2_overlay.png b/src/main/resources/assets/ebwizardry/textures/blocks/runestone_sorcery_2_overlay.png new file mode 100644 index 0000000000000000000000000000000000000000..f469c0b4626f55e2d6ab51d97a61e107424a7d47 GIT binary patch literal 678 zcmeAS@N?(olHy`uVBq!ia0y~yU=RRd4mJh`2Kmqb6B!s7*pj^6T^Rl|7&0&>b{;;& zz`(#+;1OBOz`!jG!i)^F=14FwFtC?+`ns||DHQ39T=F3N5_vjmoExE$qwu-*JvtF>8?XY35S{A&5!hc+<}Y#-{V8yEju zKk;EfM+bw!OrL;Iwr0lFSGht{>+9vSbs1KjDzQ@a4Q6X*Tzs*^B~-HixW#jWV+;Y; zP4CY3Th7oTz@d2LyxU?y2Di|_&`mndE*_Vs2rx06+i7v*D#M=dE3|IEowh_fD%*2X z%kA6Ivz8r{5DqLotaRwzJH2bSegqbkmy0j7e10RxOy~4=MaAQJ@{YS&E->@|HTm!; zM=v!pXqxKYIDShjt4E4maqG`NK3*O3w?=5*zJI#x?CcY}It=EYH$1i>ZvFefxpU^Y zT(sH|8d_LWb7uYf^M@usw_kGqy}Q(1CBcQc(Pz$`{;99&l}gA)_?fngF(=VO+6~7H*u_7r8Vp1?}VcZJQFIj59X|x9^brk#);YG^-FT1 z=MQc~LUC!~9o+g4|eiu*?M&IW|KsHknf|9)~wU0GqQj@bY9nvi|g zD%rY~^NwFJ^DVCDzE{2Nc5cqMdzS+@U;A`H^L_1^GgW)tCaZLE?D>9iS>DIA&5GxX kU+p?pE&upl<_CV|hb0m}%!)2EFfcH9y85}Sb4q9e0IF{;e*gdg literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/ebwizardry/textures/blocks/runestone_sorcery_3.png b/src/main/resources/assets/ebwizardry/textures/blocks/runestone_sorcery_3.png new file mode 100644 index 0000000000000000000000000000000000000000..31f45408f32db1421754d5388973c2271b964a1a GIT binary patch literal 619 zcmeAS@N?(olHy`uVBq!ia0y~yU=RRd4mJh`2Kmqb6B!s7*pj^6T^Rl|7&0&>b{;;& zz`(#+;1OBOz`!jG!i)^F=14FwFtC?+`ns||{K6J;R>Mhu2?Ra$?Cx`Hu8SB0vAzE4f-N4@jRcxA=w1T#qKrb9-)R7^;+Q+&y9W z^5sfO414zNOG;Z4rp?#RoObN+VP;KLhBH0uUT4f|yP9>hYOmT1Nqv3&CvyTr8TyVZ zZ{4+ydBGGX%~q~$aqAfaj1Qm5xGg5QFjLA)li|sn<^5aPAH16(dDuW8%Xn$as-nGd z$4}sS@4E5AZOj|NVZGk}YABVM5obG?0A!(U@N48wO<-p&+whT&#>h`DG%@^Kw z`z`yC!w(O9d>`K7z|opH*4**?MacD|U0!{r5;U}3p1sHymnZx`jvM}CD@kA0)! zh3|hWxZj;K;JN&KSA6e}>gB71SDpGll~6W3_A>1s aqxA&up2d=HH!?6VFnGH9xvXb{;;& zz`(#+;1OBOz`!jG!i)^F=14FwFtC?+`ns||&|Z6TpYtM;aCzA12~XZm#UAg>i#496c& zth}|2RpGhMxt$Yo&7>KwoG~zdwad+A#j373#tfQEKNZ|#++m$|%z&q*QZm^kbZ6Xp z;ZL)r%H3T8LX&!CNE#k<5;<1*M?v?w&;9Q+BsEp<$d;?O9JqT|mO<&z!-9m35dvkq z@3J3T_uArL?U^12jt>2k8=Ve!w!e?Q`TqL~t?r{t4F$!;!9L!aiD@kRKK=OI|74D# z^~XPde766em_BKWkniOJtGOJjuXYv6NVYKwDn9SItf;glw|nN^x5tH2&qB{_52;@okxRXy_4%!t#)>vKK;D?OGS9H~q!WntvBcjhPc9+8&+Mv0nOR zf1~1s?|;9D-!F=vj~6Q8y0VTH}KH~Q1P cKR%GZk{Gs%_w9}c3=9kmp00i_>zopr07(rN)Bpeg literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/ebwizardry/textures/blocks/runestone_sorcery_4.png b/src/main/resources/assets/ebwizardry/textures/blocks/runestone_sorcery_4.png new file mode 100644 index 0000000000000000000000000000000000000000..29a30021d5dfaa5b6abdabfe4b5793e5adf08e29 GIT binary patch literal 649 zcmeAS@N?(olHy`uVBq!ia0y~yU=RRd4mJh`2Kmqb6B!s7*pj^6T^Rl|7&0&>b{;;& zz`(#+;1OBOz`!jG!i)^F=14FwFtC?+`ns||!b$(umX^3LikupR=42 zRPjETZ^4vBxzSD>8cS!Ke{S*ol9Dlxvz4z)hoO>E##+g?#%;NotMY&BbAHNwufBHC zy6jiG)Xo=|godi?=>M2od_>~%&&X*DYo7eNtb9uLLe%0ZO6NZZ->wH1omU<37uS+Y%SN|NTEg&U3ck@|qpi49nm8zcxK4;l#0=aq+R_ z$9dbmTVmtlm^MVMy$~hrlwdad@A9^f_cq^uZ+Ps232*ybekM_~xWcc08y9I*tb1>m zt!DdvW_CIMo7lgvS`8k*dh5UF#}VF!t=~)@%sJq3cz(RO zhMLCGxGR;a2Epu1B0ilpUXO@ GgeCyDLL{jG literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/ebwizardry/textures/blocks/runestone_sorcery_4_overlay.png b/src/main/resources/assets/ebwizardry/textures/blocks/runestone_sorcery_4_overlay.png new file mode 100644 index 0000000000000000000000000000000000000000..8f4bc9481b009ff1d676f69c44dd13b3c3d4b5c6 GIT binary patch literal 653 zcmeAS@N?(olHy`uVBq!ia0y~yU=RRd4mJh`2Kmqb6B!s7*pj^6T^Rl|7&0&>b{;;& zz`(#+;1OBOz`!jG!i)^F=14FwFtC?+`ns||&=PWS(FPUs3*&C04>+BEmZSGg*|JqKdey3IQL z{r~2o%F50Th7TV;G_2Ybwf4r_vK3mVp9(#fVOZrAdp#xcSk~4>tF+dv+7!3`$Kszs}wRQ7dDNR>2nW7zY3Wx*-N7J-1!w!{N|p3h~J zn!elZWprs-_nJddK}ko9drooY1li+;YnQD$A`uwcW7zZ9<9g|q+4&dw*_Xt8`uBRT ziLdizlPRg4H*?I~r>WOHmoYrHrEXekNB^AqUBZR7$0S@@HtF=2b{}n;zHn7$Y3R}F z{_X#F?Efp#>~Tn^i|M^>nb~Z^KIOv(dx9#3a?NIce7H*7!f${4`i<9woGi>{*v#W9 z-yJLT=F1n6hTFHJdkk9yW}JV%{?3Mb)!%;GUW>Z5ZR!1g9gVz|Hjm%@?hOe&np`Zq zwx>gX=Z?AwyVePJo&5Y~=GAJq?MUHoO8@0-h8Z=F1(bK2loLEY6;7gzP2O>>T%RcN z=Pcu_M4dd^%PnLAvfr-eRr|mESnd5_5!T$_XYPNujlItJL4HGjl;ERR%N8;)Ffe$! L`njxgN@xNAdzmY@ literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/ebwizardry/textures/blocks/thorns_lower_0.png b/src/main/resources/assets/ebwizardry/textures/blocks/thorns_lower_0.png new file mode 100644 index 0000000000000000000000000000000000000000..d64a4336a576a543076711f246c3cd7c22b9a7da GIT binary patch literal 368 zcmeAS@N?(olHy`uVBq!ia0y~yU=RRd4mJh`2Kmqb6B!s7*pj^6T^Rm@;DWu&Co?cG za29w(7Bet#3xhBt!>lVATwT3C4TmxM$@vFfcH9 My85}Sb4q9e0L4X(c>n+a literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/ebwizardry/textures/blocks/thorns_lower_1.png b/src/main/resources/assets/ebwizardry/textures/blocks/thorns_lower_1.png new file mode 100644 index 0000000000000000000000000000000000000000..a646ebc67eb3b8cfd7974e2fb562f910cb6bb5d7 GIT binary patch literal 506 zcmeAS@N?(olHy`uVBq!ia0y~yU=RRd4mJh`2Kmqb6B!s7*pj^6T^Rm@;DWu&Co?cG za29w(7Bet#3xhBt!>l*X%;UCY+n`;+p_Hb}@b#%BD7G!0-Q2xUEi-paUo%QM!8Ivs`0!mZL)-Qi}X{xuc zuI}8Iw$IDYeg1c@@&AwACwzW02Gkqx**^8KL0!cKlmGq9>_?lF{g3Q9*Y@JbhMJcz zSH7R%awpRJDD$>3My8GY3|_yxLss(&MR9X{h%;xr@Hx{`N1SEr%aRlCT2!p$wzV6* zc8qp++dHM~Gt-24PR;`^TcS_>{;WIsPTGx!E7tSgs`UAM+iG`WV|%;R(T#^5yS`qc ztn8S%CsJES~E3f%wuQp^E>Z(WRKBiD+RZ;=b0q6CLZiy`oJ0Qo_l`Ki;O^-g5Z=fq&cMKA=IP=XVsZNHr1RdF6J?IapTBOoJi6G^(bIX( z3ZH1_=Q3$VSB`BGbV@7};OgO1RFYLWl(FEs-;^-m*M5ZA%Q#+^?tN8UL?Q zcJxnGHoF(%ctQLlw?q7UyVc^avNjt`%$w|RJNJ*rEzXi1x&^V`d<|>oM=~r*-?M4Y ztdQNs(}icwwF*`HuuW>m-7wEwxio$C4WXKB?9v50v)A0ba&*QEt26g2o5VPOt6G(L z1f9(KK_ssp+gvX!Fnjg+cndH~~;O{BxEE~Sprbo`3N8e)Wt7K8IyQ#zc zmywaDDZ^`dZ@XE+vyL!rpuWS914t+^XR$f|GlbfJAoWi<% zK^wBKU0)~ZZR{Sr{icqJT7!fhkCc8- z(Uwg|R|+#(u%-uJTmSv-$48|{3*Y@yKX3W`=ltiE3_fy|ag0LxtUu~~dU#h#^5>mO zz0^F*$L`$D-RD?sxgnbISF$5(L4HGQQjV6Km)n$}sdwhG9t~iO$k+JUs>=9bx6GUzkr~Xj zQS1L6^f&jOG}j|@>ua-O`M+wlwQpaQm0#X_{n@Rjw{>f*L_>_HEi&D<{k)n$!Mw}i z`vvPo{r1fc-R}M3rRGM}3)hmq-@7fjRmYxmR-yC*}l#_`a>+c>u^wss`^Xn@6E%+O@$9nL(i#|9t zee;Ie-ZRA?Z$j3;b$Xw}eBg0;@w-cF7;e~g$E?$sy6NalZeyl|8;>5n z+b(u9`JAmtw|3BalLGs{4U^ydytu~K?pahYzw5f7z44SIJ?(P86aL)LTYJ;&*x%ec z(XmUmt2?RgICXt`xQZbEtHb+WZ~F7vYV!K_t5p|{+FwmwW3|V~rfH&F=gQrg4>s~V z+jpw_{PUv~ul)Zkeaj$YGeJ${*23iWL$}sM#{9L>pIgTq*la9cqjv1h)}|}7y8d1d zJO2N$XO8y<>pJ!alV|EXybtlG7#Ji=Tq8=H^K)}k^GX<; zi&7IyQd1PlGfOfQ+&z5*!W;R-85o$QJzX3_EKY|`j?I`|Dsrs;zq$O`@XaQ{IoZh( zoB1}a<@WAbI4xlFq^(;^m=~TqsOQq&(POkn!)T9;QQ5KT^5woTbdU&vT0BF&{Y6Y0D%~drj9SEm@sOh_jj{ z!J;sNq0jG&ht9LitCf?^C}#ku$tHZ`l|A z7G*ul@^3pXYJ5yv@3VK-4|yvG6QMha&x9JDq&P6#v$NINI5&p-u?+3ZmHs2Ho-g&IzPi0=+o>jACU)RixS{9Z6>D`qT z3>j~$wO8!wT)L)kUcv?aYi*oAYt0$NcF*LV9?Z2M@v`Ug;#DzMEbCv+I=En=&zif} zB<)lGIO}a+mG#u>*>X9fzsF|0DU$L@Ixj1bYT7qnrbCdk`hW1F7b_b=qaFG&XtK5O`kn8 zK9#n4k?l|OZ*TJ$`s5{#y?&dRvMGF4=-ivHC9mdP4_H+A@2|Gk?B9B;SNSgdm>|xe z&vz{2MOWKrJBIl&zu8iHH!baqd&9I~W%ifv-7rwDekyo!SVPIfj@O1TaS?83{ F1OQiOv}gbT literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/ebwizardry/textures/blocks/thorns_lower_5.png b/src/main/resources/assets/ebwizardry/textures/blocks/thorns_lower_5.png new file mode 100644 index 0000000000000000000000000000000000000000..fafffc974afff76bd92f13be14e4525dbf84d855 GIT binary patch literal 968 zcmeAS@N?(olHy`uVBq!ia0y~yU=RRd4mJh`2Kmqb6B!s7*pj^6T^Rm@;DWu&Co?cG za29w(7Bet#3xhBt!>lrnx>v+U|^6eag8W(&d<$F%`0JW zE=o--Nlj5G&n(GMaQE~L2yf&QXJBA9@N{tuu{iBJ+27|jtH^Qt_t)*WOetL&%+ezI zGUAfqnt<%)C5b&EGg<_F3$n@r#UCHk>1IzB>+g;%`>|QJWZpFzAen-x_G%cBA z#M#^`7+{{7mwY1Q_v`ihpD&dD)u(^|d+q!uzvUR1kIxHk_|aYWw7&F7L_~5fBkPNI zSy$&BWP2;Q;UWi!9ID}vrLl%Ve%^~~M;_0!k+k|# zwfElK^5WXMNQR*IEmu>ufA<(nHV$TC_Wki%e$lp~^oyKQA)bkR`uu9&@FX1mPKzjWq~?@K>66EWW;8^aa(T93X<_w@YJNIty!(byhTRX*CRAmfb4-HC^)*)4ZUb%f{S~G|K~v75uICD!x3L$#CbX)279)jC%F< zd|RcL#Bsm;F;&x$$2{%algpR$S8b8!&HNe6r?zj0s{H&n*DuPe74Cku^2YqsPp3^g zk2Yn^V%3`6{6p@_q@MSwKW-N;tG_3}aQN5Z<{hoqUewuE*SQ!K-+p92M}Cpl|9kk*p;a?(GM!6*_wi!2d&&0oE|V%&Mjnmj zvcEb{;hNZ=_d>t>+D+qilK$*$w|?DyCEWc4+qIo#nW2wz8TbA_kW!f%&2}#%)f05T-R;=lGN$f z9j-h$lYThKC+4ijy|AwO_iPWQ_OZBnYy7&#@FVMu^@ZChv1Zr8cp0{(Ubu9F>A-&G YS6*+fowS<6z`(%Z>FVdQ&MBb@0E@@EumAu6 literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/ebwizardry/textures/blocks/thorns_lower_6.png b/src/main/resources/assets/ebwizardry/textures/blocks/thorns_lower_6.png new file mode 100644 index 0000000000000000000000000000000000000000..f4b8765c07df49b3f2d690e6b12db382ea0e29c8 GIT binary patch literal 987 zcmeAS@N?(olHy`uVBq!ia0y~yU=RRd4mJh`2Kmqb6B!s7*pj^6T^Rm@;DWu&Co?cG za29w(7Bet#3xhBt!>lL-blR`Q6e*JhdOY zW$a}yTsb7wSuK6(^4(Qp->s(jm<4A(`pC;@;Iyz|8Mi>@=d9xk4TOb_H|^ae+)%U7 zW$9)A?}Ghof8%<*4o<4?dt1LiH)g5$x%oj1yY6RS*|+`AQznZ~r|f$7?(|oFxPZxp zFI>|hM_~bj{G7KJzp2|+T9te;oo_d1V{v_2AVX3<`<1YuZ_>D=jWaKZ@lIY+_FBPfODFSj%skkTGJ~sIz_*aXOQPZrd21-+vj}a9p(D=c^58{{4yArEGZVvmQfLvaHm8bH~=>j17YG=ZLy5?cLRE zDb&g9dFCkNhH$Qn=fqege&zAJGVj>?>iWjn!buWkpKjXBkEw88`glpac6s!UuRqs+ zy127W_Gg{U?z8S!8+jhbuk)~YbG2rlL+NJm>s7WFPsFk9msI}uSa{+Ydzp^d3|`p_ z-r;SkmV0&IIY;V*Wk)XanfLF7_nn>Fbe6sniSPBDtUcw&kC^#P64u|+CpNXNe6oju zrMYgaxbBPhyBRiEu8rAcrN-dee)7qaH7S?W#Mk#s-{)9N!gZ4V?CidJMP}bE1xf!dYx8NU zm!4g8e_bgyecRI`uY0rBg>If1d*saFjpy`w=B=9$<;`Yx`N6dcCmBBLW5)c2c~_YW zUS;sdy_c(Em)bhTSaRpg39^37fz93X`ML^UmjxB6F8xvdlR5rf&hiW{*Xvvi*WLHC r);b&uJLGenF~Ep7N-CP+hxqwpQ7zWjofa@KFfe$!`njxgN@xNAfz-6D literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/ebwizardry/textures/blocks/thorns_lower_7.png b/src/main/resources/assets/ebwizardry/textures/blocks/thorns_lower_7.png new file mode 100644 index 0000000000000000000000000000000000000000..9c4a5ef000bf6d6016ee86e192a63a4ff0847bb0 GIT binary patch literal 995 zcmeAS@N?(olHy`uVBq!ia0y~yU=RRd4mJh`2Kmqb6B!s7*pj^6T^Rm@;DWu&Co?cG za29w(7Bet#3xhBt!>lbne*J^L5j|pYM5fw0m% z-__`UnWEo9>n-8>F?+N+cdn_}{prS=Z?ZFsT;15?pFCT-Bx0-PzFD&t2Wty8rX*SEUCm<-Z2m0Y-&y$9&53JT(7)|%(c8r< zQy27a(wt&j&bY(or|t{eB0g^8%Nz}mdKI;Vst E04jpdy8r+H literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/ebwizardry/textures/blocks/thorns_upper_0.png b/src/main/resources/assets/ebwizardry/textures/blocks/thorns_upper_0.png new file mode 100644 index 0000000000000000000000000000000000000000..9a25c6a5831a8ea6f624c4883ffc4b81ddd99fe4 GIT binary patch literal 170 zcmeAS@N?(olHy`uVBq!ia0y~yU=RRd4mJh`2Kmqb6B!s7*pj^6T^Rm@;DWu&Co?cG za29w(7Bet#3xhBt!>llllRd zT31)}Us6IsqNkU|;7QjdnTI*Pr7euEk@I*!fT6RVZTI_k{l^&?7#KWV{an^LB{Ts5 Dj1W91 literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/ebwizardry/textures/blocks/thorns_upper_4.png b/src/main/resources/assets/ebwizardry/textures/blocks/thorns_upper_4.png new file mode 100644 index 0000000000000000000000000000000000000000..7b494a8d752c371b1fb524f034eecd919599b191 GIT binary patch literal 343 zcmeAS@N?(olHy`uVBq!ia0y~yU=RRd4mJh`2Kmqb6B!s7*pj^6T^Rm@;DWu&Co?cG za29w(7Bet#3xhBt!>lgTe~DWM4f4=#bR literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/ebwizardry/textures/blocks/thorns_upper_5.png b/src/main/resources/assets/ebwizardry/textures/blocks/thorns_upper_5.png new file mode 100644 index 0000000000000000000000000000000000000000..a07c1912ea570ee1caa956add2938e558c390837 GIT binary patch literal 580 zcmeAS@N?(olHy`uVBq!ia0y~yU=RRd4mJh`2Kmqb6B!s7*pj^6T^Rm@;DWu&Co?cG za29w(7Bet#3xhBt!>lO?#2CKeZA;j zZmQ1ZaL?S+@efw_Ts&iG(BdShd}NP+Wb7C5lAEC};ick^E*&L-7x%nabcCBzhoj3- zK+GwecWdt3imTE2w_8iz?yUMzcmC&`&vTgDKgMq?v5mX^;(fNA!IHOg&K>f3)Nf!V zJ?UWMu~{c&=ekWzi?m{xcmGhgdt~Tyd$p|$|J3xiiyx11R;mZlxm+;<`P{hqm;d*U{{ioSAhyV~(H`59~S*M0sN%-Hbb z?1YGEjyg%F=l(vQt)KoQ%7fvJw&Kfo1~KtcGx@qwcbf7$)L#;5_&hgV^|Qrl2A=tg zwm)CQz3zSH3wP!a#SWzt5HQgkG9RP=8s>wfAaMCb%DIk_!yj5Hdr+D^3R{T zO6K9s$?LfkY}13YPVBa7J#4l8S@NgP(-ZtzUH1Ji{xq?3fs1n6lIM?^3MvhCoL5d} zx*(k^-mosunJp;oD_@dl@E%tCr<>Y$^T%m5+?lNuwb-rd+_duS*;z%ew!9HL@cpp` g!^>80rVaczLn_z2nZ4%+0|Nttr>mdKI;Vst0P#%tV*mgE literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/ebwizardry/textures/blocks/thorns_upper_6.png b/src/main/resources/assets/ebwizardry/textures/blocks/thorns_upper_6.png new file mode 100644 index 0000000000000000000000000000000000000000..737c2a6685c53b6a0b02ec9d020cc1a5a38dbbe7 GIT binary patch literal 699 zcmeAS@N?(olHy`uVBq!ia0y~yU=RRd4mJh`2Kmqb6B!s7*pj^6T^Rm@;DWu&Co?cG za29w(7Bet#3xhBt!>l`Ki;O^-g5Z=fq&cMK=?CIhdVsU!yB!3T)LXqS4#(rI@lWzve`h@$g zDY=tVCZ+BzyFK@Y?*9wZmS`SiQxe*wBWG3G<0ot7aXl|~k+VQa#|rOOc0rw27Y_2h za$Fb?aJfcSEp4WX#*6Z*n)~0s|E;_K_~8GF?Zx8%I_(W-@w`%E*pm8e-!T^ zwV5Yva(|j;ruw=2^_{){Lv9Au>=M-%Kkp?Vq@l;Q_z%bH?%#|V@;#>xZ8>)3jmUfZ zHCnlTi!<0+4qtG+{NUV^$xeUnJ=}F*YxV{=hC8QClgwT(oG5hoqO5lqe3s(z2lVcUP5yy})srM$<@SQb2wIyhxoMDr5%RVu|-*>B(F&^*t%^X5k* zhD+f!e(CY0iJg~?=ZmCPi}%adhA}+)+LrS!n#1+)t|p%zwbaM$5BNg6b;4WHJyRAX z&A+5-|0@3G(T{8|-&pG~^xaiqQ1^{J_a(G-(#mbA9-EeXb%pb9+Pbvp{lQ|^gm*{F zw{Z3T>Cn!zopr03Aaw AM*si- literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/ebwizardry/textures/blocks/thorns_upper_7.png b/src/main/resources/assets/ebwizardry/textures/blocks/thorns_upper_7.png new file mode 100644 index 0000000000000000000000000000000000000000..06172a8397e887ee7a4b3514ec006413006f12af GIT binary patch literal 804 zcmeAS@N?(olHy`uVBq!ia0y~yU=RRd4mJh`2Kmqb6B!s7*pj^6T^Rm@;DWu&Co?cG za29w(7Bet#3xhBt!>l-z0bko$+X(zuT^#&-{tnx zpKsn=-pU!pvps+LtGO^&*cdJB>SpzgR+IexykldBzt-!zjfZomy>eSD%Oz!*!CLV6 zoAcD?*UFB}dp_ySTJeUA-JyCsDyn5SCLXr6dmO@h;PM?6zvYo!F3L44q8R3!iwaDY zO8@=H$kzD$)YtqWVVMj+_K0=u_NAVt+CHurs=81D^L0#uwHfNP*obK&n$Xf@bg$L>jGZhY;dn}x} zbQ<^0^6y)jKA7!@So6bS&27bp0h<|W{wDr8uwGTM=8)c}otHR1_MfgPeJdBMzj~U^=2e%&@*t)@hM|r*c+yAquQwws7#J8BJYD@< J);T3K0RYVFVetR} literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/ebwizardry/textures/entity/arcane_lock_0.png b/src/main/resources/assets/ebwizardry/textures/entity/arcane_lock_0.png new file mode 100644 index 0000000000000000000000000000000000000000..489e93bc8f000bb1785b65a0999245a41fdfe450 GIT binary patch literal 1860 zcmeAS@N?(olHy`uVBq!ia0y~yU=RRd4mJh`2Kmqb6B!s-{#1oTlmsP~D-;yvr)B1( zDwI?fq$;FVWTr7NRNPt{9=+|c2G5^#(akJJf_2yp<``SQcZoz)6V_5yszD2?)v?` z>=Ny*f!YhZ)O0_-y`?2(eZkRvi`@O(C6N-f&1Q$1-)|I7|IT#p=I#Xb$6H>PYqXSH zJ{W5-t8CNv8>KCJYt~M^&$ecI+`IX_yQBEmZS8rpsLKlT{l1VJp{^Y~T1zYsDQ;!?z1p z*}Sl1kqESEHs#%H_1&rV?uF~8k3{@bsL*mUIMmbcen;~E`C_(JTc_$xd?Kv<#(OK% z5i_acx6*M6Ew7GTDXaOdylvM+>5Wo6xA=^e4{BWIn5eTi%e#D@>7O+wPJKn{^=B9w zII^R2+Ds%S^ledfzoh-Nvq8Cee#czx+z=+_l(kkKAq9)KGFz^>b!*1smA|!Cw@F@N zQd(1HVRna4;Dph!MRj`;uLNwlC6&0g^jh?`gKo>`7GAS_9(#Gki>>DOs-Evnm#;}V z+oo&%?Tm~Co2ZG(88-1f95PNFg57Q{eKTYq3ML16s!z@-I;rlbc(mu!NwwQ=Hl3g2 z+}CdPrSWn7j>Fx}{RKyySeJ(QY&H3 zdKw*rJ#Kobm+L><_epKdPvv`8go_siem9>X+`H@K9rb+kHL@G;YwQxf;+J?hZ@}1Q^6LzBe;l`_}Dq8(-(yAKc zwL8D7rpn%se7pTl*qYk)$s*}3RIz0WJcjS{D^X=->EWfYucxJff>*778Hw9;(`?JpG-Z5e02h%G~ z?MW&2JbOhuefg%$3;PqxPV42C8h=bMcI{!-T`3Ubmw7MvUfGXoC%w8o8ghr?J_=~R z^u6#|bL&q>t?5r@3W+^`wCGp*3NI0~tGgE%PMr z^o+!P8e;Ed>P0T|KA*omC)(x2^4A~vqd%6+)puNYeUa-RN>`yV0eEGIhe&^^!xD?lI@MzT0Tso!wsb{tD}SCExk>2u_=j zntX6mg?g*8qk7ThH8Udh}e&W-s6Vc2R}{lYQ??+%VpuQ@Xcr zZlu8v9)_8|W^((c?en{->*%VS;Ip8efq`#V6w`slbN4YE(9Een$<1=AZ&xHU1M_dQ zJ$vdMK4dJ{U$bN7q08FZc|z%*qzh7itmD;x&vGWkqWQF9(k~xo&Btn=AFlpuJN0IY z@`dDdu}x~{o-i2fnPV|oID~~EKKEDf)Ln6#A3ZyFv3%3D#OMy@zYj}qh%FLi-29;K z;kt?^UsoMXm8{(RE9vXJgG((8n2xRNo`3T4mld;P-<(+#Tqb=YByi_@ul-BZH=kVg zKBVBe3;&Z$Ev;^kNsM8441UD4=Q=J}Bfri;?YsAiFUAT|9c!JeD>l8n?HKO;aQOnE zg-!>2E^s{YyQ#}?r(t#B%pIK;^fW{+ ze-n1jcy><8{{^d470gZ^IseZ}lRsX*bhBBW5qraf6|?7R$XD*2)bl_0&e3x^ZU=Vo k-Bv18n|{Gl>OVu*H`V;IWi#I~FfcH9y85}Sb4q9e0DOLa0RR91 literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/ebwizardry/textures/entity/arcane_lock_1.png b/src/main/resources/assets/ebwizardry/textures/entity/arcane_lock_1.png new file mode 100644 index 0000000000000000000000000000000000000000..de7dc96abefaccc995b13a4cb11819d4ce449894 GIT binary patch literal 1876 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 Ib4q9e0BP5FqyPW_ literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/ebwizardry/textures/entity/arcane_lock_3.png b/src/main/resources/assets/ebwizardry/textures/entity/arcane_lock_3.png new file mode 100644 index 0000000000000000000000000000000000000000..5b2701ae0b87b74f31743b75590f1b46c9ff1c16 GIT binary patch literal 1879 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 S@hI|kJ literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/ebwizardry/textures/entity/arcane_lock_5.png b/src/main/resources/assets/ebwizardry/textures/entity/arcane_lock_5.png new file mode 100644 index 0000000000000000000000000000000000000000..2a0cd2ac054f792c7f66d5561ae01c8c1342b9cf GIT binary patch literal 1878 zcmeAS@N?(olHy`uVBq!ia0y~yU=RRd4mJh`2Kmqb6B!s-epZD;v3J=J=W>OO7Z-A_gtyV8%PygX@?QgJHt?&=-aRI6{D`(>Uu!(z(% z?`8}=j}%PS?2s~&y1%d5u;YNsWCOOE@9MEiGopL`{${i;_0fMIyP3PpN_S^vyHnf9VbnD&Ew~gLbFFrqSiOqJ6T3uXzvP$9U)mvBgO*L$O#HMjJ;#nc< zAL}!RcPQx{6f<_vPbfY-Rn#>p;nso8%xqiKAD@`accziUg6oH8$DH1$ygU<%V?0a?l6%-K58XAt#v--rO+{B=ltYWL z+;O*Gj7*W&te*I9Xp-?dXR&%t@jX^`yWTKGws*s6ZSHr?-{D|6e+gwZwrIJ_^0nxZReC~?ZsW%bk`7MA&waQfPtV6JI|OdDYYC z7~L7WxOumDaeQU)xqm|We~!#~b>*-8nU#Kblip3&K`fKk+ zJM#Xs*c^f-kHfSegR@`T}xBbm5wK34aIxd^J=sAFWO(QO)WsuKh|fWnw#*htqWxi9JsUhh>rTliE1D1Y_Ih9y!E+o z@}O^>hJk=T&w?o4oqQtixBpZKb9buWzAfcu)4Z5^U^=s|#h6tw$NTH|yeq4p9tmczuy|0Un`1A2 zirspzY;AP?s*d?HzlE`io_dge|6;0H)Pf_cRoCC!vpp=AZ-M%Rip~w9_JzxIKbGbn zT)pMn{N=`4W);1&u6eEddFNH-w#EOrt1W&nE|jP$*s{MQVo%_nLz}{lgME2z_wGMj zv*pNj#@ZG8C%es_S|9ww=kfg4=5^Iug|6=R&b_U5`MIzK0|NtFlDE4HLq9_t!%_E} zD|a$5FmM)lL>4nJa0`PlBg3pY5)2Fs>?NMQuI!K5xdb&e-u5xBV_;ys=jq}YVsW}P zcw^r!2Z7qnH`cH)NmowX_(M4B)P&VRm*NW-`Mbu%&hMJ1?~oVl_Q%zWB`haVo+)$V zhb0ceKQCy`OnYVm)RNeii9{UxWL$ON7tM|Aae2)i?emFAD91RaxDF3HJkAOuZ8&A zq|behDZYmeyj!q2ovmyk?<1+wb4QM^iCq)z5Pm@a)IK|-G8S0|yGx!vwG0{O1cT#e zXsmzbtCTIoAaU!UQ&mQ@1jDAXjd@IMW*wcG3=DNoeM4W)+s5;Tp`o+?Qt({;qm616 zt3EG%vx2ommSIA#@yFRE`#&w~`K83Cu_7VmY*)j_xb)2nWp!r!@Hi{;W2(9Colorl z0^_dEp7JhJ`@Pl{N1IJ)rR9tFF*NM_RV>-J#?$TEniO@GtC?QKF4>!1yo{MQF>ee_ zS-s%XJQl-EY9CkKd%`v+HR8sJM@OznmFBJccV}WE+j91~`%gEjguL-C-6s;wdO`56 z>8qF-0tWjuetQMX6}zCiY~P*x|9gK|zMCff>+4Tx^Wbm$yViJqvzk3~wf*^9M}Or{ zIeT@!@yFRIdxBrDf3&@cD`>91v-A-mE6>OBYcmBVTAs?d$-uzC;OXk;vd$@?2>_6L Bg*^ZO literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/ebwizardry/textures/entity/arcane_lock_6.png b/src/main/resources/assets/ebwizardry/textures/entity/arcane_lock_6.png new file mode 100644 index 0000000000000000000000000000000000000000..d6133cb375125a096ca832c21b48a5644fc73404 GIT binary patch literal 1889 zcmeAS@N?(olHy`uVBq!ia0y~yU=RRd4mJh`2Kmqb6B!s-8LC1eN`ey06$*;-(=u~X z6-p`#QWa7wGSe6sDsHU}kKXoJgXhn6tu)S#?x3eLS*Fx~#>X~oXT@2ryL`Ah3RTz+E{DSpKLy=a};trfy*i;m^@tjXDbo_(vDf6=bEj1C?*W4YRy zzc`D&M+m%`B7eS!tMb;w%#6r+Y`&k@7|yIR;+3?0Vl!X!TdcB#K z;c(sxU4loeiO z{4$5dZOh4ovnFxtB6j@ly&Ip__l=J9@+vuTOju40Sjj1DaK z`3`PiWInaI@J%G^T4v({kq?svcAACBCp65xtRBp2eyn1G@~)r9W*vwPx3)c!p{sC6 zvVYUWFb9RxQSE;?!zMVNluSQq`8>AZ(IW4A6|d)hxBGEzagf15Ht`w`M<*W7o`}Ln zsvRCvL`qFE67_ybXn6G)s#^FO%-vw+sJzr!{@I3h>py~gmX9VHT~fdOX482^?>@`9 zzf9Cm{r{4_AoyIxvO}yZLvjj_P7hdeWRh0V+F4nvSMO`nGQC!^(JZnytv7zg?{iZA z*QAoSy>4aC7HHq#Q;@B`u8{56mQ({dDQ1t1yB5KRuDv=I^Vr9=cTs`Vnuo#+MSgib zjgHX~yHAOi^FQ17$?e>~4)edAmRVQ+@;+M;Xg;(0`P;Uw#$WZjUb1Y}%9)`ReDQ`r z-l6?D+EyN~`1i|heLY!uhO=jul2@eY=bwKszs^^F%e3y=#?k{Ee~M>!n;yQ$*!K0q zBAx@1yDf4(lM7W&20gphbyrzxRaSpadC8ZRQ5TI)7R!-?QT4y7JyqmNef77FP;m9tt)aC9}VHbn`o_o?GCTtjEW`Z`yEFVEgr5`ic)M zMNIXTHw8?7R37oEBY5_V#qxnqC#icZDKk3sVe+Gudasx6_xrgeUbyL>0pr^b&jMVc z_so|1>+(OkOyJR-Y55;^#M(^zS?2P}NM?~`&b@vF{PYjFPt6F|FHbprEO>Sy?b!$*0G;mp3smXoo_R(?brWYSkF=^HLNf7Zpe zGu6!t&mM?kP*CP)Q+l3r{L!;_x#@*Wr+tzekLYZ#edeuQ{m!oBexF#!ff(J@b57U# z&;H9{duFZ74US7i`Ps}lZ};c7pE?y6`K9q`#bx>Re%7ZL(x3L`2fs*6*U`Cm`lxH4Vm>=aw~ldEe=ukx$Zo$}gs`j~v5?eCX&1NS`t5v}F(>#bFG?k)`d z3~>xc-EXek$-uzCS>O>_%)r1c48n{Iv*v)5v6p!Iy0SlJ=MvP?Ie2bb2?GP;BTpB{ z5R22LlMVA9IS91wk9`v@+aYnNALfaNwWrK+`E9d@Bpv}{HH{%z`*_GwCe69?02 zi?9h|+ViyEsTD0snYHoS;_dnOsv!*9bc% zj<1^Br@vaWInUQ)z4SWJwc?KYdluae9M?v9q3Mtt+`JoLI~ zcY8CdY{Rn{ZmYqWq+2Ket9XRVEaAo)^EFc%qfWcSi z`R_lq-dfe*xVy}p^{GqGlT$8VEh6jlH@p=q`SSn7a&24twxd=T+81@i@3qox^c9@e zzw1`?l*wAN_8sa@i%IzWgfIN%PIKd=M|)3;*UFzaEtz#}Kew%d{VuQK)eH;_44$rj JF6*2UngEZbkCgxb literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/ebwizardry/textures/entity/arcane_lock_7.png b/src/main/resources/assets/ebwizardry/textures/entity/arcane_lock_7.png new file mode 100644 index 0000000000000000000000000000000000000000..a2a2234fa3caa93bd08a77facc4c0dd655595b8e GIT binary patch literal 1836 zcmeAS@N?(olHy`uVBq!ia0y~yU=RRd4mJh`2Kmqb6B!s-E?0#_lmsP~D-;yvr)B1( zDwI?fq$;FVWTr7NRNPt{o_*=D2G5`Kn%_7$6a|hSlvwqQt@=-{T-lr>Cu@wi7A9?A zP~0W`aK^9q>(l-nJU+4Fv1*owVnj{Nr<186SI(W+Ir*zFp8wklo115EK1fKKVk7Sy z``7r*CkcVSoAS?>37`J7`1Hkxm6lKJHan+&z5KM}?v~3{W|_UG|81J{^|3|FoVoGy zYgr_AA2@Mt$EhP?-!G&mx*X^?<);%(UupnrGiU~kAB>s={`M1a>JZu_eLJJ)B|fG61Lqg*~n?T08rFCMzi;9QHR29pD4~|Y8hF@f+D!a?8wn;2LCbD@`l_;-N zsA;C3o?+08B@-5T&I&puIXP{|If=O!m7kx@-Sg9T+lHgQ+qXPr`Y95>q(!KETF9q& zW%oAz{l39{^XqxvVpckNT@7Ek@YpKTt9KS`J$BYSbK%itx?5{DZHuT)>y4Z7`<#^S zHLK*hFWvmt68b(CINHwjc+S&f>7QUz#-@;Q-Ey{U;r zWBf_a#glil7spo`Kl+O( zzcinT=Bte#CB2r)%4_&@?SJy-pC?W){lA1E{etQpZGGcKZ|*YA@GV~0m&R({u=OnC zyvK=0PhYW~^-Oq9VU+U;lfBVz)*9YO64%puv)E*P+wY=QRi36N2|MM2zg&`;8Yjp2 zbJg{uvR(zj8qv4D+Iq>{%=4Rg`P~H3zK11->l6R7X0klnaDVxvU$gJ&oL&7;@m5WN z1OM4++^50|YG*aM1Wj;$G^?vF;<5RXGZmWqipypg$BF1G#xm}k_UzCPL+?x64*wcw z@4haw-lRx>mh{J%h>x3RdTtN(e8#!4*syB(NAbegrwl#&R(^GV`YC-zyn>U-d(wOM91o!VGnhb+gajQ(rVW za_5^lXRg*veC$>|!|{jEK8~ChSI$_Tzw=-5c8#A=yN_@Dg+&Kn1?}Mf<#_S>-%o3V zKQkZvdxZaATCM26*og9%`O2SJ{pTIm_}4T?;MA$om%7(yE@!^=Zn5$|$Cvz1KeJ2x z{krV$-;2*r*x;_GS9E1A z0|NtFlDE4HLq9_t!%_E}D|a$5FmM)lL>4nJa0`PlBg3pY5)2Fs>?NMQuI!K5xdgRj zo{KNL!N9m@ZP>#4g&wu&Znu)=aa7VZ>X5OTGM$&(5~ej>-N8La;+D& z^%uApYMM|zr4QvU4KVl|F-Xc7WU`AE!}Oy z!120$`GJ?>Y-QDR&poo5WAsswf$f@(WX*(X7STJ5-;Z2TT{e%Mp|$>=n1%l@vw6%8 z&&2JYvNE|<&ppeaQ1I(%?DEO=0$*}%$_s9`+wHU5aV8}2(2?cZ1tyC#zB%MQNfmwZK487BNby3F!INMI5B9p(cU zW^KLoy5!jdBZeJJ;x9AR<2#wpJ_J#2OE+=zGq@DCX)onp8)>{jn7w1=?~Lm6Tv~Q7 z-k7dC{8DsBfHAvs_O;xpw@o*s?Y#c-&1KeLS5CvPA|X0j?xhyz{w66)78FPd%U|}} zr<8DoXS#aKY}Jrik^;O(!WO=5{dzd~;r#7~`W|4!YU8K=9#_Ff}{ZQj2Bx z-&@Ru=eI-)d#-%bw1CM{K4SBfzlZGeZ8v%<{Cj`>@6~qx z>bYkZS;;UTNT0IUO2#-wQ!@R7;~%wUdACl6FY6NGoV(;B|L$11_@?hZZVU_z44$rj JF6*2UngF(TdrANR literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/ebwizardry/textures/entity/combustion_rune.png b/src/main/resources/assets/ebwizardry/textures/entity/combustion_rune.png new file mode 100644 index 0000000000000000000000000000000000000000..01ff7e71a8fbb861009f16bb2cff34e90e6b5640 GIT binary patch literal 1512 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 literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/ebwizardry/textures/entity/containment_field_2.png b/src/main/resources/assets/ebwizardry/textures/entity/containment_field_2.png new file mode 100644 index 0000000000000000000000000000000000000000..03536e9b66461182e7fd52c6d60d4223d06bceb9 GIT binary patch literal 587 zcmeAS@N?(olHy`uVBq!ia0y~yU=RRd4mJh`2Kmqb6B!s7*pj^6T^RZq;uwy)-(0zq zfq{Xuz$3Dlfq`2Xgc%uT&5>YWU|=ut^mS!_%+AGSYW2c6QHz0r@rI|1V~EA+(%`*$ zj~oR4rM+Pil1#pK#G_L9x+ece7Ln^qz5GR&I(=vRV&m9nW}4qr@}!_=djCWFP~ z9>q>1((qt&1uMh#*L@5MKR%bQFy{yq5_$T^$Ga<`_}*8ZnDy38 zJ8Y-#=I^+@+v3#HyR#fpMAw*~PcY*0Q+lfVc*6c|@4KFrhHXt}Sj59Ht6JgI6i(~O zJyUndei5(QWpRp8AtHa?`ZK+YWnB6h5-#84E)G1Wm{%{Rqiwr$)$~~o!gE$vy|hg- zdU$ls;ireU&NF+vcY?=C&I=z+N~lQ_UulN%(4S~zqmub1|)~x%#lAc zTWMEZ`4bFVdQ&MBb@0NREGLI3~& literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/ebwizardry/textures/entity/containment_field_3.png b/src/main/resources/assets/ebwizardry/textures/entity/containment_field_3.png new file mode 100644 index 0000000000000000000000000000000000000000..9245b9a5cb480051d2d7bacbc99300a4dec03b03 GIT binary patch literal 583 zcmeAS@N?(olHy`uVBq!ia0y~yU=RRd4mJh`2Kmqb6B!s7*pj^6T^RZq;uwy)-(0zq zfq{Xuz$3Dlfq`2Xgc%uT&5>YWU|=ut^mS!_%+AGSW}tlf_ICyb#w(sKjv*GOOM`dj z-F6VDHC7Qg-l!qB$i<<4QB*2NU8CR<@27TC7oPHXeadxLh^FYacT6w*Szavh;hJ{$ zjUQLG*pvl6#w_I@zR7O>^7Z)q^E(2z-IgreJAZEd{OSA*%f#D#J8-706_=Rm# zMn~2B+ZH+s-&~&`n9`8Jut;(5zPrB}9^|fKXV?&Ez{Zfj^XId53S2v~mN7UeS;y@? zZ^dTDb!|CW4JTc-X(XSC4*c)|rq!m%v`f&*#h-U zfeJ2yGla_J+FSp9H@n)rp8x31U-QGCd%fWfKO3@iXQYWU|=ut^mS!_%+AGSZgzRIe=`FE<0(%U#}JFtrNMji z9ytj7OS>NQKtL^9x@U^{!m`S+c?zypT2-rrLrZeCzE?IcUi!>;!lQ24;}JhI%hX*Z zviYAblguvv^7gy&vfKCT>mJSC^!a6&z1`F2_n(V0G<2Wkozb80ebubT=gvLiox#uW zz-PwA-^b^kF`U@ANWw+4V;vJiK8XiaO(p$Y$u`?C$=`nR$YxNlWkd${(u6=UQgYpRy@4=*tQ9 z>A6B{Q*QVkm3$@3s#))b{4kBFA z3w1U&?cCzIh3i-1v*!6a&ucZM=BU*vrjG~>eWXe)>l?mz8>}m-YWU|=ut^mS!_%+AGSDb5&K6wJWDc*E1hF~s6@YtZh# zTLA*L#$^*X99px}EaH*>3eDzk+#OT$w10(kWKA^_%{?M6uzlsp=?Whs9<#FSK0DX5 z@fhP4uVs>_?X2c~UZ8)!uI`ZaZ!V7RoWzTuSMBK3Q+&+Ib!7VctV z$h@*!;Z=ymB9G1_151Ie&I}LUp5|ewnfC04?5~5Lzg2(bUKX|C&KE`oE%$rx(!<4n z=$u`+izDoOe?aVyY0}PH6s}I{F5-G*t-SpD_T{&`4|mBP*lpFR#IWN?qsAuh2&u2@ z&R>#YsJSF_>zl4Q8-w1dms5A@nujftU{L9+Icb`Us5<5PW~)2VhmJ|$oplN$>+Is$!R$cnXfzU{6A#xCiPYC zJ>O?7mHS1>_x;rDyo)>LF*wB77;HFy>CX1aos~?>ZY|w%VM|=E=gt=ml?fYXn%q_RG;zD`QnD3zG8OED_sR)^J> zU*A}kNp-w;5V={Nd1d#vdE51kfBkv9J#On8`^TG2_@~X@x1-{KtL55NI(l*rrTMbg t`{nmV-AgDsxJ%;aH0kJYWU|=ut^mS!_%+AGSC9=7;K#PHa@u{baV~EA+(#f`Y zw;cpp@1GIs&^fs2N4n4n-yM!7jiAle zdWY@?v>Bfjcv4XItUCYY^Y!-jA6#F&{t&n~gn#~g`*wDQWAgV8o!A}2^X}^B>@=r( zHf2$U7bfQvH)F-kjRj(`0HsED+P`}9Ka{r>-rhiA~X`QmZ{r0qNr#r)i z^~@hTZr^2ltC&3Z*iOGiq6{-G%)hy2aRMJh%=>HU1&b5-78x?kSbbVL?EHF37cPc| z6Zg_WuX(R_*uPWj_0r@cCQtbMzJ7QAoVI!Au00ns=QL|DGAMrfTKc2HO!wo7&9S;q z_i1JD&wQM$?)7-j`YFp7C-5y3aOqque_w>X ztUh40VbiUxH-9{iz8$E3(QA2OUO40B3oMgg&fIAg>AA%4V9KkVNy<~T&euMODEYK< zQ(RP}Eb~r@JBw{oR4!TEw2~{a(LG?o^6^Bi|KmIRo~P~q_{Mdk?EmuD|2|IC-QKRg zd)DSnoNB=xm7C?-PlSm+oy+-mrohitYo=RqJv&!2SK6K-{GRTjnzQFa7#J8BJYD@< J);T3K0RSvW4yXVC literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/ebwizardry/textures/entity/containment_field_7.png b/src/main/resources/assets/ebwizardry/textures/entity/containment_field_7.png new file mode 100644 index 0000000000000000000000000000000000000000..7eb0e5c54f29f6fd7255867adc7eddf06abccdf9 GIT binary patch literal 585 zcmeAS@N?(olHy`uVBq!ia0y~yU=RRd4mJh`2Kmqb6B!s7*pj^6T^RZq;uwy)-(0zq zfq{Xuz$3Dlfq`2Xgc%uT&5>YWU|=ut^mS!_%+AGSWiBYi7{S26c+JzrF~s6@>Ew-h zj{*c--`ni==y>$u50Bd;|Da&KN8EcZm4&)3+TZ_PbL)l3w(`eqtG27R)0b!X@$OsPy7h93o4#JkIh9!M zq{PZ_rEp7w$ExoME0~SU6}VbX{9;J>c9rdSR?PRiJPc>voj?Cf*u`1@>@o(0>*4+P zPT&49xoOw?w1ks;bH4LTn={u}A;{@RLRXRR@yjv{ulCJ$OsQUX<9pm^^|@simoMaF z*z*2hfcw-LR()bxa}U3Bv9_Mg(4cv$v|7%3cEcH7hAYkYPE}-@v3m0{2-szqS8lw* za_g{foKC5GiOtzsh6}yTPh+cXU#wNwbd|+HD0#pl-adaC|=zdqYb1r(ZQ5{wSbMz<4Krj@74C}mDI n4@~%!bn=`UZ;8CgKh}Z^YOCGDyALujFfe$!`njxgN@xNAC9D6Q literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/ebwizardry/textures/entity/ember.png b/src/main/resources/assets/ebwizardry/textures/entity/ember.png new file mode 100644 index 0000000000000000000000000000000000000000..27e6e197c84da5e1b9ec30b55119e9343d672696 GIT binary patch literal 1244 zcmeAS@N?(olHy`uVBq!ia0y~yU|<1Z4mJh`hLs=Z)iE%zuvLXblmsP~D-;yvr)B1( zDwI?fq$;FVWTr7NRNPt{o;_`i4$q(Yp?6d#eBjVwublJw?Strlx&qb5cD~&cWvMKc z92C-e!};z1|5kqwD#|cft~XpFz{58^W>Qag#y92j#?t2Je?Po-Cf(Xrj>AW6^WFU9 zh;MAW55!N~yT(GY?7v<>*6V|1brZrBI<*frW~gr3qi&#W@Kp4~sZ)Cd@_ujf@d&)H zzfkA@zIpyqk0PY}&aGmRkB~j**OTS3qc3Sr({`(dsJTDoJMHdWeyDXoi=4YnG zL=8mh?;UacCc&w!6x=vR)OA~;h@Z}cjhi2znrXe=Qe3a$#gfh>G0mi%0zHCBDw@H0 z=4|DGCt`A2Ua&q*NSw+pHZSwCPq>9r;Zu(la&894wDoy^^##9Ab~c>-;{n%>ln}E3 zo~JWT8r)gH@!fURd=~k~j}1$<23+u;r7Sk%teKL-zq6mC3vX&}XeRie=X?3%YQLO(o^bd^qGE=Gtm*2|<#Elc+d9 zUoor4@aPTji@9~ z)$oyz?4MZ?_0nDgz0Dn<|cBP(r0nw!>b z{Be%|?Y$|VTb5OJ=dmb0;d`3l@tybSzpHO&W|^MnpF5YUH`l_$RBSgtW74!4)n41Q zS4=9*wmVmrZK7}Pl6lZ4+suC6Y|cWqS5Z~hR+q$|ZD{VyYcyuQ%gCPbLd?R!dHVrI zsa>pm7beuH-&Mc4>+wss=-?}ae!4v;)au&I4Kr)@ zEJ?0c{Ql|#YyC5~-%gfqxHCSiR{PgfXJz<}DX}E!4eKGl##h`e7blTB+M3v@cNe|3taTNMogNX_l4_EEq5Nt4`+xgf-Ne_w-1Y5u zkdd)M+#~T{O(*k(-PDi8DfH~yslH#O$FFCvgGB7MJ@REXRcjCKOI+ed&%en>M z^xyIpq%E+1(BrWEz(F4n){Z@XeyvMAql~Vs{k2Ea=Q1!buqAoByD`M|uL zfq{Xuz$3Dlfq`2Xgc%uT&5>YWU|=ut^mS!_%q%X z5(ej@)Wnk16ovB4k_-iRPv3y>Mm}){1_mQf7sn8e>#?U585~ZEtF6AbDI0h7vY52pA7aeFfcH9y85}Sb4q9e0PQv} Ae*gdg literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/ebwizardry/textures/entity/fireball.png b/src/main/resources/assets/ebwizardry/textures/entity/fireball.png new file mode 100644 index 0000000000000000000000000000000000000000..138e68c9a988681d74298154ec54bf1464648c05 GIT binary patch literal 1764 zcmeAS@N?(olHy`uVBq!ia0y~yU=RRd4mJh`2Kmqb6B!s-6RScZN`ey06$*;-(=u~X z6-p`#QWa7wGSe6sDsG((kKFV`gXhn4kzy7V#-_&`+`jNW`!QMKO;p_8t<`GBTxP}! zc}*;u`S1Js#D9klAG&C<-f)S4j@7E|MLrYRlUf@?}={5U&yX{%|xny>x} zzKXN|_U9qnpEEUq~IVDlJTybMXd*;Fe zHJ+0KtM_>RiBWFaHo0I=W+c~^8xgM7bL;;8_<5qJc-B6}`i3uA7p)(cd(1w(@Og`k zqR6^mPc44l-m$a&%YnCk#T?V0wSSCR?)+|^@YbKwi;o)qvWhKZbm#jW@I0_j?Ap|q zYm>tr0{`sky?k@C%9IZ6K*n_E38GWHIwcJFimqr}UQl;ss+Ld5oyb7raIsZv&4LLk z>)7w)iAk+t*yqV|NA#hB#M9GaR#%oe$1deK+Plc{i$IIuwm)Hp@sTFS_5`??#qDc~ zwNaK1^Lf(IqpHKKWU?*z@52Y1ZR~}^8JqqU6dz&StQ*YqK!0A|K~?q(O|5cYceyXg zP-zn8A--~wwF46+zE>BcOLX8Q(}DZK+M7Xn})3S&CgP7 zf=nFx2RoRgV|*K)&T;>~F`;`MIriL84JsSm5%w=2dRKvwWw# zSk$kW)nj;cjs>U0b@e;PMS{I7oip2>^xT!?F4Buxvg47rMpTlgYPebGs@412R+(N4 zDSoWR`+Z02GTm)gik9~Uyju5LZr8UP!RMJ5nx*V`=q_RP$Rq6u_g3E5vp?}($yj`h zJ*aqL+=|4IuOg0<{r()`>DZ{uuuhm!=&-RSqkd7JdXcd4Y&F5EwuyC3mot>uSYp+` zHS4{}J5kAe>5uXbNrr>_Gs^okXI;(chEb*5P!AngS?pwBMid9hL-iezN7TSurrQEvvW6iXE z->1C0>!6ffSgLHd_Xzvu63fnw(`$9g4)5b!6?J`|OyUij)1@NkxVPHr-#2Ev-+n+w z@7(Qa9U1vsr|KPhJWimSDK zr95kH*XcX@JojJxk z$B8NZ&d=7dZmF8klOJfxd$DYnoArt`?}``?+(>>iu5z(GI zW9D?lOe)xN)4S(?)bq}S?|)i;AGwk~`Rpdk9DkGcBax3M-SB>8TYE9ZnOXDg5s{T_ z(_PEr7ll1B*=ywX;iuk=)AJZYE;9YQuJ>`ffQyn}cD*i>Z>jg`t@jOkel{fCOP{hw zb4jyCmz-lx++>fB=9@LY?0&GbKliK^ULGc z7w$iL=h<%e3jK+*uh0CG9{J?||H#klxut&O_&$^0?OB}o@7d>73=9lxN#5=*4F5rJ z!QSPQ85kHi3p^r=85p>QL70(Y)*J~21_t&LPhVH|$E^HfdYW@*3TZGfFi4iTMwB?` z=jNv7l`uFLr6!i7rYMwWmSiZnd-?{1H}Z)yFfiQrba4!^IDK@IAzzb&fa`rBD}Bet zu7_;LF7-7Xniml@t3uG*`w*{2#@anioUN_PHymv`c=xEPqwr&Yv&na7{!cIezaq`I zTT*}_IDzpDBj1M`3)H;p*i5Hnl&x;_Ff(0o*|k@wLeN=(ZJm(!_6brd>TZwpoVJ$> zp3jnJ%yd83P%O=C$-VSgLwc$E9EODKBWq#{*Nc5v`z~?&$trv0B*(-nJLX+b-yy)y zc_q!L+@N^H7U?|kzSVBl6HfXTEx3?3Wx=;wtoO5mW^WUnAYv7sDSezbNQ-?w&n5H4 df9h=*jT@b(Co3A9U|?Wi@O1TaS?83{1ORu?En5Hp literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/ebwizardry/textures/entity/firebolt.png b/src/main/resources/assets/ebwizardry/textures/entity/firebolt.png index 313161076d8ab8fe4740a1aa3a401828f120e790..a01db1e0ad0edb65d3597009e510aa38e49dac0b 100644 GIT binary patch delta 1209 zcmey*c!X<$ay^S}RY*ihP-3}4K~a8MW=^U?No7H*LTW{38UsVct+ip%(;jQ_{JE}` z#yRasvE_{8mgVf_KZ6tAEVOXXBQcSKbxVV$Gzf;ZY zkb=(b$;W1k8{fOVx&HC`GAla{pRTy&`)7aS+I=8?neF*fp*Qv4@)kxsZ~ywb-9&tn z0rQ)VG=-C-Qqe5bpJb&5;d9M;)6uBT-p z6_S$=w+frDTYP>F<3$hA{y3Gz*NhHID7a0rd1AJ=P?-NA_Y$$QH~6?#%S2SP^wulK zJZm`6%A8nkAokk&v3svwVb)r4kl(a&m9ccKlQGuiG1oYhJ1L9(V0CrPu610j zZx>i99Ne;|mi5H`sC~J5vQFAEy1&-;-I%_UL4%2j+n{H2kNEMdn;##!o-l4c!O$qQ zpj#?Zkvm$ORpICgtBz(ZhnzDXZDNj|N;_8X$f3B#Du_QfV3xpXiSECTeGkZag{|Fq z&FXdThKp*;*M-k0zV}twwDRk*==XcRA9SCukzsIK043oLaRy^6jgz{cWb}G`UmHs@;CG>Ad3cIb9;UD;_`U(qDLFl2&-m(yUc$ z*Zq>pT2sF=akXjgvYXFlet%XfZpXY__9E z3|PL$GKLAgoTb~?J8@mi^_$e{1my98S%+z;s6 zRU)tPJ$8Hgs;MS=Rw1;F@#+MXC3V4e@1-v!)q5yzjd9jic-xvDdq=`_ ze)K1Asc%m=s-LawzIh<+@EY;H_fcV`&%N$b^>k&U`Tk2=j{WJF-4_ySzF*4u z^e>}}`64rIo?VQZo2fdxdE&HfKGv5XHUyU~QhKuaq1e82A4Gh-KPFk7zi?Udj&{aN zo_C^K@=yK~k)1nvXJYftdWo1F=9}kM>#yHw`FYmj=O^dBQ`x26>V3#QY3cQZ^@&S2 z=hpjt&t0!%A~WarA6?cPx%yGx*O#u^ac)~_fmz_rho`MQJ0~_;+PiJpGPmbm*s1&} z|F)=GrvJX28~5Upo6XCYKVMeK%GDnH&Rp?j-m&u!F3xuPwIlBZ*Y@-qFOnwiuU}L6 zi+7QA*sevNZ^k;BVi)zj$fs=dUcfwO-Gxw|sfrUG{CuAGSHa zo8KDkKA(R}{tr)O)dtf)2E7eG#m)HIpKaM9U&O$`z?S6g?!xeo;RnOpZ0(ot7#J8h z3p^r=85p>QL70(Y)*J~21_t&LPhVGd{l~04f;=XE*Bf^+Ffd4#xJHyX=jZ08=9Mrw c7o{eaq^2m8XO?6rxO@5rgg5euPi(0M04MWG7c#Sir!*Ae$KyQR1AR lo12YWU|=ut^mS!_#3muGEWf-qbOr+hL%pYqV~EA+)^diNd2#T*4a{_G;%EOq8xQ5I3ACTzcYOqLS&W3r}Zw q^p^LWaq&qI^f|RdNYF5mnc*RizY&kod~pT_1_n=8KbLh*2~7aEQcb4- literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/ebwizardry/textures/entity/iceball.png b/src/main/resources/assets/ebwizardry/textures/entity/iceball.png new file mode 100644 index 0000000000000000000000000000000000000000..ae5adc82bff47e8a7ef089c6eb6b2a3e45cd63ec GIT binary patch literal 1803 zcmeAS@N?(olHy`uVBq!ia0y~yU=RRd4mJh`2Kmqb6B!s-1FAwIN`ey06$*;-(=u~X z6-p`#QWa7wGSe6sDsJ5kkDT;IgXhn4kzy7Vho;9H+|KYm`!QLkEd1-YUBCCv=-;@Q zM{M>9AI|A7|NpT)6Tf4IYY)GaYG*`@-OnSEQ!~C#y*_zO{Q1vG>rYL-dxw{2vh&Mt z*;A6=Z!rG#dE<3s|2A72pDDjGHO}+?^f~fTr(kV`SkV^o4e3df&%5-UKUKGX`d(da z%~y}bUcI#U``yH7Z!CXL(_0{@e|h?9EzYkeu4xx!Uk+TJ{kMAI_4m(So%+zZTRHvX zl$Q&ef9vh+F?!(XmnQ!_pj=~l>$c?y-Myh#F1NmZem#BO?9*SJe+n-x@3q@tZ;> zAiTNy=!82@cb9SLmwonl`RHw8>cr}&>DBWaY+}T-KbyOCCx6+y`weUKw9PBCwO6;* zr7qg)#+i3i|AxiEdF6*>1%*UQ%sSRQSU07^@v(w`uMzL7)oVf?E_!~hYtqh5i?b4X z6qE~NOMX{gPGJ3b*7ZV+B0IbG{e2gr%+@~Da@Dz`A+@62Kr-<}{@rKVbC1nnbWM5O zEBfcr%A5+rnaW1fF7WnTuvpN>`k{3HKDG6HJZ-GSN7y#&7PDQ5XWH9wT6dAG726c+ zK9Aco83YbCGo%a1&08~pTP0=cO%1_@9tDlVrDgNDGZqT$IOzF}PjOj~#(`TBi?{45 zdXVd;#3FdGvydxKV3xw^-wc0O^j`?z)B7RN#KLR1WWv#tJqChPX9jMz`YII?Vw!a+ zXHmCZn?_)AkLI%@Clw#JwN&^RE}dd5c6Nqka*12}9B%RO8cx@)X%Rsur}~y&y&kYM ztJn1EogF*dEb=aGIXW%s-4(^9@2X#1+IoCmmE43|1&8|$QeJc@&zzWljc;xKyZjAq z?WS=)XZxx)v#ow*%6hg$NG&~~$F{LxF3$wxGn0*_Pgc)6<9jY=R;Pi%9G=N@+$I|u zys$2mC@KDaD8|6=A5T7;%ZK?1=X_r6J8&oZ-o50tPfIWCJbHoWFz2e$j(uzF1pG>u zv`<_;w^T*vRPJoc&}mneU2T~)_0rv@9;MQ+?d@HP$>suWEz>O1^!DE5dvV@-+sV@C zvvs+TE*PJiUg`CJfr-8BkNJKkU2j)gsq}Hg>X|tEtkv64IFD_&q96zRoP~L5^`DsK zXdGY5#3G-4 zbxW$i=51v!Uv4y6&)cucyRg@Pex-T)##lA;=0`;lD;&0^o!+oNvh~onEkEDMZ$A)y z;&NbR%blDv`+0Z1?&V)37Z@>nZZ%?GWp>< zHnZQ~PXFkU-fm>yyM3*AII~G&USI}q>U+gbv!51JEzskg$ud2j0Y zzU8~{$E*KbeGS*HEnIi?x$+O5srHT59(<*Wy#o5L;-=p^W4fjygd-`Pv`ufbL(ty-t@Zpy{z)w<TkFrc@QCZm#3BYg$MdE| z415P!C)99jd23F%6yPd0Df#%hcL6^XrLBV;oc=t0cgFm`&6G7OO1O0zq#y8cFwT4M zp<&kj&*?$W?d0r@BCDhtauX}}?F$lToOPsiF{iC>OoWsF=PHZdrYk$2T&=mZ@4c6z zp3Zx9>jsP11D7tZN#|=^JwvN?y@EJL496YLK&u?b^3}{Nd92@GOYLh~xvC-2cCy;G z=LJ)@Z8y6T%Ggx-)D8q)e%XvfZ-=E6uvNChK;i|L$H1y{$RXOIB=IY{N zq&-POyL02GY0@{}^xM|tbMsb)XFWRfB}{VZve?J2?OW!BzLA%`l<)WR|5w&!<-IqY Ud(|x&7#J8lUHx3vIVCg!07h(24*&oF literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/ebwizardry/textures/entity/wizard_7.png b/src/main/resources/assets/ebwizardry/textures/entity/wizard_7.png new file mode 100644 index 0000000000000000000000000000000000000000..69ccda2b29d4a99332f1cd424d6e2ec6c8cf6eac GIT binary patch literal 1599 zcmeAS@N?(olHy`uVBq!ia0y~yU~phyU{K&-V_;xdG`FsWfq{W7$=lt9VF$wshBhvj zOX&;@44efXk;M!Qe1|}oQB=dLfq{X6y~NYkmHiQ?EUzl(!ZU1K3=FJiJY5_^GVYy? zh|iF5mH2=5-J5%A@lEdBN9%L5|wDZY}coXcD2* z!8+Aug-5a$$D?58S^;nE5FL)*Ya+T?-nXZ0S+Y&@YtioQ)#i3FX-1pPf4|q$t=n+t zUCsS7XTQJyUTe(4S@P^le$KBymJAN}SJk!L-~X>brD)yrYXu*UdrtZy@6IQmRJ;1u z)QvAcKM%OIwfRiU?u9-1JO685k!*I9Iz6qgZsmu5-+4~$lbIPpV)&otyFV29T=4u< zL02Wu+k5LzTyE(#)jU)G(}E#pht=}A`xh0kM=4gmU2|mW^Y>3#DwQ)G-$~wGma_iu zU;W^DIwmH2I$N&mzrE#nK`k`K|KmRE@N;Pm3m^J=v7Bg|a5+(P0Ni78?M+6mBV!2Lmo!&p^-Am0w#o0gX1(S8I zG0gGrld(H;sjWWbM*H#2OWZTB^C>;AuwY%bJ}$gq!S-m~wbAn{mgqW5K4f$Gcg(#MmuYb%8>AkKgn^%1N+q4PAJ`4xm_49MEmhM=1SU~T(7Q?d6CJpC; zeTw;IIr*H))!qyZw)1ogvHt_(e4srGCygZ>`V zrVSezA27XDVhET$w~y6v^LBm)0}G24AKJSequCZPBp4}~otrwr_K0Y0kO&a74H z`w%$Q;n`$m`8OhBg5q+3do~U;Q`E zu1}bLveWqNjSo+j{r&Oof}hN6o1;%Y{}aDGUwq=!VxKQn-#h!F@ZR!uB3@QvN9SMHTc|zVeS2(x(gUwbKJol% zj`{9>TpwO%)UWM&ooTCI9b5PR)%Ev`4Cn23I8J>0I3?k%6&pk2`=%(qX}a+%IpY35 zpY(t+;D=*?>sG7vCvKOiYiwn`zeJ3KLqg)!SB81fe3I(?haVG{{kAaYmAzS|a&f7J!m@MkPW-ei(e#p%%K53+sxewnA{5LA&9!cR?ndB^QNRt}gq~Klyoa z#f#71mwc|1+Lw6Y*v|TgCu`JCEN*`6P*FTbUHgz>L$K}#$CbLz+IkhFHDp-t@A(*1 zy|?b+%M&jWdR{6wR2!Vk&iv>c7B@X>>w)}l3K6e@X1Be+ZYwDH$JU5dW9#faC(O@P zKI%N!r?7&{)h8=c+54HHK_jQt;w71@OaH7W5iD<7%cQ{Y#OhP->Eoe|A%9(+L|E2H zRjOw!IohDJ)Nmcwk+YADc5&pqKH>dlS$9yL$gS(QHyr$uWBV_u#4)d+V5d>tmm_l? z#Y$Q~(Go~yh>SbPm6cuS@NLJr-@bniIlWBgtaX^u6dY{aS=+$VGIy@4?unCfQ=g_T zom#YVrCR3UxZ~S<=6t(*AXg#MbEhB|vo`y_B_a=Y%7${L?2G??@Y&0h<5- literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/ebwizardry/textures/entity/wizard_8.png b/src/main/resources/assets/ebwizardry/textures/entity/wizard_8.png new file mode 100644 index 0000000000000000000000000000000000000000..38e371a1185257735e9fbc113773240e42c3218b GIT binary patch literal 1598 zcmeAS@N?(olHy`uVBq!ia0y~yU~phyU{K&-V_;xdG`FsWfq{W7$=lt9VF$wshBhvj zOX&;@44efXk;M!Qe1|}oQB=dLfq{X6y~NYkmHiQ?EU%iL{_6*e7#LVjd%8G=WZXL& z5uYLBD)Im9yEpgL%9n*t4p?|mC`i!x13!mSgyymz0hu3`@;6;$_hwz2k=>6muG%# zep>eYcUs=Q`u*=`D|##_POnQ27C*<#@GI=A@}GZa-FGWJugc?Xue0);^e_3(iNtH$ zSH(-t-c=yC^kQzxuV22YHJAVTFFq&1b17n5$rtU``ZrH9ODrrI9FBes_?IU?CrR#I zj-;Pq|3leo(aKpHHmbG$)R$*(=)Rt|^>et$I|pr*^>e50`1EJ*9EE%p-4nKpZ%=u% zb^rg=Q>c_c0%n_;a8= z_h!oV7vfG8@u#aEFBDO3S*+N{q4+Y$AuQtG(-MDw!Fkb#|946x zZ)AH=V^sIVz+3uXV4}R-`AMK4b2<01fXgR#_reDb?~S%@$*cQxaT`x+i?qPc=<9R7 ztbHZ^_>b)zzK8Eue0^-t__(P@aAwfr8U9C?2hN*p{_Ec~-?NslXHK*? zXWq)q>}Asn63RIlHhliveCRT}y5E8Tdu=tbSLuZXk6ISlFc{j)xIWx+^46C-TFi_L zH*NlK%>K?)@@&P2H8S@YKHT#@f7nPTV%h#12|pZOZgzGOtkZb(xia*GrP{N-4Ep=_ zawjG;A8@_p%CMlUR7;HI>^(b%0~an#I20exbIXWp3s$Jj3oem54%dD&~wP~5T(mu(2 zf796skDt%l_;BUKy+8haD3h_SoOSZ~U;XX-6qK}|&v^0mo$&8soi3~76>O^>%61=$ z)mYn>GjYd-lXq@eEvuL|>Cp4P2C=htZ>nJXz%0>nV40ds_n~FWB%Ze|cql!o@t~>q zqCGvl4>zhv?O2`uabDuHs5ckGzwLW|t>FD!?bbBIYoI!iU&^(+5Ajo7(lD zw_cB1j-geaB{XF9=dL}uPc`E)|zCxaeWdjXT684DR*-`9QE zrF1`3LxX+R&LYcc`@cP8_ehfDsoB0&$}2Zy_2&;--Lqf3h!NAwmkLwXb@~*Oxz_!* z&HLs11Ru$rtC<-XXe+RkNB+Fh`2)A?-rH}?TP~HzT`ZCOQqOg=hq$d{KrYvRi%Prp zcDs6itM|(vO0(t8`7J*0OnH-yl?7jm`SHq4N;1qASDECe+)B#3!Lh0FP~eBRv-P)M ze=R<*vxo243_GSB?34FQ6SGfwTDmff`%fBw(^9>ynLq083Qs(EUpcrTX!ptPn#Xh0 z=SjTbXj&C;WXUwMO(}BB!ZQ{ad(GMwb-dq8yiomy76X&RI_3M@YGOn^uEwjlI38Fv zvAoGGiswX-)ZF0mDXlquBJ)1)9kxkRr${d}*iiJq+lz7D?ZBxH&wiKs+w74#A^Ol>WLmiQ UL6$>h3=9kmp00i_>zopr01FuV-v9sr literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/ebwizardry/textures/entity/wizard_female_0.png b/src/main/resources/assets/ebwizardry/textures/entity/wizard_female_0.png new file mode 100644 index 0000000000000000000000000000000000000000..d3b871371f50979bb2ecc0cdaaee14d5789828b1 GIT binary patch literal 1544 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 Sy~zv=3=E#GelF{r5}E)ef$*aM literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/ebwizardry/textures/gui/advancement_background.png b/src/main/resources/assets/ebwizardry/textures/gui/advancement_background.png index aaa8b52c8f37d328621bce85bce193ee17caa7c6..c5de2e8897710ab98700065f45a577ba369c4a55 100644 GIT binary patch delta 2327 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 delta 654 zcmZ1|w4Zf?vH$~HlDE4H!*mej33~B%au%Ch{Ua830e$8S8<+143`{BrZfB&tX`_jDI$I|vhnLlSxDeV6J%5IwGiyhBzxbZ1&iuma(mvx+>#FqJH`S+LK zl3MbNw{LO%??2r};JDS%qx^q%%VixG`Ly7rBtzQ#{mzqJrc5h0C}C_!jbupid9mZU z&6U2)YkmwIk3|{|ynh&1$L!!8+XVwL+$f(9or(Kz&R{fqZdkJlgNSy%TmHM9%Ncam?2(__ z+OKB)Gc!-`+l0giij3aBzPys}6lR>|CL#GEs;ByAuLa-5l(wBqb^jb-PI%xtCH{?4 z`w2l~mqh0DV+-GZ{qMb?{;tLB4~a8cuCz>gH|5$fquuNbCfVvOb@Hb-d0tTarT9dc zRUy@7b)AdSG7e_`*cPAEQArjXHJOLwEZsP z>n*_(619xy#g643x(n~VQ+n$o)^K~Ze20l!hUPN43+w8YdUU$FUvH647b((OukP_~ z_3tU++m5THtvS=ezxK6qSGU(p`xpHlZN0LU21a^3nQ^iL$t!j!m45v9OMO@3idnPG zetvq@A|%-&Xckbjj4NdSk5y-kSChJDCDGUq@ N44$rjF6*2UngBMlD$4)> diff --git a/src/main/resources/assets/ebwizardry/textures/gui/arcane_workbench.png b/src/main/resources/assets/ebwizardry/textures/gui/arcane_workbench.png index 772720ef0b8df5a27f33bdc7317819ace2bf107b..29914ec9583ed974fff8b37772aa9023445234e0 100644 GIT binary patch literal 30590 zcmeAS@N?(olHy`uVBq!ia0y~yU}9ikU}WH6V_;x7I^kS81B0Y*RY*ihP-3}4K~a8M zW=^U?No7H*LTW{38UsVct+lf=i=J9cYWe?Iq?m=JOon~+%{vKw_VbKw=lJ@4`)2#Uf1h7}==t*f zf9}-&Pk&JTr25YDwzem8#qufO|)mr7U{?~{nJxVY%~`$el=!UU>iYW)A? z8opd0@w2>Z>i)%jzk}b_U3szn(N_7Tf0vfk)%11jpLXcyC(8wY!WN%Duls*z*?K4Y z^(X2|-cFB?*!rse-{;`B@9w_6_qnuOSyU_Z&huq|o{PMXm$A@Ht&!KR3H>+yXL)V> z-1WzF^{lqNeD);U^0nBCZ(CDtx5Zk&|Gnv`P_V_qPqrMfN zZQZ@=basjTEc~%gtor)f_f@B*!tWiMc+g_z$IksVJMI5|sQ>)+ugiC?U1?frzgLOA z<~n3@I^g*ibN7n^yXVh(7JmQx(>f`)|G~-1vS-$x>6MnLtDBpY_PcTIk6$vDdcU94 z{3@xg_jBmnQI=*X_Od}=Y_sTR)0QkZS?Rx$Yit;Pd$Q|1-*7gziuqlpANMY^`76Km z@mkjWmB?BsXerjVB(otS%uDjml`97>oG?_MUaYtC*|cgo)oCF`noGqBudLX(Y*zNl zt=n$B&e*tgT6E^tt=De9Sm>^y^ZnB5*K5Dqv5CvhsrvBppkVSDgU3F`=Z#+HY(BrS z;k=jj`c1F0REmEZ@;USv37X5WU{~I*DaUN??`xiYi?`!Rn17w>D`|9VdF>worE&#&zAfBx^* zcKedt{^c4UO+A8F%=%TKxb1ZBGBb-sq7C|QwhKltKXt})+JlsiBhxQ@*Zk`Ds{H%h zpK&)xAR-r@i`aTzG4Jaj)IyM{WE@Qsr{Wn-*NPZhbZT+d8ScvCBP=T)V`6 z-|~OevG>oVs{>DXf47KV`0es($15BPe>HWCO1u)hWF@yj1Ry$Ge{eDbd&(a_@8YClD_dQuUf15TycpgaXHtAr zjU~(+p_)l(=@V3ex7E@I>jbm|-j$UJ0A?r48 zZ^7f*WWyJ;V%rMuO+4H*D>9>@@cLSdv$s>McB{@fH~*o(tXO#Wo#|(HG5k(S^ICFs z`R?16G#P5D#1g#}&K!O3r<8Q}wdHn$Bm2IsiC^p5`Ff?#SD&Kthy`MscssF+M+f**NK(&?OU&mRA*LHyxbwqcu=6xa00!37z#(ho6UCim=N~ zj_nXDpL6L+dhg}MYRN(KP6VYbvfJG%vwWHSy_Op*^5l#+9lFM^ko9<*QL&RH%l*62 zo>niq>i9};^6&euC=wxCZG{(jRXe{VULT=7-9yWyI}vcD}&citYWVfxsbrf_q`YgaQ3{Wp6g*O*3V`aQXL zlzEH&-_;))QVo?V!<3l~G`@-kx)@JT@(pg3PICW$T9>(RVf_N$*86w!wlt^t?sI#& zE@XC(=qgL^xfM*ETMDMe?NnJW5PtW{iw8;1&Q!iRr{EEul=&j-y6%on=`63#*Z13> zHE-hkUuMw0YkvP<)*t_Qp4>0!k^bor>hPDl=c!fw&$shKA12=TE3Hr`Aoj;j;h*f` z$y=V^y(PiOXInHc@Z*NuqDz$~pU%XbT+ZycLrge%_2KAg-wyC}C<%QzG;@=*fzLFt zt2GYc8q+-u1SD?@su(X~a53Q7;L#FzpuFwK!vjZl$ewF2n)~9AU3kh$-`2xXN@35O z&TrXiln|g=th(w+kFEHEzP}$W-(9*cC3Irh$3yZH10L3BoSAM>6H{^Qrt7;ib5G1I zE_%qhU7SU#UHbgNjYo3N?`UOV(f`+>`CR@$0mI=K!8twoZg&j#{!@`&A@3$W?-|S4 zGNHeG=gwN~w5alRyr9#5BcXijTcZb0mwZ)d=*URm+u+z*ef-n5vWXI}biLNqH!7<= z%74(&t1^H3Iz{y_9@8#dXe`;*%x%3e+~8o${__jl{A?bo9=^5z=k511H|`EQ_h!YX zxV;*oXC`wllIRGmF7kbQSpD;L$(NC#InR?Bd(vt@KYuG7&UE^CuY-h1a#Z{K2Npk{ z$=PnTvsw_7pnqX)=l_NOi@ya}KUY3Bhv658b-_mdcJ5`bt-n1>D`>4^z3#3n8?}X7 z@#{SYeW$8K-dB#d71zI>7+1sbc6K^`a=d+VczZmOqsd;^6Kc{(F$94TX zK~KJYJfi&|$F+8WM|S_j9#QQj%(thuJdhpfE zQ?hEA+V|N^nEt8A7&OdM`BY%5YPEk&!So+$Z6ce#Fi5uQ6&J~hSq4lL;!-|wXh$4# zU*n{Wuh^~`hc0-Nxx2^q$ShXJJ}c%^sR{aZD_vgu6wrRRf@&B#W$tN~$ad4=xpXgn7T(s#TBgeO@IY}38 z&e(V&;Yv8HadP~RP+7|qfBQA>qa|9R}p6#_~5Jz{r!Op^KbzhPsW-0-scRsMWt&3mge z(nVh1wsf0p8+I+#OHnH2%j}C>7Jhlt`;C;jee5%<&eXm8^NFj&RIBMqv(Eq0D%IMR zIV^W?D5Ud5|5=b zj1-ozSRYsxu%owFLh9T^=ZA+aw{DtsxmS7r=83C1tZhGN<)PBUjB-x#oAb zxBR@r-S}#T*Zt66x`)rzR{z=A8vZxSN9%Z?U8uap^0)2FPG|GBlsn0JJG}G$8Dj4| z?=UAvpaTQ@jRX2J43B@eGS@KY9zRjC!gA6s^UUZ}(>Buv?m0oihL(TY|7%wNp1$wo zYu36iTNt-sm)=Zzq{xRv!p~eWG=)CNBiN&T)XI!5pUOu$+#VcKdWg9xb zEs5K{;#%PK>$kHS1rqMBkAKwv?)?7HY|gS<+-Ljy_sM>1U;Jvlc)|X-hrccVtquKC zQ}w+*^5}W-g81hLmMz&>DE&h7zvYrb*0zHU$z2Na%N(pPF)&a5xZHGSe)wr==d|*6 zhv&A16B{-#vYIe2=#X)pr^t0WLCEpYEE6AwJF!ZV{K6N@UQ}2(T;;eID){77!OzxT z6`TTprlwp{{5a`oK&&QfXw{m7Hk1F$?g$Q1n>7F6%mbGkbbvTL+`Mxk@IU;S;r!aA4-!<_B4~}UEn06?;cqMJ(P1j9JJ^aSP z>Hw6(X>9!1u)b^0K&O%B(hg}52Tlx+u z3P{?y#7t#ew^CUkAtwaBK!@aF79)`l4kOs&aMGOIaDST&swF?b|R zxy*es)M(oW<4S>luV03G+_cSB7v(T=UZ(ES8lU?AM@QZSf4w_#_Os7d?(6Asm5=$u z@bgh=VGxU&W%~N;#gioq{I{;NOs!t`()9YV00Z`(i3Q&CJ*wSzOFCBn4zQNl;Gn&6 z*3;Y8Y`QX0OO^k&>N-yfn;LQ1VFlkGk(VpWUPuQrns&#g6c_S-el=61tjo z;#)7JecBtkl`c;IyKc#jgeaaf46Oo>x&L*qT&BBY-lBB{8jUlb&Wqx#yC!10kynmC zLpu5EkrU2t6Q4TF_TlJW9r%$m+IIQ3Gq0kSe01SVeAX(xlS9>pn>}hliSnMcjxL+@ zCB&CEI-a|*FziQ}@&7+}_ts~aXP*Cv}dYt>tKG-vtz zS>q8pQ!Fe;MZTu(`m;M626D$b?)+h?iLqr5PtLsR5U=F3sIbm@?T>1iW!DpSo>WM# z=9C3*hI^>tUo=Py|h!E|8dk$&$P$4Yl_%O1EalXI%R#e5UXr-uC# z-OVpu*6Cj3^5YZN|87skVuj`#RZWXhnY8R?e`IxY3ESW$%EzTCd4qGA+S@mGh3j~0 zosUj&`m{}NJ4bX|@D^5a!HJ~?i#;CyyRy#d*#|LZ^3cYHYT zY=J+2=f$LlJi0s41Vno^~{tr*QRx{`@T;H?VE+ z5ba!8nD%{lm{>QBey72GHD6gcV{7HzjX8p$+o&iP|PTPFtz zUS3cec89aE!}^%9gCdJu#wq4Vp3ldwCG6#7Sy1{l?~2HyH9A4(zh0ZB{LJb@sdMOo zPm>?c-Yq9T#btMTG>1d6!H2nQ!h2YqSGnaS9&Kj1ZSWy>_SOwAe5y8eK9$(;(I$o| zdb#MT4O?ZWOcQ+77eoe@yzVeaUvmPO)c;ltL$EPPTSY{=D(*FZWAkcAsO` zGjClWUT@oS#qG*GLx*b((veMDF0PQ6Wp-*otm`uOpTBe`@XHunI42_8-1<&4?(ocr z<5s5>T_^NPis)5;$Z~wOF5e`q zSePE_zpqfoXl08N=eD=9vEJ1WBn!4KKUCX$NbBB#IQ9BmOV>|xzXd*!YCZU4>(5;e z6I7-(YD}-05h$2(al>lv)p=@_|Le-p?&Mx(do8s&;PY1*hx*AedE$b-DLfZ zcOG{<|8Ri2T=?r8G0tn;aVut)zWr#dD{3pbfHn5#Y36D2(pT2XsTNEr%IIG|olV5x zsKi+ne+#kC>)Y97!raw=-t}E4v%;g*Icw9}o?SmK{=GH(;EzxZ-W}C8DlCRP(yi?c z3nX6c+9ap{#$}I+(&`%ptd5^^q~EtPYe?Vc33I=2nxo@VlF-s$?-OMsH=nzx%J{?d zjDD%(+VHVntu4St79&b{PRsns7B$>lsd??}D}W7fql`FjJ3=Uv{{`}rtOpFq5d z`)`RV_s5TJJ~(k~rsL-JyM1y+n-ka;B?a)x^Bpv-iV)7Nb>Dl)F>ubd-V6N4)-QTi z<?XPU_tul70klv#`Pwbw9 zkyBobm%akeDz=x|&$%y~bfi=rXu7nI_wKD%H_lt-TDdt}YQA*l|NULJ>Z)p@W6j42 zmk()YyD$E2wKcV&i#f8LIl1Z?ua}s~i4d!rs-+8-uzq2?zwWu}=iE&bipp8$Twz)o zG1*S%jB1a4=0(5g<=ZGY-I_VS^CY9uRE6(xQ$34!vMhesucu(7 zuOuhQ+`LO@d4X(IL&Kf}&bNA;?g{$(q#ZaowOd5l;np>~fVUj7=PhR+Iy#|ezUfB2 zQ)#jN5ht29_`C9*YD(FKqg5_1`lw*f(-UY}p{`A4QCr&If%t%;d zzQmwcg00Ur+45`O*`udkT$R2QpnX9#Wy6-c9TQ_3Q=M7+I@bxroGqH-6Ry28)b_xn z$%?aHE)`zUvhJALW3LB#Rr~@UpL@wVZv6gkO7{D;zUzIzb)IqGqx#FYMr4^_;4 zcQj(}yVEj0w*EY4e2S~yE*F0F!7#hA`ayei{{p>Nj#g#y>m4-nvTk!2$7CK}5!;_J z%i!%^Gr2Fz)_0tiVqr*3+HAFO*W08iF8p0nt+sX^eBZw%N(tVi!@YK4siL0;}b6eL* zZk@VJr*Y!-*R`CH)hcUi1+oMA_KNK-X=m9RdT_$r0=G|xXBzyC)4!as{_K^wNv&se zLX}EOO@6#xsND{dxu40PH6nhi93CwFa7UycrTQh%q-ry zTj}M=Xb6(4*m;)L>wsI-#cGGG~&c(Tem2`=l?M zA9t|)P=3>xbmNS`SqH-j3XV+b0<67L6%5jz9N^Jm5=&z`I6=W{g21cxbSeKOc1ny+ z8O&);N{z}(<}Z%O-?e*H-rGMr(&ukJx9@pa==Ji__pDb+YU}U3db#!6t#}_!C%)r# z4cym%zF(jGdVhcXpGV?eaW;&%T2x9rC@irQ3v^RaSSne6}ZSo=N|uRj(4wk>@BhH>NWD@*e@E@Dx9@8n8?R~U=WE!TckA(YUxpM5d;9PAg^v3@{`mO# z4|ns!*Z2P`wRh<2eYjZu?+Q`IKHH90yVp4{+Ro>2y*7RCF}=mlpS<6pTkxs;$NM?S zQa|^9T&U0K_EF;Md8PN6->*KOdtCKKCi{Vh1r{=Wx4VQq%WwX>e6F0cv$lzwq5bf~ zf;*a@-gkZZ_^a|rz z&HnyVhOa$2vMG)|aQ)|<*E#(eEyUF7XJ0?QqE4*RfA@O3^~-r=_>Swj|BH1xEX#0w zu0!XN-8ug=pYLvIIsC9-jh0pTq&W4D?c`Vz{2^@B;n;fE1yv9D{df3^B%8p~jjr+RJf z^6yFx?T0sJ2|8@qDRRJ0M*2NdfsQKEw~sqz`HtTeVSHUDo6lTwM{>>Ti1W(z?T0t= zCEYusu%I@JxrFgS#Eb>kU9ZF*ZUXsBd@e&gd(C#`hpqd5Jbs*f^YZ!Kf=Ok94+<>8 ze6PGNlZ;`wW4I}P%8BrwF|*a`Wu9%;dsGgQz3^Iy@psz)-3$>8OLlYoI@&G1X8X&^ z+BNgGZ=XId``-22W1lMuX-b%LVQ3^{L!< z{qe2l`sX`OYAs~=+8;l&u(Lb&tnZHN4u%&U`@CIj_!mxJx4G$o+WF4wxwl1MM7`g= z?)t{{FAFSWPA5c3EigHge(UF@+n{|Tl>%QMDDA<-h7R|;yIT^Z-jAy z(o>iwlh-1U>Uoy`e^2{e&S=o=Vc37)^;hh+zgt8O=qxlmU%g@7fn}`+mMtn$2L%~d ziR+7syK6M+Zqb9ex-wonyz!=zy*-`P}cOFw79sJfHP`vr4qm7wJjq-YO-XlPmANHoMc{tHWGm zA=8(;i*)dX z19-(5`PvUZWJ<{V^nTO(+%2(1oY!Q1r^hY!<~ifV?W3I%^SOHeXJ=CxzV^ec2l(9n zeHObMDHMA(`~H-U-Iqi^i|C&dGSjv>HaD;;bH@2CpO+r5;%zwmuwVy6gy)m{uA6SZ zTRlIVXG+Tfo5fw`iin8G`)w`5*UsIr^yL04x6Icv6im0jz2`T}vf6i{HOJO*$gZC) zdendSdVj_e3mHCf2JXrKZCrNst*DRct7~P^*_E#n&mI;3HhzS3Qc=AFNui^|3N9nk7)J^Zl1;+u5!ZB~P|r)ond){6(O z`}Onso^9c8Ry~M3ehyT0>oJs>{hGh^W&YiWX*Szk_r*pFc_$qN$!r&|zRMa=#GI$a zGHv6&>6$B|zn*$HyQ_DdA0ycJ3^#7R*k2OonIkRuW>*^9n%B0slAp0QLK4~g4ZgQ` zO^KfGHgDU7{OFX|Vf(>u*~GCS`_bJ+OSWk_&H4HxSDg1&;lW=qt84N>x(XOKO!L_7 zl5o54-`lU|f{eQ#CEQ4U&DRJ{WH&4o1C*Bg3Qtq@tNy!X7Hjo=-~I11kDu?n|FFQ~ z9b4Hxwgpp+xz5~}TUOl`oGcaj!t@onX zxm=f{K5hG0S@y8P3KWv82Vy3^-?Hz2>f&pei;KJke{6YM6?>cG`O5SeSA93|Je^U`q7<-X{b7NF$+xGZV?ZicjpFIRcqpY$JGtNxoj zdGe!{eWAOhKg)=3|0N5~$mb^h+jH@|meQ9@){1YH{(gSbe&wX6r zsm?XacyNU8?wsq(=##yE_VGn=B^S=wEZOgQaPynr^PlhaSFZPG2PJ3jhP9lHuAP-v zf4(W@ZY+6Gs;?%nCr+MF7#Iol^wO%j7H&As~u!G^o zE{=%y2{Wd%TW?AX4BIpH|_`s|4l%E7seyJ2oIgIDOw)th!M7ksg5 z)yMFcENim!{_pDB3<~WsVOx6^a0=VOyrDQ^y6N72&4$YR-}PkE!6}(}gNfj}t_j|( z#Y>qE=H@@!yx#Wx?|V}pzX3&dIm0w1C+UZJ(J$*JSN_=S_GMl0hdU`UA2$8{z1rp+ z*i^<1MnN&tCggeDyDitT`NZq>r}lk!bl_`0T=;vVxn@J;>V|O7f3Yrmde84&`TdP{ zBgjXr2mBIee%n(y{o$J~iHPIXbJHsVuD{;J`~X}aZFBnL5of+OAim7#o^Q*sT`dPT zH6`5hsJpey^*tM?jd8nk?@GoQ?dtL4$BXLf_FX!^WnEu$7*5`HlZIk7AeK~e5?`%eGcURmfpqkB)E>i^k$+Cyvoe$P35 z%@>>i>^EH2Y`9c$%h%=C=Y8TTr!O6vC-idKyUp6l72e5hu{HE&eNL%mF}#29`Wt7Z?V{%AJEX*#kkocC-Qfd+@sAck*m006mhS4Yv+4m z&E|mhAz$r%RY0a4W<7AulJT||`;?Aqsf*>D&AGzs@)=4jWcqe@?w!Gsas0}hL_?yqJVc*uBs*L!W?qGg+aXl!wq+h&!JbRuRo7mfv@vINeZmvle{q|SOE0K!!aWo71ZlyqN=ix5f#3J|b%7l9ZU;kv(EKu4p}leO zyYlWm-<`=4Yqej`DZ2ee#PSZ!vkC>fK_#io-pUjApM5o4HQ)8#<#(&kS5KaD(B$>+ zWh)zI3q8;}#_Rt(#(XXBj+4)4s~W_BW7L|#xO0z+z?<4#pvJ$e(zA7*)v@1W!>`m| zzCPpmU%l6CXR7Sqv4EnByJ6?a{o0p~zkY6+&w4~_(Q~1|^HRsH`CsNX%j7$q*=#r4 zmhFYvkM*EZVF$wu>3%ues9&z2GE41W=GvTT9^$1;+hirzKe8<^^{)8xzF>`9{EtK8 zHQU-Af8%Hfno?I(wCPIsyt#8P{`^__O=`8uiFI1vE3dQZCmlTReeLuao*C23Gz5RI zISy+)PiV6((*-W8APRX|G=5MlV5wY>$BH z!W+1Z?zHSSID2gWOT!QGphjy-$bIEST7N=5y%!XoEHGjJwmHT9vl`}cPqYu*VJOTv z@dNA0_>LWZhaA*gLWD0av8uBAn4iwdbinU(^j40Dr^V%KdFG|n=Vy04=<17o?r}fU zwa)J!UwiUHj{SNVDg$3o5+&_xQfrON*5X zGXy@ic)TjO+tQ)-^=PI5bBwU(TfT!$ObM|Q|EtYus61JGHSpt>Lq|dd-!FQ}4Qgr^ z8eghE(fHsu??LxN>lJ?aACW)LeSH2!-V4EotPG9yDpjRyYPp}>1s!HGa7=$)aC?U! zi%pqf0W)KO)ThmQkK(6u?CAWvmp{+p`tR9OnF>CYTgaIAd}Ds-ZSV4{R^eY)$LeRB zZkROO`n&fDo5n|DVebM4qhrsfFnNSI++?+R+dxSg2XL!P_Yz>fwD8$Hx=*AAY!l@ul{}>@D^lOY%?7|K;#$ zs^Z@`h2L=s|Koc8xLPwh`{BFilo#Ae4k{CN#$E6GH#2LJ$1g3eV-I+GUUy$E z6ySWk`wiEZ{MYQ-yj+`(+%WZ7v1L{HOuc5;)nArRtnB<_3-SuLP`&-!3I`q0&KFPP z3YdBXHfS=uQ+0Q!QoMBB$-#%Yi@_)1D$jJ|8_-w&=x#&ymT*mIM#?T4>Yy$u9nSc3V zfknd)c87n>4$qi{)-`wALE+SoDM;A%VMV|Ur=S+ z#j!hE=DqK{!~6OtIlT1ZUlY8-LZ&ZT@FV|&bcOofe~Tqv9M_n?(myGN;n}Lpzmp#@ zyr^8IF`qTzM0_`+;*b38Oio%3(F_y+R8Hb%T(?kTgC(ciKc1BglC2`gEo#06TJ*l| zzAPx%`_3sV;houm(xkiV12-LhzBljQ)LrJ0kFEJ{mhbJaoZA!oM> zX~eJLU|2n0z41<{M9-nWZV&Am|5VDnTRy*Z$)XkeEM!C7{oBjK7}gZCHHb>g7Le*b zb9DYS|M()lJcX(q+0OUZFdd8h&0qFXJm+e)vJBsGrzi1(9~md|96GNh&Sd1#*TCX< zpmxK5?v)HW3{MmoRCrmE9zNika*5%J2sAb^^>XI#+ITuLB=Y1114a98udu2z+E>h!aM$m^vS&O#%3m_eewid~|E}r! zI#ww$jJ3Y=&F)KLyT!g*%k;%6{cE>PlALgX(RFqFuY>>W7VKeLFh9P}wc!F&#%;#r zFZ`_y5iA*MjLXh3wC-XG_&DE^;TUU2DMRZY`@F{u zN+#Khux#UE{Jqe0!xgR@-iI3>@i5#LU2v`b{02MmRsWrj$g44Wt^VsDba8&zfA_?O ztN%=QFe!d=|MXl?z>aJFFzpS(SX;pSEQ-Cy0@4zTR%Y^Ya#%lm`OyJ&(-gUpjB^KbrVWfWMPAj0t1hhvK?Lk~yZ&Hti? zuZtAk{7qM=<@m9AWqldPg(Zc|IsfJ_xIh2whxutd1qzjGf2>#h)NfgT>XJ;(Gr1EQ zODwdMUS1Vne)!dkmvR0gdp;^Gc>MTrbo3Nc-BtTf3N5T;XDqet-~Po?rjPYR{Ng{& z8cZ|zJ&sJ+-^J*+l3|&n@Y`drd0r+vDo6_|?42O>Vg?sScf+T%4RiYcsBh-b*v9gV zxuM1S#Qa`?1%`9vmzp`eo38!eQpDLyfLV7tbDFHlW`S4TmtVhn@$y9&cSB}o!zF|H zna{oZ?;bTzh}GDHmRS=+oIiY^;voZ3(M61 zhN1$ue;*Q9aO3lOJ%^58JLS7nuJTGaKDnR2TV~sfi97aLybX2tU!T8~Iia)a+P;R$ zXMgf9e~UjNsv)@LUV7BT`0GC_+Zioo_}pjykT;qr?UPayouJyH(Kj$BlUGCYYRb+KZ>W+7J?+huy4x}EGs~3O|6*9~- zhaX0yKgsv=VXw4W@RViA6b4}*ww}XHTx%P7F4lYSngo9|F`c0GRQmOPezQvZ{OQW) zzB6{j^0;i^@R-`*$(V6v{j~jYe6kEDKd}o61TmaRp5*ZF?2Y@4g^Xuvm^DNHiE~LU z{ZJXMdvf_3!>E(11|mpR1qv?Pv0NzG!ec+Hhy_xh99ka}26A)(RbL zM~W^?sL7G{VRA6|bl$^w3G0rPEe*cxM;IM1h$^J{7$kcwU{YUjMVtTm(#66G zlhUvKpKi?<#*m=PFguoE()mB)t2$j}8v~vHL@~@*YRu+hqcX|Pu-8c{*<j;lmPIl%kh9ldXhn`3w`DDGgWn(xMuQPm*%jOoFQ z2O0uwXD=w|^>9q9@!hax8_TzDriPW`Tu;=OP2hi9>-F=01oMGqEBYS(?2J%*d&l12 z=(hbNd)^>+hcmxlSIfDwJ3RU<9wpHld~yE1hZYAntYpuq3rbv5SnSqOw$b$hYeRBw z#PNF^?T`BymA>~pS;(#6_V?{C2F{)Jf{&SQ{A4gP@NS;)CpX>U1&6>5E{UTIu0di_ zL1tUjxf_7!VbTPE7p3=)8_h1Op8|qY-U*5ozrXh{3|z;{f60%OCn>I zxHc}I{OZNa3#_0qV~brU>J!-hOga8{l|aHS_eDq6w>E|;Y{=w24#wLf4h;oDQp#rNrK{YKG%_vTCXEWPMwbf)?@Yq~hc4u(MP7q=d9 zmX;Zs99QXRSj*1^al>w>fA8&{Ojy62wOZ}h^TT^i#e3RMur5CFyW3On#oH2xq;l2= z83|SfcNu(EPRR2(nRNZy?tqHrf%g4pXWUyR5OBlgzfR)RI6+M??R0en z``?U-_Zw!gFDxi@Sb3`6?FkOS2_r5Ai=II@Gm<6j_82=By87891~U6owg zTV41?Pvp_jse7Z?1DsiUp7671xSWykex7hUPATo|?_v+e3`2#-I`tW!7Z>i3=?gF6 zEm^WrGIq`3+C>tMr|tDWiZfjj7co9t>h*{9Q~Twx>m0ioKqFeQ9sgzR4T-TLX z1|@G+{&_63+Uvr}RnymW__K>V&Phz)uqKhto}<0)($hpT41YU43Ams74++|1e$q@6JR@BNVf=@;z}n%L*Q z?{-?yHoq!pVM{cRwRqbGsR9>UGabo=S#s7m#iC!3%Gl? zP2zfS{xf@p3fHS*>HsxnW{sBDn8wmM zC5z+T)87m~c6BHYW9!C$>I?Ju${AO4 zEcm3yczgGHzJ?on_D}k2;p5!G+jui0N%b|efNaW<2H#+h6|p*Bem^eW7RSu4^73oN z8NFC=zPjr;|I?}8ZC_GfO^|c`aZ|O@w?>Z*_ih7ZTnxU@;~GMSQ67FS zo4pg5oE(&Y9-hX1L9L#v-%6r|a~dMP=7;~0d$xVM z7{^Kpjwj~@{<{DEZ{_mq6-Q4|xI-+1oFmKa5>}72%zj=?zfDX#*G%AJXUODbC|>dH zxYFLZ-Cz3?q7zFP))+Txc5=GBZrylfV>VMq{PKS(N4qCGSuH%bxJHC!ZF2F2D;h_x z9{n}1UHT6zXo~T;*y8%wpkjvA<-YC?0xWA@G8*PF>|p4rte+z!(al!vQgcxCaqE@W9`JVBi0 znfhA}kE7+DEIvho0&71X*mme7>x(xG8%!B~e%U|ey?nsx=l0qMf{Wf2C?vTxO%`5| z+BK8eK=E9Z%*LhpLc921smUHHz2!b(ufK>d`@9#JPyqGy*>Kpn{RgB|E~R8-`H{S7rW5*>`r4rhb5bZTX@~ytP=0KM9Bkhe${0}dM|H#b5YWQ$Y#KPMq*cvLYbf zMkdtV|Jp4<$a)zw>A%S=(W1qFy}nF}wKI5PuhGG19IPM^?)=TU<4?N^lWV=y$IGFc zep$|WUgI#qkL%2dcoR_rzbF3N-tRrvX|aoOig5n5|Lc<*bbme;Ij}5E$?a;+E51#K zYz_4}#gqOzCh|AFSjQIqX1NmcqRNY9&Tkwfp5`(51y1?K=6vd!IHbmoR$@>%lrH`A zd0?Fiy9no^myHSnN#zc9#tknUT&i43M3?XJwQB6d8Ti~8 z|Gc?rT>1O$cJZIhZwhiWe${7)-Q`gF7B0Zo4Wn>-An?#jw-K3D5k-)1QK zbK{+OtHb$-|Dke!v!C>Lx4)3v^8VnR=4%W}HmaxP7yrA#>%=VN!9C%{y5_ptj|Dr{ zB{_&Q^hK*P$@KX?zPUMF;NUccZMWpR|7&IW?#M3XNGRbKX7PR^ulvzy|2`h(i&Lup zOg+<{77(!GOn8Cx7PhWjUYFI?JZtlXg;qUR-F(3?@TiB4puO9F=HR#Shc_u!FLL>E z#_*`Xbbioq!T+1voIPAmFm%*S*v&9!)nCbSu?>aH36mGzxc;b1MY_`F)(!^fz~0jM zBcKLau+o8*CpPK|T0Q<&GtqbE7xpWw1RWL~cv&8^_3eKRz8OIa<+>Q&zLXcbtRc## z)HpqhAu72!*IRL)7$29EaA2&gZS09deBOn}9xVFeXdtU{NHpW*;Y9l@eugfa9ZRk; zERSSPy2B|O13dI3!df+9MX^gCvBb(Jc9*nKEutv5ppWBb{UmiG4N z^J>1lxaj5a;OFP(|7`x*aND2%__46;?&IVA&wF;s^u1lY&muKxm;a&lf+w?GYUX>q z6TbL+#Y~g$Qi6B+?cXS%bUWy0fOceBtW*u5Gby{R8WU*C*oYOdo$z72F$j zeAt!DvFEhVWlFoj=VeXkM>DAH)rWBo% zYF*w{yDTtxY5&pcoZ{aCZ;y*P-Vsc&W-CZPka4l&KifG6UzgGXmVyuGmt-CnUZZ^= z)p_roZ`T=}XEHMcS|*=uTxK%sPwnMdl@r`QEjpxP$+GhJ{;c^s*z+3t%-40Scp~)m z(DNA0s(@0>1dt1RhwZ^rLj!v?1XAvJ8zTQ4q?54xtRpnOW} z52sS?Y_SR1k1R|L=3Vpsw^N|Ph_96Mp-T8!lfw_<3SLxbY&Y&ZW5Y5h!{U@nu-9UT zg~`{>wZ}?tSkb}e@GtB_>wV_N_pz&P{G0jL@5ueusfW86Wck{Y_j)+zCQXd&`O~XB zL3Gc|r{)&62HBF*2Uf&HcZ3Tu?>NZM(RX&&{Rrg+dIv?fu*WUGc+h4|-#nh}g$d4% z4@>{P)65fBIdsF`is9ppaLrHsM{6fs?>}CDr}mO(drg3Zf6i{31)H0-CH`E_uHXOT zo{{;2?d#%wKr`5D7|%Yl*ZP~-exm>$mY~~QyyvL*A zhp}SH+JEch>gRssU!pJdGMl|2Q!ynb_0H-1%{%KoogA(`hBigMI-cCGY4v!<<+o>5 z%H1Y9v~FS0JG$_K(eYhb+wz3%*v%chRyHnFJoxE=Lf`ZC<(+>fb5taSiF+U9oS?Y% znevKYq4n2i{*!%j-Z7?7HjVFzU*D9L`7A-x<9?dOIvv^T`3R?D zT%n$?%wGH8>_;9OezD#aWPFq^@$+=)Ec*qs8JGi)H`?uT=%_w&@v7sc9o z*xRje_ddi{t6839J0jHPr2lTW&DnE$H{`T=%G7cY@ikk9ru_@h|vajVyEKwFgWb9Sv?TIF?yREUIx#OkoKz%e>IBMuV;7bYlOeJid-k zs;6Jhet%O>(dm-7vcl5skKzNs3DljTU{lj$`6`w2m!h1DW7QWpF@3ud{o7usKB`aI zpxgd_a(oe2PUCHhr$=UY{VZL#EVh|rLuKt>nO8Me3T{rS*L-h(u9ZPg_L1kaTLs_t z&U|n7``l^nj-rVIW#UI#LeQU)VxAGh}B71DDrmBf79Iz3wKPkzV-8l%fCPcp9edhWKMl!HnZhi zH|NvlIa)vTEIA!DJ8ai7Yj!v)`ZI!tfaY;E#92?`=4)_RGX2^`v+0|y7&loasR(e* zey?^!rE`PI+2i>~4ycqcv}jC!-4tLjZF_Iucd-vYb6z>Cz4fr4cdYRN^G$d2rGCdl zf^}_9#>)T5TdI14%Wr}K=jOt;3yfLw`cKM&7KPu)JeFB@bGe591zrU+K?MuuoAPzL z=kJ>?$aDO~{*%t!zE1wTRGKDvDjDiVU4FenO-z7!sfbhX-+kS-|IG^+4G!r?{K?7I zP;=DqsN#`xw^^rh*0BF&W6)c+Zyy$Gvy>`o{X5cO_gJBm8*H2S68lFz^=FQDFlJt7 zDG2+L{_eb#A(Lk6wGus+87lohk|!z%?c1_AL09Tdwed3LQ|Y%Y4HcI?`(e0pYkuEq zA$u-eUA7}mwtvp~oMpfLn`7SgBtv1AuSXBx)2g=wEmPW&?4Zs`(Cb#CP7U ziQ_x2qFibySaM>054L_Q7kgiBzh8g9o639TN57x#W52wgzwWBc{fawpzYDJu z|NQr(YRvbnP*cgjmH!y@n>TMZuKM?9r+vTu`9tTETUQ?5s2-T^zC}$VruS%fVBBfR z3r+?#b6QSJRp4^BaGjwr#DA&XM$K3{YG&y~%sgJ5JGe;(fuw?(MI8 zO7nATHr}_My8ri&h*_U@EPZIoz}J3wqunJ#mGjT|>uj`N{wkQi=Bf7zU$L7zJ^e~F z*jPMb8a^x+jQ{p|8;6m?zcpe_pOO!02n59Vc0{?)|1`zh?ccX~78m;!uCIT7^v|Oi zzt_t_^0)7q`Tv$3ZRooBG4n z7Bh0coM+wF)#Tt1a>GM3mi<(RU)1;Axk?JPdW?o@Do1|@oUE95>GQ+4m;S9w<&%4U zh;?3-I>eaGHo~0Fr|uluoUtlb?ZOrY+v){V=4QyMD{p?$k{{WtyNuxh!x`susy=*4A^@9wk~(3e&A;lJ^F(~RX4|9o#)8eOv{Y{E|PNXgaWUJ(wa ze;1Dbv6-%%=g2KDbb9TDyI1%)?EIB%6i>e5x$$kZFLA{IrwUy5X7s~PR#e3SY2m5S@R0FdYD6E;VNA>-g z2OsuwCErfd`@vGbJZ$>3Lh!&%_GX49A}9SHoru)zWYPO_zgUUyT!+i`BSKr*PYG-- z=l^m`Fz59ztv8Y{1OxSR% zmRbW_mixsr$8}g0cV0RHX)vr2pZw*xz1Y{S(eI-K<+ptiefHaXOONWUt4ep&%8XX0 z9<^e$6=t1%JZ<9peadT|iE5X9C=UBrcI>h6-3f;ZH#N^&GUt+~62mfGwngG|{7!__ z@oCylhm_L3pVEatZeMoxrv0nd%$kb&W4d)h+paQtx;L#q@$8Fbw0pGZoQ7434##dE zE)BWc^xoM%+{#e0h`mrixu%q1$wRNS&9fqV0v;Xue&*TlU?%ZKt3J=7@`|7ze>M2? zAQLXuVtI15qK_PY^+^9dl6ODYiT!xPLp!6B^3t4XLdV&QwKt_YSJ(<|+`jT{?9+=I zLvB9ySXFR0w}4@l4-04L%g=?OC9F4=c^p|LRJHSlkVuX2=egU>Il25dO>?}c$EYdz zzolb|Rn;r-m{FOOP)^mvO{#OgH~1HAZ%{Y59N+55o8-W`^zb(IEo*)2CZAE3rI(I9xNuAmPydh#CJ=#q>w;0{nVHNn~pw**m zU5Pv9)(T8G{IK9nCyPMGr?YN$vjjYO>u)^d-|taf*uP@6LF04o`r}vkrRzLlUX-L@ z^Dg!I%?WkI(a!%4)hfNbEHgW~T;k#1VtaA3Bo;@tmM=TLO5c`$%@`n(a(vFL_a@hJ zMb2&B%V*AiE%(y(D*k0^whEA9ia+81g~b9IE`Qa6p1k>JYC5e@_WWvZg@~>3TQ(nj z6}D*dm(7(m_JRo(`d9qFKd$Ro^4;*4yvcHpAAg^1F5LgN>c(RipGC*jghMJ~zFJ&Y zTyB4I|6-44rSq;iZggmU?O@T>QgSfMnsM2xU7(#|*4EL#T>n)5sg&une#zhx9qwal z?|+6XZfo0X0nRr29}fRg4+aFU-r;|XH9xXN-j&JadyHVP{e)Nr_m}LSWQ0#z%vt~a zjkUxQVg5-MPTEyloUe8M=g5<}oaMXG!zp^Ni@lUDeAs>PMEnxZ#}CR+^=dr$5X)V6 zeg;?9er;{rf4=7(3q;SIKmT|Cn&jsne|$_beAt(9r~S5LW}3=%@*G8t`h$6TewTn%y<50zxqsf zsqs`gTgiFdeEaLa>pNa-vZ}JW*Z=tc2Km05dkf|q>U=MJx>jhHc;DN-&#F6)Z{5j% zu~w;4evbcr*3;Q9KYlEc?YpUMv2S|o>o+frYV?2n-Ses{ru0ims?vdAaJerQ@%#F% zJquUOH}>A4XQMVJeXpPY;{XYdDbN4<=Iu^>|2os*q|kZ~Cll?px7i(2csgDz*k^IK z^4=ebY z_S2)2T#d2E73%lfc%%m{&bb%Cbun2);PD091-i}2r&ixc{vFrx%y9l)fdmy7 zg^F!URz9zEaA|*7A`sKie7E78=>A9F85dXtOgTkH06?hK~a&@`T6$WpMQKF`J=M0zkjZq zOf{F;lXJbkI?t@SbQ??MUJA#kKj12m<@($tp>XbmSJK4UVF&v)#P%6R{dw%s;g*dI9k;LV$!dG_`1&ObiC`NQXm!d1!j z6DL+q77~zTZd5)g<}p7zDX{3`p8po=?H)Rz9q-)LnnJsG3o_}SO%2WzncKBG*bLS+hJFO)SwI2=k_}lrspMJRX;JLWvFJ=3+ux^2o9@hl>{vPH9f_5FulEE7TCiI?W&g&1@d+OEyo!}ltflg~s zXhr9R%bh#bCRz#DxIKHE@;CkYLJ5P}_r!DR!nmc6wA%UY;<}zw+vH~uQoi`6r^lJZ zyYC9Fx@Hv%*qgKHd3|gA@pOX6yQfJG%5{=Y_!=ke;raA=qu7G^a?6h!#^s-s?O(gg z^w`IPUwli7C;U0?dqn?*n$NYuKX(|x-v2DJRr{bLkHXH$mijl|r7NE*ROwdxBr}^s ztnSo;w;UzRy}*a`FuCqX}q9P_wDEN_xi0Ee?{{3 zb_?1?7uZScl8v~)_)>j&izCYf(eTGASKgFsxE=Ut5&6%?P;>eesSZunwy4Idhrt05 zp?%}owc}SJb>)lfUNG=HC}qpN?x=k+SC{d*;Qo}~&l9cZ zu9JJVMQFQb&+F^r%axU+)*jx(cZB~X@3j?jpMKTMux46Y)$nZ3gXBZGPHM73a~a-B ztx(WaX#C;sVw6>P>&1O5vydNg-u9c%H9|Z0imMi@2gT3nJAKiv|FcFsS7n`)Im=|h z-BG8bu9!ES*rNF&S#F|-s}Hl#s?Ow%Qp*@O9IC$*=e+uL=HywKC*~)z>h&r5UHy1A z{aIk?mlV|}sU7tUVKyBMI=>!QKipN_@|8PMa6v}kgG4W0gCz_(dmH+MpVfVydt$}Y z6HDGNpYZNv5R3AQCm!~j->)p>xi&Ql(khx=z-XcUB3Mao`bqolSH~};iFGh5)jB#g zzAByAC^o^-FwuRTeYPQsVuLj2Qpw$C&-lKxSFRUjxD~pf#cYMX-_~h~PAXsbq+EOQ zy_C^EyGwDI<$?|UinqeW8~BrK8!{FuSTX;Iuxz-^7U`&PSz!lTv%yhA4hG3>i|U^l za`twnrgT|cY~6TqzgTUPLC?E`QIM&dYkVsYFOtxG)l~OE;;gfYMybM7Hx`dA|4c9W z^EvqSRNYE!!5^7K3N)g6zylDMuHN7Mq_s*!bLzMJ z3D$COigJj$R{zrE)Lllo?YEs`!E@Ddi>#`&z8-bX5tUZCop9P+{;UM6bdKKZ)uwn_V&^9nNRkXDTWHX)}QjG{b9{c>%|*C zA3vtZ@kmcbcv+M2lwGXXZbm}(i<>=W5?NE<7-lHKG>eHNsgboaWrDDMyA-4KGP69c zIhP)_C$}9H;AJ+?z9JvfkY<}Fy68)t!WON)`i3pX6s&ekpE;|AfkAc+=v;tvF6^uK zo#5i$ctGIU`{JoZpJu(vSo_D+g|BRXg1NKXzqd+`Z>CJJ&|Z*brk&;5MGwW2P$ySq&=dHC=uLxmVB6oZ|aVS;|Sp=F~|; z9;T#KPNDxAg5u=AUrIhG-*|QXxBZHByw>==e_<2B&V2jsku#zklUZ3p+P`RM z8$3}kT6BX!y@Z-`c<(g4==;mj>hbDP-ZiWUXnT*;(UiRF^%q3zh zy{oU!zxMjiT zU&>L2N%pKlW=nMT3VeOEk5T&JG`ELY|KfXIGi0)*CB2*&p#SGc=`m5maFt8u!hhee zIc)jJ|M^yf*h}*yh4(@YNltbgu|mp9a%#Wh7uQKXTXJ4m`HkDo+l#M%-ceY-sC%-U z_Uqn%kQ9~1C}x?gy+Fu8A*k)Bt;3tMUGa0D#&7sLb;e@b`-`uzwevBE{N@xqKCj;F z$@$6P9k${)s<=|wMm-`T7G$~l^^ZNDy)LFYoSAj1;v$vU^rpNwBz(6pyU zS!YI-N>ZG@^z`fw9<#ftvh0Bk0X6bx~cA`GTE(6;n8yZtyx(#yVKVr+@c-J3m=TDnDt>CP?>3 z=aW{QTE_gt+x8_Cr>9(Z{WtN;O@VrgLVbalyzj=|58{RY7N2}~{R&fw^oFjfb|HIi zH<``Q7q}##!?g3i)7i#?hkutZaz5zW&UBgIa{f#GlvO`C-B`GA|c| zclJ;ECvZag2%}@wf)H+j*DP=TGzgaP=cF871aZR}ZUav}hF&L8>nDFrMP)wbEYuhw-%f@Q3kXD4_&IU`msj_z-_80S^`r9spDUl+pY2*V z`Q{_>wRvh=x6O2_n?2!8&Xn$L-!$GRaMZpt%;%NmOF1#0OPF0#pUG#Ai$dH6(SXZ* zi5ddoiTqAew|$-Yaqr5t{N2oNA1S;Q$mmjyiY~1-*aqH(lwwo+}{wX?d z!QikWWA)?)iv$gZCvSE}RH^hNSFFxaS$||E>xKm@w&o`Y*)0!{%IyCAmix*2_gl4j z8C&}{iXB+#eF zUc3w%3SP{d_1{`%J9FU&f78Dztm+Cv_HL&gzIZIzc!EFry~>k=?_1~n7RmL_K0UvZ zKj!GG|IeN`L`A=Q^g(fVbwbiT_N_4t%i^-QbGDi+JKMb0is7#C1u6a>zlNFLt|M9u*d!&CWLy7DyruCZdxi+*moPDb$b%{aIXKjMw1GkInN@;18KR+$~Us!4( z)7QI;!GCEX)mlDx1J?Sb_QQPXPP=ySRpTKQsqrtOv` zvrkN8-6nGDsH;)u>u$>>j4G=c6}q|`9?eQT`HasbUyxgH^`AY@{%`TN;<*XMuS74XFU$K|-`{s*$d z4{A$t-P~i=u4sNXV3Fd}&F`$E{!1MD?-kCdAj0UzyWn+O=dHOMGx!`GFEuM2sEg(> zm|!2Rc!B$gtx}fj&%*)i3||>)t_tkWC|oe_i($pjOLvaP@m>EITKeTlmGu7d8B7n- z&(G`pA71i?bIu>x?VOAEY|x+mEIcsnr}wG}=?`<7;<8)v_k=xqHFr*lwD-K^DeIgR z1=q0zO`WkSfN{ZP?za-r$$xM2F-$Y*yuiblwd%d$+{Wh*Ee!P7jTU!44p{IZnC%#E zz^C=nLeCU8@-**|bh;<6`)`Vnfb>W9ixZY|?Fdon_*u6@XL0V|OR1&|pZ?xY`?vi5 z=6T`2JQaU33D!@XHGj_kzyD5dXn3`L&*!CU|MLIo{d|A<|4+;J&58Yf_5aWPQ$y|U z`+oRUUdukW{$n<`{lDw=&sTrB{=Z%RdG5Y{{eK?t=fC~fz2{#1ug?8%LY~~PI8>mZ zyDmASyjinCf|Grc$fhUqSxje==6?z2ac6w(Qzv_7@zE-;DYjY9ZVL0) zIpz$rWEpbqEx4wY5bJDlUqoxxE|#tTHj6NvW4&-%;%~biH{Uz9N&AKD`K^opyM!+k ze!w+{@xc^I$8@Z|S?-#`BQ+aH~m|Ly!pfB*i^jGsP!nEh?` z)7$^IXD_UOZ17x0Q1M?<@xSW-A-@glXRmuvKV`q$f2qIXU&5IR^O*O4$$l>&c+uVN zPkOY=zEjUKfBu~*F+pSw z<69w*bB)(TR07s@>v{srl-^1;f5S7I9FhKKpg?-Syv}zy5K@skM@E=Jr3kdpUlr{~53M=b7$H&=F9gt|zVU|KNFC8_Q!M(waF#zzxY+$({IQ3Xw}cs3 z-~3-Aw{WxQg=-8BRxPV8sNL{hqAw~M&6Mf%Q{!G?&%ezV_ZEiPPuR)T*z?1Cox?&l zhxw~bLN{9O@64??W^MR$Ltbcap~t6(-ize-P0#!Juv+E+Y1NDM74y$2-g3WWZ)dkm zTtDu@$B%`3eAgfTJ!k&>)A}_nFMj{KH~UXL>%QY52jnl>FMhw|fBQbS{}Vdu{zy}Pt6y$C zAE*8LwF+CoTYXl=1=An%F(^Lb>`ZtUf9bZk2jiAYvaf1PwhAh(6mF0VVlv_Q$}rhs z-{Umz#5Iu`XCC)AJ=nF9Q$hIb=?S+=8NL;*j5}~eR3$v|_O*HuhCffg3%6RC{(S$h zQ(Eq!!f9@I|mYQF|^*;N5NAGu=U-LSCdHkPK z{JJjx_J3!e{-u#$?$Y*sm7jn5Ih`sjt`Sa(W&enfS3se2E|I_?s`?c!Z^NC^NY`u8*UqUzj8~(RnbR|B1rs&b{hki5sp8xvCtR_E(z#aU-g)#;Y1C(Woc}y8M zcKaUx{^+;dL4V`z3KMFD-#%UyXML7`ZFR@HrMdspog8EvzZK^cT|8gI=b%vk^IyJj z{m;KDS4tQoK3$)$+ASZr>#W`J)Ahe&e(bND{M26c(f^hg@+&_(*Y65ufGUv>2dVLO zY1sNR-|OGCXZtmOM$fLj{ABmr>*W^jL}q0b2Y(U2{9B0qx!2Ew#~3FhoK=6MKcDGj zG4JUvwg6^a(Xgyl$6?x>!Q3)=I z!|90y43F+LIsDtTL465#)LjM(X@@iZZBdJZfCLV{_p1OUq6n&yPRLQwmkXM|0C)3t@r+ZvtPK~?tA60 zQ|Eik{r26it8IV$ZYP8P(tQ@PL2*z0KW-8@UTjz)7X32*aO#R5$1`g!&iXffonOk> z6U@I?jOEqO9DfEr+`eqK^kbg76XZeNY&4LuA0C;9jME8Z-wyzjN=|LORD#k%efKG(nQ{*qk(_5SOc z5Bhaa+h0u17ySD!|F0A%2tFR$_J8}no6GrYCcOCm@4+Oye;a?BZ~I&SHNAd{-N(p9 z<@^6${&MZP-TuN)cfY;1mMITmx$<@Q^6O_W%wO}tKWKr@(yscGi|bYX_n5rC!nnYx zLHhOnmAnDB<-^3&ui0;VytQ47bDc)t=6{kw;xDoStc1DQFIW4&ZMl(|z$WlZ5u>qOr#|Ncu-aIX0LYN-Ggok^eF1vhw{llQEUhNjCU92K@*486Zq z%`T^!GO#KhSet57S{JvQp@PBX)`Wc%H2-y9vpe(9T~Q!hEP0(Ai-TIy0mh6{eTJXT zcbg_0nDy{h&Ah^STn1kmbQUTYDF1s_V|+9JPT!x+VFwfEv2FOx#5I@E_ul?{SMRTm z)BF{Fqvro6jfwke&jx*2zv1V<)Ig=b`v3pvpQ*V63VJcUAHjkfG7iq4^ug?8Ik@l- z6kH(sZsDdmrNwtc_w3ua^z&0=A?3i`Gt_jJ3s(OVz4Ki3&i6|(-%rJ`tDAj)Tq4~) zuYUc`xgQJPAN(96{E_X`?PzEV*z&=r zliQ;!l!xKv=TPU0m>V9)9V#?fj3(&_+E3cAm|LYUU_R%G?W2M?qlF(<)!x7K+9iqq z`}EU&$6vmdOjHV2;EFq#e*F3-rISMS7X8yd8ZP?Gu&(3DE~~1b_rKl;t8*{(t-n0y zzs>o|;3sB(7f;j%QVF{eSh{^~(R- z-uf?p^EKg5-bx06H~%l3)^FX*suOT|g=WtUNejdIsZ8EIB{u`E3oLe$Qh29xK@$d>uhuX5hjI`00bnG1K1Egm`cBhcACeimb1{UVdb4Rrdo>6W=>`W%RSH;U9nf-X?hA z;SGKD2M)$?1SqIpYQn0c)lTnQcFoIy$aY-B8G45&g4Uuzrrz zjwt9z}#|9`#y)p7Bwn9 zk-Eh>3xWNg_H;39R8m;OE9Sx4@iHYL#?prG`_-9@JJuG+tUK=Nc7adB_!!IQ4RfVD zoEBJBRqgHHZ~s@XDbD0?EeA3(lRi=R4N8)PBw6f5#ktG^hOCej+}d;ef~i z4HlpG_Q{M2dOsKDtV-M`C2@?E+t0M+3Y)azf{XPfjAwirBEDpNXL*pIFo&JtiN2Lg z#uWE|{;z8P&3&maHB-MkHjDYrlFOiNZP_A>kAFQ%l$xTP<`lO(scwS%@r|G4tr%Ez z{u?mOSedn`_6@@YMTf#fe!u^h_taa+|G!dX{i*-CudTy|UzQe(LYEnn1y~f929_`$ zTPw`|NL+6zV_VDV<}GRsFK4y5UA=gD@AK|Bal`fAEO)jXTcGW}U#sM*gwCg*_J3E} z-+MLv=g0os?f;&vJ->6|lY*Rh7MqC^CSS8;uzJG&jKL#wgMVT}-`m5}pV>_cy>?iJ z;ow5smo~32%r{VPcsoJC%(*T}{8077%6r}4#doS)yq+SVrecxKU?0Bla^u!l|5vU2 zBmVp5S(_Gs!GRw>4 z_x`#6_nZG^b-Ul%|HN-RyuoXp;Ih`yY|e=ZJ1rGo7EU)faf>nWfq#vjLhMeTC-)84 zu(vaAJW%|p`s1D#Ar5BF^$t8o#GE(2t-X7=#X`EOWo@I!pYVmQpR_pD_O0og*O!0! zy$8=tIh%?Dw`Z{iL~(q1aFDs`=clJ}GDl|TvBrr1)HjZ+5PkCgaieVCTwz9GrCsav z<@!2bFmOF&JE+#a$X;&ZiG~@!R9Hm+->jVc|GC`6FNYT`;=1+EMD;?%KOu36Oz#Cv zpB){1MAp`y{mZ?y$>C6$!)|VdV5Zh>#{-xJy5$Oe3lbwIWN10KZSVcj&Bu@=o7s>$ zuUIy-A@lsrr+yK$>n}ga&;92+dH>d*bN|Tp)e12Azk2mz<=o=@H-&-GclfStd|aQ% zx8Loz!K~@l?94Z(FfL(W3F5dpufhAX%=?3Sj1pc`Y|Br++n(IUt=>4rU5ce7`s98M z2D6E5GoG8?t9Z<-bjwHTz&^L@)xV!a@0Sf@{QoiR#D8XanfA~_lh;o84+{K5(SrLY z??1fZ@2;?BHRFk}=>M{N5#mk8^HWy@1=hDW%jW;ZD&};abwHd_0cS$EIGHnUDs{UVgl8Adqo&0zj|@V2je*ZD-u{2>+<_3yIMm+AZeJYVtsSJu7rTlgBD+14#qWwQGzmaF^x|JwX-FPY_+tbO_i z*1#(IRBn;iD6n9eU4n~Fvd}wod)80?79O9!QhuHJ@*BUdbAM&9_$9uK@s@CK2LF}| zP7H5Jr(eOW4PwkmTk2|Rd_apapH?Qk z&)2{GB0jfXgfWVz<6@QbwdYgf=kZq8S4YaWPuGuk6a4UP|L?nNp9czV=xwqWVZ5#J z!&&gbllKL8*c3mga5P>{jQexkig|&*lkE-W3(ZaY>*9X6yD_9lGfw?uDbKLvLU&Rc zLx+T;LF37WmH+qeli zhmS8VDp&paQK-gbkmW9YzpL?5?vDuXe;QU^d<@@|1M9kpX|r@X6cIf9cOucJrpdj$kk>NY7itd@A$y^KMHqhSY2M=_&< z8;gMz<0RqwY!!n%R-L!(9Fv*emu<1%&Je(Tud6|?>GoRX*e zZ<6(esY)~4{&ng9J@b6}y;s|L_WfM@zk2n4h5uLUKTM9kd+Ph<{ZE+AJiOt0MSS@+ z))%W7AM9acU}bo|Xa1skuZi~Ui4Jq0%wNl~uls0?H+O^HC-)nkjj_zNIk5*8yZ7(- zQgfN5!S(p>lk(RuUP^z>^i1)e(3{t1fBzJ(wQWEA@P@wQfgG*>+_4O2jvVTh6Sx#G z-{*z@S}BG_0yo(MFI-`)XxYDn!Qqg*qCqpya=9<5YyO2!*nD)cd;hYo&d~kyK<6J9 z2$-&HUh^qlx&8r%W7wnuLo0^uwF>9M8U@QWf89HNez7`evA%^&uuMa!+i}o&iv<>C c(*NxlGRhg>-*vEHU|?YIboFyt=akR{09qkL-v9sr literal 28839 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℘~_$T!1cz5cY_h0uo8)}-iFx);G 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 literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/ebwizardry/textures/gui/curse_background.png b/src/main/resources/assets/ebwizardry/textures/gui/curse_background.png new file mode 100644 index 0000000000000000000000000000000000000000..f81ad1b62e8c9dace25f701d2b6ec7054321a72c GIT binary patch literal 621 zcmeAS@N?(olHy`uVBq!ia0y~yU}OMc4mJh`hM1xiX$%YuY)RhkE)4$}G#MCJb~Dal zU|`@Z@Q5sCVBi)8VMc~ob0ioT7}!fZeO=ifv5N}m>R(M-4>IbPr;B4q#jUq@75ff3 zh%`KW*~Yx!wS^0B`OBA8;y&jc3PL-y-Xv(Ktcf&RpKDb!--Tz1{(JEWJfT%5JA*>F z_xj&^@%-7_#^=lOYYseJGpANOl(1_w~^nMpC&AI+IB`HAyCZ-jyU>W|kMIvSonKg~R0(tZy8%54n88XTCu Zo4NYG@4KI8roIPx)YH|^Wt~$(69B47l>7hy literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/ebwizardry/textures/gui/element_icon_simple.png b/src/main/resources/assets/ebwizardry/textures/gui/element_icon_magic.png similarity index 100% rename from src/main/resources/assets/ebwizardry/textures/gui/element_icon_simple.png rename to src/main/resources/assets/ebwizardry/textures/gui/element_icon_magic.png diff --git a/src/main/resources/assets/ebwizardry/textures/gui/elements_picture.png b/src/main/resources/assets/ebwizardry/textures/gui/elements_picture.png new file mode 100644 index 0000000000000000000000000000000000000000..263b4ca3ad6814a99883f3c4ac95e41e392cdc59 GIT binary patch literal 7821 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 StDk{^fx*+&&t;ucLK6TF*T1s> literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/ebwizardry/textures/gui/handbook.png b/src/main/resources/assets/ebwizardry/textures/gui/handbook.png index 67a4415fc2b054caa0655f629263d088f6cea0ce..e45749c61317d9b43903ae55d2b62bd193c04975 100644 GIT binary patch literal 23928 zcmeAS@N?(olHy`uVBq!ia0y~yU}9ikU}WH6V_;x7I^kS81A~NFRY*ihP-3}4K~a8M zW=^U?No7H*LTW{38UsVct+lh#%Vc+!wf;{Qkz*>7;CmD`ud)4o{^D0bi{RN5p2ouUYZ!=jHe1>5u>Z`}z3(;`@EG z*Z0qx-#Gu_PuH{WQ)fSpdG)8d#?C(WdBv}nZn^vSOWd!&cwhSGFS`fEi@rM^wB_IM zzSp-tU*ym4CqMqw+g#qX^XjM1BG0P-Ro2%Z4lp&{cQl~J@8;AK-(Tcv?)@ z;!VH3ttiy1pZ!@q`&aq7RnOm~m)WK*n{(f@c3Fje;k|$@??Pv;KeRt(b<^7Q$HJGY zs=bU6x%nV_*E5?;8@*jmcUkA%pMTl6P2%sj*7^7R zf*tj8NpY=NVLs>G$@Sr>#$2iA zER$uIPZTV_w_us{gY(zd*H5|bz;>CpIJN06-`&P9{ZHyd!gqA?&6)Az=a-4vulF)4 zCb4uL+~L5Mvn)BLY+FVC3Qnd-&w%t7b}sfF-QFkl*@W>=Dy`@(!d6}DD zi3mQs^-5Iq+q2sl9xZdT-*zkN_1yNdcXxK~Dt3B*xZmKBhjPEstBl3|`Drr>m(5I{ zS-S1!^!UV!$FB=XXi)N|Ng}u zS)70E&)F${I`NT@Gc@N%TO9NZI(K45e_xAu>H*frdyCRmcVE;lJ~cCU-a3zYj%upu zmZ?2F$KKXhz0)qYH=6Eq;{VJ&l0pyv3(qw6y1ReE&ikLgEnl;?u2b(0&q`j=5a}2D zHoen`nP0hs>78)LMDdFKyOKXFHJxh`Y?^0$^W`_I(xXLJcG=E(a%@ib{-;mu`pdJA zg}vr@Cn6ucKJm7tdtu`Dz!PT-wywF$u*L4W=GLDlI-Xl@bY5C%^1*P`(Q9i~$}`0m zz1sb3a*e*SY}=N%kA5z*KCfb4pKkH{%(cswrUxU}`W|x@I+eIXF;~HSYK7aYUhlnb z{%_xe`13jBvTl78VfIRVZiu#>z zJG}LM#_M~m4e!;rUhS~Bsl8bEvdIKbk-IlO^Zat3Y5slZT{-C;!iJ3!J2>TKuI^sg zelKd$dk<&1E6RBo3B#PrYO2 zZnr0hGp~JYGRb3>xMaR``Vx%NP0wN?N5)c)W4jdfPRA3>Mo3W0Na{X!7` zFNGruWhU&{Q+;~5`mWbmYoA^-y8N>?NQ(8$neKygot7Q_ZLYC=F4On(VRN4Ds#&qn zR(xZK-Fk)_f(r}Iyjfi8RPjq|%QcVcSJ^I09P_j<#qTX%+^ED^dX{ww>oEguUTvQn zvoGbGmU-kHsXuRnd(hD*ya5WG&VCB_ZZRgho)`M%vwPah{FN2{%-agC$wdA)zjJ$a zyN2I`PPV&?S2jOibosne=a*Y63VUKLZ|u!laGSTMIV&V?*5csFZJU^+g12qGY-Sgg zaCQ0GH*Yt3ZFVrbs#lXZ!S35$52gwB&qYic)eE2cq?+HAvS8@i?qxK`p-d{0S@!X_ z1F>f=AD>mLETikbtK#ByWsmgNoK05FN4&!R>E62sW-#^)?ZpX99`H^{T;`RGIZ@XlN?f)sBWp>8wpmpQN zMJAdDK5|5ts1?h$zYcH_KkgB&Jv)d;p;10ZGsV%z&-p^G((%Z6ZO z?#e5Vqgu~jV%xywFfTK6#-`m@yzhMZ+nFfH`)5|cMv=QFzU3YUmEZhbg*~gXw|D*g z93gexqE~RDKLeY@3eCB1pWk>Xp;0rfw~x7#bLw0z5wC-Fb%*pcSOpHpO-uM8Vl{E^ z-h6h23*}!DzR90wdUtQL0?RpN`_%_m75wcI>XH?6G7fDkX^wg9^qu{a+d|!CVRNrc zy?wx{_lU?(6YtbFGd&egIk1X!EoE4AMqDB^W*>9>x7A!{o;!1-3QgO7=9;eYjwe|S z(djI+O&o>3Z~49?I`z9rvGecCm0x){N*t&BwJS*wt>=}`-M;j6$KMAfDy!$Gom0~n zVOTNulrVSnuG_2`+zMs?1SfJ7+=^J;)#7%1Qq&=VTS{EV4vQ@6V`DU)$GO=NaQVJq!$FBQJYu}9dx`QQE{%)TNq%&RyKxNVB=H*1VJ5&W%hlbvm}`1giw z{PvSha45`ul(A*~LH9*$cRXZX9C6xqjJ0UdngyGrcC;JwzNo*y!1GL&dr#UHf6WK1 zA(Oe!$seL^+PfnZsDv!PQUZJV9QWlGL39Dcd_!LdYz z&H}@dvX~WiuZo_3_Scq~bGWRaKT+dy_pKK#?q!P@)ty)kI8JyTJlV^9OL?X8F~05R z%hbv;-V4ZO7)9G%;Xfj!yT{UU`F5!Qj=Mnx!Y6c{Sk@Tbta&(F;2+O}(=O+8*f%cL zv3k|>a85g)kl*@8Q#HT8(JNQjps#T9;_qqkbuKHvUg7z~_OzkUuOu=r>fDkZEulMN zQjN3jiF0nBFfU{J&cz)9izh1`y|2Jw%m@3AXY2aRaWxiPT9go`qq0-i$am+h z)@!1MUW}q_9S(U`sZ)CctPXyWwhEm#ed~))jXTbHe=z(X71VL`y0m2^lh((NZYyp@ zZ*`C{eZ5a+N_EfS>y^(}{{OzE#bps^`}w!uIO8Uq`ghOLL@Vyy4#Ca#b-rm`-aB_p zF%c{|lIPFvyrD|LuHWe7)i-BuuIPDF{k&76`sSNiHey@;HVc{Vzy88r^WySF6)()@ z+6YmwKvRKHOegvc_wLbKc9>I~MvHOQn}TsjtodEI!LAtN6mn z*^2`9vSf7xTKh9hTiMe$(|*5$t@5@#(^3ngT5S4u8boH)saRNq;sZA6oQ0VNvk%Y316}6ZmS5yfi(vx8nUtk*SS=2j@nb{P<*=e0fD_ zu*Ro5f>ClC179DCcGTz&Vb_>pIc45Xu|w-$Y^r3PgeZB) zJ&TIE+36#qJ1JAdH^xBqb{U@0%9^|RHp3t$Hd23lz z&C0_|lcfHMw`RTn)DZUa?LB90p({L0VoLlbl2eqp9U?Ck^n^}ae2GKC_2}9ig42_m z9F@BZ7Bo%ps+6C9?eB&PyH}27{J;7Y;zQ(`|MA?4s!e8$rh&}Njrp^mEC02aVWFCvbj&K;E<7_Mw{L5Yi_?nFDGq$z zvrV~^T5~5hsn&`bM;dYT{c{kQI4$$d8`)JiqvRH(-7j`tbul&R>`q%Hnc^1}J3FU6 z3_11G;sV!M|BXhGtBy`c(ozh4k)&|@UD;`;!>gEfe|CLt^&vVg+Rr3&@AO#>+XTI@ zd|0&5TUw+3Sh&@!FmH>%ZN0Ocn7H^(#!60+o!XnQ=(9|Kb%lvB_s5lg9hd$nJYyvy zF!SghKWUa;mzjYVj_EF0mi2ejzQO^{ip zG-~ETk@Z{~v?DIP54)>i- zGKyU}_R6!veS-Cc^pzG|I~;fNY-ec}`NXN&!oIjT;OEAVQ(EqS%gmpkv#{!Pfq>qZ zQ!y(xdEFLcXI`{vYf{yWi>VW>b~(ge+a_caqIX05;lJN08!I03Nlz zH9KUCRZ6}&HD~Osi2J2ma#WPB&fLeODA#4}vF0{r7X+O>hymvTe^C)RI2fon4rf632u$sm3R`QY=a9w%+N2`#(wkU0;$lT zEr->AXp5OShd8+FPLkfFV7}t0%OU;4v0Kf8F1H0=*xcxr5mLdoVzrjiabd1?w=P_= zOzn;Eyv6gt(L2uYqyRaLy6-ps)RIE(iF1@JT+oW9_vFz!rgL9n|7uudy z^q}c70xRe8zhq#*+u=5yx{A6Qv`dN}XpXfr- zZ|Uh%cQSi?Fkj1~#3-~yVG{3*I|i4T{)C%vs5eXt6kL z<i&_o4<<=Gm~`>h2J1Jyfwyu~ z+g4pw+{7v}d#0Q0)~MVg;%nzQOZ>?3u{C9>D2SYWDfh#@345G>A5yXS-=Zcjl^(*^rkW%vsa56ll zV8Op;VP@sL$!c+oZ@kv#AIX(Caxg2iluOa|rjv73@&Y;a4k`B~ep{T|kDa-pt3LVE zR^Bj|c@IOrMzL!2?Jg8io;Fb{??$PGUrgi{mF?+_cP|<%hv&K+C`&S*l^LkCKylF| zp<+C&E^xne&lNQ2WN=%kbs?W^ z;=>0ovy>;re_%iD^mdi&+UW`s4hs8~VtGXuW>vh{pm}q(#sz_-r&IULT+&vVW6OMQ z#^xyX_%anD37)`6q^6KmZEjh0qT>!&kz*ZFVKxEENfSgRa4Yh!R^=QUrCsS}M` z95%1eTj`gWb?sexcGT5bCaa8Z&9%OC^+VIU8Q+{)L^w~lGhJg|X*;oQR$HA@{6$ZO ze;3$P=C*v9!)A0K^6gn;XJ4B|&c-Z9PIHu1W*_kSCZWFIOx)MP{NDL-l}=yX{mpo$ zzS@8ONb;9-lk-9PFWG0xp5^~)E8Vf=?Y$%MSBthxwsE}nSVBrC z^URd{b@J|<9-iRn_%@)fIAuK#TF zKHF^m&NJzV%Ei1|7Mr-dW$c*S@>aJ(AmCMtNBm-^ELXABl~#!&z8+B zE8Rc8PYWymc717xh}SV;bIH0(S2Cw;UA~ladRq1ttqU(RS8R9sA+i6lquKJc?^^w| zt7bBCMH{{C-01S9W0u6M0_*a%mJMpM#X7Rrw@>}+q}p)rmU%?gc~%vt<9_VPPeKFE z-0He2ohi-K=c{j1VWKt1yi4$HwUxyoNfXN`NdxaLtuAMUhf9wqUG8@J_#m4xzv;MY z^Mi-2>i0O93~x=CArNq^z@fSF=)Tm?t{(;SW=~^d{OY)S$=8z3i+x*C8E#mzf4Z{h zuk+#$j@zn~U6=Xz6t&&6IW)aoUj5dRv(0>+w_5mb%ok8|T)cM6&L_^Qn=kBs8TEBz zoE?`tQ(5N8x2LwRdur9M`>MuK2ynDU$yKh}*o_z6h z&5x?FUSTxfs-^jqr$NEAh&45t3j?_WGYoFDRrJ5DIjVM`js2UGWzyjbhNW@-$F5cu z-rpuU`>4xkhBg3)S^}xV7jl zt4;AmHeU8VKE-7m7ps1^K6~l?TKq?pknvX4b$d&1?~ZeN^z0VL4CdfsWroGM%R~LI zZ(ZP&ll|w&Gsf=tHWstJ&X;bl*(ecz)LSt6ap;Y;7Z2JkZe?gL5wMTs4rnlX_v=dO zJE;wELVGWJcT8IJefh47Oh2@O&i$fV_JXSb|K&YS%8kYDHKi7#&Mx%WnyO?=G>{a2!!T@Efu(UFU|JtsKi z@}U`A6?Gm#rwi|2sQej}ch|jsJ5OeW5{ubn(+8{Wh#pvX`)mF0vS&d7-lDuU@4W4v z^UbP?t1|DJ?Xl{{mAZf@^71M3)O}ycZau4?d1p#Mvu>A~V4%pkyH|D``Etkk-P3zd zcOIA3lKLe3(%R3j{5;d2{dOS}Csp3B{q;Kiuf&^F-Jl=GU(Q_b@My-gE2S=L?SE^Y z{I@NM|1KBre{lxhUsDoQY-<@97?QBgAY>MlB!gxUY&#F~9x&ix`ae%e`9_=8Nvo~) zf4^S*8>*efEX3ru?l)(qcgev8#YR(~>UwjRep$uL*P0ks#<0yp#PYSRUDBhU{-KqO zM#Un}?k=4W!oa{Ek{J?F65;D(m7Jfemza{Dl&V*eTfhJUHue<-iOJciB??KY>6v-9 zO7C~?S5nAKu~iB;^)>JXl~0)0b01O41w6dlDS zu4M@Ou<9rdsVqp<4@xc0FD*(=buCNHD^W(av>>On7}?I!;#80j*xflPY5Enp5Sx+p zxO@5r!1aKFF+DT40IUO~8d+sZGF)9jX;BVXO-izUYEEiyYFzJrg*y8DuEnem6D&FnPLTInwuvYrzRR3>YAGwn(CUQ8kp)@7$;lm zTAG>|7^avcS)`d6A{phGS6q^qmz)YRsv@^QFEca6%F@8t%-q7#RM*7J)I!(9($GLR z(a^+5*U~W2!YIi+H7VIR5y=SuqRjNnyu=)2SAmR5$xN{_FfcJTw=^@6bCI;pRMPaE$#hLkeAX5zu^vu8#DalrD`9-;j zCALbLxryni`UQFEV2O&{0xRdD)WnkfqLBRj99t!jqZEwv3=P1ULBR%;tX(TgtbFp5 z6G7PltT;8r4xAIf`OPUYT_4P~(Z{D4!=&Jh{PH}oMo6B+V-7+o+!V*6lJfkbZ2uzv zq^#8B68z?1Qw%pLC^bE^xTL7klYpnt)Y(ANrAKCQNq$i!lKsJ{g%BRZTREBFpi)o( zXJ4ztWKbyDDitS|rKW(RKmjI|oROH9o|<_hL%_?ES_BChaJmUjErgh4qmM%!l74Wq%O|KESs6sPbACZ(QD%BZiGO(>UhA61Eip9p(b5V9g;7gL z3g6M-8VxRzLVzU2qp52&xJU{Ck`#}oE~*6=7ow}2nwMg$RIX%i7bbK;f`Ng7Ey>&6 zg&~W9i$T)a_Gc>t0|RG)M`SSr1Gg{;GcwGY15(Cb;_2(k{+L~!PnhwS21_&p1A}CV zYeb22elDo9!~kv&rKTv9XO?6rfSUH}qt1_yh z)T%NPS6p3{wqfhzV>8pPq}n7c6#Uo_aEp6R0)M{E_bFGU%Pr0u9QtggCh@*(+Uy;w zJzqJRdDTB$h|Nz=ZJ*G$^dLi6O2&-`677j^guh2s-&!V}u|)H&zy{4-ukOl+>i-T6 zOAAX24J!?O`d!#DAa?51sWaa{{r&Hr`TgIvj124Td0SmRcBt1~V+xYq^Q+nAV(Q=H z>(7Wyn0zy+-+`ksyncel%6~Q=H;Ww%TKRt$GeiGg9{<$ZXo-kh3^m3~H5N1f|G%j6 zA+YP|r(c(k-mi~4-Eze}(mk$TYRCG`tna_5J*k~5$@o9^e(Ie|hNpkT?`2nbp8xgN z+*meh^k>s8mO30D-pT{*`qCH&m8>)T7t9J1cqxhJ9NYx~#Z-hT_FSuQXZsQ=sZ zzv6#o?*7)$ryIM3)&@*nu6pa7&`L+4#eXfQp5R*jD`B0>8v8Z&N3Y47J2uEMFzn=W zxWLS??f#zsUOWHuD4&g~40&vq@#^Kv4WF)<>0T_exz4+%Be?H2?>DuA_;l|$*^7yP z6aQ*1{kP-j8wP=U^?Uwz?f+rAOoWCEn{v8Mr zaH#nI@t^j;f88%GE{>~=uxtwLF|-@yXOuoIubpoAqf)4OFXx^O`K+^~mOcM- zI$|PQxw2*Ng}Se~*>@Q=jz%gT zJQx#RB*Rb~VmDFZ@MnJ4-12Ry-&ed%_q(sXWq;DX*Xl=Q+J8p*e7Bs^efozTL&As8 z^QGVO*3CQebmsl@^U8Cl-Y%JzzxB%Zq;vP*ZoRRo+C-gWLsqt(mt)PBrGN8RJ2sqR zWq6a$GNby3-|w~JZ*JwgCT+1_K7EG7+w(6iXW4K6HSen33!@*+m$#Nio298Acvrn@ z9Z%i7Ia~}}AD{HkJAPF=yx`g6enYF8V-@wk59RN&JDIV^^u29ueBAfvtsv(1IXCuw znEm6$U;e_`hd-|P9Qa%J`bO(mXZ`0-uA55#tWZ%G2&h^5ay3K4jkOyywRaayYrMPf z?AHUY?YOUQ_F8m(ebW208GA(6Zok*HOgittxA}RRKWBXVe|G+3d%J(hfBOGdb9mnl ze^PVoV8gqkNB``<{EcffN8lIj__$YFclwmPIdyW~9yWXbN9O6%A8d<$_S}wXgR}Vm zr?LD}?->ttmh(T&S#4)tyd&NJUUk{+UuPfAvvvJD?Q;2*pCPYg)~rjktdHKG7T?p) z%y5q9%X3yHF4aH9`CW^)>IT2uck7N#Zff{TBh9B0tDpY)^6Tk0yM4d!^=O#iEpR^f zeC_soQ5%lGn)?3#>-7(w|2Me0bo*?<5ApK9xc=poGwk{oIpb}M;Y}<9G_fF5UigWj`ujhOIcUz_O?zeYk)?a>ZJnK>A z@6T0oVfWWB33#!8X-f>}ZcC1iyHbbm%wBZNtd3*<{pW8=V(-@7KW`LxeDkOKe>Nn< z>V)jqu3S64+;&FsdhLVzf8P_$*!7U@@#mt$l8pCQj_L4~IW7F3E2h>}|Fnt0`s4Or zx3wyYqunZ#8Mqc6iO<)WbL4)v#I4-ys}e!ncZeC{jvg}n@252u2o)CxJUG^*_K%G*?D{R=NXwm;s+J6UtG`#*`K>e$ zh?9z4p1arV-chq}PlZbDnVIbS&YrEDcI)z&D&4=Uw66x})v-&*ZU6pRs(LN^-s%edjy-{_k)S1%|C|7Z2f|Kq%H!rN`n&PT|-fo=6wVCOemDW+N*4f`ZOLs8m#WHM{=x1Q~ts*oxJM4K6*S1Z6Zr)&5 z=U6fIo~34dt-<~O&-fgl&$?=<*D!BeNUDnVQ$YsVhC2ZQjTq!9U@V|C#T5XEV0URCv(0XR6BI0*0o( z+23yGO_=%frt!+WHK)${TCV!7f1WYnm&c=NC04Ol(pzTCWw1XIU(TfQ@7lC|vHcUS zJpY>-{!F;j@bSOuC%c0g8!BFHwfyw@^A0%^#U+1COt(B(dHq>}(M&Oi!aRm_#*~UT zsU626zrEdl^VN1?ZZ`I#j9Shxoj5L9etf5Ry43y!Lx}r&L&IC=SJpA=hCgMf;9}VJMsBO`tAiKswXjI< zHd|2szV5gv%S#5I`4Itsnj_b#S~9c<1nCxtHCWHlNfcURq<@OBV37>>Bmt+a_Lo`A zB^RG3Gd!QS@Yj4thk_&V`oAa1G(4B@diEzbj-x}sX=cgm({b1e8FF2>5n zcu=T*b&=jJ#uqW0XN6DSA@%uSq2iLDT(;v3JH%PJ>`%{0X5dgPWtMF?G-X!=&&v5m z`k6cjUVNC@b^fzz%N4Qm`@5CW9~xLOTvg<#IzQpc_7AU9{n#6Rocj7?>moblB{GlJ zTQeS!>#G0I#9%DkX&B?H_Tj*v^B-?6PcMA*!`_fVq2-F)9M%VMKQ#XxG$#aTm~l(RxpRpg1bS$ilJpf13RNg zz0(T@0VgJw;|u~$>j9*79!NUuXO- z?hiW;1Bc>P?SH$39XJZh7`o0eJ8&rGX_n7E7|GC5QO?jck9C0%vdtPUKq3{D;n4<%q;H$7;`&~kxM0gR`dW=xP{aPm-`!QL?8Rw09gwXjnb-#I3Q zBfFUkOlN*bw@grDRBG`Fk3InL&l!*dm#Be^+hfU~d$CN9-G^gktp!_yKt3NsIwK^^ z9M~Hw88{S67&sO(Kd@zpxc60o@B5pFS5;ahWZvCOULzFc35oMonTFTl?Uk;aikB~m z6^Jn?UVZ?I9@7Jc3@sry7%!}~+r`kb;XA+2`NfWXj0!D$42mGU+frE3! zkJo+-ibvep7i>)B+xA8dlo~pYMHfE0>%6C{MIhR5Pc_HI3hk=z?~YHqyEyf?>^UZd zC1>~!xFqqMw-<4JKI>`>-wc5ufvqwH&u3k&__r`4vc5Z+p=0KejQYU&7a0{=CP+1b z_|r0WFTJ4d_WPnxF8?0p2@-G5>#^5}srUV#{GH*!yXtTQVFg8%_QST-TJHodF)D=F z))WgY=&qj-%dq(`C|5YKD<~X_IRAX9%f1WB467d~Xr$h|VZ`pss|$93JUA=HeR;L_ z`|6gvC!dvX_T9^|Khz+_lI_7&c@>p>VJDBJnoHk4)M?;ZZ_gWk{emz5&TFoI{3Rt5 zuW!G6fBp6cD*_~MpJS?c`Vo|mWy;TGHndD|T9Mh{2g=r`9w)2*7dy_7QgFHMy7&9* zIz_Lx{<{56=Ii?vZ_hG1uVrU!J$0i@>_F{YT~Leqfd6ELmMQxg>kHp%-no7==+iz6 zHihQk-?`U+uN9vdyngKwe}0}b_qTE>y?XlV2CGw+*n#eB|EFvWJWL#lTUGv*Fm!P< zy*aW`>{VZ=LUQ`oXwJP?7c*)g+=10IR%P z`PPMNmd;!IQ|8Z_*bm`Hx7?b%-Ngp>*RLOEi`XkZ<#kZUg%UHCmI(=+`{N758n)kCd;NUYTbngi@BH4g zKHas0i{XyTlNjy>fgp~pVh!@PVcQ)YE*!nTc5%>Z<@;~l{@vz`Gn{|*b7|pQh8;UK z{r6OJoZc;$;_c317;*3Gg4LOa>Nxf{B{OivM{gF*Gyk+#iuL@M5@nE|Mg}*U&Ht8)zJ^bE;FtE`m=mtvT5|6yd$@4bPd2d zT&~PM%6Der4`HD@3JYdzWLULU@{RA0XACTs92!^ZW*~D^)Oj_m0TUxz|5$`fan~y6bvvE7h}1 z4_?$eHJvTl$~cGB!Q#x6x zxO?N5Uq3@rS?rfxi>^x#tjUO1oGAW~m`{aW7EJweaARY>alX?HU9ph!*N?93 z`(ea8LBQ$Gw|{?|DnUWI`|77P&-RB)`yJ2PexpD1{f*4o3Nhl#t%5#9F|-Ig+PeJI zR)#;Kb^6(iGmb90wNW_JI#K7@=Bj;qel0g-1f8;Y&oOF!zm!iv2OB0v?73%l=+tJ+$(8%v+}LbuG4E z%VOX3#qa-L#MIz4wOzpJPe#UCDMc%WrH{k@oV9%xwaPk-`-_F{uV4?EwQ<)!m0rBR znTzSl-|6BEB0~SqnXayE7j%kAzMl3&lH~&92ep4&a|&mlKW>w8{uI;pD4i2p1}oa# z8NwQSe%7c7C09B+a4>+n&$FbWZe$5Mo$?EI<_7h<^+5%R<5Az=vHD8s=AZUXV9nba z6{p+xM}KLLbo8?XCBtd28Ni)>wN8PcOs~vp3vPwO$@+({nywL_82mg*taSOk^>ev{ z-hTe;&D(dzN9EXs8w^rHdoAb3_HFMlywhL6R9AN%ze>{DDU7zs$d8tYY zP9C{VAJy}!_B$3jawTs2&zQ!f(sHGd*`Z_Vk7!m#N7u7VH_X47p85Cd?2hV>@&=$5 z$vSY6|8>%%?J;}~_jDM-B%M6gLMvUbd8`RXdzM+O*HdI%B=xQmT63s0fGRK1B8EjD z!{$_c7Z7JwYI(9yjM?hrJ4KhrYoV11sMcDU39e9m!4)c~5 z@XNcq=U2OP6#Blu_xHx8>MKUSXWVyWI65EPa$x|~uv5UbMpi2ygJNn4gPKrs#lM9b zR@c`&yQV_EUpESvuUChHF_WOnfQYQfMmms8P{J)KeD(OpK5o^QW*%NSf{5Ek-T z_W9m(9R{a8)(mMe>oP?!R@&`kilG*3^BYD1Rk{(ZI=WUJgl+}8GE)qI{$-1aqCe? z18(h!{6ZcE#if=EdrCPJO*`$_8XOrETV)$opL8ia&A9q11E=B9!CtqdHBru>lb)Uf1luoN}8&a9v^2AB@RDD;$|cnOwj=c;KvsXJN_C4GYW&+TpaLSsTv1e=2$_7ieh6zSi48om; zHva>*JTf;^Tw-?7n(Ms1$l2G07Z??m9Fu7%TL0FUW2L^<#WavW4_|}jrsr7=EduIV zTcs4z8Fwff-s(S+VXx0}TDDiW7^#gSEX*kAl*NCJsleTPi>&U&GB!p=;rh^bY3v7l zPG&O-IB{HOTJg`J0n{(K-*s%7Wky!U!=eK%6K=I9Gu-KBYHmpA+#hOLtjpl!ao2(U zz+R1jACb@Ytzq*3HTANXRawfm8F2c|{QZcbz%s$9W2Tor`g#Zb)K9CtDZ`-0;o`AjMO*c}WQML{77GP~ z8Be3a*c%)j3}#$3*u3IA$IdGl)Xi+S1*wk=qcJ<#GthP zpMoOegPreKqzu*Hdq-Ejs%)@l%GIP4g(a0diSASpM-t^}6_BU(a{qA1; zT<12QHfa3u=|@9`3H^I{0?!z}{8m3fP4&)!sJ*y7Icy>#1y zqg$7A-QrS~?|-tld`CL}vwI@CJD+=Stc?2@erB&`)=!QLt8zC8*V{jkU$r7@5&HVR%o4$+L#vy**H?q2Tu{k3{ zUfhMY^=I=mS2DSCXtymPG$U#~sgd1hZBpNmGy7RFWI>p$Mn0O^t6^F5ov;rXnq z4Bw>t8P7cWzkAE6evwod4UK@Ziph)r^N$t(DaIDA-WR;}B4IyDs{x(pou51CAAWAHN$X zd@i}Y;$XeQv2Xvs+=;CDyKHv$vc%6?Vs(G#&9^;~)OXUqk-yc+wKnYC<4;-#o>rNp zZoU7~Zdp;19Dj(r^nZnW%5+t|G^3h#rgBByYI_X@^6ezZu_xYl4nKLnxzLK8GiP4P1cC$ z>#PO0mdpRv-sV`g$y$4B)*?Ip-7?odbbmZ^=bbV0-?qD}`F|Mk|I5lf z9pbRu;lSDV(~9Ei;^TL3Dy{CRySm;hj=xwkc2@;s{{OepmfvgNT$9+h^~Lw%V@xiO z*SgIP^vn2PEiSgY#i4Ak-)=)@9wx0|w`bY8;bD36{#&y#w9ZppDYu`C>5F57*01m{ zf9DHN`wbeCt=*q-u_D`1P|y68#F&qwCmX`j{G~lIzD0_zrymm zDW7&fU15AQPI>ncv!yZB`cEILJy>((Z|c7Lj1tWMuaxJ_F*jd+cEjt9RkF+!?8-z-2-rw1DedUb%-+otw|G(H@7%lPRa{l@S%mFNZdp)!ZHxw~w z{J0z*m$z>BRb__d?{$AfF*hV1*qSV`-kx{ogKStTy&8_P+70XJG&R|_|VY26rjoKcyF72%b=>?Zx^StJN z?XUUOT|8^M^6$Opm{vTW!w8zH5v~3&$=6U7d|o4zV|zCHgjefqo_(1R_CoSbNbSi& zhKTxz`mQzhWryN8w%@*1eU1S<;j;I?QkBbs+swPJW=n@wL^yPWm4-Tyt_@O%7|_WWA+KcaQoU%3{)Vf>tZ*UI4eyu7T8 z#Lg=M;gdN}-+2@EG^eiC`}mqUHJ9FhQ9JPK@UO>P|Ji&qI+FYFlQl!!_O+^V)sl}& zRc_RM{-?d_Z(m1%g#X{a`vulNn7>rcbA~eOYWWM=7lYTIORpPn2*?Tz2!vZu?jk zh98S_n?07Vb6ytIz@d1_fP3YW&?T2VPh^KTd{J5AbNfx*D!I-84u=dc@fL>+H(?ix zmH-W=PJt9I2MK|P1}-ZY6%{A!E0esw-rwPb2?L`dONte1ixWp{I>REyhmwLmb(Vcs zww`vdV(l<+Nnvx@!T50fnI<1K!7dYpx#!-+Grhc`qGX(=#OvVa=d>(XAc#q^vqXz? zNzjCsA}LmvXLWqw>1cCvk(#Y|Nr=N$A+2Si-%^E3njHZwF9Rf$N@bZ8mmE!bR&!Z1 z;ggiw`q;)fK52b-nUzG=<>XGv^w3dil1 z%lqj%eRaRxrr?~o=cBrzXbXp}MCAUTGZ-4?&YmXm-uBaUd5$HlO9XD-?^Iw(`1H%P z<&dBUqeAf03G;lMOiUEMK21FlB2@IrN+H-mqvyk!$c~z&k}F?NZtzi>yNhqhWr2kS z-)4Dv2p;N@?BzH+r*+Ge2`^Kg-8&T$&9P*npTE($c8Au*auM#8uelVQ4ECwB1WopI znDNe1&`o0!=j+rgBjp1@PEjUhnG8yo7%KNNzC4-YmZQipvuV$~CLdp=xqF&?n)hF+ z2{`oX>#wu!t%ZI;_WwLjoXqy9`|0}Z$05Ov0^x?&0v!%6X$(RWZo1jl)-oB*6=cx7 zJhS%XmgjvNuQxbu{M?!vrlrVm;;X%-(w!-hrizzme)3VnCJt4=RvG!ka%3@E(sY}PQT;fTrv zp^DF~^_^d5_e(L}`*qfRW8LS zS(dGTXHE8vKf9)F;7XYj_xRL>^{ELB_A zezrxC!3w4MmzmAJcC_9zUg!R>yjpk4iP`IW@7`ZxWzf0ZV%C=Uv;Lj`FR?wyxKtUv zK95ncv5;ZQF_ZKsJMJxJZ`k*kJ)!Qr&aYrT2e&`mmJH0Xg~#XpIr;Ozo?dAk=7t59 z3}t)c?tU|ie9*Xy@6Frm+n5=id_VT}{Djv*uNs^Ber~o&Kk&+S8WX3M;#$Vg=Kn|D z?7Z)A|08q9v80Zzx-M&S72nlAv2;n^xTjv3`ESRuB#XKP@k`hBAOC2KJ@z}V>W81% z|5)eXy?>kEb(HF}lR*ZIPn{sd-u{jm3n%wK)) z`u5TyF*`5Gej$#9%n8?5oSXNX*WdcryH8h-y^fc?_uhid;p-da>F1I^9lO8z?M42Q zqZfDNs47iAC;i?sS6+l&p`N9tuHeCy$Cu`Jzsfl8n*Gh{g>7AK3`=Z7!Y=MhdOHe! z^-OSJW9Ul08@;jOs@0N7kB?P9Y)d=+{MW{9t(Lc6-i~5r@cNS;CuMkVcUkh8Pdn=# zZ<-1c7n5dKqOSL|?4zG-EqA%j-?*dS7OStic>nVMb?HvM=FeCe%l6iD+3nQjd8zWD z)lOYy0wV(h&)2_2ppG2>mw;-BAGgAds~zqaRXT3;;>gM__p$H#q%CgmwI zjaeKF-}Y{lG}qm+_X)#-8Gl(kzpQ0y_;N&5Sz;3x%O&CIOTJl3S2%HOR7iTx;F7%Y z44d)tuo<)VOxtkhWc7X<7KVsT-)7FSVJN#}$}-2r?Ler&f+P2Og#NF5FLR_Ke#3GG zw!lAMANcY&ROvJ|)aK{3{WN6AFLmN56lBm){NCjCYw^Bl4bBO2EEWro#Q*R6HG2ZP z++7w68@>fUgq=Ft863n*o^s5%xVBE=`^3iEEDmLk4#n;^&%Zhxzmo35;BqC&w#@GY zbAO%_|ABe-iY+3-3^!PrwG=Kq|NFYamm%fd*>Eey3o94rpR}G<=O1#q&LeTkkK3$_ zuLK$1);n=*JYM$GXt`s9_cgob$LwXIe;2nt`xk#>+u|T6rPZ1CEdov_wpcN&YPY}g zy=>lG`zznKZF&9n_$@K9H@T9W4HG0!+FuZzUbgq|u~h9=uYbjBRZm?~V)(()AmDUL zh{5M6!;eE8Ov_mI$4^W8`pIXz|nZU(v^Ii9P!BVZsz6R?XlUd!`v&WA50h zd*o5*>lQAKOV{<4YyWNv?vGFV{MY+yPW_)|env~i6P#yceoK5d%M&R3`R};>4}tW1 zHWPmGDYghW{V8YYE6ty}>#M!dhkZTAl9*2TGMHEyDH*@4-+$uv%@YTHA5(HrfA0LM z>^}ov+8l;prUjkK>`PC5&)@cYCPRmS6NhFpgMsS5nREWl`a0j-;k?%O{~-()`j4)@ z_VCG{^d&dnxtnnq9Qpf2f#G${|5NYwXJ=$NF5tdhmT>PFuf@(>cF=GUhhiNIgZDK% z<-StqW4CVgiX1rg%Y5;jhKmygmA~)5^=|j+aHXj-$II<(wCjGKoxOD4`}$`$jyD`_ zuzy|ie`a#PBm2*nIHKg^SW}Mi8gQ&I`V%FxGU&Hzi@+jVrV}iT(W(t|6b^8y{_753 zD}0>)&7@V|<$I6zoS(+yIOoU)mOIaXhc`1#y=$NUxNXk+lx@}yAJ;2gNpjn|Dc*@g zaT&t_85RpeqYM46-`5CCzAh9|a-QqsJ$?R@Ab#7AbYu2=OIaEHdcN~6F8yoNxUv7@ zuDY2Pn?HAi)X#2iNjmypzi!verM?`BEfK5?H!c4sr7XA~xFtFFZBj{!%KQA-Kcafg z3=5C3Fo4s4zNpHE=kc+&^+$Ieyli1!aqIhigZJhuRx1cOdE8`f=$WCv<;;ua%m0Nc z|2=zSEknh1ftIRy`A1uGt-1O>EdLSCzr1f>>W$CO+5D#;U1k1$dNL!2;*v9r4WeFu z-m=`&O5G40ae8T zcB_cq(pPK|kY{38{^uWqi{i)rt-41xzFT|D%RE?4C+`nFt#-PSSSM*q+M z@qe3^=3aEZ&OEWWd3kr#wHq%5+bZ|-+wAh3Qm{wI#EC=GongVJU+rmU4xKpgyJPEC z?pj-hxf2_|r>@CW?32GS)tEKFJ^obrqZ5v2ZtrmHk+;lH`IEV?wsE3@$5NJadVDHt zp8Xg8Z&CV1*OHg{r&rX%^M6jX3OIH6Gd4__**9yS+<_M-Iy#OeZF|kA6StM`W{ShH zh{ncs6>0W2|7z~8e{{mp@}9X4gT&&0v-9I8Y?cGns0E3)`+VdWe9r!7FFMZkC8vJd zihHYeioXm$fBn2%iRRvv?Jttn^!>i`Aamm1TL0^xm$7b-wmTH?TQ~HFX!*VGEKjzw zFf%xDe6(g@xO7ar)|R36oc)B|at)jQ^~>K-oxY}4ZTZ6M(?5rn*>CyEFy%lrBm&OL z7AC6xQ~zJM`^)1ee_#FlWiuf^>iWk0nFrsxO*m5dy+uH10>gtpA0|w^AOH2&+-uAy zb}?!(2Fxqyt^cra>D~Ne$KGuhsb|>nI^H&Ni^r?%4bv|GnQp9QH&Fd|*x_4Y)6^f6 z57~Tpv20Jwuiy7>!~~qU+S69tyu5f@s)7TDVyP5^#>H@_cd5P%tLN<(`n$W$2+a8^ z`)KEN{mn|cU+&c?rXP4$ygFBsL%_*nE-QoAm#_SHSQs~MD@!!BEvP&Gx69a-ZSqDXT~{ktX#}+fNS+V zTLzie_qvX*zIJm5(|d7|3U$A8+x?Z67_kdwe@XxGoX!7qPXFBkmNzc9=Unl~U0wCZ z>xbsA%gl4dojhEb8Fv5qx9WJl>X)*cEN5>#{T^;xuf1?PH`l8j7pI5qty%s)geC@ zQ^h5R7#lWy4>eK<7EpLw_0#X#e!YL6&GHO{nCHH^t(f`!cCzt=^QC+&t8?cvF>=+H zcI}INbJnln*X{``!d~y3Dce_@pR?}umh(J$9-(XuGw0P;`_Z*#0&Tt9 zRc)<8^;17Q|1`0A(@y1g8Q;(Q^gN34Hrdd+xa#BbzJ01^_kMP|f0^~}E8EqnRhoaU z-VEL*RQ-4B+zC;&`)8e79q>SCijnG)C>e&8oBq2d8#1O$`q#tr<#ZC;-??-6XKwv% z?08_CY{t8eQ^k9PhkoS*Os5poMx&a z5|)(zl{r|s7W*1QQbBcO@Xx=Y0t?J~wr))i=ZKlHIV&NLVS=afnj`V&->(n*ll|^Q z&zJCT^`HjgYPMHB^&b?arXMw0zge@@Fr-Q#p>AKqo6l~amF()?x;xLcwA*=n7PD$LKZIr!?xE9OD4tNc&8(*@+JACz>$+@lI$|})iN^NSjQ}| zvm`FsNJHFqX~DOPjwjV?UcHE}Jbg-R^MwA)Rde-!YqFZ&?LQR1e{bF92f-m6imL1k z!Hx&6NHJ(}Y|Np&Fufgtu zuYW^uPr>TVHtZWr{9?0Xw6g#_D)W zmdKCdUVlX6t}$f1>v(?S@6GqWwElhdTYBXFn?*Z34P#ar3q6tK5~&5(gKtXg4UI0m z*SJ-+AVK|KTvNl!T)t;I93|HU3WP-dYw?)GSV~-d&?5kDk21`({0qt|wkIF6mpO`8 ze&%XwWvN@Boj3d3_b1zAE44YY?r&X^{(H0QSwWNA7qhn182-Mbo3;Pj(AS3yc-T_ee^GOmtmH5h(2F1??dET>4H!4+ka0|IB=Y? zV&5C}+mF{;e$)@wpS!o-i9=J~>p(8+)i-Q2<~A(cw_PwhddBB{!FBZvht6^Cm{7=6 zbYy?w%~N~6dn?)&dX_UUx&6c{%&%!%);#^+D^21qas77HeAjk2VMoB@Ud!8GbLzv& zY<~t_We=)~Raqitc)xmyn=Hfbl6^N>91eN@2|lU6q2j8Q%ra-Yre0{S^S{O4HxnpR>w;k$yqtaMrr(D>64S1|vj;Wi9^L=-VbvMshMzhciUQVUw$C}|!J&Ay`>Bb;%-FW@ zwLBSa{(@`P{Evv<9nj43)t%wMl}-Cjy*tk>p!24VA!$#(#M;->6aO^x{{(d+K-Kbz z?e8z&bWlj$E!PnF=j!MBge*aM*9hJ3%IX5!qWKwu%j#eMN((=0?o4I>BYzIXmMMx17n&I+ zZ?IPDGVIK5B|8d{S)`nTukBau>N36K_FVQn??RFx@fDtshM3|$+{x|R0XfM`P?(->)QOoi|^{swtkefCqKeWFS_&NKG{!C zYB*H?os}(|nSk|ITdw zZ@$-(3)B#0Xo$T3Yn#RFlPnq~8_%<`>KF!@7pR&#o!G+85GC;7<>^!J!tY-_&hX;= zKSq%=kJ6>&70%e!_Ax572soV*VAvtcyukkV_5IOrBpCkQ+`nk2vYw&I*Sf6`1zA=M z8YXN9{=Bijc1`cfoc~G37$R(cU;ls3@8{%Gt{TrJ81{>;{#a+HApmp})Qc)I$ztaD0e0szY#(Bl9A literal 12848 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 diff --git a/src/main/resources/assets/ebwizardry/textures/gui/obelisk_picture.png b/src/main/resources/assets/ebwizardry/textures/gui/obelisk_picture.png new file mode 100644 index 0000000000000000000000000000000000000000..9b02781944c0d25518fb8e561f42347d7a0fba38 GIT binary patch literal 123931 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 L^>bP0l+XkK37-PO literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/ebwizardry/textures/gui/potion_icon_containment.png b/src/main/resources/assets/ebwizardry/textures/gui/potion_icon_containment.png new file mode 100644 index 0000000000000000000000000000000000000000..9d2781409678fac5a2f82c7a1480159904b006ce GIT binary patch literal 12674 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 V;7!GuN(Kf722WQ%mvv4FO#oddX$1fP literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/ebwizardry/textures/gui/potion_icon_curse_of_soulbinding.png b/src/main/resources/assets/ebwizardry/textures/gui/potion_icon_curse_of_soulbinding.png new file mode 100644 index 0000000000000000000000000000000000000000..a45e94f3c51fec4ebfe069d7858793961b699c4d GIT binary patch literal 13480 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 P7#KWV{an^LB{Ts5IlvsE literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/ebwizardry/textures/gui/potion_icon_curse_of_undeath.png b/src/main/resources/assets/ebwizardry/textures/gui/potion_icon_curse_of_undeath.png new file mode 100644 index 0000000000000000000000000000000000000000..fba554f8de1073626f5c0879649c332ff2617aee GIT binary patch literal 6870 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 E03UxA<^TWy literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/ebwizardry/textures/gui/decay_icon.png b/src/main/resources/assets/ebwizardry/textures/gui/potion_icon_decay.png similarity index 100% rename from src/main/resources/assets/ebwizardry/textures/gui/decay_icon.png rename to src/main/resources/assets/ebwizardry/textures/gui/potion_icon_decay.png diff --git a/src/main/resources/assets/ebwizardry/textures/gui/potion_icon_empowerment.png b/src/main/resources/assets/ebwizardry/textures/gui/potion_icon_empowerment.png new file mode 100644 index 0000000000000000000000000000000000000000..165092d43698d6d0196a7ea54ca5543a448d14e0 GIT binary patch literal 11629 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 literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/ebwizardry/textures/gui/potion_icon_fear.png b/src/main/resources/assets/ebwizardry/textures/gui/potion_icon_fear.png new file mode 100644 index 0000000000000000000000000000000000000000..de0039ab63b3d2f89631b876fe6ef09e51d8c6fe GIT binary patch literal 12325 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 literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/ebwizardry/textures/gui/frost_icon.png b/src/main/resources/assets/ebwizardry/textures/gui/potion_icon_frost.png similarity index 100% rename from src/main/resources/assets/ebwizardry/textures/gui/frost_icon.png rename to src/main/resources/assets/ebwizardry/textures/gui/potion_icon_frost.png diff --git a/src/main/resources/assets/ebwizardry/textures/gui/potion_icon_frost_step.png b/src/main/resources/assets/ebwizardry/textures/gui/potion_icon_frost_step.png new file mode 100644 index 0000000000000000000000000000000000000000..d0c4f08189ab9b74970365f1ad9e72e4d7bfc8be GIT binary patch literal 14405 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

    *Ax5Oo(_}-|I)xcBg1Nj( zD~j1$y|x%@B-%E0W!*TftTT%vu{16<-uBoU{s~9b=0}@^YC4})ma95#zl_bHhik&4 z-B}g${f<7ep5Mq`YH&L`)3#=Q2g8(%$5Yoy)bp=+rY{)kyz0RH*^V&^=Vae*`+0VQ z%ftZo(4&7lCb56A628aaY$z7v7MPLcQd}1G*4)_W{YCZNnRY$0qFFs%8xJmxynB7p zzln=~&TCjS@1TFF*O}AKEu5iUaeS?2u5E=Y7aEF)n})t&i1;J?^atNFr|Gx*V#-%c zSemR<#K-cKcboI(L+`#%;GXMd)ZMmlk+ZAd%eh{DnIB8+)7-zAS+8vNdFQKg_i+ZXoYOK~v8%8Zk?_YRl$<)h&evfXK=jpvS zH~%iF^(*(%i|>xgM-0=ZPBmYvu5hCyPW%>stGB@fp|FpC`Ft5O9-j00`a$*b_qnqs zWz1T3_uiv*F^bmm4!2}??QO32Qwg}s!dSC^>ygP<${aR)>u5L2k9xSs>UR9qT*a)% zwtu8#OIKNCOghso-Q?e(SA95M*6^yT{N7g&yf1sMZn3smBeQ;|^8VLmPu@qrbxwWp zq+_Y4&Xvbblc%ip`Yc;^T;EMb|J(Yn#^0>J%Ji;({qOCjXx-mGW?!~Qy($xNH{eC! z!}8@H8C;J~SKQEBHH&H4Dm&&FajoYi&rYsPnqQH=Q|r^Zulvs}pII*zaJj=KZ26+H z3pI^esjn^to!;YhW&gAD^L%G~&K0_@5TU%pY+v!(wOtK)Q%+CXn7hDtuHL1UVvnRZ zh0mPrdepMF!b|9Qkd$NU&y~lx)IC&7v>)D|zATY5?E3!*%`NkP)m#*@-*aIK)3fUJ zjN5-D*SxNJbVp-H(emvkUYsWPUh3Yk&f4<6QoE+dT2qE!W<*=;~fsc9U1N$o*GVMpMk|^{?(K+&i5&S50cJRSaw8 z1*P-?ZnN##a>q6*=doI-Gyd~nS;E246?5gJ`rZObk&jm$x^J(R-z+#^NoCQ)=XPdi zP41{EzhnF7zGrH!qWu~_pNk9gW32@4XgR#z)4bQ$x1z>)5%=BoW_%N3v)(b}#Vim^ z7C5pfu0}p$b>L#g6GHY)lPY}eTw>I=EnRp%sPNv3${^F_OjviNcavM- z^Un&x?+zMwT1?eq3k>vAWbdp>!3>f1XPH6>2l zTueFqJYkdEze`X4eU~er5gHo&-s$w_=L~z>SFB__`Z8c`<5~BujEl+(^WN-Q`A}VP z!Ug|7GG1pq>$fgdHh2HJs$kxO%xp;4%)ZITnlnqU)?;5{z$h;~!WrM^+p)#I^R!ei& zMa;*x`Bl7rRpN3@MRM7$S%xyECxouI6>Pt^@5|y4UY;eQ~I=jtEJ7k58iIQDLPP5Rd48FQbew@M-mL7BoGWxljDr zZkL#Z1?D>!1&fyGO|o8J^!fbhcx8jSo^288X)CuMeU)G!`^5D{@X3aVds7zOTittG zmX~kEa@XLG^#^P8Z8W#n`x@5xgnCbtyZiVQ@?C=KxZOKK zeUIN?QySRz;odR!>W?wLp0RJPrhL6*m?@RNZ($@m-_d7hw!D+B`JbCs68ng~KhBx= z&8)U(*<58u70o6W>UN(Nm1X*FeB(&D0sC#6kP|y5H?I)-y5=0$r;MuVjAaS!Nu6ia z%D(ROSsIWY&viWGi+EqCU&Es5;g&)3nEO^wPF*-Da_6l-QZKGN=W^P2_`s&?o-@C{ zZ}{EstoJV9>vQ?!Dbc0sZdb}>cx!g;JF)1V)D5nvu*XvbuQlIat(23$dor_w^rh5L zSzA>(6(K#%-cRjkKhJGGaPpqS^eZZ>-(6WRxBEeU|J?2KEw*1xUhc5`bK%EF)$eA; zKRV~7bMV#2by=6vPXw&Z|Gly>^#0TL0@W=N`+R4JR&DNh6%$fwbn_Xf#T{n-w9<*Q zUK9$2htExtnl@q0V#URwQQqu9Z{H_JPU);+-+ZFgJ1`kOC$p7Ue|2R_(QEpxw3_Gn+? z%g!yW-m}F+F6?eswv>Gq^4>G8z*8_-X?mwl(Ej6&8(BTsU5_&8rz)4&JY3CM)Bp94 z)T^H|(OWKCGoHMw(jCgR#!@zX(xmXaJga|QE;zaW?6evC`KLdrm(aVJ74h@LF{mmP24yec{MpC{mjZPtXi}F;bufEu_uxgs~mMDooQmaB-EpBYt8G2`e<<{HZzw1v(4ym__ zKYKJkNB7ryO;LvGm4#ZF55%uu71XfFyQX=>^KHhfnFmkasJOhmZ+h1(*(dCuw6!@e zKeN87yG7bm@vFS~ybr6nPAXNsthgJsugk&Bx_Y(4#ag~cbH2}!FJMVL)1-2j%SFa; z-#Vs-lNGKH47c%}cU-D898@tK_U? zbGNVGIm7JH^Ce!7ivNmERPx?i7Bao1Eu!RK(O&kCu4j#^mU38`g)bLc9r)7uOrY|0 z|F3gae4YB8IaA7cm9J~tExXC9CW$6qt==HDan9B@O^#PqXW}0V$1djnT3zGRF0i_w z>bzt?d+Vj2TkpsJFkN={ylpurTXXI@t_?e@^-jsUUfX#kR#W0e?Ss$%K5hxz^Z%8g z?9(}neB8H5B`??dZk=J@yS2uDtB$Pd9fQ4#nrB~Wt~ssJd3B@y-Hpr6P5yFc z;`EyR%__VH{Y8S8&pCC&H}TEfWr~w8-ei7tJ3{gPv8cKH3ylNg8DbA_NbyWvQtr2n z?JlSPt5^13X)D-w9r5_X+Ig#4;QzVqJ?)qG-o9k%;r9Ga9q;}+H<3AiRT@iAU3qKq zqx{>Fm@R!eEIaDv`FwouUflVwD6)6Y-n?I*+b$_am21^%eO4n$FTZBW z{juBlGwGjmaLfCQW9qXj%3f$|q=meCBKT>C@LKztMSJTuy%yfyo0vICY~I|dSEn9& z`)hto$?kk5HqMW4Z|go^_4w4hd~=Rh7bI0ay$veccxOwDbXd`E=_&nxj&)|7dw={E z`l`IsLW8k2Q(Z<;STzb_uE7Y~J}?@A-at&8RCH9wOhBZ!fa?9a78wr!&v- zi~6n*L;igNOX~M##=hOVS@B_0)X(^THexw8^Z#b{KbM;KJN)XO1LyrDr9@;CZ}@lT z)z2*r&0S{2-nL`ngTj@oFE{40JS_29=Ebd;JtP0=ll&^h6|$S}Bqnq)Nax>^y>of* zCF`_sMZGik{hg=fzP@mQ(XZ>ym)=(io~B&0IhildOu5)$wRnqoZ@@~;o@LR zyJ(h1`An-h(f`vqWgS>!RrYxn)%CiaN!%yy>}`0oX_wz^d#y#85~+8cYfB~E+k$_l zmWpvmOo6o*y{f~LQe(E}jySAlb+INCKx9`{ediLl3rPl;i zBA37Jeehs=M1W7djaTjJ%c+_y>6Huns-rr>l)p}y>d}-tNT&7 z{nX-R&B@EzHY+EdOwP)>@2d2(`px#M7kgP! zdzWT}FxEu&mQG<*b*hci3iOP9ZnPm`t|8NF!@xQ|1X1kE)CoKxJ}^3#{16CHfPvLxHKkVDHZU+SNS3%plsM<-=BDPAFgO>bCYGe8D3oWGWGJ|M`UZqI z@`*DrFlKtXIEGl9ZVfS<)NH^LWB8LRwQc?kEnD929L50_%>5o+7nV28R|$V+Sj~Du zP;KUAo@C{RU$ayd3*Cx-yOFbq{`?hJDxr*JPO15GH}BN`ey06$*;-(=u~X z6-p`#QWa7wGSe6sDsHWvlRZtwa@~^u#iHe$=gfD?*qxs#d*;(~V?k?!LUMpqaKR++z`fI2ERSWm#JvsH7asB-L z@=xB@9{9X#W9EA4%I{T0JO01>zI9%R_rE_}kH7x>yQ^+l zfALyY^IFlflYjQ^d;azP|G&9Up4onxesceeFOT!Twa>5Lw8c{R*S-h!n*)CR_x#NpcE^&=C%>+|v!RvUKbq%W^3Ium9`FB^`tNM} zw=jpu-&6W`CdK&8JFAgmnSD0-r-azX-=-@+`h56({r&%w>*TnP8J}$x&+)%5Yf#_+ zZF=#~I{l?h`1>XH{f7;{o zU0>(>^1J&s-^x+H_%m6tb)nkVk1qGuRZo596};@vNB_8sQfBdzh{eZc%_ZlbE{nKICxMu3}4om5IKetSEw=w7L|Fe18rSlq5(Tjg>ow0ADVbyBm zEp|I{&s^oRF*vutUr1?h-t15F`XBGMVAI(4rET|-H`AqmMN}u<)9w*CKfR#S&h35a z6;p|TwRbN4+4a1>#Cx^%v^#rOO7j;B?-SjtSGVVRrMF$p{mI+ERNu5Po7}CcTfXW{ z=(Y45mDJNw->!4KXQ-E!GqYoEk)5MxRQ=wujwf*P-^!NtjK?k(Szhk| zGy3%J-I)fn+T%K0_H`cbe_5@gdh?$3jLl4f0+$~j=c!vVRp;l9+h$UYhPmyJb5=b6 zayG%oKKI$)M`w0^+GE?LZuaffk2hsui*M_{KXU)+{NvV@j%*$_LQK173$Be%RiBiZ zS19PQF#VCXfQ3r;uOkblcWpeUu4BGkeVg+q?MImQlbO$Sjpg6U%%!!6ihXYzL9+1 zKx~0@0JrJcX$Rhkq>HZ=TU%KsWxaLNuA`EB6~yKV{E(mchm-H%bAy7Ncb#W#RsE+D zZakScX`au!9})4h4HysEZZFqmTd*PL-A*sAO|wE{G-M9hZ493(db`huB{(WqZ9VUO zYrS4U4{zm%c4AZbkE^jp9NC-9a@Fxs-Cw&ckH6o2%DkfHW24KT0!@M38>_!XeLu11 z^C86_Yd#l#x;az7ZQZ1|D%aA@T4kQ_2~D)>cmE>D|AT$c_Vc?MuKVtiE~@mEs#nZ7 z)j0X+{j%?s=8ui$&A4v0-AlATx;W*J{wwJP$p=?`WPajscH)Odqp*zChi=%sd(~k& zZ;IzE!Gfr6m0dHgr=EN)@tZe`N8-f?`#(1CIXGsVl(@d7+5g8LxwALwOPmk0e#-yy z_n`0TO|{qe$sbHVH=*Ot9De(`+^hFah_Y9ls?IavFwcVmA)6a_H8qciCbg$1kYJdhMQaRiSiECU?N^P6>;@~l(;#df?D zp0#ODhm%-AQuz$s`bGwB3!TY-9V}(4TK&VlJ5qkG(fyegckfubf~ks)*LpRx;Gbuc z?AHn24c58!;gzuPc{xs9w!Y?_at?tzn%2A2yWCmU`_Q@3SU_u$`{N%^W|(K*Vq5#t zLN>oyamtK2$C3*#9BpX~l8(8XP&oHb?mN+kf=lKf6=9nfS!tqED7ddpKb$q;=BALn zEp2Ol=PY%QzqP`+P*U9!ld3*SBs~37&EDUp{7r{(9%Dp~ zRO{+lXD5EPdfDM$_OPrv@65!!i%Vz7&OdK?#FJ$S*N+5OH!f=xTbtvj{_-%UM5%aW zq+W{7*?H~Iq3k_wtR9DDo-Sn2+j;$ZZtrX2X>nUMCvRsAKa-gF5`Wi^rZ z`7FAYLVa@%OLXg;5&6X58z1w4bK=S#o0gIrmrb&-JT)(3BmQlvU)+4r)JitPt(2 zc8r*@>R8PDKOVEp)U8kXdWxr~{kV3(yLk2|tC`$lhj~TMC$JP5Ec?q4)i{OaH~VkH zhXzkMIZhrI`=IhYjByL6MpZ$DPtZfDJ2!7GTD|YUba(ucgY`U-gKz{$h>E* zP3+rMd{42OH7CS4O>XYhI{NgA`m|R@yHpL+l5(`lWRF~#u+Qp?zP*^s>2A%urOgty zEsPSDDqgdUb!Hs)R7%pSf5IhUGxM6(`du+%$BwX0RNiKjqPasbuu13Etat5itd4GL zl$SoajXCWK|Br5F*+X*r>Pi;v8W-&xzTVMMT#}`~#^San zV2VlEqh3R0(}Fw2%|UztKicgt1gmSzc`$v2?xB)`sP)^+&9**jmkvEyqGXuBv`yy= z`x`sw6#`4_OeZ1#HYs>=D3Tdq)$>>9=4~CCF|sTjezTd{+ZnS+UyVXD?H8oE77XMXBb`;KkbB+ zGoO2hLAr#Nw!hGxjOF{DD?P7#I;(S@kafr7vwVH*y{n^}p3mH+|Jc0iz++A$uD$~d z1id|%OEn#6K$B#EV z8+Lp8`Z!5WHcpt>BOG@tc;opwYmfihv28-RYFA{Z^Q3vU z_a2F`uq=66rfy)ys4C9G*datL(wg)C>O8xkaX0ASylG(miT=PK%$LlJ-{$3`T84{B% z7D&jRnfHGC4u-b8d+PH~wO#nL=E^j2nZCfEhi5RpdXN$(FiC&C$*$66%{ObFJvpOk zTKeJrCB6u$XO>5rFHA0Wu$It~oN;2uw6&-9RR#3qOw@U#>*EQIQ$&? zmKn9)eD6|t`H1@@i;{2ajgHCpZer#Xo@2Q0$ZQ?IRRX1tKFhCc^6(Z{oXqv+qtcSy z9F-1o6`vNZO86!bt1{Up{^@in=UsNjuI|sBv#LHkuvzzhzux@rQ^nsmHO>*3wlFP5 z;`zji2zgP}8ksN0ebz5>+PmHB@@kza7yRF!-Y~KHYmBg?|JzH_7Dl()_NH zrSZ;l?$4Tg(aWz$`o~>9vRBPT^Ktkgfi>q<(oXKl@wQ0ubzyt5`upC$m&7HGoDr6o z&vIq%dKDUv!vvRZ^;!@jP`$Hcsh`gA%US!4U-n;7G-vJQITq&I z9r$v!`wvkU;ho%mjcKgf;UcPerbrp0KT{JqMHKy=uNy>U@0rb~NQ_uLBJ5O~@TNMA^K!nrR-{vO9devQnUjvQm|jn_@BZznQaY&q+~vLreEhq}D__pid) zM>dL|b+=o|)S=Lk_1BGM5&3bcpDc%-wqM zwW03nhL*bv0#4c7VV?hF-yyq01vmfxo-*V5oRpe_ej9cixN_l@M#YwC)#iTDj)oIu1&^Sbuo4@+!k7-G`lD4yFcPh!lM}`{0jt8{VwF zU+3>+&TiVW)sicPG2`_)hsMTS_Y=m?Bc$hPp1&pdS5@}F^}^~OryZ_3=k2<7$@ZJM zWaWgWAolG6a@Jlv(s~{Wlgvzo1R5?LTRE}j<6QrB!e&?O3rp{oSxjpd|c99)orisDaEKQl0S1oT(0@3>@=DXmEm@5 zzmJ31kDXIZ{5*~24sokIRF-P&kgYVjuT|D0xJc(?(1BbB)5^pQruC^O{8)8;vR>(_ z``0x-y762=m90!u@au_LyqYOYD%);ZC22x_|MW z7vrqCRmYAkIC((%>NMfUUtS%25%n(PyA-_J!!YXzA_p3Iu#c-5oA@?T%~_iWFp zub%pzkv}99J7ek1c@kTmG;e5o^`J<1Zk9?%f$OzZ;VECIpE$I!@O9AhZTv5}{0_Y- zX(@H;``UVD)n4cMP63rdh9Q%*w39hrPP2{(*etX(G%zN0!%G&;tBZ?Bj&KAi>IwF&Ql3zIZDpMj-^C1xxz`Wz9C)dq^gFs@ z#($qmfjRqIj$h(x`+0uK@%e`i|JnR0L9gPtvG@_Wmz?&WqGm^JIN!70_NLe-jz+;# zedT&(yI$EX^{Fcf>X}gbgL#hXpR0;Kdqm5QD*oerzB4nh_5E$D4Yp03ADXUC+P`_# z_l{hTlPA_o%gr~~Z`m5Qtue91U16HwdWX}-6OJzW`LXe>P1YnQegU_FCu&~4Zk%a% zRS&E-43Sh*x>6YyDF5n%R3Y1sveF$*T~qAW_DF2H8g%LB?MIwP<~2xh?(*wNoM=|C z`d+{`zL>A)z8=5A?%t?h&E1igv1s?!+2KncUOMKUy(KAtWg;&_l7d{Kj_y2-thy5B z!j`B{-|jsWeewUTb_?&1udN#E74G&4S+mp?M}7Ub?q0~W%;oy&kBnrS+oeLEoqpHH zoIKy@;A9EjJ7)~J9n#sS2)$pIv^F~Gr{=jAr5tk0k4$jB(_{A}?5@|q8apB7K8@rv6Xa5#3xi66R-X6sFN_KWU(ANl2Yy4vQsHUf`6aoG54 z@&~y7s0__m`bpfMIZ|lzWqZB{bwr@U{oMvcU_x0VE;iA3$t;+qUCVvlGR5!7{4`;LdAv<;BLfZlbRb~-`Q|rn_ zXKv%#<5X~>=Gp$rwVh%n>woMm{`lI_^YZ7n=cn?$T^n>nZ3%Pob7rS3*_72A)LG9O ztGX)dG3B+)-FhkR>MT=p7TdKG*Knk7-1BOshmq!_lP6P5W!qft*t>3JV3@fhXz}5Y ztL8VV^_TJLt*_?%%)Dv$idPG&BSi$(AB&07U$>#ih ze*WaM+%pfXm~v~Wq~Enw+cFd@`};lr6!JYTF^I10iVAF)DBR&*b7euQNRs>7%kx$= zdNunj5bm@8W3x|`FS_gfA*Gp-ce#3}=z88`w$j(XB3HPHYm0B_V-`)fborQ1%b6xE zyJj%4L6`gQEVgw)j6B!>JpFX$g>3r@)l|_fMV#NB8%_Ahv0;B$SHbFe8(7avJY3^b z_&#`odZycw^{(qrUQqC=JoYA9Yc1dV5G}T4zXk*Tx|-!z1Z#el$bMn1`?aJ`JZ@?H zv*0G4bxHrqw#&FGI4$_EBRDfyIVtOe{mjl2W-C@U7`VP~?R=;DY4^ST+KShfME#Uv zHe0!EdU>GyXXUl)ue40(S8e~}H#OA$gJ2Vfd4t4?;GkQ1#_8L;)h9I==H&Rhq<&wq zt36(rBdF9{S6HLy#I?4gtGhK;M=bo;Gy8SdsST?<-A(Qb{I}0_PIL_0vdZSiy$8>0 zPRxBeZ_W1YzZvA$d4Id)u}bbzLxd*1Y`XOG9k&Drg5U;E@Mr_*Ey zk*!Bxx^LSdvuXR3(D{2wspJy{M4GD5W+b1qg6cXx1Cq&xNn@yVB2wUW&HWz{dS`7`uYDcn@_{0UCI8M^=Z%4Wd#k% zC;nvFwr+j&`d;WGq56$GPnbm%tX%y`F)QEY+U2Z^2+1neeu!r(@#!4e){V2 zU6r9NVZO0Pavfsli0K(^+S}o&Y_4uPjAf^%imY?=s>V*tD)I~ACq`QU-!i%|9ZsAwVrFb)=l0c z#e!T7T9r(*Rwv3hnYox&uwG?f;G2H%aMoWJ(Qga$xL%xCYrWuWTD{s2#k+^HnRj(G zGOmf9Ex@=`Aul#Oee$)N??0uPZ9jQguC8)ZKD{zUP-%N^vcm(O zJ&!F8ct&O3xpzi=--yZGMCe!tIdJ$+j1y4s#~=BM|CN&Q{j@Huh% zkE=Rwd7m@&a=&PQvPU6y?eo9O)6*1|JWJ28)LWr{RI^FZD(v;w4{_R(ee-54&5B*J zvgxAM`)36a2gIH;A68eG_Fv=Ozp&f3XB6)ITP$zSBJ1Tm_wK5bpLhTI8ouHCW`;J~ z9gX)FPwe{na*@@v9q&UH)=%E{_w24$GxX|nBppx8uKkvL=h7*GL(5C1*ev*VcB-cX z-_*wTu!+B8{qkSc8)z}F-W@TMooC&~6wR(F2_G)R&)79h^n#4#L-DgKyZIK(iJLg* zZa}<^xMEcO>v+~f`@;X-S-W$y*WJ(xw?HY^8LlywQ(YHqjFz%UzSgp<)3bI~Z;q&k z#LV5IU(&O;Z(euPv}VWLzlSYcLu^&M)CSzjznfJ)AD+wDSw+!Z#M@em1RmuI*9V?jpY8%yxxu zwjQ?f24AC%=S-{P`Mgear+nB(v(5fj6lQT)eOfQIaLd_OSC`klNj2WJJ=@fKsj=(D ztOuD(-C?s7F$=RG~G^Okes`S2S%e{r8XyXDHdbt@OPZfvw(Z~Mjm z?X(YCg7croo&5D@kzkhH)GO`AE~R|_S5DHW_>*;8}npQLsC1c^tQ-pBZs&$^KCb>WtsObb}-t@cjb zx#F4Ng5WIwwV~2|qJNfDeP<54cj<5NvDgXB{ioK(i|cNB_HE9$XN&G^+p^AKk!#`f zb5|V26m7K2?$kDJ$(XcxM}yL5Q;8E(;x?BSCC^>{y5NV8+&26CFSCySjqg3R-YoU= ztKhKdMQ4@H|GpTveAz#3HHJlz*RPrRq*X1@U1o9poY<<_o*h%wD~`y$sSt{9*muZhUCzE^NUdwHdm~Zq|ajx}f-MQTDig@6{ zw2)=aUt1?Q89!h#aaYZGd+GmkUkm%U2Mza|JzNlTMPsd<=%4-nZe)L`UENsuT}tEa zdndPbG3T?sh1UOFvFCiut;cIw>(^GTn8`8kV*Fi(f2VY^>tb!EwinNRuVyH4XG31o z6m!R@r;Pcy{g6-Z5l@xC^f7-Y|{_S>|W!zQ@ih@$bdgId)Ok_L;4z%`5qL>A8;8vv(Q$zgW%IKYK38IQHTq zvtouLy=(r?zAE=`#??&;OD`YuI{VG4M1}d_+u&-SsB-axcS}~pvb;09V;}k3#9@mM z$BOkce)B$Gut4QU)ADP_%S!LeIpuA(er?p#bAs=SW_dpUe6JyDYs3AvsD<2qc@McR zEMB&Dx0mFDrpfoC4tHycZ4wiGDDZe??|DUo!o7=<`F4pJUj4jmuhGYoujVVxUp1>% zOgye2>D%>OexHC<7h<JI{!+Kb83=LTPdJ(ald;cP)I!8LDJGlUq6MYVl;L#ot~|5zu?IvY_xx^ZbXR zPrlx^oU^*}+u~sDEl%9W?tL?wa{lJ4kJEKCvvexI3(V(B`nLUmXA+_J5L9yeyU zEZa7BdCA$N7rv|4aF%bJcja%xp0ML)Ey1f*ld6tNIBhUkcI~CvwRXo92S4P?F4a%8 z_xrrZvh?rISD&}P^L1D&E;~nv+hWPohg)~<7q$sJZ9cIg&E$#IRh^)~%r}XLN{mjw z4iI{@P@@eGdJpKb?Lzs{+Dmwj%2^^B;wxOQr=i=cl)`e ztEODP9m#&^_eG&K-TzOutew9v>$89FviI*^?T-AQ>|Fa~dCOl%vlA~~uKV|X_Uf~5 zA=K*Q5BKM-Gqe9{@h5-w>a)*}ZTr7$=dC;MUj5$(rrwt=k)1aEb^rA{7xb*(y2{K9 zcb@Xw+`mTkKxFF4Z7%j(eb#+-xw!IRyN;p55t(_vQl*=3F4zB&^R7+x;p$tz^Nm-! zpH6&R-2KJhn#r$t%g?pezvO2v_J4k*#{A3OZ!a#hg-yL4ln3XH7J#|K_pVDs)ZqOx{{MA7XfDId`ek*86w<2K>A5sa8v7uFC&8cVp9| zcCE6~J!h<~IWcqYsu#1S-K%iR`lvs%$48-VU&*Tm7Uo?+w~tCJFgqw*wOx1pit}~* zqY|&#dM>bu@}64Y^+0Sz=bySSbGKfZb9L3f1I|2~9J}-u&SL6X|Ki0$mYfM$S6}n5 zQ2EOEUzn9=nc!4j8FkkwcOEh>5B>RM-|_o*rssus8*Q32|MY`J+c>;dJYM1V*EPz@ z<$+UMV#7wOaDPJ+$IlP`J+Nb(Ht*57|5r>(rJD0@Kh5O*q<=-?*^iUOuh#557``cN z=9^U~`AajLmRKc96+Bzlm(iUrBDeBO9Q#Rbo4~%>p393K+JBe-xNbw%6ZwO0>{rh( zFEiY~d^-Qn;QENCZ4c$%PTrp-|Jixc&)9!87wuL(`M<92jQ-DJ>v{jDSm<+pnQQfH zN!^*~e>UgiSuUt|eqR3X=bFAcVTb3-?t3m+zw_zjUl*5k)$2F>n-zM7U+KmB*|ygg zx4k`F_WJJqX;&hbud&>>yJDT-gNj}9f444^T7E8Fv(Mz2Yk%kVd4H^J zPh9(*8}jGQ1?*et_cZxso`vvkv`S8jZMp}3;!*pkUdRer_% z+jRBPpIg~86+bOM&%ZgPw0iOuN2ip<*S_qLa_rY#_`N@E*WPpOC$py5n-~31p7>J0 zBwL$7b<5>2X~q5=*2&w1oHXAav|n)7`nG3aWG49NzwL$SL1ix^T-$p_I*H zTy1QJ9B*Gt$Z<}8GNH7hJ-Aonl~GvwgG)`DtMuZu694CZUivfpFV|7U+6%wKD?i*d zYW{iK>ae%Gjr?u>uUq*$1G;4VPhIu(OEuI#G{Rl98&neDZ4{ho7uGis$X zw%k}3n^Z07p;+d4TrbE{ZtYho&(byT8jmzqOz%1t#d&CHv-EQPC%@DeMSr(+bZ}WX z^I&m;{Qc`2{%x|m7{6%In%x$Ob!+|p@NU1KZu&>(L8D+bUoRu$xs8U;uSobW>AEWv zp1o8mI6(c9M#Mq2wQawG8?F@{b7^{zeR#zp!SHL1AryPSbta396tn&XCLT+b%~1PuYdhcG4tpXlUo8WmS1%%`gt{tdE?d(m5aCS^av1o9<@W|Xs5yM@J$=` z?(sX+v`|F$>%}c>3%^!Igk-FT_V#P=X`&aIvmRebyzvdLTR|sF3 zlXY5m>x8`XmK~?237^aI+noI_@cG?IZ>v@P{OcCXHEZIW?-}c>w>*6LOEi=3Z)n4*FFF4-la;ppYGJnZ5|&Q;9U z-z&r9$* z)LuxMqIdGlT;+!{JC#|Vh^;s-J(KHs%#O2D&VP5>bDycEZ++8gG2fFLRgVdHKDXkG zn07VNcc19ojzyo@dNoQLg5Ugm(bLtIuW&RxY{L@u*BSf&30a!0-Xov)d~LAd>d#D8 zsZaHsYK6HhF1(9k7U|`)y7Rt7W{w-jiY~34>E3gq-pxx;z1(*uYV+c6&n@?6uaay! zGTDE3#a{KpJGrycGk4zeTKcV|CeC&r>skNR$2$Vo&y8ILQ_`6h1PH! z4x5#?L~5&U!#%6d7c^MX!sq^5bN_I~dBd2OSGV=Qb5;L-y|Z!Y{~PnN;_5dB-(IxV zq;2!z;^_;gx|+He3h$LYx*)Ym=znDPf%=obS1w;-Yv%mBZ;f)YKYw%U`IXzNd}Y5d z8{gd!tGi}Zc7e5K;l~I82L8AEP3vZ@pF6+tXYcRVN#~A7^-W8A&J?xEZ*H&b`$u~l zFRfjazc>AR?VOw{=C5u)DnhT8ez|LV{{gcsMA|4Rebg|EBd$z-Lmee0v^Hz&>C zYt>t_;?&Fgziupxo*KW%V!?N{L&r-h((SCTXWO@zuVUJ=w~A@&rV8=>=k8s#7Cdlb z@nL}yk)W;2VwS5Ecdiq=Fr|ZiuEPGQ+n27NKZ$+KqkKL6s{dubq_@of^Di^0`bhPK zcYA_jn=WnVOlDa-XKV0tMPH{Z8?AYvZ+RMiwg_i$dwnOMH2cGX2BwPg)II*+uSof; z8vK{vlcoN8#*-ca1_lPUByV>YhN%pl44OWlSJyBwFmM)lL>4nJa0`PlBg3pY5)2Fs z>?NMQuI!I^IC!KP%nhDfGB7YmmbgZgIOpf)rskC}I2WZRmZYXAlxLP?D7bt2281{A zi8C-Tyz+E$46!)9G{lhaumaDX5DodHSIobf>J+Sl<0f_PJvGlTSpGui^OBcN?T@ZV zOkQv;h=u8Cjotj00o?~(zy5h<&7+t0TF#?l-q&>%wZjPmGUFbS}H% zmgN?8b@#FiW#`LW41VqVGB3R1o>DStX6kjWWi#DgHk9|6toZ4{t!yk)dVbeNnW>9R zmLAz#xwyXTlG*L;Ee0vaI?`5XwzT)SOix}^)#ZQK{(Q%?-S3vS`*xadaAmx<;Lgt$ Q1_lNOPgg&ebxsLQ0De-OGXMYp literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/ebwizardry/textures/gui/potion_icon_mind_control.png b/src/main/resources/assets/ebwizardry/textures/gui/potion_icon_mind_control.png new file mode 100644 index 0000000000000000000000000000000000000000..fcfe155841865f01fb158cfd8ed0db6a334b7c54 GIT binary patch literal 8152 zcmeAS@N?(olHy`uVBq!ia0y~yU=RXf4mJh`hOl#e;S3CNo2o)0N`ey06$*;-(=u~X z6-p`#QWa7wGSe6sDsHWv{j&7wj!7;54|f?h-e4@=Fwa=7=jUhEf~Au}wD!iut&A=g z<$NY2IniU**ZTjv&;I|g-X-3rW9O1tmk#d_a4zjtf4cMkt)IE`3+nERzxz7#@1K2@ z{||he_Wa`g>8gA0#qW7vC%d5MdZE<&&pmOwy6Jgo z!sR&jPwz^f6~uq9j`UxpTEC~|{CC^mbYAahO7Vm80{?R>KkeC}p7O?Q zYry>TKkxg0`MS08_o`&yyvo<|b?R#`Y_5r~dA$Ac_s5nWUhjM!`2Nc7pgm8|OsGw?gz5AEloxkqq+3a8S?<2p(eSa0@5mQtZd*$}hIq5a)Pe(mpFJwRS|Ks44oWCJ; zT$+Xj&s9!X*&hyjUGR9@LBHE?w!OCDvyMnAIGrjtSNh!T#EQ)idR`qXEWglySMT>L z^>gKQ0(|qz@BWT@W0`BaTzXrt@eca>VYnysGj ze2r=U)9i{TPuW%1{r&Ly>-;~jJ|@_t>BS^e@9Jy#UA<+0(`kA4>U|QGdn!{t*T^ym zZ)`e|wB|Uo|0cUzDf8dVIe9JVL{qbrce&k;zUZ7Dzk`pOzH>gGz&dC4{*&KouDX`r zXX7Yz`Ev3{PyVWW3+)zvKDX_S(v+}>!lhHgBTKjXuE^bgxX=3Sp402nwwJHpd*|2f z^Y=f@s;xXL>;JO*=iTf*vp?TfT=PKXRC>i3*6zcbZ4&kt`q@=?@g6)`{OM+}Y^0!U zcTdr|EuSRhcuw!y@pkw7x=KB%`Twlzj4clRHMdEBvTOf?o%jEKn|nRYy7inqzb0?$ zmE)6ZcfSjrrR_WQ({cCDciAt0vzRXvJKvU7Y+m)O+rOp;`&-}Q+Vb?x^&Y$T5AWn9 z&$hMDejaxtvVYszS#Ms+N!wSZ7wJyB!zRx4;H=>>OGQafjydTMO!l9-J-Pn(kLAo? zcQnuMzjh;7uIkQ0hJ!m6y-%$EUiv1kEW`M9aB#$jxU)a^YJa;bziV66>7!eHEzE=x z{r1}$3jf_;xIIrXOmXe5Y-OHyYxY|qe{Oy$vH8Bou5gms^|~mzy7PN;-YUK|{j2cH zW6izyUOzLA9Vu#mo%YVR<>_9g`JW2AcCDCTCFv|F*%#4xeCe8~i)!rrr|qZAc;U46 z_VLWePd>B>mGU_}D|(XjwdR^cr@PqQ?<~1RFKVW;R@hqw-VXP<7arkq#Lrm#bz7xS zX0~R|5{brcMRpG9)5cC7d9LAMFPWRKS%qy;j0$R4V(Z^5Rv>@&y7|AC%IsYd(*l}* zpS`gmwD5x5h51X@rK@~cS#+}ahV1QCa<}bkf9(rb`)7R4!^uoI&F^Ag`lHq9j#H0c zzdmuv=TBERK7C^|f9uz6w-r?*R{}zu8UH!|t7jE71Bih<(dQDO{x2o<#8}&BFi!+|}6#jBK z=C}RF-ClN+^v|h>O~W_Tg-l;~r(1t}pVEv8s&@as<_IJgOsQaUz1TCiL1FRqDPETv zi>H0~;xOZS?`i)p>t=hlK4rSb+5F?e;ksiX5$kx5dpyX!lg4?If%n?1Uj@1rFRmYQ zD183w?d;p-uA9Xk<>a-zIolJ}bB%S;+zWZf|GxE{%w^@VcNo zw@=JouvCm+sA^(RX<>s1&yMhk-gzyy9N!H+zvr;8Y*=h{hh^W!y9%9*|AIX4ZGRIi zX8$cMes=&9#Pw~e7j8pNm-Fdsyx=CuEKqcey2$i*Wf}>V-gw4+}5WPCR zTfX(mv4_kOCmb_a-P+gdb29pz({fy{l+BVD{AzW;rt2Q;MF*Cb2$|@wHhI;0<>>py z3K0iKZ<~ne2RDb#4?evs^ryOA`I-$;n;KWCGOXe?$WC6+nDqIl!c_<9K#|j$p^2fV z!Ykq!u5S-pkhP&((Rq57tN?FR^e62@A7sC(*{w*}q0jbiG4G@F-D!u{6>piUJuN(T z(H};3(^-ajaf!+PiocGVJes=2Z|2S&X{pa9Emw9cvwA)8hlow8S{(Q5XHK0-8M9OK zxND;~2p)L$(sfNnRmbB)<}+@WNhsb^-G2O>?@IT(3sNRk8C+*NeK^X?ratJd#`my# zbpxhb-wrtI^S!A!DPC&EKWFF0q@xFF&q1Udlhq+!h$=i`dZ{_ z^6zQvmf^~3GBwn4VZOam=5F_o6TK@I9(bsBQXy)mliGB5_piYnM^+o8s=Sqby5v*q zif{fOmT^u>w7Pq8b=L+nSdbL6$i17d9pw#!*Q`2u zMB@6Fh>Py_?Nbgd?ccD)S^l)mmyec`=1FJTZYdo(;S!{Ms%Nqt3(uBA+L;PdbyfN7 zmWsVSC3)j$ZBg|512+?IAAC@zBwA`MuxR;?I~;*et=Fq;FtR`YXcF7iJCha*E_3eu z^I_f3A7#w%n8goBiT<(Do0hH`Df*V(&QoJ{yr$=Z{7}QJ<(~tmRIB?xmC*eXmTlv6 zc~!I8vY!cB8YZl!DFV!|#20;vwV611LxbNQhCKojDXy+Q2j?0JRNSs;*LoLZbCLP_ zNAZf+yS`Y&AKl9MN+_~-hn1klyAOHc56XjMb!w7-wHI`s6yjW=%w?l_t0$^L@Y}{9 zWyZv#fw2r;2RQ5Yr5FQf;?1TKvh8Z^FYcKq;C1%xq>B~>OLrPvKf_%YI-jkzNScqeb{^x_?wQ8ZD=s%% zNN7c;t*$biVP02Ru;aytu1SFtY|dTLxj1v~quIOk_fA>bbUN2cU~zUsuBP;nnvy{g}s_1fK9R&YEysf~}8t;!Wf46XKuFKF^~Pt#Z2eEoWl^V1)4#anq>Ohv-d1qs$YBz;GW^;6;B~R^quG6}|4XAjzufbI_r>j%c`-|GKiV** zGKQ0P#-yzq989E|&OR&Z_#yOPW9zIZOH+TIv&>gp>N!>U*Mkyu)$|>nuk`#f73)*} zz0$7W;J19Wyi_jFza}j#EPSN|)1%e-t3A7URh)hZbiGM*W!e&Sc9m$q?{aVJb1Hwz zBDbGq{NYew9q!yKCCg{Zc6}Pd$n^Xy3rDetO-F89W~^eQ8lKx*b@iVUQK__3_r_D|QQr ztaz7H*fm9UN|VzvfuajvCbV*|P{|UP;S~`Ret5vpddt*@r?Tq|J)C%$B!o6-{gY{I zPSq8%adfHPn(9>U7*pV=tNUra@T!bt`Q1O=J^y=E-YG1K`W)_GmI`QlwI_ZRM$xTm)D=cf{pI1xsdK-F0#6U!Iv`MgE(qE4wxq3+Y| zYDNombE7t&Xr1PiV3Q#vX0(GX-_`y=XTzp~y;3eRI?ul;t#7*bs`ONm4#zL&8mp~B zw!8kBd_K1Q{j7z(`-C36_T<&5KdI)>a3U^%@s*7VBYS`+d(X1nJ-5U?=Y;n?>XUU3 zz9e+(eD9>wfuCP^MYtczvpXgcR5zz5xy8)rOnTtnoge(DPz6gYH|WA5-HWC9FQ{W^riyN=*ws#)IK^ zKlKT@2rk^xmmWKzbH?Jg3K^>pN+m?SRN509FYce+NK zC!9^#>K^%Hkz`ZPgcA=0gXVCs_IM`VaE{{0o>UXiSaqo2L|N`HK`Blq!+^sg5_|5* zmE4&S!h7JT5erAv(l_&Y?5@46)cno2J@}vOQ;`Fi0ZbcT_1ro;#o*HgzW7x)xDFU@ zWptIf?J4(Gfawqq>%&3&>Z+GdJ(ZJ;RU|Gow1g7+?vI(tUa{*CC# zIZJuskK9yf6!47h2=wATxpM9nM!hM^kDpJqWMON)>Sz$F(0pcMP^rpSAAeb<4O_mK zZAq&>AbyF*{a4RZhL(=N95MFdM8A;h!X2B$eEhr;IpoYj_9+I0|N130SJwY`g#~9hw`A{__4}=)>NzPN&fih%vXTXIpEuliE6n#wNlLqlWp!I@ zRf&b6)kMo6&YRpntD{rSK3nr~O~69&@7c}nT8H08zZIA(&{MZsc9Ya5XSJ2VE^Swm zgCAumXDrS=v@$sHs^e-F2bBP0!Q8i#US4rkOP?w@?M#`-u@))5SK8?wf#v~y^G%)1S$cn;&X>bh=>@YkGhEoHwMpFiu!`TKptUCX zrFu6SYC?40o?5*i>$30OTG5b{{=KYMV_&MWYAMt)_b`hyrE7{Z$35^-WVq!O6}IA3 zqnL|R^ru^wCp-zBE)x6fRIA>w8i_} ztN6g19b$R`QerjN%6@;_IHiO|Z$@uPed+p1kGp3v{Roy8)VOXZxKlN7;``sMhZkM( znO@`fpz^8lG}g!x0pBN#lei7vxP+|`%Q)`f>V8t-xRFlHuNN1@cbn-~{hb&iugR2o z`0c-6AB3K%aQVwRmdnpC>@jdDRk(8cihKRUrD>L&rd+o6he|#fyxMSXdYZI!p1V)- z)D_2?!uhuZyKYo_%2TRxz1w=KPo-f!cKEU~`+ZkyO_BUVYJBv-DC&yi>Q!`EzF zm9s^2wx3PLz7{EujhBv`ner|0;NdNY9y(+?=PaM~_PF>J|6D0ssqYRVj#X@Xq6&Sl z+e#auMY6NPI7?SB>|asr zAuS=y*=x2U+4i=>tY)TV+Lv!#?F&6RIco~1&Zi2-f-BvDJ9*aI-&WbPO=R(rFg7s` z>BW9!XO^7qShei$nV1KL35)IrJlVZQLO<|$>8;;eYjyfp@-L1FiF(U-FzDdZX$Iz* z>5bJaU8<(Z4Yx}_+zZS(D%r*~X_uqRH7yZ$zH<@jjm~w>Ck`qUz6dpSt9p6uWo-7V z2BD>OO_TGdS=qmQBRSjfLyvUU9r=jxZRzR}%h&Z-W-(n|nHs`Y`jAup)b-Y>1p?-g zOB<|tS@d2Qap$sD@~sFJ@VOgrC1oAAswq)yd4T_PCyt4yyPdUEaQ47(Pk zqBUVhH|@JK<6M?=Oq;dI7O_R!F5ll}%{*)JWeqidif&g{ zrHU?Yc8FMUuZ!WyE#dwj%9`G59`LC+Nws#ZJLdVOZcWhSU!s4uu2py4wB_T(4HfSW zU)C|LI%L^?y5Hm4ru;oY^?<;IBOU(*bUFYFfsTX^jv9e;;>0?))6#X@uuBWVSaXOR5!PmQ%A%w}* z)>`zU_2=RUfrRqo=l?aduIOq`iqueBt0q#tulDn&lFw6DG{4&`SJKXQQ#Xe{LF`#W zU}6G;+$&MR^3!_rPsEnK)VLXB^Fd5w#_|)*?*+=)bLR*bZ9J6yyrKM7zBHTE6-~br zoeV}yIbY}SzvEvedugMdSK0g}nYmK8t~R8puGv!@s?@Sd->pMTH+>85-uT|K68n7% zugCNsdf;~QGJln@%1cp|uxQ&?CDtqEO}V%2!A05dO~j7I@8>^#%_=3!pGe^XP;j`TTSuk$vYwYzTUi7mUQJe^G-+6568Xg-m@=i zbgyzV_gP%~{Oi8T3vs`DTDEEPyDREN?44P zB=d#ye*#3+L`BQ_HeLI6kij~gLqLzCZHqW(?0P}T{oAyza!$Cc)2t+95_%!ies6=k z;Hp_x0I$yufs@D4IKetL(Z3=FA z{Y?G*l!a2SgRAO1{625r{Q341n?=u(>*j52`9Ei2KIbn*+q3O|_T2oLoHt3yRe8aT zzm=u4@~s)ojN-TD|9q5mC1&flo!l2&>btkU(qGVIlXqbnL+jz-!yD@QU!Gf?l+){E zGfQv9jQ2kinZ9p7zTGxEQ?tSM(36~~{SGA)<2xr;#kTY=V3;YM?6KmR6nEvChlaVY z%A|L7^tiDfcS^ne#6;Qe;BnVm&wm}xE4?~{h4J2z8|AAv@~#)`6I{g`y8TeeSEh}I zJ-m0yZm_SpoToBX($84_t4O}BTkT>w*{2>M{O;ilUn|k-;sWm7%p1U|9H|V*o6VK9C2{{A*YBk04PnZ^cK6A&l zy=9&ptA)>z5Ru0DZI)Y{e9eeVenMhv^BIee$Mlhhx6S;>t}_S)Mthirm`4x&ew|H0Kyx$0%!<@xhE zpA{KeZOoaS?I+=XQO~*Du2gKU>d({Ddo~^IT_Nq~!|IT5GdMYY{mSm0=ffV)^|qMZ z+jmIXW4$NeG)8unb&-4PlPgx*+iaS_{ZgP)fImM~q+?(dkq)%u14Lr4|F<(il8GUOX3 zT)(#G@&)}V7nZ1U+lSf=GBD*7iZSTUtGK7o(^}gocT1ru&1+2@2}5m`@1IN!F#5X zuXjw+x_ta2SS^}+el%olxw-WNPj2}-2BE~a)9U6gGLS!}vFz677~6Gz2fj?79%=Q> z|M8~Nl2@-AS8?+!nX|`h?+S-JM_$X!A3ACw`)+>yAkSuXHha# z*kfLHS9?}YeENDGlm7HctxLX`vfZ7_9;^M&aiN-4{pFI+tYRK2imo0n+BV&9v&;W~ zD`WLZ{_ofGIDbF9ct`zJszbtO<@?HtX47NYHaIX@D{SC1c@Q-J{g!OLmCI}9vp5>) zmHvGf%T)f@Xw})LU0HL=7Q{|i_v2GlmQ90^M{9|Z&Bk8$_Qq31_x7w8YHC`UHD$x+ zy^N~+?=}=ghbZ-G?cINWO|l8=R!03xTSWqz9YUp9XL&4(I|ejwcf0) zS2?f5n)I!>_^y7^iQC`Rq;4c$e$sZa$`%ZPDow)L*ovA&&uzvgY-%=~B3 z4`WWIz5P^dYAkysXuIjFvRyyzcFsC18>4$^!O=aw5&L)}=FQI2IA)kBFQWKA-0Q?$ zt3SufI~IO$`SV(GmeH+DmPk|6rP4;{u7phEnO$C7v!iCWWz+w{o9|ziR_S?^|8-=N z_BQih=yN4zZa(iczWa*l8#LyfvrcIZAmw0%ueY`;VV9oL=96HL=mfu}` zxw&h7$zuGM#gKJD zmXD|L;+wwa5Lf4{(%DO8KNjEGwKFWbRY7fGOuNF%l_7%Ju?On}BK9Y0$@p*Qc((cD z=}cz!Q@e@__k8dSeJj6k@=tYxvUhn`->J1o%}=RYV0zWcA-?=_#oeji7lQwuf4lbL zsyC}e&rRJ?uzE&b+|@GM03Y3jZx*sY6hBvRWyY8Gjx+i1^Z$1DKeMsC(W3Xap2vAc zWf|`}eFg>wwj^(N7lx?}oeY{jpI6r~FfecyctjR6FmMZlFeAgPIT8#E4D2PIzOL+# zcsO|Exi)v6R%T#ekSuYHC~?lu%}vcKVQ?-=O)N=GQ7F$W$xv|j^bH7aUyhh(JI9= zWmm_q#1=W_AB*O{_~P=F#j{XsVb-#xS%ywr3=CSV`n_o{S`rx;7#KWV{an^LB{Ts5 DtTu>; literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/ebwizardry/textures/gui/potion_icon_mind_trick.png b/src/main/resources/assets/ebwizardry/textures/gui/potion_icon_mind_trick.png new file mode 100644 index 0000000000000000000000000000000000000000..99d59d3a77899385a40aa4441bdf9bb8263a90be GIT binary patch literal 9578 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 XJ)4{}k6JS@Ffe$!`njxgN@xNA?P=Ux literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/ebwizardry/textures/gui/potion_icon_muffle.png b/src/main/resources/assets/ebwizardry/textures/gui/potion_icon_muffle.png new file mode 100644 index 0000000000000000000000000000000000000000..40ae2462ac7bcdb5330ad1ad8a1a36e56cc1be51 GIT binary patch literal 9869 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 IbxsLQ07w!fYXATM literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/ebwizardry/textures/gui/potion_icon_paralysis.png b/src/main/resources/assets/ebwizardry/textures/gui/potion_icon_paralysis.png new file mode 100644 index 0000000000000000000000000000000000000000..8225301ac8ee3d9bd34f761ca3ffe41a7510fc23 GIT binary patch literal 11924 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 literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/ebwizardry/textures/gui/potion_icon_sixth_sense.png b/src/main/resources/assets/ebwizardry/textures/gui/potion_icon_sixth_sense.png new file mode 100644 index 0000000000000000000000000000000000000000..c8bb581060a881d3acb26a2a4122fd5c16624a31 GIT binary patch literal 14563 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

    UqRi78+POO4Fq?e!(=eLqP}XoZaqH#73tw3= z^?M%Ss(MuTqs(a^!$HNxW=G0n*YZohcp_KumTgnBlFgZBHkOxK6IQWJI&Qz(HaM%g zcvrIlU+>#ZTPt?+W`$2N{AjRgn!%MNVe9`NZ9H^6P=aHX)=tx?uU8fCa}@}PJY<_F zRq(Oq&9+(ccHg2;%E(DA*7^BGxbgV8{gV#QwX9Y>eooWh^Fevihb=gtJ05J|M_e5bxZ5&EqXHfN4P|J!cQ~GcL&FW{G^scbjIIBok z{wKqZJC*;JCY^1n?NH!17XRYdJHu&RK&WCsC)@Sb=Lh$$`o3_kP4?+G$D-43n=0}| zU*R`REV%G^MUKw9Evwj;JmYMtG|gXCTd?}SsBUP^dNEu6n-wj_3*M;sP5XBxG<40p zG$rp4*7EzCloN`LHI`<|n}!^ERKY9pI(Dh;vw$mQd_ zVy^u6b5@;Mz+|zhrBr;*Hv0#eoO4`eZo1^~E{&0cW9sMcSs7W&{}Q-dVkdj=j{n9e*?<-ExB{2?A6m-!Jh;DB-O4U<-=s-0>*Bv%>$;uJ z!z9t|61DBa7cb3v?*hZEH=T{yS7yoASiN$Xv3iP9C`Ke%{`VGhjj$pj(%B`&ZKhR@2j_EJO^V^ z(&Y!$%GOKcFk$&?pQl$!xA`lJZ=8PW(T&V+jQp){t=2Xi zPjeOZzp?s!6wAJ=S1vQR6#JUrX}Q~DzWZBE&5P&fEj;rcFf=({63)olJ@GE7Y>J%pZ*vV82{ndA?BDm zJydFf$Sld65Zx3as;oZkN<%<1hP36AowjO}|Sz542wb@bZI3m(4L z8*3dCy!j@qcPeyne$2^R=vQH;!*;7>-K|%qG9liQHrh{k@-9^cZceDst}DOxR916` zVoTG9ojd-YUGF*5MR|Lz?TRvk73m?l->k1Z(fKEl_u_#l;gWs9z2_n%{DyR;^oXnR~e zpXH#pWz$yH4As!Bv(q>OjxJ*HYgi}Ydg(>Dule#LE|raas!Jg@tQ;5W?+sxEsiPtOY}DY(EL zylyq$gv+-d?A=N_ks3## zPEmRpWy4S?+nLxYWyfkC?>?!{vTL&Azo%Mt#VYal&E@5PELQ$mpnTo>&pW4md-Cn< zKb);}xDXm$)Dq;Cx19OX^2_Vz|2wGBtLNMMUiC-EZxaoLZ&8kHsi(heT$pp+y6%J*lY@fEmt`5&-qHpkr2!9SE&jFjhULshQNCY1 zdJ7bSI5v7DJ$&*kdfqd$%Urki>}Ou_m8WcO*pAs(?qo#-)>#Vp9iA?naK&`~l}3}& zR>x!QjJEu*R_jOC_KQ2k-(kOXZgxA*YE%2)-fhYDeqWv*Qn+C9cv9j6wmtL8bCc_@ z}%t<^`*UjN(?z?>%|H}BN%d$U(@yfyQI z!`{c?`_(Ubp1otaT>fDF+MgY|`K4P@xj(F$8sYizr>*7kn`;((8jD@I-X0wpy&yY7 z?Dqwm(=#i=O76YZm?dR(%HhEymhMH}wlf3`o~_*U_-(e@s$H3yN9_wdCqz7P6xkE2 zUUHc8(X?gLxJ_@cY@aI_9NuW0btB}}yBp_kPgG%C7?N^w zR$hQu)k&9Gx28-v7x{Mn%+2dNHwOpa&)<^67<*MAf6be6RjX6x5q|9d`!9bATiL(j znc>vD^duv-8Ad(L0ZsdO!GdDF-R5vEBG5#UC5=HTC%F`jdSPvd-348(tC$>MaO5~idW=sDw_JvcqpM-7q zJbnM!sad}|!%c)`XHR<}J=bsVDTZ?{Z~b3Bo1CjQE5X_IzR9emM?8&mek{50F|6iS ziK#~GI%lCYYt53%brSxzufnts{k?qGV&!i0NcR(}5*G{Y<%K20tiC^6aGz((F5O4c zU-w78xV+TLo|~6#;&oN+zbi~Ke%QQ?&YbaPM^SoObezjHeg+t<}{sdhw;F zGPv}-f2Ul}712F`NcugLv7(%;meo1?O?Pj%@6td^0(-eeb&jzQmlEeG)w~j zZb)6lShMz3iI%UzJkBW9sfHJEr`~ zp7g%rP2^Obqt7169#oz7wqQo^#1KDDIku#w+@`!!MP^f6XFbvd4rCrfXYl9K0k{Zy(s}DDWUvAnNC;V{;!&TNbKl zs=nXmnLBeU+n)Vj{8v;vEf<^P*Kt|I;QGov)Bj9t^;vOa=8^2ILZ?|$%&uDV1e~7p zJTNrvyq7Lki=iUWhaE>-5tnmJ$KgIt@kSkICCe}NLrwc)*?dQyxl|2<>p zSai+ICo1>eV?Cw>yYx*Bl2si`I%F=)^4}*bE&2A)`gwi5Vt(bTW>wypwLO_xa2{LN zI+mt3!Fvl;LbrE{%O0rOv24FA^Fx=M^mEVngB~!N_GIph`+D2e^zNS(?T@yk-`Uo4 zx$(or&dK@e=bq*t-SX|5!klXjTkl_ESekh6m_%sr`BO?VuTwr8J!xO`Z^am0Vsk5EoC7Zm?Nv&Yevz@Sr zN$m{Z7R6WZ?@jwSW!1WW&r7Tq-@H-&VB?|*DZ(E$k~Yt}W}#W<*lmATApiE!oO~XE ze+wtMopqS6b@TPh58MHz>n*kB3M^vNjQDD)shBa%Ih`>hX3u_Jzdi%g+{ce^KWxeU z5s_PKJ%?+CRDQGY8Q0U5tlzr4dricfICa9pcC)L^5#fIHuj;?I^wF0uo+(M{pSKeI z9;x*5QOt**h85*abMh2xPX#;Ny5YHFp_!)a`Wr!&(PeoSZLRa(iB1XG$;%X+9cygH z{z&%8!h(yp=P2a9nC!LstJa~ljUjiqTkN#Yyec|#kNxUYt!fvK31`05IoOxEbzQjf zY}>NkQ|zmrpWEj@_w9`CKD7&mS~U%(0*_Q=g*RO_c@*ou^U4x~#vMn>(v>)5^yZha z+GkIWVwbyUvCc5}^}gFDTMO0)#y);?(N^fOTt}gm(z{Lx-YqPdH_BYPjw$YYdw=_d zwQ|$?eqZ3R)6+E1-_y4Hp5A@?ugQ-dnRu|2GqXKAoE7b3>~r$} zj49^--%N>5*Ktlgy!6z45&J;nBR)U2E;yLQ!C`VtPJsOtL+IT2Oq0T(`5PJLFS|UA zqfx77N`v0KZ)*>3V|@Pn3j5ZRssArV-+%OS?exOwCtI(G)kQ5nFY`aw`Z`NRxWbLU zwm(%g*6KEue#+@*vtD>2Hul-2_?kw~GR?+?N(xO43s!J&K6>ecv~K=KkLN zzvi2BpPe>(pAlWDe*4#b_Ve$qzE5dcm;cY=rdr7FHaVS~K38D%?qKirUsH^2_C7zk$2a)tO_#VXrDiox|Kg(-TWbWYgLVvL+ve(7Y$%5Q7bEVsV6%a*Xg z<#ENrxqOXE4cnx6uYP#FY2CiZ-U_iljNUJ+c_r2V=-*GBGdmSGUe;gLSMLzG^0K`D z^$e$KQy+KxPj9>%b}umPIzEkWW`WgO&8~A%vH=EDHpf_9SI+qoF!v^hiLdG5yTK~^ z{>&rUul~`?tKSq? z{7LSfr4(}I+M0+RiIro+qLAF1!-I!tQnS`y9R}o*N&YTy`Ni^I4~y z;I9JIt3@ItP`Ak!7$x1 z*Q{>JWxj6qE$Y1&zQ0^q{l-FS`r_78<}*^>sk$od37Qu$cYVPZkx6{pd1mQ2YxjKO zIAy+%y}I>H-@+F&!V4D{&ye4)8F_f(iURw?6D>0;cdebo*?Ij;Sf|tHs-I_SR{1l3 zt8%mJzb%ljb7QKNK!B@ZPtR%R)OmGk@6#Il-@B_2WKbE#D9bR^(Eb^UoQRzomQ0V0&c72u~ga6L?wDOee z6-_g?+&#(1X1V)jl`1aVpM2~iPZNLZz3`hN&+Ar1*Zi7!yJ7#z#iD23>@s$FO^JJJ zTlv@O;+x-%X+ONW3mN__%=%#YbJ5S(E#jANs%_kw9<%=BgD_u%SF7%D^d)yhUS0Xw zq*Ho|Pk`bdAF0)|y_fT~R2TG}lNS86Oa6RAqQCWqm<_gxH6fi-RA1ikYyG%%^}4|1 z%br#i0n?TWzuonEMaiwHa}|p|@%Ae%Uy!^&j&XysoTGWS-^-a=O^>F(`ze3dCYrtE zRgSz!=7zT}H@tdgCLPOsyJzjx{Ql3!HS63jEbTbleMao-v;%LsKCE64 zGdYYcO6&ZFezt8ZPP*2p{<~?nU*V5*LpGNy!#+-@@;d+Lg>378lzH!q6=c@`C1+W} zr+6vg)63h(*7x)a2jrd3s$UzDzCa*t?qU6`s@DtR+%=VWe@}bK@hs_^K}@CRKc>qZ zR;o|V?9*DW^HB6T@0$QoZQt7;Q!@TDUv}TWeD%HPvoEWbTU|N!^v>gk4|*?cc{yfV zEoVHLG1X5j=I_fj``){M<^9SdlHup_zO#~b@1CsP=YBY5J&##%*|A@J|8u6RUqaSL zU9c4Qm@L(@bzk2iNfv=R@<)3jZ{mb<>+{>@|@3iyj zufF)hT_&@>wd?OuXLgJ}W>*({xUtV7a&p1;@+qa<7RNsw)8cr~JM;C9Nzdo}EO(pv zsy5?n_u)(DdG1!mFj;PO^Zoj7pE~=?Lf`8<()VnQ{PEV#{op)CzOAe7?!7I~JpH4s zydS$AV*P5B_HT5q#7)`_FGpU8~TyjMoJg1g2k+dd{*z z)Awvg`6-doggAYJ2@!K0iUl|~)$ZG|hV9k6{jysx@$j);XPNlTd3kW?#wpLw@F(V0 zusc0B5n3neqZ_y6j#KFai`cg-``5n;R%|hU)DnF6PEJ=)a`}^``#sZ58-%@RLN<;89(}ucNNlRaBxYg>LX8-O)pSAlE$@wNv8d~m~ds0aDRLJq_u6t|wSN|58vup0HAD^R2OJ=?htw{D)ygYx0 zRDs>=dVdG&ip7g8_;zV4w?A)Lz3N777K_BbQ>83IH_lzEeEvRCF4jHy#g=O|uaC1H znI<@9r>f{f&h%YAbjv$gn_2A^_06kIe}oKYm8NYFpy z%#H0!f*$F%xo+P#w|d9k%Qeg<+Dxs{J^Qj>wHbKtWnbKH{7C8RhksL!mR|a(kaR(D zzwgSrX7Am-s{846Pe)DEAIWL#KdneB~ z<9F%4IX`XkK3mF)-<->N*8QVJ%Ca@B@LisD88RVyD2Ax5XdN6+9{^HOW+slMZ}*e3sl>dG!r!OiJz| z?;cq;e)Y47ebQ5QZ)VGabNfT>?i>EESv`Mp=x(FsR%%;6pRn@NVQ$-Ab@x2u!V@Vq z(Mx}BJM;eo!&CX`;d3A5eru86>#SQ}%}^?~@#L-B!m4rhE7s^|~^r702klV%OPq=hK7y$lJ%C^=6*`wzK-o9Iv2f-;b;7D@$0>X6XUmFm46>V= zD*`>fR@{)>BJ))yK>meOeaRv+MP4v zgPZC$^W^zQ8vTWvVxD@+-*c`Ax_0s5tHR*&wj+y^)~=0v?%ZXhwe$YGinJTwEnmGC zJ8H_^^rN#)WHDp$U*Tu!<~3K0p5Cx4T(;nxvFJ6|9eL|l?0p<;+ft?V(@nPL^%I>1 z3y-e8wD_=Ys9>qpDR%$WEUj;sn@^kH&Q`$@IM-;umjB9`uQM%9FjZet6kpE!V1e7- z{|>=+{vwg`-&cAI8~Q~)Z!uMoJ-#L6t;d84r5WFEyf)3>zxmTE_RXnHRt=f|%1-^R zKDIkpa@oh-|5kQio!t5PV6?#P#=rj<{x3f4W-6TT-xi(j`o=EHR{fmIo*0i;RYj#K z%j>1Q&L)31I9JPmZNIHn=$hX=_r2yW_v1KbJ8zy#d6m#+H+B(kv%lTKobzv7-H|PD z_NTb|uBd|t-~2E;cp}48DE&06i0`LEb$Ks8zuxUaeape+qY}^P2pXX4Kf) zr@1a^@AlTp`ndR=lNT*qUEwXYbjJPskAFXw^f%OLr*rkJecpb0wtf8n{rmU)%%Apu z`{~*L(|+2=$kiKMP|nQxmX&nH(LCbpt>xDv(zSBKb?0RB<#^YwYw0*4zpRe4=HBtV zIYExk{xx&0d)T%iH}v$WpWj7Fa`rE47SRfkEwXy_JD=}`%Khxkr7z#ySYXVtm}B>| ztNHD_lyXaho^co@)XWO>nhlBWx^F0yxcHy;FiRsH$JPtOITeV5SWwJuX$z{TE zE0?CI9hhZc^+3IM&E+Lque7%p{JLJ#a`@^WdDeS@ecyVvR5CCyuqAoByD&^;=w#6J z`MkP@fq{Xuz$3Dlfq`2Xgc%uT&5>YWU|=ut^mS!_#KXZO$F*wGuOtQr2FViFh!W@g z+}zZ>5(ej@)Wnk16ovB4k_-iRPv3y>Mm}){2FBflluyEE(4%l<{WDsSfK67iOwq}1BVKfThreD0Urt5(;4T}Tky_`CG_ zIc|A|_Vg#QAI@H?PibfH>9%X%GFH_Cp`=e&bjy=Dt(r#++ zj=cL<*L>aG6Mr}LZ{1rt^Yf0$ubb2Dx9!vYApTI5snyDHTM+{T1B0ilpUXO@geCw* CZxp!z literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/ebwizardry/textures/gui/potion_icon_slow_time.png b/src/main/resources/assets/ebwizardry/textures/gui/potion_icon_slow_time.png new file mode 100644 index 0000000000000000000000000000000000000000..a91a7fd57f9a53f88abc42cf6b930682b4c48e0a GIT binary patch literal 10784 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

    pX7hS$jBo>eU$&eoii% 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 literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/ebwizardry/textures/gui/potion_icon_static_aura.png b/src/main/resources/assets/ebwizardry/textures/gui/potion_icon_static_aura.png new file mode 100644 index 0000000000000000000000000000000000000000..8549cb1318096d95f806ec1b90a3e706c5199062 GIT binary patch literal 11658 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 LS3j3^P6^X_+~x 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 ZxV|i3^YR314+aJX22WQ%mvv4FO#p~#to;B0 literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/ebwizardry/textures/gui/potion_icon_ward.png b/src/main/resources/assets/ebwizardry/textures/gui/potion_icon_ward.png new file mode 100644 index 0000000000000000000000000000000000000000..ebcf28447fc648872502bc821381a63a860c1a2f GIT binary patch literal 8631 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%0DIeEoa6}C!X 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 WU`NIu@7oLv3=E#GelF{r5}E)6c_CB) literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/ebwizardry/textures/gui/spell_book_advanced.png b/src/main/resources/assets/ebwizardry/textures/gui/spell_book_advanced.png index 47d76cf696d9fe779110bf0fb085caf2682459b8..72b51efd3f6c6b001ba0a9ca5af6aaed55721f59 100644 GIT binary patch delta 11181 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 delta 4429 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 diff --git a/src/main/resources/assets/ebwizardry/textures/gui/spell_book_apprentice.png b/src/main/resources/assets/ebwizardry/textures/gui/spell_book_apprentice.png index e1d14aaa6fc7b5eb3386cf3294cb3ee030d5ec77..7c1cab34985b412a5f59642aea22bd7aec0ed1a9 100644 GIT binary patch literal 11927 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 N#M9N!Wt~$(69A-1`MCf9 delta 5138 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 UtA#K@3Na8etqY> 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 F2>?Fra&G_t delta 5335 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 literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/ebwizardry/textures/gui/spell_hud/_index.json b/src/main/resources/assets/ebwizardry/textures/gui/spell_hud/_index.json index 37fd0f8c..a97d369c 100644 --- a/src/main/resources/assets/ebwizardry/textures/gui/spell_hud/_index.json +++ b/src/main/resources/assets/ebwizardry/textures/gui/spell_hud/_index.json @@ -62,5 +62,17 @@ "compass": { "texture": "ebwizardry:gui/spell_hud/compass", "metadata": "ebwizardry:gui/spell_hud/compass" + }, + "mahogany": { + "texture": "ebwizardry:gui/spell_hud/mahogany", + "metadata": "ebwizardry:gui/spell_hud/mahogany" + }, + "oceanic": { + "texture": "ebwizardry:gui/spell_hud/oceanic", + "metadata": "ebwizardry:gui/spell_hud/oceanic" + }, + "planks": { + "texture": "ebwizardry:gui/spell_hud/planks", + "metadata": "ebwizardry:gui/spell_hud/planks" } } \ No newline at end of file diff --git a/src/main/resources/assets/ebwizardry/textures/gui/spell_hud/mahogany.json b/src/main/resources/assets/ebwizardry/textures/gui/spell_hud/mahogany.json new file mode 100644 index 00000000..c01b3f91 --- /dev/null +++ b/src/main/resources/assets/ebwizardry/textures/gui/spell_hud/mahogany.json @@ -0,0 +1,33 @@ +{ + "name": "Mahogany", + "description": "A touch of sophistication.", + "width": 126, + "height": 39, + "mirror": { + "x": true, + "y": true + }, + "spell_icon_inset": { + "x": 2, + "y": 2 + }, + "text_inset": { + "x": 43, + "y": 20 + }, + "spell_cascade_offset": { + "x": 1, + "y": 8 + }, + "cooldown_bar": { + "x": 43, + "y": 2, + "length": 79, + "height": 3, + "mirror": { + "x": false, + "y": true + }, + "show_when_full": true + } +} \ No newline at end of file diff --git a/src/main/resources/assets/ebwizardry/textures/gui/spell_hud/mahogany.png b/src/main/resources/assets/ebwizardry/textures/gui/spell_hud/mahogany.png new file mode 100644 index 0000000000000000000000000000000000000000..fd68c7d3078f47e99faa65b8601e5b794e20b3a1 GIT binary patch literal 20766 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 literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/ebwizardry/textures/gui/spell_hud/planks.json b/src/main/resources/assets/ebwizardry/textures/gui/spell_hud/planks.json new file mode 100644 index 00000000..f5bf90f0 --- /dev/null +++ b/src/main/resources/assets/ebwizardry/textures/gui/spell_hud/planks.json @@ -0,0 +1,33 @@ +{ + "name": "Planks", + "description": "'Look, it doesn't have to look pretty, it just has to work, okay?'", + "width": 128, + "height": 43, + "mirror": { + "x": true, + "y": true + }, + "spell_icon_inset": { + "x": 2, + "y": 2 + }, + "text_inset": { + "x": 42, + "y": 20 + }, + "spell_cascade_offset": { + "x": 0, + "y": 8 + }, + "cooldown_bar": { + "x": 43, + "y": 2, + "length": 75, + "height": 4, + "mirror": { + "x": true, + "y": true + }, + "show_when_full": true + } +} \ No newline at end of file diff --git a/src/main/resources/assets/ebwizardry/textures/gui/spell_hud/planks.png b/src/main/resources/assets/ebwizardry/textures/gui/spell_hud/planks.png new file mode 100644 index 0000000000000000000000000000000000000000..f29e78a0011bcfc605612a443239218546f1b3d8 GIT binary patch literal 22007 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 literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/ebwizardry/textures/gui/spellbook.png b/src/main/resources/assets/ebwizardry/textures/gui/spellbook.png deleted file mode 100644 index ccb7aef4cde39ce0dd3f7170661dcabd130afbc8..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 20096 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⪌jI+57wUSGVBHAue0y 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

    J3P3$A`Rq2*B0qN=Uh{Jp;|nbSSa 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 literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/ebwizardry/textures/gui/transportation_marker.png b/src/main/resources/assets/ebwizardry/textures/gui/transportation_marker.png new file mode 100644 index 0000000000000000000000000000000000000000..9ffa80c5ea537e92379cc9275e19c42f15b57233 GIT binary patch literal 5708 zcmeAS@N?(olHy`uVBq!ia0y~yU{C;I4mJh`hT^KKFANL+XCOonJr4 z{Jp-+a+~-6{zY6Wt}C49_)Rk6n6dxknm@Bvtb5-5?{oJzpC_k^o1g!A?RM{;`Hp#= zzSU}<-t8>jVgJ24GJKWAgKW;nlKbbs@0b2z`b)T`OjB((bA9vfBEPARAFZ44@%EI3 zcK6>^-hFZX{4>)liIb!6{p#NDDOPpn`&ILM#`UuIU$1$3Iy zuI;+t?rfWPn>TvL$1O)E$WA-C=F^k^pN;B`GV(=5`1JDQ6Q>8KCATW2uidG0xTE84 zfAHhN53j$z?tk>EGr=ZLPiI4Htg*m9xwq;&|8QBX}pUNWV+7OY@;ch>agyoGwZew#RWC@k`CYtqs3 zZ4z}-sV~xa63}heCXw7_IV~dD+ivBdpi`b5w>F(uJU*xBoa*&EJ|9)5LE61#VYiDp=rL*|u?f0sar(AY1W=zn1zTLNO`!wxy z+bpAMWEOsDIkI=+Lp5J9ypN zw`yL~m9t8F6Lan8md@Gclf~Q_-&c4n%%AUm|6+UL$!)X3H!FV9-`-tsHRG!H)3fn8 z=4D6s1mCr;zPm1_a>-Ar{PQoqTfJ}G^Lu*g_k^?gyH3B|x%$Yt&vkQ_1%79|dH3iM zuk$`HuUu!B7XP}fsyFSYBzyLY-Csn@S9cuW<$mYD_pH)qW}Izz3m@Is8*{^0w%<(A z`SlTwC!gg`-P>ryEWTvl!Cw!je-639SKF8OSi{&|cUx49+lSxcqJ@KACkx{r=JN#{wX7uzak7PAoihque*t@uqQQ}#5u$A@o z^;RdZcfWczeQ8mf>zl~OhJ{NGT{^JfW!XL{vB!$Le;FjZTqrNSdFqu}9LUUlu))==3`1v=RqX8ikg36Gxv(~g@Jt=cQM-CJ3iseZ=+)Qjo&8Ao}51^KEXz=%I=4(E@R;t zBe(D2&nH=5&n;BZb=@<)aA%I2W?xHxbnDZvXBqYghucidZ2t9D^Y-;GyviqMC2!kj zCb+#!+Rk}hNx%om;Ix)4eq7J@C~Vo8tlaA&R~odS)LZ{tmWQ3wR#~6JQ@kb5|2fQg zGj8e39ilgH{M9RUT;Dxm^5eqLP*y#r6qUa@QCytm%j(({7JZq>Q8O#sm#e2lbLx>@ z5#Dv-2XddW-qVtD`{wVh-^v_%e&ZhYo38{nnQPRt1qdf4G^uasbhbMf@!82Wec_X8 z+qxxeE5n{81?on}doZ5a<>3=rGS_xO$b%P-cMr3rne2ZirW4oltyE)@Lh{91=MDEB z{QQnTseIvf5B8d~X44ricUgtp7yYIo@Wbt^yi>oEOvG}o=cn19KR>v*_{MX+%Ej@s zEVs+COgJ@PpZ)7i_LP1xhEIPPrn^XPU;F=9^RvQ-C+pH)%-sCgP9CU;kQQb6c=?S^I})vY!x3v=eNt2_0QJp*em93I>5AG zt-yrE%CQX*%9qYOSTJkCp6yrat#lF|ScbO88##WEKfU&Kj!u_)KMCgQM7c8AgWt|KQHT1+m!C}pZpUZi$tj$_iA@bv+T zn^%9x<-@i z#T2`OLvoko9wa&S+x+p1V&%Ra=3vMD;v~C!;8tVS`zY30tZks;kY{+fvJu#g_h@+;{qZT{!c(A{Xh**xzC4+v{Fh{Msa_uh=7?t6oZ^_ZJ8O=BQmBg+!)#1*Ok?AA*FligA*IK85ybjubSk&WvP*kSRN(?^26d}N%u+~>5PX^WlkI!aE*>7u7Z_Oz=j z7HdgK7@V0lc_*WxYcs<%LHR{*CpWF`Q&CqbsSvpM<-UT_nUAi;UsYShY;9gINj)B~ z@bBV}eY@Reg>UX~@BV(kWy9(zT*jB*?09PBShrdAe*KH0O&!;RGLmQQOf3E7ApPZC z`~9q^b{pAf zzw7#%rFvRr+^WAFmw0xtUV6%Qs&i^dm4mFTaG}=~(Qg6fUMkMhmrvYvHt4y;o05z2 zAEn=Hio5^3S>n>6B^MZ+Zy#y%`jvE>#bf!ef0qMSY%LPLaC_ZFd!0F6`(J#!aY$F? z&cm2X#}jqq4d*bZ|B{HA!u`+Cw!4?*EbkhX`X-seX1mi)U*>ExUH$ds7Pp@&0Si6` zc4}1mDbL&Jkul9yVwH^=%WezPIft6|=*>FRuf)Q?&*)@*`lOd{%V)Zrnc%G>yLkH& zgU)!are3+9*QVA6l(e4+Z#l6nF?7n&(2ZX;SgK@pRsLvHG@slWcAz1Aou!wqhx^1% z^NC*{)vjUNZ6kB$QHEwnbQj+wma2w}=eFLysg{4T;I!)^T}IyW(u(?G?iU*2?L2uK zk3=WxuMBk9e{6!rTi4%xQM|GRKIb^qGFLO~>TKFrwjv|M{@$0rm&ETq(rcQYl%&SD zE_%lE?;Kpq8ZR!=WiJ=ob7N_g@H~V5cdOoIzSrqnti9~Hb?ir*Si@NbEhQpT;+_iH zYrWW_pQh4Z&^L*#<*2#C?MA8k4O7)_tg@UJzGQybmqx84{F#l}M;^(kp71zi!gH$8 zjyIfNe6q}@t%eo5j(5h1>-GNp@K%e}r$Y15bS}4Z0#3~m`;J5}c_et);_=jJk%zpD zcAVUj8_2VC)k!OdYN=~o>=)U#nmV&vm;H+QlT#}5W5!pHgbh|Jl9m=nbXdt1`p9*> zu{pi>eS+N6m+P+9zdfV(c3+Tptj~eFZ}n3a>`<0zzw+2*$|oru#~@p#3yPWEO;Jw! zWOp^_yt%n9*>k<-tG%(i);oz8&Q7Y^+}wF9XLWYMge2S9rMI;0-g>GZRxuAK@I1S` zMKULycdxPI<#lWk3uTt6viIw3sorC>^xw8C@v<*2tf|t!e)-0c3AZm_pK<<}RH^5T z&WW#YdvCa4EyMdSsOZuWq0D^M=Tr8-lCsF$@^73E~P_Osi)7JS&dRK4i! zPqyQS*FKx}>e~eE2O0f*8k6*nn>o!DD!!cGw9%m~?D_qd56?YV?DIk;vyWMBnR%+t z4!-h0hEB2X?9W!QJ3dKW$RYB~e(q0^PKEkF<+9A?FBkVun!Dk|bt$>cb&m}f9-4mq zjQ{k%laD{T+_h*)N51WI;i+Al`vd&lSG~McafFi2ma>=j(t_D zbPzWDbu-`*1M|J#K~+cW{q7e zJ?v%O93Xe`?jz+3+YB#XIQDBg$In}TA0CRIwBY(`UExT!`+v4(=T8y8J6$T$AfR{6 zh7S{;H!NCQaN=Oiw?!LQ%nvHL^`A?Jcb{D?`)YgDNd<9%)y4Y?g(TJ;FUe=Bo9bjJ zvFuz><25XCG$;pO6ZYuC;n`f{Oqwi@nYY5ohGX!)^NqAo44^D-G2E-U=&L zWgnj^uZ7RH9Xe{5;q2Bsv-Q@)rn^P8BD3YH9iHv`eOW46_2K5`w0F8DRf2D-vV|P? zv9b9XKluFR)W6c@zK6P|9o|xRf0|R(U5V|JUtA4x>wN#B>g2B#$1P2+FSl{Jl%_aI z?8jlfn4omy$Ho|LkiOCyK0J?D~pDK0=R`9G1_sFz z*N775{M_8syb=cIqSVBa)D(sC%#sWRcTeAd@J2py1_qY>o-U3d5r^MSug?h%6*+GI ze(%;;_vdQP6FQrU-IP`sI2$Bvic&cu-^tW@MdZ|lt20(~s;RL}kZ+n+|ASfd|Em)l zQiJ|YRGl$#!4*E<#s+CM1!aZA;D7?>1*w~J-pBsWxW9S*``p)G%hg@qB7=S?>o|4(d2bqY zWO;wA+|1B>77V7WWpT4=80Oc#*1t7hwP8--nX5xz({}ut?SYHm&mC$z)-qjf{^pp68z%7VPJVs0=GYtyDP}hxa<6nKgSm&hQ|dm9=OB%o%uqQ;)(A5Ei;~-xfyc!>}+O+ zo?vaA>_{eyZU1bFjvbuX`~1`8Y>Sf0O~F?8|4ZswZ`ysme?^R;*!N2;2QKzL4+w5L zx4kaWVW(XcL$TS_4==7|X=!WcI(|O0WG=&*x^gaKyA?@yT8x~(hlFlETKDc))T?b_ z&Qnj#@iko>?pPsF@btab^j?>PA@Td{@?&f`N}D%uNb>WNAj4J(-im* zw)Xkl|L37_MEins^=x*Nc&AdQWLf(+w)5*i3R!?}b=O32_AFs#P8oWL) zvVEpJLA0~&mqp`>`Aa{~wYX!{xT5}s!<>-MI&(dyEHdoovE?beTJ~_;zR;8)t$&e$ z3}rGgX-6C8NVhi0F`F!0zISd<^J}|m0%2eJk)#vy^--C+NjWmKxJm2a(|Ci5;b$xOs<_z5ex*$G?cQZ8j+!dZt$XXjV013$$t3Om zvzt;>IL#-SB+N3-+Z261rI3+9=4K7s@<(P&S?VktN*7H8vp88DuU;zAs~3&@wxG*y zg2PiO?##!h_Xu4vjx>7lDCoZHtL!lBG%&)9V=|7zhd2D zjaobN48NuC>iiyMC>sm$+sT7P$G$&Rv|%NatfeKlo~5^H5oZ!16a zc6yS-o7v@l$8%OW#oLs?KR>FCu;+nr=_o-$9150^-Z;}f3|4s z-p_yIo7nZcm+mt!?cSD-Q{|F4lg2Z+X?ivj$8-ZTEH`V7OF0InFh4hGc>UGoP`^ zM#V);g03#Jlsp2CG+Yc&33J&fAQG~HU4=u#P{K7tC*SQ__qsKEzJL1k`|+Cmx0}E3 z{QYL{`6zLQNz3)8PiOOHoN!9`L$l4Cmx2=mOWrUvFv=w~XfpVOx$TPIP|YE5^7Pr( zd5T3$@hprVsv`C<6PS zeW8tRT?SLNADKV85yEH8%pl^KBVG{EsbnT-*eNgcMCs8}h6f&;@r8H7bsnT}ADLd{ z>3#lTv9J(piR?7JyH{?_a{T@zWoZEm(_scR?U^UjFUMXAx;%4_41?JFKaoa{Ze4P9 z-Da|N+ZGcOW23*T0{)kN&iA@=+qFva$If(twg0={uK#mMiXq`lXV&J=-MZ_z8qVo5 zoVfct>9Pew!;%&Gve)Kl&tgHR!FA*49<^J+VA}iE*UNu7~s6f5@}{E0tq&oKwL!|FE!YOXsql)7}DG zXCHsYwIkEUYWny2vwrX&{}%nblU;e(xZMPt(c`LTgy15A)pM{MP9FAhdvK z58Js`?gz33s&^RVTdf~_{$TpU%!bRp`ME%YfS}Z(E(s-`Bdj0Y7fq;W>0jgCHGyjh zW2Wn_iFQxajJnP!qIQk!HTly=xHh!j(0UX2Ci0Cy8Pjhz_aiGGoGEy>LqmptdjIMJ zvIplL#TJ!AYEG&Prxr~7 z(C}fBhsr9!wVjPFdWFgxCsp)R%(QT;@t&mka$=0fMHR(N_Ll-LWnSvNRGsN_P04!F z;uB1t_==2wGW`_%*~{X3$m5WAlkP^xMQ)3nlRO^nREY};zT{c7HDz5&>l4nCuO}G? zRcPvJifb;rQngZQ<>VmcpyEp+nZcR$FGF4my;QywzGQjI2BRpWJfobMOf#E}#8ZxG za=6ZYLG6JDGO++KGA7WS1(M=*|+? zZ4L9X_LE+=H+s>QBbl7(C%>t#^=_MX=CtnA;wg_$h@RYf^6s>1b^qz*ll`aNSG}+K zKY(%Rg5?4$CM?|$|8UWvGeNI{ZZBQ4)YZFRfA4Y*?N^#?n(IPsR@_)`v3$vzCkv;n z3t3v?nCUii*_#z}mc*>9ajT4KU6i!`P^f0O7CtO>8cI$TH_YQ_1-J3 zjkq5)fAxO<`U?!X3AqQ1GYljQRV1w>)18c&Pty{TKgY3J^rY@hW$i=X~7y>Qyw__E_oNe|OE zUR`wjQS;KNs`octExP4(SnJxVYgsLhsVoLw64TdSyms!I^cw%j{aZI~5xgO@{pZv(&m=|Z86^}KA(2B_Tzo8`f`q|9rsj^ zU9PfxvETW*zH@$_dwcG)o|)e3m~%Uo*2%4NUB{efl(#VNYF_`Ht9OL&MBhob)v>u& zHRrQS^{E7w)uAT^V8pDzYo^ktK0ooZq0?5 zgV7gX^8eZUr~J1)&jr2+;Sb3QY6c1$)INAl$P9=Jh&NERQ2XKW;kCf?3701PUTC%O z(1m#hCpWy<@NC1+g6khPeYnW+xT93?x{|2U&WW*sH&$#|v24Z8sd?Jp*UahI)}hxU z7q@h;R`u1XSGiUPht2Ps*pql{PKWF9w&QZ0wdcR2n;ATRwC7RQ`0+jmMmay9!qC)SqNC`PHOnlmAZUSFQKr^w0D@ zy7btxc~4G$m{hqp^Hk=|%;uNBUbenmoSk#+O{DSZ?+?vW9VAy9?P3YJcs^u*fcp+t zi)oqjBPah<)7E+IvaQ5Sf49B6etPw}ly%kbwr2-sM`l-l3i)jIw0CWBRQP_mDEaOC z(wl#^HSr2d+nUMUbGb2P&&%aClmBe`6F&Q}dAYcTXpWA={YM*@E)7^TA>Lxs)w1ln zW>?JKZEJk{?Dpzy^*Tx7vASlO>on@(4{7cE)%((X>iwEqg8P#fT-j9e-|vjyy>ky^ z`F8V7_niK8TJQUBx9FaCNZ&gn_Kea1Ww6vPDy0zL}yHWJNY%j)E-?_a1p{&#JuSLxBx_k0EXcUFF1@jl~1)(VRb%Ndm)Jd-1m?{DwP zpFLY-R@ZDhnMblxwlXCE7xZW_THTm_T_kGO%*IA}HYx5Ux6_sZ` z-g10io&4{=9}4F`wpEuIqdSLRyAJMW9#&C9vB@BUkS zvA^AK<-Apvy4AbB@I3T6IMYA9`24xK-uC9jb`Sql`1_py%PlCL_m%A%U(A=C6+b8a zUdmnTSDUVXJJzoB=(AHNSNE)*dtGOJ>6hp)+yAG04F28l)ZuvP>esR6Yw}C@_2g}g zpBR+c6eucAonzUswERZM|7i*(28fN0;CCjytvA=1bPi)$?{X>~vor z9It;yeDB2i;vc$?bMNo|P(GPE^8Lp5+V(H%Ui^FU`QyRmSN!MyV`ZN4`OmH+FD^4M zFt8-h=GBDv%n*=n1O*?7=#%aX3ddcU|?V`@$_|Nf5;^&#-`&i z>7)(=1Cyqwi(^Q{;kVQ6GlUC8j@$27n0hI|%EQ7*cu|PU#g#Ly%1VT$Yl&EKFt)FA zUAZ{u?m z^(+Ur``drne7JepyY3ZAO4A>tuVy}QK$fY(j*~y3P;+h#XP4K@o_F?llIqttrCyKl zIRD@6(Xm%oFTZR|*PqX@VSo6=?=?(3cNWf=m|p)w=BBJOCr6%6r2UTXH@GJ;{J8OF z(fY&l3@26}*pzMcTcI<-xNmx17UScsb3^LyvzOd5((UB9aqoug!TozTzUJfw_;=pvlM|iI@_VK@p6fco zazf+U**0~Ref7E7pC#2N%-}y^!Rl`4vFLtr>EGLHlfA5GdtGalJbHm8<(Tg7WelO_ z(lef}I(N^$C*%V6p_WfhEB;)zS-)1?(k9~+Tb9tyBfT0sHs;%K1r+XI=PdX`dTOTK p+hpz^&;PTgGo54kW6o5^D8uzsU&!v{KL!Q{22WQ%mvv4FO#s*mG3fvR literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/ebwizardry/textures/integration/antiqueatlas/shrine.png b/src/main/resources/assets/ebwizardry/textures/integration/antiqueatlas/shrine.png new file mode 100644 index 0000000000000000000000000000000000000000..951b274105dfda2c1c0d3052de1a21b9935c4904 GIT binary patch literal 3333 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 literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/ebwizardry/textures/items/amulet_arcane_defence.png b/src/main/resources/assets/ebwizardry/textures/items/amulet_arcane_defence.png new file mode 100644 index 0000000000000000000000000000000000000000..d1aa14b4015262d036c004484bb7441a827bb566 GIT binary patch literal 2150 zcmeAS@N?(olHy`uVBq!ia0y~yU=RRd4mJh`2Kmqb6B!s--&Tc0lmsP~D-;yvr)B1( zDwI?fq$;FVWTr7NRNPt{9y#sl3cf$-qI+3X3_G40%)4w|ar%A2hW8U9w{MF3Ub^gH zgh!*3(2Xzu|Jt63|FO{}drrSp5Qmuk^q5CIeYgIee(iT{?eEGB;m=d=+|ieCZVLOh zxXt*U;kgOVjpO>~^%VYJqVe_fqCNXgxC_2EEQqveYuUzFEi$`Cgj4=>p8fQ_I?|Jl zJy*S=Y=7?eQ?@^|D~p9Je>hxx`0mCr387!7uDSkL>$_la(X7ukmRHes`>}=7C zuTJ+QxXOROwfK2_N9D4TkKa-(TW)_kZ81$C{#wmOv;W64tlaLeKCPE<@}bVFs8g>T z*ZJhHjbsczvVXhPT-)_6-V=pH3$F;Iu!b*n;gMpu%$kxJ5TCo0tE11l**$HYP6#iX zXo||Z?mTmSDH&By=BqlQ4;3VyN^|RO&YZb=iNPHY-bL*Ta*mzazw3;D%dr`pt|?!? zi57f3W3phz89_;J0cK^BzTm$_A4>QBS6k1-_P1zrQsd2OD;d9t`}aSXWv|$n z+`DQIJPPt=Cwc6;p}dte1DB>)c%!Gp2v^;3S)()|J={cEP2O%ruOMu>uXVQ(sOm%(xm*BM>&4$HQAMR&8Ga+ zUB3D0?cV%(7UnnBy9ZZYQaqLaDE#*6Ko<3B>a1U5FT_aQ7vU?vz4q`;#qA=$zDjR? z7QJKUwi730Tk}nd=EbbNrMdp&J&C-RzY{mS_B)e);Qd?af9iLhr61TnEr-8NC1?YW z<>pzZlP)=45qN%g`_4AWlCBSP?%q)5b6TCP%am4jqP%A5U%wcH8!-G395|+Me7MWhX6m&dEIYl|%5eVEyCMWfR*TUzj(W<4k`3u@))k zQ0bXZt(VHJm?o;fFTiiF{CdsbOR6UwU-G1H`|N$H%v{mm|2PESH(EG9#`(g5(Da=f zG*<3AHs#{_i$yyt*R``+A6a%_>#B!~*s2~~jOu*tuufKbZoT9=`GC7h+Sfm{S1nm# zwz{9|N!`R#@>z$Y*YVbi1<9`XDY9JM&*+mPZ^zkuL79`WtG<0$xbj;?2#Xu*^Nqhv zpIC!(~qRYa~%3rc85*wKl;P+ z`PkF#dNp$rXWy8(SEsH2g!zZ|N%{}YtQM|(?vS%-QrdKR^Y!-+f|PQ7Hs7jS`q_7l z&C!lH4oQy7>MhUuZGJiYYT`+6SgY}EO5mo~j<+`LU#RdPaEsvP^eC^bY<7VU3o1?& z9-lt*_;ubJ|1!NTB;PDmI_7g{TDI?ow%S(>ML%p-KD9|uKbW~(*5`>F!)co}C)`?i z*|+|?7d7{a+RGnvzm{7+yE|+3oT)`!VYArRZ^(8ycrN^}=JQt{m&NXGj_^p@ZTao! zgFjckUVC`XjXy8zip*QiqITzp&jSqXJyu;iH*Mj;|Cb7X#9Y@tzO(K4n+m4TOCNP2 zR&9E2D*YvJR?+R$6j$f}ndj(3Kf@{C8+8tF<&;A zs%4aw%^Z09wUV*(q_htQn!i7oSA1{h``8Z?P9J&UqBK=ydME2?_polZ-yYhD|Mz+y z7Cf`ZS7~ZW+7%{&`cmVUAI+T~Gyk#6`H=Wnef_-YOrP!~&ANO3KBLCEs7a@fgiJ2H zAW~8B-6;9Fa>$+Jf8Xvt;^F?Y(?Fl0xI6Qm{$B1oTUI)jELLma$_p@CeIvbk=H8hJ zf1k>I`__Bls-!$fD_U|m^yj$*#(={9+f@RLJN707 z{3wx9IPrS&UHQ`gI?j)oZ`|fvD;TnR*7el?vvS_~X*8Vt5hndJ?%{&p#%9HfN*1@7 znVv|g@wPe{clKoZn}$ohQ5ViUTE)5`>QT$#-?f{_#+UVpuLVOy@CRNscgHy`>~w_lVU awwGOX&hE*AgDeaT3=E#GelF{r5}E)2^%s5s literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/ebwizardry/textures/items/amulet_auto_shield.png b/src/main/resources/assets/ebwizardry/textures/items/amulet_auto_shield.png new file mode 100644 index 0000000000000000000000000000000000000000..960407ee5e0d58810468525ca05c08a3c685c142 GIT binary patch literal 422 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 HoD!MMDC literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/ebwizardry/textures/items/amulet_channeling.png b/src/main/resources/assets/ebwizardry/textures/items/amulet_channeling.png new file mode 100644 index 0000000000000000000000000000000000000000..1c4c1e077de48b73a141445f3aa64ba91e4fe3b4 GIT binary patch literal 500 zcmeAS@N?(olHy`uVBq!ia0y~yU=RRd4mJh`2Kmqb6B!s7*pj^6T^K?cbQy$B&55^X zU|`@Z@Q5sCV9-+rVaAH3_GJtV4D2PIzOL+#S!4uw#2dJuTwq{ekSuYHC~?lu%}vcK zVQ?-=O)N=GQ7F$W$xv|j^bH7a`+@@52EC$M#>D;JE5&M~H}X zm+YAdniE`?cQhw+{pIcoc%@TPG^J^C#ES-;S zJ+1?rk1pNA#!yjJDZ6ji6XysE?q@e2CGE6x(w~vZpvUN-xt_IYzvz$oi#Nq;&B*jP zd4%H*d$ix|$A^DOA7JCU5f&9!Z)CZ;E97jZiQS16GIcoyQ!WNGI2`5`+^l=*h31_5 zriZpq4t1@vxux`f&%Ns>C$O%1W@40*=oG7SLi%WtEUR&E`D2Onxw&t0R;`G!6yC?l z65%J!@L^*i$Lnu$^Sk<*-&rv%xc266&XSKawtX)s+T5~Jlr!x+Q`r>Z=4<6yOuFwS zMRzwwZ5FrK5ix^5Do&n1U-pkBPb9~jKl_h~AKgAJOtK=bnSp_U!PC{xWt~$(695t~ B#%TZm literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/ebwizardry/textures/items/amulet_fire_cloaking.png b/src/main/resources/assets/ebwizardry/textures/items/amulet_fire_cloaking.png new file mode 100644 index 0000000000000000000000000000000000000000..080f16ac89075a1248d145ea4b1c0e9a18d66cea GIT binary patch literal 1803 zcmeAS@N?(olHy`uVBq!ia0y~yU=RRd4mJh`2Kmqb6B!s-MXN$0N`ey06$*;-(=u~X z6-p`#QWa7wGSe6sDsHU}kDl~IgXhn4k!ltdfu_d^a)Q;(w*S;5cE_H7_exSYb%TIL zAeZCJZ}<1#{nOkY+5B;l;SvEIx%oAZdfc}Bp8S0Fn)&a)CiWley)#FaXQK1lZ|5bZ z?QuMJ;kl}Q_B@`QF=}49r8(PWD}9d?N?PdXIro(@m-*&=nswsirZ?Z;=f+Rt)qGXT znfmhkRr|XQ^Ck7)PibZe>ffHeT1x2F#I@l+*77abTOjo~C0h7y?QG|%jh(ZV(?9Yt zFJ!Kn9^>}*W7-#f&c$yPrQdH+W{u8SvuG~g{(bfL6wTScxc=l_n%*6ELf>ch%L|JS z-!&9D_iN>xC*FDMruf~{o91kxd;dgeyR+W;gSUQsjZ1!?8z1|P(VH(j@OV%fch&6= z*JMNkMC>;fT2xPI5!$HA^=O6C39~6qof0NxpF%W)mz%wIVimA854&=vRaTTakwvoe z^pe~CPIE<%go`_tIa*kF{5;}xIcL^0E?0?lBD{;54Q_Vy+iN{j_uAXf>zeZTrS^kI z8!tB`8MvqDIP&%c#QRNs`C#!K`{ri-^W=MOa@O5H1IxYVTw#O^I~y#6PUs{ckXlEEfYAx8&clKFj(GT-Oy|36+E@I+)zld zLqNPIxS)A0=cYa4NBVztNSu0fq}xMas)lD#LE@VY0wz5@v#zcTzqnvk;N&#n*e`)e z9a70YhU$KNlHo$%lDjmQ&Pg;$e%5nQlFKrG&(5>?n_7Lh?^voUZgx~Oeo4zB)oCF` zPhV+$E94E$UbFI<8}Gs^HIv0=ZMzY4T6W>J*zd7bFK#9KFMB?DtLtm$pADu_Yd)rA zX}mfqwPe+C5tB=uJm(HbR5Lxal2AyW!Jck5>ATGg={Yx#+z>s)pxHdftJ%=th4jV} ztDV1-{Cc?S+s&Dke&idZvz6K>yqmZ^ea%%Hek*fHsoMn>SFPUcJEvHDX3x}TT7~PM zwAS2-iTfnt%n%*Nz_{GNd+r8Gl%IM*qnr7c>5!F0NPl~+Sqne=YGug*Y}WF z=@oCD-`nQq*ZwPH+8n>E_^VQ{_*8m(b}pZ&c&)X6#kAn->z1~J{HW$tE?c&1%9IHxAXq&y_{O;(F$6re9SbO4353_&ePTABA-yGZ2=M+~rYC-npwpX7^*G{$x9!*nVBb--Rky+drg# z?0E8D>aF#L(yyT`9C>1e#{#$SOBL^5_r$BfaD7L|(ml`qe0%f%%ar{`8eUX}8-9p- zD%#TW`M}3_hq9#Wn@-<|zh@`sck8*sYU?uD^{<1vSF%>k{dJ~%=ZEEA@6Y$Jem9A; z=|AHQPRUoXYc}m;U|?WN@^*J&kYvzgh|~Y$4=O)73p^r=85s1GL71^(seKs(0|R@B zr>`sfV-_)P4Z}MMI&};T43Z_T5hc#~xw)x%B@E6*sfi`2DGKG8B^e6tp1uL$jeOz^ z42(gZE{-7lw@={sy<-fFyCS6?rwoE+&=_2?G$w{ z6b&jUEI2zwL3hiHr2-lvSqHmJEh5jU{#Uk~?6dEs)4kt!PurKjsmPXmt?ioem21mY zrBz#*uADV}6Jxu0>2$}c7w0Faweh$n>Q$!-cymtNkt)T|aPhYKt+@+N98uKCc0X-W zQ2Se{XS(`s1_uSkz()^%^aajfJn-_O*{!*X>H%BQm>eGd=wpaTX?x4I=xE9wkNJ+? z`o$~N_CCMT7;f_lz5c#_g0DAkfW<$~rZsW^7hZDn%Y5o5oeak~$5y1D<2{CS7xw@0#@ zSu#i7@Bco7wY+lLm)#r6D;j$H!|N_yd3fI0BCa8G<-sSvc24h9U@$uTe^LCm^Amr) UTeWf`0|Nttr>mdKI;Vst0G75%vj6}9 literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/ebwizardry/textures/items/amulet_fire_protection.png b/src/main/resources/assets/ebwizardry/textures/items/amulet_fire_protection.png new file mode 100644 index 0000000000000000000000000000000000000000..daecc00828e0ffdeebd09fc4c1b6068b88455ef6 GIT binary patch literal 405 zcmeAS@N?(olHy`uVBq!ia0y~yU=RRd4mJh`2Kmqb6B!s7*pj^6T^J-8G#TRb|M-KX zISV`@iy0X7ltGxWVyS%@0|NtliKnkC`(qXfQ5L2(%kK9xFfd4#xJHyX=jZ08=9Mrw z7o{eaq^2m8XO?6rxO@5rgg5euGcYjx^>lFzu{gaoNHOn-fxw)}HA_wyeBxJPmC>=; ze}MmkXPs-@Lw^&6H9=FF6&oAXLm#HDc6JS2={@Vj^EHc=V|Q3vTU*a+He?I(nv&YN zNMpg2rXa4+(1$av3Vff(cvSmd-Vkw6_j)NWgTkT;5euP%y4CN^r?1(nbJDHxyWF*? zExEH#@yT?0tQQvCz9;_NPJ{Es1?O1L9gr~RIn10EIzi&twfUkT-JkwyRz1(NX z8-@)r9gTvP#|mR?PqAehmQ=2PZRMe9zEEgqeJ98B>%#l;-|u*&I{R2`)BM-$`|R!) z*vD-;)@8eWq3OHh+{-eZ?tef3Ta(zj9kww4Gi!?*%9T89ZJ6T-G@yGywpT CW180h literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/ebwizardry/textures/items/amulet_glide.png b/src/main/resources/assets/ebwizardry/textures/items/amulet_glide.png new file mode 100644 index 0000000000000000000000000000000000000000..7ca29d2db5a94b6611b11b54998a5c8d637c07e0 GIT binary patch literal 440 zcmeAS@N?(olHy`uVBq!ia0y~yU=RRd4mJh`2Kmqb6B!s7*pj^6T^Qm)@V?2hUIqpR z&H|6fVg?31We{epSZZI!z`(#>;_2(k{+LBVR9w*W`~AZV3=EPbt`Q~9`MJ5Nc_j?a zMX8A;sVNHOnI#zt?w-B@;f;La3=E74o-U3d7N^%v-rL)1AkcE$U&Nu~#Q`DT9ZXy| z4utM#5f_~N_<-ReCMP4MEQgkN3Hph;_AK9(@4B71m!Ecn_3Ad=Q=3|@Nri?kT$g>N zw0BwNhuJ~bnX}j0e2QKF{a@sPsM!k7Wf&6fmoqqUJPdPrx}o?T*Ak^ge|$PUCLWHx zu6m$)ez$VV0T-1=I?q~7I*a+zk|s@4GPys z!%Xgb)v0S!m7IDep5D}A$oAPred8k`)1x-6Gdd^TnbspZ!mj*M|4j*GgSOLtp%syKHjzSe=MKg^c^2`}tp|*Eepx7BP*L oL2j;mxmdKI;Vst0J8qGUH||9 literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/ebwizardry/textures/items/amulet_ice_immunity.png b/src/main/resources/assets/ebwizardry/textures/items/amulet_ice_immunity.png new file mode 100644 index 0000000000000000000000000000000000000000..5fb31676208d8663675f2846cfbf8ea96dffac9b GIT binary patch literal 6552 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 literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/ebwizardry/textures/items/amulet_ice_protection.png b/src/main/resources/assets/ebwizardry/textures/items/amulet_ice_protection.png new file mode 100644 index 0000000000000000000000000000000000000000..dc49826a4bc82b71154ffa6a6c22609680eb4203 GIT binary patch literal 1873 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 L^>bP0l+XkKYUk>^ literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/ebwizardry/textures/items/amulet_potential.png b/src/main/resources/assets/ebwizardry/textures/items/amulet_potential.png new file mode 100644 index 0000000000000000000000000000000000000000..6dfd63d60fe2e776a2000f929c377a45b926d53a GIT binary patch literal 478 zcmeAS@N?(olHy`uVBq!ia0y~yU=RRd4mJh`2Kmqb6B!s7*pj^6T^Qm)@V?2hUIqpR z&H|6fVg?31We{epSZZI!z`(#>;_2(k{+LBdh(TSaL*Nht1A}CVYeb22er|4RUI~M9 zQEFmIYKlU6W=V#EyQgnJcq5-U0|TR*r;B5V#p&M38?%@k1={vc6?RmLIA!PX;Kbe| zVk`NT6jit_SBE%m*zlQm-PTQ;BcwNaWflrJY0XzsOyW_QaAV0Wk&k_!zwDWvRX+3Q z|N4J3MfbhGoMToPJ3VZ5>l7hP)p^eY)m(lFu`o8ARqH*TJdyoDO84)-b_}PV8qJ;F zptaOx`Q@9T6ZH5F7xcSk&z;k2Xsxi3Y4uh$p2Idf&3My#HX2r{zPl*Vd~KEj$D}9U z?(RKXwIOuE6HCd(Yl65A1Nz5ARrkG`CF{O8l&vv-@f6dL}1oyB|L z_OIrnmz6igiMBFqz8FwbU#sTx&(->_+|sBS{_06~b32s21$6Pwy2|2MoYuDg dD(3$fl=5351tM4NW?*1o@O1TaS?83{1OSX0!d?IX literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/ebwizardry/textures/items/amulet_recovery.png b/src/main/resources/assets/ebwizardry/textures/items/amulet_recovery.png new file mode 100644 index 0000000000000000000000000000000000000000..41312cef26573dacf4ef6a324bf18f47dc28bf87 GIT binary patch literal 6026 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 literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/ebwizardry/textures/items/amulet_warding.png b/src/main/resources/assets/ebwizardry/textures/items/amulet_warding.png new file mode 100644 index 0000000000000000000000000000000000000000..1c7a6381cfe1798e5f593fb030cf78b03d9a40e7 GIT binary patch literal 430 zcmeAS@N?(olHy`uVBq!ia0y~yU=RRd4mJh`2Kmqb6B!s7*pj^6T^J-8G#TRb|M-KX zISV`@iy0X7ltGxWVyS%@0|NtliKnkC`(qX{ZVm}VuWcD7T$9SZ&BX9(SD(v~8CT_&Y;}vAmgwxonVl;T zX|q8pY~J&EI)75HMR{mC>l{28mCYb=<7-}((weOX$2b@w`Xb+|>+P}FEO&z8o#3Cf zIhUI3qpz3pv+qyox}zi-S)Bi;tsu|ebJ77z_n0T|wI|Hqa(nF}i`Qpa&+R<%Porzi z!q*?gt|eA0O$|Hp-$Nvk=XwA6`+uJ6GaNX5`|^VHkMfmfAyF3-s~25=ULKU`y4f{t d^72RQ+hr$D|8U^?X$A%c22WQ%mvv4FO#t0~sU-ja literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/ebwizardry/textures/items/amulet_wisdom.png b/src/main/resources/assets/ebwizardry/textures/items/amulet_wisdom.png new file mode 100644 index 0000000000000000000000000000000000000000..9ad1d0c0054b3e23c7300e0997146c9396092c83 GIT binary patch literal 1793 zcmeAS@N?(olHy`uVBq!ia0y~yU=RRd4mJh`2Kmqb6B!s-*{VV!N`ey06$*;-(=u~X z6-p`#QWa7wGSe6sDsHWf$ei?5jpxsK%_0_+jdJZFVq-8p`qi3_HFmAW&{ z{DkDMJx^0_drr75?Y!|V|IdHUx7sXn*xQf4^~kWiaC?K-?Fk>g<%~Bo65P_Sie3YZNr=WKGwy4gPC06YUT`mnd26-w=ZljFI{0|P$(?ayIh)s z^@FOHQ}&0H!avFzE4p%)By>;x_Tsqmy7}wUl#?h* z{~hG_&3#>-=G;AZE6Uz|sZn>I@aOIv{%gnL-Ih#-0waXN1t?3d8&M7=PJs`<* z>gtdyg{4=o2PFIUN(HT)nKnCnU#nR3E03*ucS~-^ez*OyqRJ}r_7=Ol@f+M`o6hs$ zb*TY}fZSS@f&sf)3 zx;)=HttrYdJ5D!f^FwcwcHz?ZPq$vIcDb@j{!!tEPbYmuyWgHTDK$%D9`o#8Z_|F> zXF^F!*H`Q<6nj7C&yKKi<{FRNQrGytpR?Rr!jp9`|Hmt#fBgm1%fG((cW>@K8Pl)P z*Y?ag&fWaV_T+V*2Zv>r%YFVDRb}^lSJb0zM~)t-T$s9YS-wTUeV<3yU;USuyCaL? z^;`EfuV(N1FT(V-HY0v^@c#BMx11K$wf~iS{+6S3?wj*(TZJmOFPI}5_-I~K?u|X( zH&1M6Z{P84R+n+^waxvLe>@M%JbC<@Y1z^4!}FrQDm>ub@xVgBOi$>~t?J|lEeqB7 z4lc84FOA*Bd31fhg#%Zg)aL%Z(^TJCsu!>Md24yZcRi(zV(DQu+I7crdV_=CC+v>6 zp{HV)rN6sG=yyce+Pghfn;yLi>VGU!6Y zT^sWH#8)0G;aqM1Z+pRIt&%8TZ{Gr@%Xgp7U7+Ogb_M^h!lTN%P8sLUIyx-B?)bX< z>!V=b)&DCrs*F~BTM&CihT|;+&tGo0?a`;9QiNSdyBeP@Y+mq2TW68xY>eC(gjY81Cuf7-Dg{chbhJLjfXf z`!94)UOPcajBC*q$9A7an}+-a6VzWQePcB${lCgD>W+IH7`$pMVQweTbs}G&s(v7kd02e z|2TC`VGHLPhkePX9nZ5q_?ta_kQbdq zd@_$=@=uLPYfJZ5_5FD+`$D=ga))wEuEEZr-)1kLY`XD||Jv!>+rRn$=<9v8%!+Z- z{mhI^|7Y2cmv((LYAg94yWZ~vTSL}Tm#vf5lw0)Pc*lRNu=V|o$}m0M zqP@h^WkufS>lUne3~Lg$oJcLO+HZK|qY>MJSnWBg%zv2vXzVsRKb1F!fq{X+)78&q Iol`;+0REv+J^%m! literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/ebwizardry/textures/items/amulet_wither_immunity.png b/src/main/resources/assets/ebwizardry/textures/items/amulet_wither_immunity.png new file mode 100644 index 0000000000000000000000000000000000000000..289a6b97b6e07129b7ef9410c12e86f15ebd4274 GIT binary patch literal 1831 zcmeAS@N?(olHy`uVBq!ia0y~yU=RRd4mJh`2Kmqb6B!s-8LC1eN`ey06$*;-(=u~X z6-p`#QWa7wGSe6sDsHU}51*u?$@AyANHt3f!@fcQp#WvR;wL_G8KU^ADyTTrfM4ufX7?jY-45H!sX~RtTMa@nXVyR-d5lOf4K7 zG6w{j8Q*rwR$glA_3aQi!O$eMKzf^6vslr&kOq@!H=AYFFx@yNvGC?qi_J%Fa5%Ok zua7vuJ5BAxrfZ4+I(TO|pWL|loaOr?tm3hs-W=!p9QWr&;N%Svg^yfSJfsIyon|>}L8&#p83j0$aOv*ZojZoe~jb zI#v5x;n&ct6&shi@dmHF`D|AHC8uuPQlG8o?v`Dzoi0}uVjH_AH%k5zf5hUmvu67A z_7!bpTX`bTG1{pG*7 ztGYoz-emUW75hpSc>NYimouzNe4Y8;{J@p(jU|@*jDE8Fp0a!TAUI>^uk0ep-&eL( zt$H+bRd>(2%fg|rSZC!g++FeXQfQUui^&ChJ9ktqe>79;a}%FwwC-JlW%FO;R=KWI zpIY$pz~7>hlSgV^ubF;K&ba-#!#kPWxS2~AyWaiva*yOWx%P~_-OZcl-ains{cqQ| z4v}5Dx_M{(%-_7|{t#nyyeLUZ%qVBw)2FZQ_aw~T>oVU&esxoG>q=c$+5fE1P9Ocv z_EBO@U))*4HHIzo*G1+$7JtyfdwfOdlT#L_W410plG`|JkGI z>?&vM=eTdb`|5zm-B)i#ehMq_r|HL=_D{sVRUvK!S48NO86ZqgBU5Y1NzclQ;`TEmSl)n%{j)+^v4!#R+c}vQLz)u>Y<8 zZr?8jxqW^9KTXfxxDl0Z*vAmIEIjXlw9TI4?-Tbwe(kj*D52-!-|N1nfA^*&XU~;4 zZ_n8j%^A-1?6c+Kiyfa+SBX7-;rYY$ll=9&+i&TgGW*QHz`)??>gTe~DWM4fK8alg literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/ebwizardry/textures/items/astral_diamond.png b/src/main/resources/assets/ebwizardry/textures/items/astral_diamond.png new file mode 100644 index 0000000000000000000000000000000000000000..679f6954e2a97bc0401abb6985f228959383eacb GIT binary patch literal 2141 zcmeAS@N?(olHy`uVBq!ia0y~yU=RRd4mJh`2Kmqb6B!s--&ci1lmsP~D-;yvr)B1( zDwI?fq$;FVWTr7NRNPt{o;&T12G5`Kn%_7S7=?}>tl2YN`pw7f2Ag&-zid1+<#JuJ z!7-+5~K^VhjJ#`-MU`Q**VZdI{WFIL>&f0s@E{BGMHt3M~+xvS6N+%xTa zvYgreBpX}12^o)%A1_ot`(}mYE}hwqaoWOGX8vadF3a(Md(%}L{`hj)oBpRJh5mK5 zeM|;bhZH6+KG{Ey?eK>q5ON?hR;`z{Ztk? zmp*$!yuqfA6YeFKD}6b1YwM?W@z%XRp5GTPD=wQ`{O0b}8I2)j+g4_4r}GQ*JDhx; zE;;>y{zCodp#_@TZZK4_&t_lu%!!j_OM1t`cBwRp^xIC&-4oe3qZYZ<^l5U7W~ply z#wJc`nD_1gM4-_eo0)O-tEl0@6Wn2fd!Qda9&W zt-kWt?e)DqGlaI^Jag;Vjl*~Or!0Q!%^4Z>XvZEAzQqU1x6k`?@5o}_OH0`3T}t5$S%+M>Go%Z9rh9jhaFzg|mw@!R-A|C$|f7OaA~KQ>+!P~<%_^JUAe za!~_*^W#_b?{*y1y8ZlBH4E2ao2k|6Yi}Onm~qT>j@2Tmg?A=jzoGTS@{CNuy$1O! zYB%FVCadRum2Y@ZcDDA_>+|d6Rya8KpT21pskcOphj(+A&SU-KMRL&stb*zscY+TK za%D^pDq+3+^r^-hw|f`DzAnz0Ecm=dFvWYe%KlgX*8aQ8$FSr%*Se>VcA0R0-?!=8 zQkQepyAMd+JaeQYA^N~B_DxqOTuuBOUKBce-#KM}Ir}-gY|8Uv_Q(3U%1`W?ynRaY z_v$H4C3_ERPU9=MTNix5=T-TG0z+T9I+Z0Uw_O~L-H?BL;~HmXO?_`*k<+yBQw~n= zGmTp&zsR0farxfGzW)w)tXg9tq82dl{%lyia`pCS_qDfw-*a%@8t=Dt+Lg<0JnH#* z>WrZK;lF7rPD%HQGL=7Q9G|-AuEVi^HtAo~1Fv&yg=|aQRlnkf2;=Iy|{mSaXyUnhwO1*UPBHNt!nYHSNi~`Hbv)m+JtT*oXV8&v@$PxYH z=fjp%2yyDgQn<%hzOP|F@~G z-__F>uIH)UcsT#f8=i^#ADu7f^_6jAoco)f#YcBd)zU<51_lPUByV>YhJJ=PhNJE` zSMFqBVBjq9h%9Dc;1&j9Muu5)Bp4VN*h@TpUD+SA2?$!S{`7g!z`(%x-qXb~#NzbS z$@Uq-filPK^(}c*1b7zZ7Vl&(JUPK9PqO4?fY(BWD`yY-bXkZ@Y+~d+5&3jQhSx1e zSu3u_3ld*MTshjC=ZaX)G1+>NM>WssU&VRFXGPOpR_uSd_kQ*L_us$&-uwRXA@138 zHoN~!pY0Z|wDd{pUv_q0*Ohx8by#?tNU7D8SQS)!Jf_PacYj}}K$6nIBX1ZaUT#wr zDq!T4&MrUpPP@5vicmw2p8u0_`G`H)8~(3u-WlpR`_j%U&UrRGlQ`@h&8DkA+Ln6J zfI(y5O~t7J3)!zeH@j6RyE-Ic_nxN@o$9tR?#Or_@cWj^($y-9D zLgB=-PjN;|S1Bl3iXQ%XZBf?E3(Uo9nu(jC5kh96dOMMvR%(~)PF&y)z$50w|egB|Mrt28NdDG`S z>4#1g3(B(GJT&)e9a$l4+umDIUs%~1x8B)8WMR#H33UsPAFltt?)+!{kAb`U@ZFEM Tcf~OGO<7WUG%Ee+vm(c}LIO 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 literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/ebwizardry/textures/items/charm_auto_smelt.png b/src/main/resources/assets/ebwizardry/textures/items/charm_auto_smelt.png new file mode 100644 index 0000000000000000000000000000000000000000..3acec715ad348969af050d093c7d8eec50f8c9b6 GIT binary patch literal 419 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 literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/ebwizardry/textures/items/charm_flight.png b/src/main/resources/assets/ebwizardry/textures/items/charm_flight.png new file mode 100644 index 0000000000000000000000000000000000000000..7332c485fa43669bd00342902076a260388c500f GIT binary patch literal 5949 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 literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/ebwizardry/textures/items/charm_growth.png b/src/main/resources/assets/ebwizardry/textures/items/charm_growth.png new file mode 100644 index 0000000000000000000000000000000000000000..408867e53bf12c0bf61e7350bd4ceafc794c9879 GIT binary patch literal 5722 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 Rmt~-#4o_D&P^Z4DT~__Br&akU!?Ifq z0!|^G4nDu1zt8)3=jQ^6@;64BvvB!)m$ChpN+d->TGo{UPvh zEobWM?|1DJ51jAmpL*b4C6`$IX?G60MeAyAFx+`nutmHtdCuwE7uvU3hDzEM3QuB= zx3>}5p&uyZ)ve$CTru#BM$ zt@RUT=YLxBPo3O*^6cD8CvWGbyER!Gat`cHzDbfSC)V+OLB|i|CgrgHNM&jb-lR2 zt^MPu^5q9d6Z%fbu$US+)i%FUJMjGXN69^05+%ZEN0}~9Y-hbNUv@9+be~16U3^cy z61YmG8C*UbI4CJ(P*5S{KCkaU4wGO*h`^KwR^3l|qE1+@E10xa;V6?bw}JUFmRYOb zRCI0>Y~oPA=fPm^;X5I9t@9t2)g23;9Ep5Br~Kf`ZoSHn%7^#x*S%Sx>9OG;tGv?% z0cRtvtg9=pFIW{A{6ynMVXTXtTd(1=7EfUv^&YNzcJSqHY8nSldGB@6ZS8|HaZojbQ=rk**wcgwBmfm;1F6Zkno;~|o`*-#= z7t?yxgPjdy);LNX%4|AT_J}P#p+~pzgMoyC;hE;m&L^Yf&hVb=J8^>Rc)=y!A}!uy z2NvWWS$Fy9UFqU;9sgzT@pL@6pKy-nRb0ZmiQCiHTs7ghn#t2^BC|lQ=}or9RpIPc zhTcar4{a9J413K{&-X9r)r#KD^H-|Hhq)i*eC<8AR3&uzmRGihrU|A}4?b-)nP2*6 z%b)$yi>BRmF`ObayN-?1boTTp(X7O-v-&@bmz(#04$j{4EO=jqQf$la6N-7SqC;ap zHatGJLE7}3Zq{_~f0s8|Pu?b*zk92#%<9Mv?~j}3dBr%n&e>+UL6vj)8=c-4a?yp7 zT1(d-%yPDIzNn=7J?VJsyUCZ{czKlS?%{4fa^i6B;YR88YpmWeM=slURB#jfyt!<9 zZ;5Z~+weDUj-^&mlKH0N|F(opebK93e~e+1x)rhDY3#yOR)#Y^P{A=HFIPYG;_4f(;QvGyJ?>anfhnef< za@U;6-rB0?!+Y+``D=Y zUu5nu|MAWk)Bb&N@0QA{J+7-P-?~*clJWV+n~84cv(L@nH~-PK@`5fi(Z}0M)sJt! z`{?hpf}0VuIG?}T**bIa+`}PnQdeE6HF)F}@ay>A=gFE^A0OMs7Zh{;W%OU^4F1|@ z(IW8-g;Sora<g!$&#&98*7XVgm-){frl{9ixw3pA0|NtFlDE4H!vTib4BEbH{(fa(VBjq9 zh%9Dc&{GCs#)_r(Wef}q>?NMQuI!Ilqy)L-|0w_KXJBBEEOCt}an8@pP0cG|a4t$s zEJ;mKD9U2QS zVhZ2BhW-l|-6!bnbDHm1p!tJoX0*(bU^7P+MUh7jCWtV#3Yo<2nV#*l#Q9~U-uF4b z|31H0eC{gSU$$#sMg5ldroWW%6W*O#^m^|n{bh5x?QEr5ch%RO+!D{pQDE_kNgzLH z+2qot9bv5e?y--2xg5lv8j0-e=n2@vUN7-4~IodZ+qyPIY>wh8ap2Q?!F+O;G8U9?{w>y(#5bXA{<<) zBDQN3xV`3=Di&Dz+J0Jn=hs15z2}eT75`-XZ@Vt7L12>o`=^`kPPl!|W5+x%K?bH> zFJ%-}vVC6*aVSb&@Qr!GH*uTy2XEea>loR?y%ruy3Z1oWzm?X~1yc^)K5na}qcrD6 z{=Lewn$~^$0>634w@!F-&*y{nF4s#+kp1XD-WhiiJdjwaW}91 z^1t8-d+nTCT^SgXt2^fGUr=zF@p_mD)X4x=ydyje~^$V z$$0n39UqRlx74fHZ6qWm%RXG5Y+SMT-YWOi{|;>P_E4M5!PYEs<@d)QA39F2miZIp zY_YNbB>&Z0b(2%<=BKMoR`fjfxNy=F^J|kFb$6;J8ZW;8jN9qnz8RJOHPsmy7#KWV L{an^LB{Ts5Vw}%C literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/ebwizardry/textures/items/charm_light.png b/src/main/resources/assets/ebwizardry/textures/items/charm_light.png new file mode 100644 index 0000000000000000000000000000000000000000..e7aa5ae68de6a2d12728e8aba88ca622c1e1d62f GIT binary patch literal 456 zcmeAS@N?(olHy`uVBq!ia0y~yU=RRd4mJh`2Kmqb6B!s7*pj^6T^IrxLK$YtPnor! zfq{Xuz$3Dlfk96hgc&QA+LtjfFtC?+`ns||;$au!*A)G3ro+I%AX(xXQR1ARo12dAWn(yol^-_-4#DyysI;9dmzy$=Tn9Iv04BikY-6EbJl z5eK#9UI!h2F`jwxM*V|v$0EIRO|z5tIb3TFMP&f@`Zo|DWI+ey#1?%=pr z#9qGt|J}XSAJ*quNL)R9aK*i_qGnA&rdQ^)-5z-^#B{|DN42c`mdKI;Vst00gV6hyVZp literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/ebwizardry/textures/items/charm_minion_variants.png b/src/main/resources/assets/ebwizardry/textures/items/charm_minion_variants.png new file mode 100644 index 0000000000000000000000000000000000000000..23085a5d795062eda0816ee018f85479c81c87b3 GIT binary patch literal 2098 zcmeAS@N?(olHy`uVBq!ia0y~yU=RRd4mJh`2Kmqb6B!s-Csc(*lmsP~D-;yvr)B1( zDwI?fq$;FVWTr7NRNPt{7P;w(2G5`8BE>8!W`#1>I(8nEsh@Oq-Ky(fr@h;@m`BxM ziIJ-0)qlUYudXjJ)Ju&Okl%ZKN6was!d8o}PklCd%iQyS-RGa192?8bGubiwTKvb` z_Y%_2JkQmyp3AbkIznTc?S%R4m*P57^9#!ENJ~aZzu3FMt6K4Jb^7jq&!0~F7IXnU-!msM%?jhnx-pR51=@ap9A#kYQZja&MC+aB+0hg0{@wOV&Z?%C6W z*J@5b=KEo(+x(``{Z7*qjgG}#3a58)yC$8uaWZJB%iLQz+@cO!?pQ2H)yr9-A;FsD zq8FTJo%c#cp{Dgs4%eZB2TqBL&ANSTXRPAEV^duet2nwZ_DrzfakX6StDR7n$LXV@ z1s_kCERZ-QsOdX{&2>e7&|Q@uch+COaMi)lJX6eKMv0uZ!@oB#`1Fih&1Sr~u#RO} zz;~tv92_zSCNwhLnq2tAlU-z+1B((Xld3~{vZb?FQJ=QMCevfiGAWGTj#)Q83n|-k zMx#aGkmP!w1~U)ej?}fze^|6T7C!0Oe9rQHldyQ~r(^v*pY47G1_m1(WD~F9aCGAF z>=e}Y+ruK*IZ4UAx$CvkCqu6uL)DyF8;TCy<`fP(HOF_`&D8nM(`1UZ)^urZ+wsU- zBPhvp>gtsz9>2<75tQuPE9JEE=CfJ(3q8AaOIxDM@0MM!<&Uijv5j4o8)<*XKA?A7 zmd#Wt;loR%)+o+V&6px=Zql5T!`alnkU{dOjmc%FYo7x0GL|VTYs)Y%k$w~+)#d1T zyCZhF_wH!Rpho;u5Y`ayT0|^Ti$&ko2Tn396$Jj zf%D6ohnYdkjh~7CjJ45S{oNuiI%J0B;)SPfrz)SkHnH@;nolxMbe2wW6My>bZqfUw z($%|S({8_Vo5RzT#aq1o#!P`IsgKXo?3n`RbnLNMs$Zb0^L)b8*I#AU&IsCfd~($# z?ftxyU5fV`T(WI%G`8GTdGuV-uM%hH|O=d=qb1M z3Y_yOmCRjJBvzjGbH^+<)`ZLb48ex#mp4}9?d$sYgTNryjea{e*zGXAFD`4A zX8(l$rGUEbmj0>FSIfLi&fogjSKT~(Ta*6n#_5k2o3CAO-?`%F+%Tm+lPw*8IuyL;BvU z{9Oumv#PK6G?&EPIdVer+0-r0f$`;AGvw-GEaMNHt=WE0{aGff*hmVSXJ&2QW+vS}^=PoBMUhS6x4_7}JRN6n1LI?9{rm z`&7mDS5r>?Opf}d>L+T z9)3c`Wu+v~{x|K)hi2x8bAB>t_AI&O`RUSu`h$G`c#jrT^aijuH_9F2+Vj+-|80QT z-Sa`wDTXyRJ!`Mdxw!E8m!BVO-hcny`226!!32TsqfLh&9!T4qxc&CV+izd&>U&qn zykYm;MWHLhc<(-b)^(G~;p2-5ci)OUEZA``J}xfL_X5Ydsasz!(+J$cxcDFA)~#Dz zZRD2!wQ0KhR%F-lvu^|SUzSJ}f8Ss;uim9>eG6lUuItjnQKI?w{&!!OFb1p)G5B_8 zf=5bUt9thq&O5XBoX%i-hiN6@L_ z`ZBAON!3Z`SI@)KvRdVfI`i+GcPkQ|yz;x#@hhB@&d*=9(C)3c#l}+!_0ydg1gALs zdfcuSE+u9EvuOE`V}Ei~!X(~Y5Bd0G5)V($hRIdTtCr~9Nyw@SJ60>4qY{?!J90(S z`u+`*tIj@iZvT}nwybG$klnvS&rXYbec!RO?CZ2C{q~DjXkGvG!9VfW<$M2^o?|!~ XaJY4@;N!at3=9mOu6{1-oD!MFdh=m_`dWM_Zgto88tq{s7n^zUr1E!5^q-QL0wxZ%lP?~lK}rKIlr oxb3Ys4~GErUXdRYV*fE*mk7ThHv8=<1_lNOPgg&ebxsLQ0CrEE-T(jq literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/ebwizardry/textures/items/charm_stop_time.png b/src/main/resources/assets/ebwizardry/textures/items/charm_stop_time.png new file mode 100644 index 0000000000000000000000000000000000000000..f1a166fd8098090746f21a3b5cd915520e4dcd47 GIT binary patch literal 569 zcmeAS@N?(olHy`uVBq!ia0y~yU=RRd4mJh`2Kmqb6B!s7*pj^6T^JY`{xc*!N$-Eg zz`(#+;1OBOz@VoL!i*J5?aLS#7}!fZeO=ifvqUX-YC&4OzPD9i#5I9kNT-RX05D zP+lA@>(Hk*A&Gqr%Pj^AZeOLXJed=6rd@1Y{nPWgeIEP7ty6sC;WGe==j{!Ih?A&ZimX$hU2b)NOhwara!(S^Klx1^c&qxZdm)v$p4X zz3fBr#4V~Hw}oH&VAQo#XQ?Pt=GP@3b${3@F?@U;eph!zZoj_D{~Dh^7Ha>F+A+>J XFjeSlnR_<_0|SGntDnm{r-UW|Bu4Sa literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/ebwizardry/textures/items/charm_storm.png b/src/main/resources/assets/ebwizardry/textures/items/charm_storm.png new file mode 100644 index 0000000000000000000000000000000000000000..32bb5b8c51c52fce3a7f531023e0386252c9e6b5 GIT binary patch literal 1945 zcmeAS@N?(olHy`uVBq!ia0y~yU=RRd4mJh`2Kmqb6B!s-tE)mHN`ey06$*;-(=u~X z6-p`#QWa7wGSe6sDsHU}kDl~Ki|8)X#Vrjg%=*=TZkBaS=E6rbiIsGov@_Bp-Z=v-5 zeb%fJXBP+FC=eIwPM@)v!)AhtP6|C~8}eSm~? zpJT z(Jv;ku$vsCtD73*#6sbw!C-#o$n6GJ}-rCRwT3Tuiz5M z^Lh46I834C*ug9MHP>_Jl_bya5H)xqenyb{%(gd*UCZ0IrF_)c@cEkL?x%jY&M`D_ z6jxg~GqL3;d=xpMwONSqI7gk4O?qL>0fx%+y=NHAn>+&gY@WNxFHJo?uiQ9@yW@k9 ziz6=+M~db1h4Q6>Qm5kf7~lK-;Hvxl8a|T>>T7uHnqIvUUYaZ*wu**zgfoms%d|6GpB^9mz#%gvpFBJ&PP{q*!(d{RQ9WbO_A zT|27{zANV++a3S$*!vmAlXv}RFHQ?8pYeP0_WX$K%C{PuIA#S}7;ZJ1a3kSD^0OJw z=Y1*6th<^xW!v+dZL4p@x-XMGa%}SFC&H%Y+UL&4zMg!k=GMpNMw92;?yL)FjMZ-F z@b@&-HST}wksDe1HRSQ}yqV>BTkOI_PffnEF?G$(8Bx56)-M#!v{$G7ydJ%4ZqnMk z{fZ2KUI*Qq_UtVCtJ3Nvy}2^4)Go#>I3f}qtKT`V(`>a+M&)ZQqhptP_IkanIhHVU z;x}){eZq0-ck`z8Ee?FoF7W1Q(uz0cX)Kd(D=Tv3ey_Z0?6_JwRz*&wC3Di^%gfk3 z*`{5cx&QdoDm$x%S62PHZ0sMlH0PJ8wSjfbea7ZBpWbBnq|e>z@p!}a&ZUZ(I-eWn zI4#qyW^WDKzr4?uBmQSX%B`z?G1fcYtuwn4{%~eKb7R;2x^kJML*E!rdSp$tFzbv> z)<0xE;n|woN3A{`lw#v`5463c8Dw~5;X3n!oU3IOmxjC*^D~KXUtRzFZ~wX3PyZI= z9llc#;1T=Xe0~+%x~iwI5k=GilS`X{*$(Z4rOS z{pQn-7p^JOL@(Uv`>^`a+@h%4vRQ38w;}`lCT7`cuLyQs`ZnV5wuGbdRmi5a8r547{OIFBjcZ45B^^j z|5`monXmHAG0#1DHkq^4Y_F_9wh2cdD5y;eenB}gU!qTUVZ*;dg}Srj~%aN z%)Y(ya`~${@5|5q{A$fpzhybY!>~IK?;lfAJr9)=#AVeie!1N^`BSm@M$yfU^|A~G7i=2V+|rpg zXNrK_fogqbhN{`QC8EE5wm<4CIaahrNB-iw*7lXF8?JrhvpKczgi4X;gv(FW_PuSq zzL{5#(`ZV>igQUzuWv4Qa{kV*t)j=7<9lZD_ALwy1#>5Ud3iXXT>W=gXN=H|*Yd0k zKZJunHdS2tBC>eH8m46>ch4_*Q?m2p($DYtmnNR=IoA7Yg=trY=h`67P=%_==9Y3> WTEhZ7x)~T47(8A5T-G@yGywqMAhgQ> literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/ebwizardry/textures/items/charm_transportation.png b/src/main/resources/assets/ebwizardry/textures/items/charm_transportation.png new file mode 100644 index 0000000000000000000000000000000000000000..75f8e7ef24afd4c8d31d82555c7ba56aae1b53c1 GIT binary patch literal 556 zcmeAS@N?(olHy`uVBq!ia0y~yU=RRd4mJh`2Kmqb6B!s7*pj^6T^NEGf*72wYtJe$ zFfecyctjR6Fz6|RFk{71`!WUw2KEw9Usv|WEHZq0tcP~Q9%5i%kSuYHC~?lu%}vcK zVQ?-=O)N=GQ7F$W$xv|j^bH7a*+;-(mLaXM@ zoX5Js)=!sykXzET{iesKQ?4`Z6Jlbf{7>+|E^!<)D7O1RJrj}Li0ZFbTB zRqbX5uiZXtisi)m_3tiN?F*XnBz^MMt+^l5nooBti8dQ9a?qQudvV(2iLbZr&^Q^w zbL@o7OC8;{8#Zn{>ie#%vC-~$T@I&-ZjS5XV0RQq{u)yS_@hgtT_7 zIuQJ3l11$g_W9S9c{V@TbLjg?O~wr~Jtplvr@WnQVs!KQqzau+syVa2t(^N~j~oNf z<^;x&__PjQb7Oh?Wf~_B8F1&Q)>%ngNKXA#=((vv^N&RZ!={>|vPA@_#`s z0|NtRfk$L90|U1(2s1Lwnj^u$z`$PO>Fdh=h+RU+lHGp#9X|#JCRtAx#}JFtTPN-J z7fzHoZeM==-o$Oo7aS2PDNwLdGLm5b%PiBgdYKTT=wk(D9XH=#VGoI{4j#T!D>|8* z4QFTtUU{K5sfqWA0*k?xE|Y`X;?{qEUAkx?qxfR~Pb&HMp8u_Dd;a&p|26XtK7O?R z@b$J^t?zTYRx_^+^@v}Td)zv6`@*H!NlVO+PMP^^hR$W-_e&hFFMWG3rACUO^7SH_ zz}BVNizFN@SSM>5pZ#-(IjvWu^PY;|Md8xQsRgc!HTGz&;QA0ded0Zl@I0Qy(`q#Q zABCCdTwgjR{@6ENhK*|(IdWw0G=U7idq~zqljFd}U26ND8U5IA!qla3t+4ULzr#E> zJH2@qtlsZxQki&+J^#_%4HI=GQ_m)9PCpo_ol6ff+In5dJ$6Fx(e$}d4hjAp=cT{TGz}^#El>EV*FUfC zV(nkK{CVjcdPJ9a2`KMAajV_;m3hdnU(qh20^4FTOTI|H@8&+U#;@RIO^@47x%7Xm z46ABbtn)Yj+vt(3>Gb?*w?@^DZ{ml{E=`{`rL literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/ebwizardry/textures/items/crystal_fire.png b/src/main/resources/assets/ebwizardry/textures/items/crystal_fire.png new file mode 100644 index 0000000000000000000000000000000000000000..a044d55235cdde80cb7c9c812b16fee0322356c3 GIT binary patch literal 623 zcmeAS@N?(olHy`uVBq!ia0y~yU=RRd4mJh`2Kmqb6B!s7*pj^6T^P|vPA@_#`s z0|NtRfk$L90|U1(2s1Lwnj^u$z`$PO>Fdh=h+SMvjESjxg&G3`;~!5K#}JFtTPHhu zOiq+IUZ3x}ku(0RXy2KW)fSR^FVJ@>o58x@M?)SkePyrZ(CyZF)A}^`jrr|ByE@l* zx1B?RfBwv5T7LP&=lAZ{G)~k%JM~A=u+Fk!;acgy6AIn8HGMR;eBl$=FTN;G`^}au zNhPHh-t(MZ70L4_3eJT@hqZ@n@>Z zu00wr(|`Qt|7;+_xOQU6BimN?WEE4$C-1Mma e^I`j=`YRt_U|GJVe+>fz1B0ilpUXO@geCy+ffI88 literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/ebwizardry/textures/items/crystal_grand.png b/src/main/resources/assets/ebwizardry/textures/items/crystal_grand.png new file mode 100644 index 0000000000000000000000000000000000000000..ccb7a620cd182db086c3a632a3895c6a0f1bcf52 GIT binary patch literal 667 zcmeAS@N?(olHy`uVBq!ia0y~yU=RRd4mJh`2Kmqb6B!s7*pj^6T^P|vPA@_#`s z0|NtRfk$L90|U1(2s1Lwnj^u$z`$PO>Fdh=h+RThUTnIx=z0bQCJj#)#}JFtXD9i3 zOlFigUSEB`+|2u|Lg^AQDL2-uOPym=*fllQE)5V04Dnc+TIV(+LQaLLcZJ5w$6`_v zF0!vwV!Iscj^4SFnQ?aF62&(&_ufBHlVel$jO)?9o=dN*^gcL+<^tWWJ==)rWr0;@Y)aj^To_!SQ>{?kiWX zciH#;8pAVX!#TVEbtEik-nA%=X(5Z#tgdxGCBE$VIJ@LZ!=Z)EtrqSIYor53|32qT zj7>iFHsz41>&KHaRlDXnsW^Ew@3>KMrNb%F)3PtIccGp6ds}Dj`UM7`Kbq=oZ$9}% z#4P&r&xE)(NAb3|#vUHY83{d!@1r-FElH}r*mhEZjX`w5-o^XvZ1qY`PMUn!_;_*H z`txcp%#H0VPOQ Y?!GNiynZZ-fq{X+)78&qol`;+00$r`+yDRo literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/ebwizardry/textures/items/crystal_healing.png b/src/main/resources/assets/ebwizardry/textures/items/crystal_healing.png new file mode 100644 index 0000000000000000000000000000000000000000..9caa21f164d2a23c0b7a4f57a24c6cde49fc24d2 GIT binary patch literal 618 zcmeAS@N?(olHy`uVBq!ia0y~yU=RRd4mJh`2Kmqb6B!s7*pj^6T^P|vPA@_#`s z0|NtRfk$L90|U1(2s1Lwnj^u$z`$PO>Fdh=h+RUMTai&C{VM|l<9AON#}JFtTPN?$ z4i1z!R}+}yq8#iQd_><_peS$V^C;bf7E2OVFi z3AzLv@swd|QpkOJ?VyvvwP`Bm_su`vn^WEI?2*ySD)`H%o%wwK^F8OQ6ZF4+`6iGr z#=q*nS$%}fny9mTylf@zi7Ndw;XT5^(=r%~qMlx6d{xUU?e5dX8NGs*B$JD|PG-#Tpm>UGL+2o_WRR>+=O)U*FxitKmn2 zL+swqt-HR?$#PbD%M*81$)rdq`>W`tAIvrxH(&n=lCy0{bAC9*?(w>r5nIDP_6B9uFPR)#dE(@Bjd=C_4U=U*xc)nAbF z(_&_-OcTS7ODww^mq#m@7q&PaxlquuadGQAVWmXg@L4Wj44D`Yzopr0C}4YtpET3 literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/ebwizardry/textures/items/crystal_ice.png b/src/main/resources/assets/ebwizardry/textures/items/crystal_ice.png new file mode 100644 index 0000000000000000000000000000000000000000..aee7e55a3cdd69ae29c2da36ef549a3125befc4d GIT binary patch literal 562 zcmeAS@N?(olHy`uVBq!ia0y~yU=RRd4mJh`2Kmqb6B!s7*pj^6T^P|vPA@_#`s z0|NtRfk$L90|U1(2s1Lwnj^u$z`$PO>Fdh=h+RTdUj9|q#hnZcjQc%Z978Nl@11O$ z5gaITy#BkYul36*w^j&DeDp*iPp?csgk|Hbpxsl1j$cvqs_B^Ir?f<2{WaGmDJz=0 za#wn^gmKqxY4mfnl5BSAxM(Kd>X-THlV7{p!Y8Un%RcZ=KW+QH{@?eSJIw!?l`ehq z`z`)__TuDC(>>-!MDNc1*P*DSWc~Xd)2|~-UI+Wf;Q@m$Pa z2i4^hJB}CRgst3Wy@2a|kB2SO)iaeT&$x5*x=U(W|GbKCV|Ly%Z(g$U?qgSeIA7h; zu~qK;@=1UGee5l%Y5khSINdq;w=rccYg6QOVP?~A40TISUukKS%R z&UHX*`jSh|vPA@_#`s z0|NtRfk$L90|U1(2s1Lwnj^u$z`$PO>Fdh=h+RTdQGWIMQ%4vWm~1^=978NlZ=D?L zF*#A>c>VjRbC=Yr9=eNhPP(_GRzg(h)^wpM9v(@Of>Nc*87x|triv@C^w8I8b+cEDixBj@~qtwA?Q*iFErTsa}Km334ch~K9 z{!{wt;obDF>#!#_MDg}`_dvs+WwGZS>{C9*9@9l`Wi}m-UwekB$JwQ@9Cn1bgQ#- z*WcKu+WA#Y`PH1}wW-HTJXjud=P2L5q#IX$UrF1xbJi!DsA{&0CXP-?GMXnpa+ESQ z^e!PYVD;iy6;_N4vS?k}cdz4Tne|~hf*&p037N+F>;k;kc zN(-m!hj-U(IGQ-riBRvuW2fy`ZFNMjzA?I#3(G(ctLvz)ABD zZt*|7(!(NU_P#BGH&1?Sp^ literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/ebwizardry/textures/items/crystal_magic.png b/src/main/resources/assets/ebwizardry/textures/items/crystal_magic.png new file mode 100644 index 0000000000000000000000000000000000000000..e74c1d92416eb837101d4c621d21ed7fe805f8e8 GIT binary patch literal 519 zcmeAS@N?(olHy`uVBq!ia0y~yU=RRd4mJh`2Kmqb6B!s7*pj^6T^P|vPA@_#`s z0|NtRfk$L90|U1(2s1Lwnj^u$z`$PO>Fdh=h+RTh-oVvtLJ$K3;}lO9#}JFtcPAQp z%nlT3-T(d9aubcO>k}?;O;zGZ`3ha;3l6et$`dN6*T&H4o?v1ANcHMT>$hj|I@M;y8qu$2D zdAmHiGY%-~uc&<*wPu}ztA)nr1}0yXPwFzK-J%*|maRE$dOh5B#$28(=XY6}lW$E( zU2^k)=i=_aPXv#qS%gf#CBLomVddHP_BUs%O}k?G@1bE0v;IV{hXoGN+fTagK9D-A zrAFDMdG(S@FZa(`|Lx`_$@Z20D%;FH@a}u$taEJU#Uqtz{THfdf4C!4yVq8w?nvZM z3&mH`7!mg_Oi|0PkxDMuMRBC?qSGhZ!5h&+s};O zFHpk9X77=!w@#fue_QAL`Ht%3n5a2o3E59WG*~xjXx5#+{I)JmRsa0E$Ffz&>Vv|Y Y>ZTTNDqGIUz`(%Z>FVdQ&MBb@0GZL>!~g&Q literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/ebwizardry/textures/items/crystal_necromancy.png b/src/main/resources/assets/ebwizardry/textures/items/crystal_necromancy.png new file mode 100644 index 0000000000000000000000000000000000000000..b7a1a759661abfde6ab687f3b99f8be91c681e0a GIT binary patch literal 588 zcmeAS@N?(olHy`uVBq!ia0y~yU=RRd4mJh`2Kmqb6B!s7*pj^6T^P|vPA@_#`s z0|NtRfk$L90|U1(2s1Lwnj^u$z`$PO>Fdh=h+RTdj+1?9=t>3##+#lljv*GOw@&u; zxLhc4-2Q){?|-YaTiwp(I$ABhapvZNT`tv*hpLx9m@mwJvhUK;MnT8xe6m%OPpm6l zd3cise`3M~s}!*nPork5e0gMVp6&d-9a8XUs)143eW%R2eKGKREBXa%0X|0dl)#<7d- z%t$y&Nk&4I(qN=?>}}ZR!=|IYPm<><<)C#CoG|pQZ(ElHr|L52Gmi=;vBM(~hxc~cX z)bY3W=mCu%GcCjo3=9lRuIr_|c~gDnLwE2L$2RvF4-bEj=6NH(ql24SB4SGdlQOgO z#sBql{!9G(o1BpFC`suaD~IzhiK&${Btw7Bkeqr{Lb5$mh@D~97}C7#J8l MUHx3vIVCg!0DvEt9RL6T literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/ebwizardry/textures/items/crystal_sorcery.png b/src/main/resources/assets/ebwizardry/textures/items/crystal_sorcery.png new file mode 100644 index 0000000000000000000000000000000000000000..9b76a9778d4a2475e376befae7ce6b72844d5741 GIT binary patch literal 620 zcmeAS@N?(olHy`uVBq!ia0y~yU=RRd4mJh`2Kmqb6B!s7*pj^6T^P|vPA@_#`s z0|NtRfk$L90|U1(2s1Lwnj^u$z`$PO>Fdh=h+RTdL3-;=`#B5@j6XeH978Nl@15-L zaXC@unEn30nrAGR8nT&9lok5&Nb~aKD+hTK+xc4U`%h=F%w8P9`7l*3=?35G(`I|# zJTPNB#nCCmrIIA%d~>1bMi-N#n%OxUcg@Ie-#A~|wb7A(&++GnKi5{o{g4-OnsZ0z z_nJd>kH6hlbmDk2!8@iZq?)1Vgz7e}>P7jVW^K4z@=r|3lz-e|PTQ z@t3j>GxwcoxaOlJx$yo1Mulh_74aHP#uc*)e#?7?PCGHBjI-izOWJh9u+Sxw1fOuq z*ZEITJbqQJn`y$5s2N2o#s6++YW$dHYHZ&wQmg|C;@UWtTmz*I(}!KA|}ML-nF1THYmb zl25O8vz$+tdmJ%aJ@{7Y(jBK7uJJg`_EVpGH%z;A6~m)*>XUMB`R=@Oy8n#Y_hauK zM9faVVX$IG^p`ZQ+pM?Buh?|EO_@BEujt^CDbs1r;MT{^>8O84VVg-=IR z=HE7VxqF9Yh5M=8y+-4)MoM}1_lNOPgg&ebxsLQ0B=(fxc~qF literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/ebwizardry/textures/items/flaming_axe_conjuring_0.png b/src/main/resources/assets/ebwizardry/textures/items/flaming_axe_conjuring_0.png new file mode 100644 index 0000000000000000000000000000000000000000..401c1591d338c5191d10af8b21f785b0eea165b1 GIT binary patch literal 1979 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 N44$rjF6*2UngCM%i~9fo literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/ebwizardry/textures/items/flaming_axe_conjuring_1.png.mcmeta b/src/main/resources/assets/ebwizardry/textures/items/flaming_axe_conjuring_1.png.mcmeta new file mode 100644 index 00000000..eb5c833c --- /dev/null +++ b/src/main/resources/assets/ebwizardry/textures/items/flaming_axe_conjuring_1.png.mcmeta @@ -0,0 +1,12 @@ +{ + "animation": { + + "frametime": 2, + + "frames": [ +0, + 1, 2, 3, 4, 5, 6, 7] + + } + +} \ No newline at end of file diff --git a/src/main/resources/assets/ebwizardry/textures/items/flaming_axe_conjuring_2.png b/src/main/resources/assets/ebwizardry/textures/items/flaming_axe_conjuring_2.png new file mode 100644 index 0000000000000000000000000000000000000000..4317eeb8939a9ddbf6dea487186ddb9a729c049b GIT binary patch literal 5994 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 Wz-(>t7kT~p?_cjf6(28u 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 TcI;^e1_lOCS3j3^P6(%dC? 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 literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/ebwizardry/textures/items/flaming_axe_conjuring_5.png.mcmeta b/src/main/resources/assets/ebwizardry/textures/items/flaming_axe_conjuring_5.png.mcmeta new file mode 100644 index 00000000..eb5c833c --- /dev/null +++ b/src/main/resources/assets/ebwizardry/textures/items/flaming_axe_conjuring_5.png.mcmeta @@ -0,0 +1,12 @@ +{ + "animation": { + + "frametime": 2, + + "frames": [ +0, + 1, 2, 3, 4, 5, 6, 7] + + } + +} \ No newline at end of file diff --git a/src/main/resources/assets/ebwizardry/textures/items/flaming_axe_conjuring_6.png b/src/main/resources/assets/ebwizardry/textures/items/flaming_axe_conjuring_6.png new file mode 100644 index 0000000000000000000000000000000000000000..56bf06f4d706775eac859244abe75869f4d465ff GIT binary patch literal 5743 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 bXLxJ1=a&D{rO>g~>JbqPh!O0$;^ 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 literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/ebwizardry/textures/items/flaming_axe_conjuring_7.png.mcmeta b/src/main/resources/assets/ebwizardry/textures/items/flaming_axe_conjuring_7.png.mcmeta new file mode 100644 index 00000000..eb5c833c --- /dev/null +++ b/src/main/resources/assets/ebwizardry/textures/items/flaming_axe_conjuring_7.png.mcmeta @@ -0,0 +1,12 @@ +{ + "animation": { + + "frametime": 2, + + "frames": [ +0, + 1, 2, 3, 4, 5, 6, 7] + + } + +} \ No newline at end of file diff --git a/src/main/resources/assets/ebwizardry/textures/items/frost_axe_conjuring_0.png b/src/main/resources/assets/ebwizardry/textures/items/frost_axe_conjuring_0.png new file mode 100644 index 0000000000000000000000000000000000000000..401c1591d338c5191d10af8b21f785b0eea165b1 GIT binary patch literal 1979 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 literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/ebwizardry/textures/items/frost_axe_conjuring_3.png b/src/main/resources/assets/ebwizardry/textures/items/frost_axe_conjuring_3.png new file mode 100644 index 0000000000000000000000000000000000000000..754012d9f38f9f57426fee46914a8ac85b4346e7 GIT binary patch literal 2012 zcmeAS@N?(olHy`uVBq!ia0y~yU=RRd4mJh`2Kmqb6B!s-H&=y3lmsP~D-;yvr)B1( zDwI?fq$;FVWTr7NRNUGd?m0Xvxd}|D>MD*UVAQcX9r5vbwup#Zzyw@Y{cHrmb0Xzc_jQxyw6t+7?J8ZP}Aw zYyVC1aaFzI2}%9)kJYX`R+n?1{`~QT=V$olCX4qgmsQU>x7YLeULF3^mhpV2kDmSU zHIC^(MwesRu~M~dKfV@=xv|W#Sls(sTsS%9o2+r2=sCM1=kDy%e{i=-|HjRlV?QOi zlK&ch(3hB7c&UG5G{@czWoQ3<#qY1CesnlBd-IBH&DHFOnKUZ* zJ}YFc5&gSiU5j>7r|1In4Uq+*&YdzBOyie!%#=QONpOzfy^7su+?(xp=Jg$$aY=R4$2QSN zMZpam$wub&iL6c;GCrjbck6v#ApP4xr`a*qz+K1S_NG{orMtIPd_1!uSo>Js&ftvW zj0%VDbR~2gZ1{S_YhF%)o&e)eMMMx6r+8y|YZJzdgEIE&pdtpk={?1qa&&k~|dM`-Dt? zNhI}XK6@gxxFz$G<_wWwFU#ahJl7@j(<7e5#5`1T?bcs-WRlmq3I0=8UA-QV>}zU% zeTU-T+4%>z+z2{7*J{a?rP<$YzuX8u&m1Lflk(z&a*xHO6Xw_WR-a#Uk-Ip4vs?St zlQVR77o_tZR*cchm?k`TPNShZ%dx{L3{7Q|jio)0_&!rhKar=>YPG@5>SU&gBy;nn zlP?!YmzO`=_vGw~nr`#&lErC3-_2(jPu_L-j&;8LhHIa01y%@}Y%WO3s$8();DY0C zlIB%k>W|)RrTqDuDZ}jt&kpT5xGeg0s&&w}+bX6lFL(N@83a{rT3i;)KCMoNOXtYC z<15bG&pvyb`H0!Nl_?R9lJ zpH~%iE^XVpA*A|A)U+a=X|W7Rz0zUUF+S4#Q{q}`zf4t_qqtx6iS&-6dF(S+yySD4 za7uky(-ofTZBnz(3LDH(Oz*qREVtoY-G0rhO8d9HX7LFW{q|}po66#2-hVs}-PyQB zw4!y{*K(=0kgq2+jtkDb_%3?w;VFkK^Pg|LcIvm_uZE;C4bHY zI~!WtZhX-q`|d`)nGY+szCzvup|Q^5+~9D-kUte9aUFXbT1F7)j7(Knt-OJ|-fS$j8^+wtoA*%|%H zNBTs6`&|q6xuf%DPqJ(2jwDm#8{3MvRa}`R_*LiJw|~8l()yh8N{vs?NPX0F@c2Tp z+Xv6tYOZ@Lk?n4g{Qa-ZdMVqU@9l{aI;Y*F(k0t8OPb{^h+LQoz7jXno+Kq*}?6ha1!Ng`16!Z2Y^Xwck5~Z?;j{ zyVV_KQ%+ZKG5vFj*>i5rFU$I8{G8A3`A4#>{jr!~ji2D$YVF)#jmXhj{y7Yy;yxW|*V=uEtZC}wURAe10^i_Y}6Gy3|=LHSyZ@tic zzIp9phJrWB^MkZC&TWegafBQ8X_Mfv<{R?Yf zp8nIC@UPyzM>)gjKjY0U=C@`EtHv@gFt8;_2(k{+NSVP~6gT@uMmR2F6vME{-7xti`r z{{u&omWy8ea!i3$T(!HYyQxI9w!umBt+a>v-7k{ASd%#+Ie!e?w=hy#H`|R`N$qudqk!Kkn z6hGtGnsU(aF0WWm(-(f}DQ~U5ezJVdxcZq}~4+2^hBM`C5ThlF6v?h`*MrhIrI5nOxl9ozd!?4QD$C;yzg$@QH6>)X&+8=zd@IV*_-v=S zC^h#Sd0f(bn`hC=EoaW1N!;_ZA^MhTqKm|fizfH$?PhtM{xUtZbJ-=P4Z*n`^6PS2 n4u3tm`g2J9h5BE$C5+Olvjq5sWU3e#7#KWV{an^LB{Ts5(=^HY literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/ebwizardry/textures/items/frost_axe_conjuring_4.png b/src/main/resources/assets/ebwizardry/textures/items/frost_axe_conjuring_4.png new file mode 100644 index 0000000000000000000000000000000000000000..8f100fe010698d1eac620d360dcc6144ab1d5dc8 GIT binary patch literal 1996 zcmeAS@N?(olHy`uVBq!ia0y~yU=RRd4mJh`2Kmqb6B!s-w^xNklmsP~D-;yvr)B1( zDwI?fq$;FVWTr7NRNPt{o;~Ta2G5`Kn%_7$I9ZNAjNEE|<8l7yf=Qm6KHt(`XDD&n zsbo7#@-O>({?Fod=QbKYGHnxSI_f`3W%|X=vj1h?Vb}iJ+*tiN@y?w%3m(I$d;JUL zfAgW5W-LZal(uLHdTyj#Ud?_%ir~vZiDP#OE&U5;$7AJY(+azUvVwr6;etcAe>N z3%+ofN1`z1pj7gWyGaX8^P@h8cFou+s3Ut&@?rP%(|e@iM{y?{*bmFRIUHX6LkPS&(>b#hNvX;+j{v`OZ>y@3d=M zVR%fWxTrJmPz{%-ZlEp&E13AmTO%sTQ#Jg=a<8wZA!|1-n>9Q8 z&V+xuCZ@XEt`sfj(=2_tuYH~Ew=16;uCeh;*0n5D?lbw+yY=uZ_iHaYcb<=2eE3$1 z&$PMsA`fqP^|UF?^5bMibnyjFFyZ^~gaPu@hfcau4Lrp$Y@;_j8krSjcO+#6q) zZn4ifdz$-**}9b}AqgU^b#hDG`QSs}qbjaEzG%?p`r&7kRam2M*EWd_zprlkC{mPI z%F(?gclPpI%GWpb@J@?mNa~divySnR=ARPRQu}49!W_kTu1`N*?{9u$w?ira)6(;0 zF`e@{ZK_SpW~(PyIG>Z*&Tf-1w>jQ>Le|9i--lUz0!7W{1c{z}@mRG^CGlOvEv`LI zm;Y(=I}^o-*!g=+}#$I_ra9aDJ|RP?KJ&y+zA=f0u8Q-1=f;_g|4%h;r%8s$KmGuRgcnIpU>^HoN>VV$2-Y2Z=dKgx~9AAKe=|>_w}o1S57;%wjoV& zg?N$0F-fBb7d92MpL}tPZ)2H@@vS7@+c#{s$i4b4b#L(|=Iwl@FVtrJv3q>R{M4=B zXRf=va!*wWH*;p`tJ(Uhamy=3PMaa8eJeKa?*f_9Sueb99i8yIPB(kE(?k2kasg-f z<}aJDLT+c;#g^FrE)ud+9Bij%=Y6-^b9dJJ>sQYw8-ITgmuy{W<}bJCXzm*;zMRh- zg_DGq&vV`R)6=VFn%1*ZQ%jaVNsgH2|Lgo=zDZl=IFRFa2@}{7mSGrstcB-yVazk_KKaKrj6W64 zLQdE-Px^UZAjPDy`=+1+U8$8 z=;5j3k|C14^^`rPSE zPo#!cUCNSKofA?%74DMw!z7%3m3eyg!+FnZ&s%

    JKR7-uh6NVQbPu>ySH2(Sniw zDxNdh*Qih8FFz^XVz+kL$tkXWpHvOc%LYATtlqhZeSKwtvu;Jk#|fR6bAM((XV`Ie zH-k^DrL%5CLUm=7E~B#0)TQ~KUtHD7cVawuw<}F#-H99FU%uA4{oSMxvY6@X--X*J zt*-XFZvH~|EklZSlj)LITLivr`+G$G$+0DGVixV^3M%9_*}C_!&RjK{NZ z!tUm7^ZnWNDNI(qzGuH%+8^8fiodWRC(PTrQmQF`qSLejckR^YliuYuC!~wZJ2n1d z+MhhRXwTF|Rn-SSs70y0|73T^dG@-i^}p{f>JaQab^PUgBk|u_)jJpc_*dGWD7yX0 z3YC9}%0heFdp$zRy8k^;H+~@@@wh~_ZSUqaYj5`HC%-LZEl;mbk9=Hz)c&*gCTk_r S_7DaJ1_n=8KbLh*2~7aaQM3a9 literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/ebwizardry/textures/items/frost_axe_conjuring_5.png b/src/main/resources/assets/ebwizardry/textures/items/frost_axe_conjuring_5.png new file mode 100644 index 0000000000000000000000000000000000000000..f43d6b4065bc8996b8165615e51426d312597ba4 GIT binary patch literal 1977 zcmeAS@N?(olHy`uVBq!ia0y~yU=RRd4mJh`2Kmqb6B!s-H&%s2lmsP~D-;yvr)B1( zDwI?fq$;FVWTr7NRNUGdo?T?3&hzKIW)aH~??)CktBaat?0GYey^g&-|E*W*aXE<# z92f5j?N0mi`MXK|!^bfK!b;w!G$U)A_-=}p9GQ1M^JH7?b@uAgd%d%(4<(*h{PnpZ z?^b<@{(Sv{3m<>g-6;sRU(}~}{?&!`Q)R8P)L)(0ZS40eXVbp$Lx;=0-2YrwC~a@g z&L&}-biw*@n|gksf3|2pN6k0ZwQsD&j-7aA{r*9`mXp&%b@A+7+cs4jtZBIP{<@If zv3i&J-=`LGZo9!y#Xeg!+<3}K#lGpH zdwjuiX@f^K%-M2>-}SYA+f}*#y2pkh^$4pb<3rN=(|=}sFu(pb_*i-TGe`4pjS>88kJ}r;sXV zx5u!GNcz z@Y314(#7$g(vp4%=D#z3c4pDL{R!uEUQO8v`*{31OU~u;fo-fRfudM&= z{LE7$$Nh8<-(uk|ZgrPAO=snou>Ve4UMTLG%6U*WwTN~a+Z?RZ8@z)3*t4GLEsd^g9Lg3q4;|Y|P)GetD^zMC%Ia^SKLN z%-pOfa@frO$qJt<{mmDmW;?aZIJUZ6dNGYf+DY%}qLcG{ofjRmSAE8Xi zShsgk6OYZDZq~N`r_F*{Ew9eEDRxzq1WqnrGP6C#VA|%ZCS4wrssCzsSXSWk$4gx8=P!S&^?4Q@ z`7+cnapi*hmYvQ|*p8JPx$UpoeOM`+dHTAeeC&N!TVAh~zq!CD%5vjlb(i2B!Yq)KC2<&?LE3hZl zwM)xDiLYbD(hAYGERzyPMn|t3Yl3oOF7@{@ex52Mzxi43m-0f>qs22?*6aJPeCij} zU?b9dKk19@*II{VmC3Fdh=n1fkRT$1VRp-l`7jGdk?jv*GO_f9&f%@QbceE;Dst92%|o%V3b zpUk~fb5haG%M-fo6Yj=L5oSN<_vn#ZP*Gsg?Uq}cqNDjXrEWIf&3?-5OxN70cW=i2 zm07lRb=kE!e_nl!`&&2v{`cQ??-|XSeui#Xu#=%-?y3#4XVyR3=TIWZ73|Y_*;OOv zTa6@~}Ov)LJR-r6<2 zUD1$stuTz2#dF!!Uf(%KOnkm?T@;+tIKlg&t9Rk!WaR{RtqUm+8{STRUp6_*Wa_

    9-fW&Xv>$_K7q?QK*`f2%H{ zGLtQw&vQbG)U7V%S%xd7RG$!AbFjlPgmb;><&@voLl2!W8D=psFfe$!`njxgN@xNAEupem literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/ebwizardry/textures/items/frost_axe_conjuring_6.png b/src/main/resources/assets/ebwizardry/textures/items/frost_axe_conjuring_6.png new file mode 100644 index 0000000000000000000000000000000000000000..af4cd7b57f545018045e319f4ce19eef35cdc2d7 GIT binary patch literal 1977 zcmeAS@N?(olHy`uVBq!ia0y~yU=RRd4mJh`2Kmqb6B!s-PgaFQlmsP~D-;yvr)B1( zDwI?fq$;FVWTr7NRNOimo?T?D$@AyD<~I%wMxo;mBe$C0c%1)vhUXiL_3O7~*@_-E zkWwt&-je*wzMlWHxZOEcQ@f61B8!h6SDznq%;oLBHxt*y-+z8AZgP8Rv3)^AQqP|J zWczQDuOGf;{g}SjW}WoP>oIaZS zr{+Ct!j=ZtvSX!c+kW&Fi@UMRu}Hr1wYPVp(eu8_wJq0g%&h*!a?iH<(79)u&-DjL zNcTI|9D1=PxT5#2(~Hin+0WbAmqu)SZ~uOS^x~HiwdvDqS%NOkS+XwV8c!Q*z^5wR zM?!yC&!on3PFFh0bwT=u&W=?JUHCHiKV8wdykOrkFHyy+>vI!I)>*}6pL#TDb+?GU zzLcMXzj4BmLe}h_)bis_+4r}6TfOAQPC*^ngOU$>`KMQI{h@ySZAOn~tkP=pu#VHd zj7mKx@BC>K6;@)^7cUN0eN>wRSq$UA-QVJav`n)jKhd z+dk!Q?999sbb7AUk}I|Rwq-AG1)pb*lD7H7q0A>~b?Jn8cKcQLYcD!?u8&-N_*Tjp zee23(-qT9cxo5pq@i}*3#%GpesYVQryHCyx{dCXwnOeHpSvOIch{XmcGfgC!oA*uT zZq9pmZ^rLQ=E8s0R}{}TOjj%Y&sv-oR6gVPiQC-QqT%YaG+%b6>-$qk;o=xphGO_O$6!ov0vipP~mzCGTG}xZz2`igZ`$Q(IUw?WOYr^n9$M^xmBn z@}7MDi2L3gK}Ca-pqu#*m+JiRe7^mgt*hDcD&}dV@TQVVg@5Az_#F7)Wuhqq;zxc2qJh#eb!v)Rw>9cw>Pjk1=st@18 z#{M`zt9be{xw&ofTEHcdE4z1D?(?my zF3vUmw|<2>sNb+;A_W<6iE@I@wJ>MFK6?Zq-!`yPJ4aYQ@}b4U^ZlhrHcnY_Tw~Bw|`+|#W8U-(|nV`tR-DebrUqm8Ob{h9}Rb~w4mw)0(_`zz_y z%V4Xs`B#59yqDc%^4aqI`%;THnmiMxKbBAaqFLtttjYMwiEK0enW6p)W#1N0^YcF) zn6;EW@9g;#f9p)vGylCHB$r(M@bn+{gMa4tvFy(hKJr~(r%6ZR6vNX43=9lxN#5=* z43!K~3{&5n|C+lg?|q1WL5c*Y<3iv@6W))8iXKyHtbB!p#3OOW)Mc7Mn8n>JhiIhg2r# zOu3*kWmce(S6*+y*``_EhLaKx^45xNmt5SlQ#*g|xs{)7-~XPwkJ)a?A~UUbx(r)$ zA4h9tCGS+)mFT4*Gx5g1#wYLjyd+BBE!hw=alz!Nt%tX?91^swEo60gTUiikSds9w z>-9-POS?jb4SDkzXGH9}dSwx>||c1GDxqFfcH9y85}Sb4q9e0Pl&a AasU7T literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/ebwizardry/textures/items/frost_axe_conjuring_7.png b/src/main/resources/assets/ebwizardry/textures/items/frost_axe_conjuring_7.png new file mode 100644 index 0000000000000000000000000000000000000000..0824b1eb3fd9f38e51aba36b085b5ac36ce5127c GIT binary patch literal 1915 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 KxvXx} zTkkBC+0@(l@Y&h(3fk{%{?GXH=y-Mi_r2c_?w@!3&b##zzO6P}43_H|*cbC0c=d0~ zmhx$_j0#f?tUg>csP0{B%e#Po#q3PZLoWOD#lnqL&IayzH1nF;)w5eNu5~U`*|4$r z?B~7h;WbPOc41--t9S3I`t^9W_l|uYkCn97=?B@yOn15|_Ean;UZrYRTfW}qJLewm zeR+q+nnx|&x~b>SlSg~6eO3Kt<*?G)ZKdR$iUjUyv5L>6V$#kRKGMG<#kW_P|5bm8 z#%%^i^X!!^3+0|2xhOKT`DB2P%9r!2O{3QK@8|yV+RClPnt~{&Az`&U1>Eak-aeC<_e~sos ziR1R`Bhr>;x~Sco%)HetEBaEI!qP&;?kQ8kCQXw0lPNBq*Qdh%cEeP+j^@R09BwyG zT6AUGp5WkH)5;<)pU>p0+J5iHwacGhf48x%-*-OzQNM>M3#aPI{fbk$&h&rjdSw0W z+d0=Kk*3=h9jS17w<&powZRG56012bkGn3IOe+60BO^v|Wz&L;i#rbeOZ3?4u=LjR zd#~0$xx0n)@z13!1=j<#*O;|$6BVmD9C24H>g?Gicbgd^a`~1VS!ouQK23QEm(!1F z=j;Alc@gEwr((*Kd{Fxdr~1YNZ0nbat;m0VL;ldyH_2r+K3cn-oIEF8mt-`Eesd-C zDZ_=QSM}Fb9ecIjzsTHio)G_?^!c3e`!{UeymoKHe+>ttISYSnY%5tdaq7{`X*REK zO_k`?ew0$h*RW<~D}T=po4XOYd@GlqUE_Odf9vPjHog)!N{vb`#G5T&6tlr|{qX>e c`%k1Dm$p3Z$c+qTU|?YIboFyt=akR{0AYdC%m4rY literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/ebwizardry/textures/items/mana_flask_medium.png b/src/main/resources/assets/ebwizardry/textures/items/mana_flask_medium.png new file mode 100644 index 0000000000000000000000000000000000000000..e256f6c5b75062abe8caf17eda3eca746c845076 GIT binary patch literal 470 zcmeAS@N?(olHy`uVBq!ia0y~yU=RRd4mJh`2Kmqb6B!s7*pj^6T^Rm@;DWu&Co?cG za29w(7Bet#3xhBt!>lx4ba4!^IGsFaa~5xN z<4)D)Ia@@UCAgKDnVFfLx6L;_-28mKb$`|!u~@U_d^H>^rMr1s<0`Tzg9+QfM7a7BUft!dwQ(&g;__WSB`?{bK` zVm0G_K+c|mPZou22lhOh5%MKI;k2I{8yj02^P-yng_Yumxp!{e$FsbzE`7q}X-PjG zJU(~ez<~n^33(?IG=6q9YB2wL7MH-m8T{}3fddCL)OEksKdcpGV`F1G_P^-g|IRMf zj6eUTgLKxWiXUDZzFp$pXK8~y)juXRHa0dIs_L-p=bj*Z{H%MpgkIgQqXkbs#Ljuy zz&ZU$bE+?o%=H}-b~PgDD>ORP?>6{;K4-LN_t%bxcekbUxIVnPWa$xO{`pDWDO;ng>swJn)x&zbeCAgQ9Et$1gT8 QFfcH9y85}Sb4q9e05{^q%>V!Z literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/ebwizardry/textures/items/mana_flask_small.png b/src/main/resources/assets/ebwizardry/textures/items/mana_flask_small.png new file mode 100644 index 0000000000000000000000000000000000000000..4d85ab29cab79826b2d92bb43737869dc9f17533 GIT binary patch literal 432 zcmeAS@N?(olHy`uVBq!ia0y~yU=RRd4mJh`2Kmqb6B!s7*pj^6T^Rm@;DWu&Co?cG za29w(7Bet#3xhBt!>lb$`|!u~@U_d^H>^rMr1s<0`Tzg9+QfM7a7BUft!dwQ(&g;__WSB`?{bK` zVm0G_K+c|mPZou22lhOh5%MKI;k2I{8yj02^P-yng_Yumxp!{e$FsbzEo0y z|DW>*4jf2G$UB*!@w2N@gZbC9xC9Q);I_}=_rw!HYJTWH_m9z0IQqWcGE=i{_3vc{ zcm67HhR+rfYr4;RqVw^oZFX(l^Yb41vitl{v0PVZ=)&rwbibi|yPV;cmh{Q15nDforx>3=9kmp00i_>zopr05oB%3jhEB literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/ebwizardry/textures/items/purifying_elixir.png b/src/main/resources/assets/ebwizardry/textures/items/purifying_elixir.png new file mode 100644 index 0000000000000000000000000000000000000000..67d28d410d6fb7a2a879c7a0981a20505b8f6593 GIT binary patch literal 1946 zcmeAS@N?(olHy`uVBq!ia0y~yU=RRd4mJh`2Kmqb6B!s-w^fBilmsP~D-;yvr)B1( zDwI?fq$;FVWTr7NRNPt{9$EIpjOWjD%_0`27zVla*VQ{6`{qAV+PeGpJW1=!n~#*Z zSXOf>r2ew6=l?8T*E9d4qscM}-8#FUMG>x%6YN-U@3nJ3#n zHvV<^G3&?W`)$5UuRPu-=REys@`bZAC8rwu^(!9VJ>T#4lFxD9tYoF%_02hIdoEJOrr?#)yB_N*gN(S%>W|*Z*7wcbxmy3h-L2wpa_s)TljKT% zEGZCgVD(qT?s%T!mqWKqKVNQE343$=KKq+v8CGuhSD&_HTA6Wf(YmE;q}aq9US7)< zoc_Rmf!=Gc9U|Uq81^=vZCWkmb;O~1!g9BnY+pmeRux<7mZoN=MIk zvvqr~lPoy0uF2F~a%b&A)BLEvV>2$PZmLRV-Cwba zEzjrKGug!s9KFq%5kJ@4ZaSpnav<=af7|mnHsS^jiUrEX2YQPIpJ<%l`LXYU)ak}@^C0dH z4h}&^)03$ap4K+h9nm(K(#(CYMIdRy0>xID*e`}hBvjAIOg-8;T_MmVWKv4$E7OdS zz^h9v3yVAw6_2W@WqN6*`^-wTdi=IW&{AA)-47uzouDmCCTTwjuH`iiTNxF6ws&?m z$A7WeGnVOYy|dEU>+bgp$cd4IgZ#VopBemDyd-k;#8_Xm> zXV0;TaNd3*wJFVtbF#6)v3Un}_^>Ht%$pOb`o7Z0+;VfLph)9Esa8+F#U~{szRb1Y z*|oFU;Jf!dpAYvR_3lqP=kw|x|Fbho-Why9cUyhU);(n++c{m2om4e`ptNZVTOhr8sh~)5@zS(!R3yZ<%&`)w3m24ofjhEbZIY z`{l&#J9ql-c^hkA`gLQm=uN-WtFpfrc23_MTD|SGW6GQJ-o@oR;%=>))+pe*=+7h9 z2Pe|!=sWy7d!b(E>}>UQyY^i(o^@3(pYP%_HRZKszSn0Tb+9lJ)r5U>I5rMrK`ERJ`=rG z#d{w3<0Ty}^_7Fa!ZU6EQO2VQ?ZUF|H7NoM-ev^#XXJm}wk>;B%u4Y!vR@Z|bej6A zfa7V-KK|D(#-|$fA8rX{Q*-WUSva#w>DD}66`t9v_A@Q}e%g6=>Y^JD@7tQJ*ZX(k zaCPS5nCx%+t`&W7@tZhj{)OJREIVCi-L`XIqScvuxqr&akM3*szkK2S&HJuh&jVJ^ z7b>DJZzL4;CECBavFR;){?v2cb!l&l7QVL;`f)M)xyZxK)~BB?aW{DucDCGGDoD@t zT3zaigP{|Q`E^)1H@~s+b9m_!|MtkaI3JDkOP48EFPXT)oKZO1$oxIWe->%qR`fl8H(!f$(Gj^4CWUaBpxM?Z zSubt7v2b0w*!ij(D|MsixYcQ;uc%mlsqO5AnU^IrceLftQ2wxDLw!T?oBLZ7XBvbZ zxN-QH#R|Ut$`?f5%({2A=*`*SNZB8Y?z}!?ep&t<8f3M_WKvim*stTmi~<0^x|(<{v4^oOOd>8tnv4vxj(N-xcSHCuKo1=#w<+zpVsiL+I3X) zxy7tVBjq9 zh%9Dc;1&j9Muu5)Bp4VN*h@TpUD+S;Ffj;dW!`wF!oa|o>gnPbVsUzIptZ;001?}X zT_MqqnMe6oJP26mJ=ZJX#iHg#dPZYj0kiz0kY;(UQrz zChI3ygcx^B__piDmTjIF~>67oyMj&5pPF~gx^ zf&9tC!CRcRbF4b1c!2e3PRp#HC+@k~RrqIIgGLt_h zOT3q7Xn0`~F#87MOm!6&%|{-10&lqbsD UD;?j+z`(%Z>FVdQ&MBb@0E0H0&Hw-a literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/ebwizardry/textures/items/ring_arcane_frost.png b/src/main/resources/assets/ebwizardry/textures/items/ring_arcane_frost.png new file mode 100644 index 0000000000000000000000000000000000000000..2ee2a69fe0e3a38d816e6154778b0b95f3d84c67 GIT binary patch literal 429 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 literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/ebwizardry/textures/items/ring_blockwrangler.png b/src/main/resources/assets/ebwizardry/textures/items/ring_blockwrangler.png new file mode 100644 index 0000000000000000000000000000000000000000..309cb388113ef66299389ed9f973dec088a28d71 GIT binary patch literal 5961 zcmeAS@N?(olHy`uVBq!ia0y~yU=RRd4mJh`2Kmqb6B!s-z?#{`xrVkX7zU+xJ z&8uv`<9I)}@@|>YlZVFwUR5u+!~Z1r#LKt`F@^d^wuo)Gz2W3-f!%vI#lKJ8nVKB5 zvvgtJ-;Kxn4IZRFJG*&@gi`16yVlx5!t<_1>UTuXc5pAvJjb0X{p(AfUnslJI^&H; zZT(t!e$260{C$UYTcXDy#l$D_OXWBP8dygclvaKS@tKCvQ=+uS*Fq1Ws~KxsVPizB6DxEjp-?q74o%9xjOEZs=t`Kx^JZv zhiHmQIRCD{IVN)&ejMYvq=0VMG6eW~>euf&q*XT9m?mF>G zRQo~E=1UDpM(!y(j=Vh=ZaDI~H=O_WbJiXs2_E+uqI_x5%UCbOGu5hy%exqhF#ifY zppq-?(9xj4z+)(}K~U6r;u?$e7LLXcfhml4H zL-m*&hZ2+fVWzx*Sqi6rH~bM?e`2AG#SZ}|9wCz@6O@lfCK`IpvCa|`(|26du|nmf zTjXB0UaeKLOw^}KSm$}HIKD)4>70!jZBKh{N^)6>hwu0yCXLxb3U)`CA`zl?~lm-Y4PGmLdLX*JgZVe?t3iGE}Qk- z^Ji{;oaUa}`|~q?JU%$})z0=`l{a{%ncn02{>SI<?v1eONp1V%W9lM#lPEugaGC_pj;liP3MBF4X6LoY(eNy6*epMN4-n8Jj4T zzJ2-pX?}6`JB1~ycgUPz=Q?`9;brRnxa?lrS9M`84|1M6`FQK&C1)p9EpiT@;dScw zO+l|C%dM`R;SkPS$ZgY<9`dJ5O3rM5NR^y4S&QLwjNo|`-P{2^lxZ0eVcO5J7DHB_cw{R?O&d~&bW(dm6oU? zZ@9Jy8rY(^sV#1`{4Aafb5UQf^Oc(@~?h0*)_oS5t?Zktmz*y+H}FJGxuSu(?9R74 zEwW!dsEU8OdDq$Kr+=5;alZFC;Fw0*k+*B=yng)NP@^rWa%7Wb!4*|rnFMzG$>vYm z=7^NeIk_Tq<`;j*5(}}ne3On>{+>Dc`ji>!F?)_ERNo9adb@e6<=R`Dl>+2WJ7-T{ z%KClM-GlqS-tX8q+aTUSEY|wWhR|Js-Tn>Ltyi`=DIIYRG+Hj*^}hS^yGVD%tDHCX zIQ%h7_N!JkvUiR zuYa5-pSun2JDTqAKlkcve8Ru;ybt}KXK=tKsq|GcSNd}d) zww;cA4Gug^?`vEAGq{hvD}NKWr}D%9i8+fV2uQryHGf-fXQqZ4`|{v_qQTBRz;GCL~=}}db8eHWUl3bOY zY?-2DZ^va*VO5b^kegbPs8ErclUHn2VXFi-*D9~r3M8zrqySb@l5MLL;TxdfoL`ix zV4`QDXQ1m^ky&P>WXGjoQsnC)w*bTk8(&ROhXSE7t;X+chD zF|wVd#i<}6u)A|o()25GAvPoHarg8Mfa?JTV|r$80ayn}HL}W-WVpJ5(xM!&nv`Vy z)ST4Z)Vz{neM3D%6c1J87Qi)N^$yr@a6nnPd}VzNb&ZlbYKVzQ;BL5g7#vJw78ndzB%i8;uw0vVN( znPQbk(=&@piYh$`cnVFO4J2K9WEPj? z7gZwJADmhU;X%BWlL-zg1qE>SwMt9|g`%xeabj6&3OEWBU{c8$iFxU%DYi<`Oac?n z#FAbu%#4yPO%056(~?Xrbxl&tOmvfsOiguD%~H&aQ&N&lOie6MO)t(*D=AMbN_9+6 z%`350a?i{y0LQa}1~i#zqN*>?NCl-K14Bz)0~1{%ix5LoD+6OI6C))^Y%AF4gGxr2 zZ*4$jhp(>{a(LK)$`&h6P=X6CEhxyzOf7a+2s?|j;su# z+d03WvM4h>qr|^F53luD6hch!$xKeoE5>U#vJyzJAXOlCT+pBja&fccve5_EVxSrg z5*DBug_ana`ejAh7tybg!_By85kHi3p^r=85s1GL71^(seKs(0|R@B zr>`sfV-^`cW-U)=s}cqV2FViFh!W@gTu^6;0o)!+O;IS%EXhy+HSNP2`NSC*7%M$p z978NlZ=Gc5;S?y+wqM%PMPaJ0qocF4l#8>4iOIIGAIlCnYGtfg%AvSu#Y&DPD|Mx! zq~_h2P|c#n$11qe)g^+clGZ~grL`TqYqKe%grUYdC?@ybz$ zzGao|HCJC*Hy+FSw5y)CK{V{BxjE+nx!plLPo@NmGfbMbi7Vtp?PccFPtR6`WHnrS zSjOO4ajGwNmxNMV^Tmz@rnhg*;F$R;cvCq44`(MG)g4V&ECQaX_qeg-9`XHSru5z1 zY>S}z%rCkduL#H5=F9ZjYa8#(>)71Ce$xgM54GroY)jq)XF}K+ez$8b+BeB{$w8d} zo+k_^Qn=sb#24(F5zPK^510J%-gzzTT8Y;s`uXO`th*m}|N5q^YMT1SoRcdk zDX-_3SJ#GLckRnxHFZRs%QE>Bvc_sp{LUZYHB3*R%@ucib_f)C44$rjF6*2UngByU B`oRDI literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/ebwizardry/textures/items/ring_bronze_generic.png b/src/main/resources/assets/ebwizardry/textures/items/ring_bronze_generic.png new file mode 100644 index 0000000000000000000000000000000000000000..73e2daa1685fb35c65cfb4fe01f559d720530a42 GIT binary patch literal 5855 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 literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/ebwizardry/textures/items/ring_conjurer.png b/src/main/resources/assets/ebwizardry/textures/items/ring_conjurer.png new file mode 100644 index 0000000000000000000000000000000000000000..209d95db0de9b597cba04d5c86b7395068bf9321 GIT binary patch literal 335 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 literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/ebwizardry/textures/items/ring_defender.png.mcmeta b/src/main/resources/assets/ebwizardry/textures/items/ring_defender.png.mcmeta new file mode 100644 index 00000000..eb1a25f7 --- /dev/null +++ b/src/main/resources/assets/ebwizardry/textures/items/ring_defender.png.mcmeta @@ -0,0 +1,12 @@ +{ + "animation": { + + "frametime": 40, + + "interpolate": true, + + "frames": [0, 1] + + } + +} \ No newline at end of file diff --git a/src/main/resources/assets/ebwizardry/textures/items/ring_disintegration.png b/src/main/resources/assets/ebwizardry/textures/items/ring_disintegration.png new file mode 100644 index 0000000000000000000000000000000000000000..9ac2518d3d06fe4d349bb6d317ad49b24cf8725e GIT binary patch literal 424 zcmeAS@N?(olHy`uVBq!ia0y~yU=RRd4mJh`2Kmqb6B!s7*pj^6T^PXNr}OT51_lPs z0*}aI1_o|n5N2eUHAjMhfq}im)7O>#A(yN$v+R18>){Lx46>Oa5hc#~xw)x%C1Cx| zMX8A;sVNHOnI#zt?w-B@DSD~w3=E7so-U3d7N?UF7O1{ho1gY#ZT_*l;y%Bj*j@j>g4_TgpEn|K!4+|g*u@ZwG~51i8ed;hW(5B~o@ z$@9PR#?61zUmO0JF8tuV!!yn1d1uM+eewyllnXI#y_q0Mp9rSP`wy7!VPKX*tb#Jw;`P5ANaw|QY>MQ~^1 z#BxsQI}@JvEBveZ{#U%Y@uj}oqM!x6yhm=@yvg~{uw|p7q2j`9i=vjq9ZU?9ugACF SpKbdF6k?vPelF{r5}E);hq3Me literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/ebwizardry/textures/items/ring_earth_biome.png b/src/main/resources/assets/ebwizardry/textures/items/ring_earth_biome.png new file mode 100644 index 0000000000000000000000000000000000000000..a1a9e59dd9b1d14f50f206e3db35108c09e8dfe3 GIT binary patch literal 5746 zcmeAS@N?(olHy`uVBq!ia0y~yU=RRd4mJh`2Kmqb6B!s-u2zLalmsP~D-;yvr)B1( zDwI?fq$;FVWTr7NRNQ(S9=S=w22<(U`tum-h>%-#@PS`Q9$)(!GkmUM~$? zsl-&ou-WJT^Y@AW4n6)LA@7phb@9>1lj_qA19s2fb1&s@)%?!AZ2Tp~`W6!;Y~Qau z=KOwv^@rWg>)rj>Z1)IH`4y?r&;665s7fS8s$Xf@+5>V2)#M%D^rh{8o+^L(*pg5G zIKF=9-@NZm!~B{0=N~0?sL18NU*q8;v3hgdgY9O#vR9Yx)SsgK;_#iAHGF0}&m9qa zZ=stq<9w%aRsZ(pZJrNZIV;*vn(MMgor^eV5nEUL&t~(Tm}T-OnQQ00dU!@W>$ADrWy4=~vEKyU`<@3}54^@v zlUkMiwkxA4euLFq+i0iYB`&TqrYw<;tEZe`Jmxr0Dpl%Ac>KykF7J0S_jzo7HDeWH zAfsDR>A|<@iyyKaFb`{p6XfGrwL5p=QZwDssUls{D;>WGv%^g{V0>K4&m`Q(+)(^uImHhNv1 zm6f-y&{=N#jU}1hy5+ApmcFZgvC;ebyec`4tp^YH8$6n@PaoHd!_x3%YubY{s}zt4L# z=YM;)Un1`9e~w@Ath_Nv*)~BB^tK(hb!DiGaVdV`fnzv}XBtYu}0TWUqCI+nl{-nrUvkYw-Z<~b;D8DB^F!nth>2D=6KxY7XQFk8p_3bM-Osr{`PpXZ;@rS%(sdf<+ydn z#Sc9YW@B}JTX@)J&+#|QnKy0UbJSqfMA^9QT*1oas}9etJbh<&{T0h3%M-_}bi_W( zZrq#WR@1X>+JlDLh=qC~uL~!s9eHxv&fLHD?&ciPTg#`N6;W|tX?L|^PSk;_#ot79 zH|BbGtgKwf9QJMpyWW};G0o!D2SvAq-e~#Hshj6qBEeAe{3@&EyMt3Z%H_7rU2NR_ zOS<~ro5<|97i$EC>_aDoNglK$2U3`tlE zxXgl*WKaQT+j)?;!GMSP|I8-ANjEN($zI~OmwThX#w)@5+RbgR>rQP`UAEBJ(qitX z^)mwJWgO~jQ8t(&vi<9ndBNIS-hE26-2W<1-)NS|lYffJ^BEZULo!1mN+NuHtdjF{ z^%7I^lT!66atjzhz{b9!ATc>RwL~E)H9a%WR_Xoj{Yna%DYi=CroINg16w1-Ypui3%0DIeEoa6}C!XbFK1^!3Zj%k|2Q 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�O9$af2qiSyGiZCx9pQT*O}aA^Gn24 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 literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/ebwizardry/textures/items/ring_gold_generic.png b/src/main/resources/assets/ebwizardry/textures/items/ring_gold_generic.png new file mode 100644 index 0000000000000000000000000000000000000000..c1c80af61a01153b112a6d396a7f4b420ef9dcbc GIT binary patch literal 5866 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 literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/ebwizardry/textures/items/ring_hammer.png b/src/main/resources/assets/ebwizardry/textures/items/ring_hammer.png new file mode 100644 index 0000000000000000000000000000000000000000..105676e24c68c68d2d363aa97e5c7c4581cf57cf GIT binary patch literal 367 zcmeAS@N?(olHy`uVBq!ia0y~yU=RRd4mJh`2Kmqb6B!s7*pj^6T^Kenyl43Et^L|7 z1_lPs0*}aI1_nK45N51cYG1~{z`$PO>Fdh=m_$|<{toWGHKmI2K z)M_UA&)?fF={AdT>BT+&yI1>2*xCO$`{CVT^R{yNeSiJGrTv@#=4{VHDKVW{54Y*x zD`;+PY;06q?J)h}=jQu7;rIV0CnW6nTL13a{vMXUeL2yYChz|n#A(yO>m6ToD(n60m;f zqSVBa)D(sC%#sWRcTeAd6une-1_nkwPZ!4!i_^&o3shgM%};x=Hvib_HqPlTPAO7{ z?U%FjEU&n3q~fydp-F?_^p>uP9CLJ2j~p+^IA^=&RYXDNGcluo`T3a#7c5?P?!bWq z2MRL$M3gVqT`w>E&(GZbP43VB_m7_b-#ks{xBsMPt6ES0%Z|AD=lX_CKjXI+-27iF zuK)l1>b3v-&MGWkb!5ZO6OKD7X0^*VPhH8$tgNi8e9s^uB_-t#NKx|g^9B-Kr;TPvNg2(t vtCw4yw&#Jp(1wkTA3RU78}O=RFR^A|=;^C3KdK{j78ItQu6{1-oD!M<9_hCU literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/ebwizardry/textures/items/ring_ice_melee.png b/src/main/resources/assets/ebwizardry/textures/items/ring_ice_melee.png new file mode 100644 index 0000000000000000000000000000000000000000..319ad2b2861b7bb0922f2f11f512e7c93bb9c50a GIT binary patch literal 1889 zcmeAS@N?(olHy`uVBq!ia0y~yU=RRd4mJh`2Kmqb6B!s-RjWcGN`ey06$*;-(=u~X z6-p`#QWa7wGSe6sDsF8JkDR8W&hzKFh#iwq_XCSH?|-t{?Q7Ouy=&V$$^OaLIW--) zL?*2Wdpm#s?qA&eo41{^;R&%?fn#oZF@`?iF3VMO5hsE%IleeLmyI{8;JseK#t`18-k z%K3hHULtW$PInRO5*J6AP?ktHZIMpLWOeVULZw-o^+Omg7A1c;ai*15lr@n-a^mSF zxBJ}Y9(4(JG@ad4U@+lRYwNO`7H37d3}Q4jT=*Stc1-<$<%+-9S399DkM`5y2aYOV zZb&k4Ut*FdDY0 zo^ZDVz9yV0k*@{plbDkopnXP>#W)Jn#p2OIV+W~?0UIv_q*L+E-ZfaGAZ}+uPb$prnlC7Ov%!j z(rxPD+Q%jJ^a$^{0}|0p4~--g7SCW$x0M*q%#Smwa;pYz$31@G9;*na-jwRP4r*K{>!W#0DSt&ZQm-iY>)xwJ#m{@bg} zMNjvNp7EP$mTq#(I`@_Pvy$`Tn8*a~}vblvM) z%&qhR-P^jOkDo9M=ww*=A+T_1l~o6GQbpCK$l#aS;_@~tL8 z1;z8bwNw@ytSyw${8gay?2|*FecyrnKg&z@s(vZlW`v2hEnEGMj@2WZTzqOpM$^N`>-r`*D#R=a# zx@~o4{P=p`^6sbg>vycu_`BlG&U>yi#lJE=&2J2mzfkw+;Yt5j+ZAoTyxPiqU+CX8 z##j9Ze#VPDoWCUQWB%@6;_N)H4o9^YnKLjjuqAoByD$VYgfh&OpE7Gd0|NtRfk$L9 z1B0G22s2hJwJ&2}U|=ut^mS!_#KSHmFT>gPAdZ27L9)a(qQp5rH#aq}gu%HeHL)Z$ zMWH;iBtya7(>EZzkx!g~fpLbXi(`nz>9vzLddoP9wC@+>Ui+@gcku#`96pn(s3jdN z){Y#TUT*OcWMO@~&g*Twz&6fr*HaCh6t3!2-N{s3{VYc%DQxG%D_=_#*jigX6U&NU zRYg1rKg;v^_r2=R_Z+x+pR`M!;NQN>DSD5=v4V=a!k5{iGLqi_4XPuEY@#3b8|Ik-A~nDb@3aw?p9`4_3v9O!-3a3D;cDu zQ{(!2gj^?Tig0NxWeD(6T&lw3EVx1{Os)HQ<$s2ci@%nYCP#)PmC3L(+}_4m5IbF? z%Vj~9r<$kus()sUt5gMLk2_}TZn@^LO%1xS z&G*|~apno9pUUwnU0U|O(tmyD>ptahEm6Kcro#Q)D*X%qT;_2(k{+LCEkDK|hh6czO$r9Iy66gHf+|;}h2Ir#G z#FEq$h4Rdj3b_tX?R)0MFY{siuQzxV;m2y7K zPEE{7HRN8ptY_22wR%VG8>XJ^Xr0u1bd8#C*CLh8GjvQ&UUIiwcBRz&tkcZogSKa{ zCWzUr4$j{{?|JPx?X+X7IHl^GY;{XmS97#vW#(lq*!a4oezGWc!ciuMDRoewgn3?gibwBe6egzgacz%T_(eA%?)$wep@=)$c4YFe$E#*{Z-|J^E&!-m^jMA zK40ZMaNm5L&S@tv&W0(Ij&2ohv--?%OLoC7k+_*}pYO3)@X$rc(QNin6W>D*4PGu* z|MqRY>&lgW6VBY+P}#VDz31VTAzlm;Z3~qqdfW`PRaGngwmtRPXZerr&ZSd)1GF?% zFJ_1wHV|pZoK4d}`LO5kGruz)fP$Ce~)FX pco!a_zF}??TWl!P|IT}ifww0<61~p9oPmLX!PC{xWt~$(699f7;oblM literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/ebwizardry/textures/items/ring_leeching.png b/src/main/resources/assets/ebwizardry/textures/items/ring_leeching.png new file mode 100644 index 0000000000000000000000000000000000000000..ff76f78d48bd2936db78976db46f10af8c775918 GIT binary patch literal 392 zcmeAS@N?(olHy`uVBq!ia0y~yU=RRd4mJh`2Kmqb6B!s7*pj^6T^Qm)@V?2hUIqpR z&H|6fVg?31We{epSZZI!z`(#>;_2(k{+LCYTT@fTHg*dG1A}CVYeb22er|4RUI~M9 zQEFmIYKlU6W=V#EyQgnJcq5-U0|UbcPZ!4!i_^&o60AKtR31Hk{9pOAxL(W&k1dQJ zKYsl0?d>f&&$jy5hu6PK+t%OSW|%X1!htLfZoRYq^0rAg%o3TJkDZ>*v*+PMp1za?_q|8FFjudfd0QIFe`Fk^SAw(`Y`63<@$j{kaEoNcFh pzQi_7O~af!J0=#ITuo+YxN92`AL_a+lYxPO!PC{xWt~$(695&Fm_+~p literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/ebwizardry/textures/items/ring_lightning_melee.png b/src/main/resources/assets/ebwizardry/textures/items/ring_lightning_melee.png new file mode 100644 index 0000000000000000000000000000000000000000..36d36b7135f58eb906dbfe61b49ee5232fcf6c35 GIT binary patch literal 589 zcmeAS@N?(olHy`uVBq!ia0y~yU=RRd4mJh`2Kmqb6B!s7*pj^6T^IrxLK$YtPnor! zfq{Xuz$3Dlfk96hgc&QA+LtjfFtC?+`ns||;$at3FiClvG=qVGL9)a(qQp5rH#aq} zgu%HeHL)Z$MWH;iBtya7(>EZzkx!g~fpM#+i(`nz>9v#hdq)S#9JLSEWn>ptnfilS zXKAyj_A#%`Gj3gU^a@+ZsBX^w@`{t=e`diDfu+t1*tm12=~(^f;SxNe{_JLiX;O<# z(^lUemX?m~%};*%#5Xyg|Ms`&{LgvC`@cJ}mh9O5qM$s~%4zD(8@=*||DVowEW0IZ z@wTr^DU@O3-{fiLi*i;PHXU5xIB(9($>(?dPEnmW>%%3jS8;O=$22yromMiJ+c#Ea z&lauyZl>$z?|<|?(k<)Mk_|#D*45rQwfth@JiZ^1-SWl4fBl>ncf0?(5}`0jd9vm5 z_&T-l%XarJym+KDcb~cfL)5RDn438}>i!i*e%sgKIB#ADOKkuHt&`S-YHr{23*l zxZKkgs$9>Zy}T{e_~(4nX-<)nj*@R!6W*Wi{VKL*)^v5&Kl{vH-RJdeP@k)t+Rm~1 z`t!`LlS%I$J$ZYAarQ6n#BK4{9F^XSHeQ&e^VacOq9DVw`*i|5yYssvr7U s$DTGPK1FkDeAohwq&Cr?`yc4fZQ9s%@$n}!1_lNOPgg&ebxsLQ0EMRe^#A|> literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/ebwizardry/textures/items/ring_mana_return.png b/src/main/resources/assets/ebwizardry/textures/items/ring_mana_return.png new file mode 100644 index 0000000000000000000000000000000000000000..688e63d0a405f84eeffd6279074f6b8ae3a8cf78 GIT binary patch literal 444 zcmeAS@N?(olHy`uVBq!ia0y~yU=RRd4mJh`2Kmqb6B!s7*pj^6T^Qm)@V?2hUIqpR z&H|6fVg?31We{epSZZI!z`(#>;_2(k{+LBVR7;avR{t>r1A}CVYeb22er|4RUI~M9 zQEFmIYKlU6W=V#EyQgnJcq5-U0|TRqr;B5V#p$CH4ZROLNVLt@o~!zJ=E0Sx9hc=u zayuRW(;)qcJ!bc=R=%5em9Kn#p?~7dq@~U;vp&vNauJYWc^t4fq)62DLuevzdW${@@xJJ-tB2s(Yf2it}rk#FnGH9xvX;_2(k{+LBdNKi`Mvi>jw1A}CVYeb22er|4RUI~M9 zQEFmIYKlU6W=V#EyQgnJcq5-U0|UcZPZ!4!i_>=}tmisZAmMu6B+==j0jt>kubex||l*-2lHaex0Xm;ayjE-miZ zsYlNzA1`dl-7!%>Gbd)X_>Fgd3^8HhKH0v9cX-G%{wrK<$-E%y9K!|aGcRYDzkGc2 zoPoZHs@|WySI=?XE|_1{5FudnZr=SvcOT1cwtuS4x^xQ5fi2ed)Zu@VJoUwMSH~v*--m4&q@O44Ut05d0RsaAgQu&X%Q~lo FCIG04hiU)- literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/ebwizardry/textures/items/ring_necromancy_melee.png b/src/main/resources/assets/ebwizardry/textures/items/ring_necromancy_melee.png new file mode 100644 index 0000000000000000000000000000000000000000..2d59a223b79ca0a3eec6d7db54efaee327e215c6 GIT binary patch literal 1997 zcmeAS@N?(olHy`uVBq!ia0y~yU=RRd4mJh`2Kmqb6B!s->#9N`N`ey06$*;-(=u~X z6-p`#QWa7wGSe6sDsHU}k1Tp>#`EX7W)TaM!Va1C?9jXkkC*TCsQPB{&HJoJozhX( zj71wyEc^fYyFvZKB))4FycgBq>*`I9dDP>#<@c%Ap4ZksuiO~^{P2#Q>JrXPVc)X9 zr0+?dvvJ<}3fm&1V_#hZUZpRpnRCKj;P~PPmnuX!b6LM}nEm7svYU0cPXBkrwdE3V z{Q>8H6+W9T`N8<}LzNBT{s$kvywUbR_}9d>+#8~2JGehJ`JQRnWVd&AwkET1x#Gr( zU!4IA@rzPyB>lN_uXl7D4t^>lnX_>tu&E2|_ztrw}W7GHM{K9pM*T`L) znz?rC>BoFOR`y=L@!4;OveTkN{Zez*JXklS!|}0#d#@4itJP~m7%vv4e>ibwYU`?l z2`rMGuNU1uJDZK&^OA$9cdNC}uAj%8ymO;oX}N0TiSX`eSIGHwD*x`Yxvt4)8k9DD z+$LJ^vBzY=j5C6g-VtnW88VAs8GR_N->0^oiLG>|<)en1(=-{sh%Y_9GeuB0Vns$d zLvV&WgAWS}mw`&cfhr+Y{`3U1Mvk@~1r27a?#E0~9#f?qHVJ=JU=L)tdqX%wH}$D) zj|+!V$exJ|d6QBmJe_l>zN!1e!ZnNhLie)u&N8X~Xnbf7e_h%Y8I>Ii4z>#P+rWqw4~>)e zn_Lk!OwMHB+OTK0gx|w8>8})PS$UkF9#Sj5kWjjWjX&sawezZf#_!A%&WCW<-!=L* zC89ba`lF(F!p2Ra?Z>XfI9NvJueACzH+Npve6y$@45jmV^12MJycL`oB>Q^`hgrSI zB9;4Eh%MUo{@JeC40lWXK{UdZTr%1m(AvD2;vtu zu+8sq{t)^2tTzZOn?C12)f?-_b|SSl=7D?W9Iq~} ze)Vv{S&^!W&nq|WuaRpIm0vb}mCkY92bqu6lkKN@tH%Dmbe-dDdWYgSiK69-U&QCx8%WnVU_I7eNFXTJM6^1|G&R+ZRN+Q{NM6wx!390 zsI4t2N^-lq-(P>1aP->pw*o1BsSjkb|6bfTU+A`U*|p&P0qbTh$axcVJ-um%qQt#F z=C^-tFPK@*eIi`+!0D;aSI)LBsJj{U z96K4bg3oJf&bRDi>YcwiF6{~3a*rW21sKjL8*QZiM%W6;CEz#v)T8d2h$pPQSSSHj?2l$uzQnxasiS(2gP z?&%v4-pD7;z`(fL)5S5w;`GwV_8!rJ5=ZO9jkW|U9pmHj+$GsLX?cKQ3CGmDxw}eN z2D@m)a-UP$ky3ogk;Chtqk62@ZSxyqNzQVUW;8r7ZWIrRds(gY&-}V0Z{!2!`+na0L$*dUdFrQqzM{OyrBfsD*22dR7p$MN`TzBj34i0{>(;Md+mWt3bK#oX z8MjmaMOO0_8O@wB{b;(6ZjF$js+ZnsQ)>$wtMsCGykTEw#jfUX&|7V2XQaGcEce>< zZJhCYrskzEFbcf>-N8^N8f?1z;pUod-TYm@Ao%t zbi4a_t0=<{!>_Ie3-81}+k9kyo?Twcuh4bvnbGT3>qJ>*{Bc+t_VeTp*3<8|a?35U SO=4hRVDNPHb6Mw<&;$S+WwNgT literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/ebwizardry/textures/items/ring_paladin.png b/src/main/resources/assets/ebwizardry/textures/items/ring_paladin.png new file mode 100644 index 0000000000000000000000000000000000000000..a4a7c90e3ebeab9f713dd6f9db96fad4d68458b8 GIT binary patch literal 577 zcmeAS@N?(olHy`uVBq!ia0y~yU=RRd4mJh`2Kmqb6B!s7*pj^6T^IrxLK$YtPnor! zfq{Xuz$3Dlfk96hgc&QA+LtjfFtC?+`ns||;$at(RZZE-b%lX}L9)a(qQp5rH#aq} zgu%HeHL)Z$MWH;iBtya7(>EZzkx!g~fpMj$i(`nz>9vy#J){#wj@QS}KDuzPbDkHs zV2p~($wq|^O;;-okCP9A0^eLYyK-`#>>Vo+cJ_m11uJ^Hy*;!i$*t`6R(5fn;-Pd$ z(CO-xFJ3C?cI}gt)uunV@c*0K`~Sc1{l3@C$MrJNscJ_sC%;tltE+nFN*ldC+A7-i zEL)M$bxZIO(;P3spWlU!cNI>mYG1Y@r#^ame6sK+VHbuN@kbuFmxNid&F_y%>%1o} z9dt`=tNn5db@@u0NReE|r%TQ)zGzZbG;MY_%i-?2W6hD45(O{#x$IQsCRw}@W%&Ja zZy3XY>8*MN39oCq-g)`#igpFwE%u#<*cyrAwpX#O*%Yg})1bzg+!9SNMQw`rD2Zw*&>v&)u0OeO5O+XWGYF zzQwl)dni0D?-X#Cv z=H@lBg4wg}Q;PY#zDqMEe0{p-LGM5P2+z-dKA-#RwxWNb=Bv4P*56+`O*xBug|pPt e)PMTBSaq~FMkHQTk78h8VDNPHb6Mw<&;$TT4eiYU literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/ebwizardry/textures/items/ring_poison.png b/src/main/resources/assets/ebwizardry/textures/items/ring_poison.png new file mode 100644 index 0000000000000000000000000000000000000000..39782113f3b3ef6ab2fdb870084062173817fa65 GIT binary patch literal 5591 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 literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/ebwizardry/textures/items/ring_seeking.png b/src/main/resources/assets/ebwizardry/textures/items/ring_seeking.png new file mode 100644 index 0000000000000000000000000000000000000000..4348bfe946d0b4f9a295cb4e59ddfb68e78fb20e GIT binary patch literal 387 zcmeAS@N?(olHy`uVBq!ia0y~yU=RRd4mJh`2Kmqb6B!s7*pj^6T^Rl|lrS(P+}~5r zz`(#+;1OBOz@VoL!i*J5?aLS#7}!fZeO=ifv&itV^QUQRn=>#lNS3%plsM<-=BDPA zFgO>bCYGe8D3oWGWGJ|M`UZqI@`*DrFueA3aSX9Iotz*cq!1GR!d}l(Ey*OEb=3ot zmevVtWhIaCEI+sRa3&+S-tw{(31ge8pA#QmJl$Urd!l2Fa`JwK69^nX5#(k_@0Q^4Zl8FyR}KC|7V}6X=GsFU~*W5d;TtdQFVci)%yFBW6EFI zg|%L{uTAtQy_Q-KlO45KZ7%}@gJg+oM2T~LZf#KgUJ7%POty}g6$B4u-V!C{eROE5)u+JY`#ojJO*NBSp0Zke{q|#cH2&- z*^E9ncrtCi2spnvcw9b0H|3z(j7*)Q2M!!KpuqEW`%Dr2!zzopr E0A@CFJOBUy literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/ebwizardry/textures/items/ring_silver_generic.png b/src/main/resources/assets/ebwizardry/textures/items/ring_silver_generic.png new file mode 100644 index 0000000000000000000000000000000000000000..81fac930b979193940a41c53eba94eff23f582ee GIT binary patch literal 5910 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 evp@Y4|HJh1>BLj>(-nF^<2#$J zU|`@Z@Q5sCV9-+rVaAH3_GJtV4D2PIzOL+#S)>FkIseAF++<*2kSuYHC~?lu%}vcK zVQ?-=O)N=GQ7F$W$xv|j^bH7a+@6%^A92HP2X=GbH?Z4*SP9FYuH3<>sg=&Xi zbs9^iNJvQd$jC}2@qYTZcy+p?_>aQ}4t)4?j=jxOINc~`r$Oh$#>Pg+3Epq^_b=8x zEU&XJ^-!9UvB=>A`D|=${@?c*{yCb&z`g81e%twSJA)%t?ZzGjoqy9)6A}z2nx|Pb z`x>ruIAeU`@B8<%2S2noHabP0l+XkK+lY?t literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/ebwizardry/textures/items/ring_soulbinding.png b/src/main/resources/assets/ebwizardry/textures/items/ring_soulbinding.png new file mode 100644 index 0000000000000000000000000000000000000000..5fed6da5855d5b7e4812d59ed742e5b0cb3c829e GIT binary patch literal 456 zcmeAS@N?(olHy`uVBq!ia0y~yU=RRd4mJh`2Kmqb6B!s7*pj^6T^Qyvm@$ODHcDw{ zU|`@Z@Q5sCV9-+rVaAH3_GJtV4D2PIzOL+#S)>HDyZ=aFyf|+dn z+Gd9n4qUyf$uL{Gn&HM`y}xDYObgNuGZ)0&4=$Fd_L8VR_4%|eL)hYZ&y;urjd}N+ zF3vP_{Bp9y@FmCDLrPDBSR0lU6=w1>{C_(y%4S;s1ctj;Q|0FAF=$NJTKV(Yn~o@( zf1x20b%hlC#MEwf-aM)wc6x=<11Hv2m#2FY^~)ogJGY5-xK5|K^)ZA{CoO zW?gM~sl=HSut;!bpHSI>GfJ8Vk9F|=dXN_!rRw5H*dZj+>XCjJh#lZ;$&DcMI~e< z<0cd4!xq;H-53}GbryMf8pW4w^#l*KfVI~gM7lW`yu6;>+|3o5)v)U7 zEYJTnudkiG?!Bo*a(Uj2nTFczqG~rcY5PAtc%ez{3kxIT7A8f-SyzSC+e&QS7r(h5 z)V1eNaQ1lEX{1!{zN}CG{D*Bw=R%!4kRDgF` zT(CeclSW#BqBeiejTdzak1lO`FUsKHv17u;sb?z^jvPJOw>d%1fIq_cdE=j1?1`Ul zKVoFaP;?Y<&=qlsKE)iovuSUYqN&IFb1f^L{#g*U)^VwdqMZD)2oJEXd?uZ1l?hY+ zB~H@p&`Y=JaA9d_d2!@W^JnH~jIV1iR^Rgfvi|O~J@YLdg>EQzHWjO{mfR~=F~Q8? zVME*6{pZ{dHrvnrd|>L1gEk3<{5hW#-ZHOzD!}^0RieJ?tYe+PvS)dFuWo#?Tkg(= zsq#yT=5On|HskOghx4_6>fgW4y7gN$>(t~QKKDJIF?Lsexc1(>&2!l|-yOem#H@0! zb64qp*|SFQ_x3AE6)(fuZC==4`&xQC=gz;M-X}VlLo60pK0Y|<)>(~T+visvNRr$0 z`7`@^uW;-2;&T0G4}MktI>G+r`BTkX7`J%1bR2JA$=UG4JINql?sLOYn;#bElzS^g zr#!j4u{?9t6^7i~o7?yOd}<*mxN`UTi8p_3<_lWNwxZ^E=B4-gXWyuaw)1>ecwV{S zc%!o16a5J9yN(HG=T_~Jk!LP2{>`(+!)3>fLNSJbKr?ZM316l>IP%W7Blkyk>)SsM zLSJS*v47=q{@49WeN#3@>^#=o^vP;cjpuQjj6S)XgMSw${kGB2Sid+!fMd(N_Tx{F ztys@@Kr;I;^Wymx^(!PE>zUWx-)fjzATs&TtrE6hx72fI6qGDZDzUopJMs*3`_IN? zxsD{khhMC&{10Y7-)*;7GjTGzTUycERLynrH|HH=uKwF>aPmyE%;cj%=jR^0;qRCc zA7jaK{&8PsWrCE?rKyLd7zopr0ICc;0RR91 literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/ebwizardry/textures/items/ring_storm.png.mcmeta b/src/main/resources/assets/ebwizardry/textures/items/ring_storm.png.mcmeta new file mode 100644 index 00000000..4c786d66 --- /dev/null +++ b/src/main/resources/assets/ebwizardry/textures/items/ring_storm.png.mcmeta @@ -0,0 +1,42 @@ +{ + "animation": { + + "frametime": 1, + + "frames": [ + { + "index": 0, + "time": 20 + }, + 1, + 2, + 3, + 4, + { + "index": 0, + "time": 10 + }, + 5, + 6, + 7, + 8, + { + "index": 0, + "time": 12 + }, + 9, + 10, + 11, + 12, + { + "index": 0, + "time": 8 + }, + 13, + 14, + 15 + ] + + } + +} \ No newline at end of file diff --git a/src/main/resources/assets/ebwizardry/textures/entity/spark_bomb.png b/src/main/resources/assets/ebwizardry/textures/items/spark_bomb.png similarity index 100% rename from src/main/resources/assets/ebwizardry/textures/entity/spark_bomb.png rename to src/main/resources/assets/ebwizardry/textures/items/spark_bomb.png diff --git a/src/main/resources/assets/ebwizardry/textures/items/spectral_bow_conjuring_0.png b/src/main/resources/assets/ebwizardry/textures/items/spectral_bow_conjuring_0.png new file mode 100644 index 0000000000000000000000000000000000000000..2d5e513c02b4021ab151df14454923740f0f7f1d GIT binary patch literal 1651 zcmeAS@N?(olHy`uVBq!ia0y~yU=RRd4mJh`2Kmqb6B!s-{#J!VlmsP~D-;yvr)B1( zDwI?fq$;FVWTr7NRNUGc9z97}ljqNKk!ltdfsV%?dS*z!`Dk7_U*0+o|hdyjt z#3c>ugh_E+h<4g%i6Z-oj$%`wz09+^7(SkedX43%O{`P@y1@~`Jb2=wY<6V z_iI@sd@sDXQBeLwXI|pDM-Ljk^%h_GdgMsP%&$Ll?G6{eIkWZ`!@afN8s?r|ez&&m z(2WAC7WN)L>yyQA#GLro#2VNCa=7dE`{S>MyAr;~UsRXgWLFS96M1Fplu+m6Od5Bk z#0uR1uzcO|t|fZo5v~i;H*|KaUg*NJg}pLsN@hTO>QXLo+wwk*ncBOrF4HS|w9Dh; z=Vb>4znCz)-3Z8l&uhmQyF*bMdSCdfg`B5}Gy?1}{eV$%J=jkV2@oN7# zYRvHPSW2GVMeddh7BfyAD!=>8`OXdgBUT0)+-XOdHtXJY5!`irTC|Pz7va~vcOUv~ zlx1$iGdx!7bH7jX z;O-C*k6|(OP?+#^uR`6T@FM|Y>i0T4CTM7R78M+1=TtmmV5;RVUOPo1sYfdK%&RM_ zGcK%HiLn2*`Mu8@8!#$ zY`Fi|QS0oCzK=$Z!G0-4Y{za0OY~1>WHIqSw`S6Jo0+rc+&tpJmAJvp=wzmeBy;mV z;nNGG%gdkbdwRB`zT3R+=$x5X{_;LMv*ew@_o>^}*KFNWCbFGlR-}dD);xzB7Zzrx zoh|nN_4d-Am5u*TUeL&0ujk+)Xc5P8Co2BWn%e=6pVx3^N}0Xk>)iEfm6FKOn5o~r zqylf7O|SA1kTQ;ES~kVl(tF;zgB#g;@2yjp`n~$bE<3I2{aUIHu^S6h%|4&CWI4hA zP~vIH+I`V{r(>=?^No@Fb?Z&&=_%L#oUzOKF8K0zGJECJw<1R_HZ_RwvARZaoeS5y?snZT0s;3^~3um8jJGp&(K7**wA4>+RZxGNrSJ1^^?jwvvghS(2w$uEYj7QqeB(EIjas-$MU-DdpxDm?}f#- zo2q-YuZd-^-x}vRV`J)jw>fToJfXJ}56(+<4Sy9~-T8B2-AUEkiuaE!ym$1Vy7KpZ zAJk(R?fSX%-{wBkjotg_(Eb+h8xtpL-{wh=|LV{5V#+gh&q|9Hjk^mkS%+w+OxrN^ zyW-EFS>|TP3UXt-=X~zGz4+WSeOb48(ua2H%>2(Vx$~vl`iezU85kJYlDyqr7%CZ} z7^c2C|22n!fq}EYBeIx*fm;}a85w5Hkzin8U@!6Xb!C6d!7L~uef-^rSOx}$@18D> zAr_~XP7d@w>>$vxfA2Eh+tc}&$`?{LhXppj^w|_2YZYexa>Ss<%0GtyVMmFU+}AE)i$m0{rXFq zf^4UTJ*m3QXkGg{!ACyuq_(kM^j=HvAj_N6zwHU!_bO12y>QuXp)~hON3F{OO@Yfp zH>geiJb^d*Zq4$2x4eGaWmx-0hi;pq&!;$Hna|^&CO_)m_#_;%`ELLC@%)1L)e3zT V8_%ts#=yY9;OXk;vd$@?2>>Uf2kig= literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/ebwizardry/textures/items/spectral_bow_conjuring_1.png b/src/main/resources/assets/ebwizardry/textures/items/spectral_bow_conjuring_1.png new file mode 100644 index 0000000000000000000000000000000000000000..ddaf2e8eab2d168fd7a0705060cf1e1cbcada00d GIT binary patch literal 1693 zcmeAS@N?(olHy`uVBq!ia0y~yU=RRd4mJh`2Kmqb6B!s-#j8RhN`ey06$*;-(=u~X z6-p`#QWa7wGSe6sDsF8J&n!pHnNSAQDiy%Xni?wR&I z`9*r&u^lxv0)Hj-DdJpF0%gyre&=VmTHF0k9y@A=IopJTtxpH}?OLQnYn zljG^~jBdg_n~c{PZ#-)2qu;|}QRue%HQ#ZGnSX!kE!MxEoc`_|b4B@kM(f$r^eLFY9)9T-*7oqF2*>dQ9w+ zAC(si1izRtyUB!aI3`h6uCwLOvZw1O9V%8nQ^JzmqF=ZBOnGyC(cQLVGgf+Q?3dO) z@-&S}spsUKJ;`Dm3kwaVw!YtWX8E3t^E*-vG`Q1_GHuqq?IQT=gl?RT@w3ja$KI7J zztP9&z;eGSq2pi!uSXhJ%HraQ92QzXPIlbcSkB5bp(8tmZAT)Xg8SVsz4=OOclzCt zYunPm@$i7)l?4qB)4n(T>5QA`92v1kaH2wB$fPF+4zhD99x*W0a__VA;xTmV)l5tM zswHKzD(ljmm?V!GOC~JxoE3CR($Cl@y=JbV^7BVr;_*vbgu17N6uJHiiC@|#wfb5} zadEHosr{{DzL%#(y}L5e>u&kWg~!*~ezlp9-P|s3bg0AGUFv7r+YP^_npP#eOTYGF zgPG*#?6^M(yoU|r)G|(W`kXs3<1@>#$0-b)Z`IPnPF9=GoIU5}lK_!N2c%A_EWen- z!}H6}kL~WAT7&P(`EGxr_v}nRGt={K{lPgiugE^Dd;V7XT2!1hmwr>4sGpB6KZmqh z$yvY8cP9VaVfz2tf&VEPQ?`YRD=hJl(Pzn9t6%pmcg2FrZ!IRg(%)KKVoOUWb|tMl zSFPK-B6qg8tr|z~OnyearxxXt(la>LI4&-K(Rr*+d)vC{ulB^x6<`a;^T4X%&cCvX-)sR77x7!A>HV|w zD1Ny_>Z(HWa_?=mH+ZMk=ETnYJn`l&R?DT;i7S6{9}B;Iqbjm(*`=n5s}Fs-BD&

    $C5gjhMJhgbfxA9v&zDJ_V`(~dP z>z{B-KxJ;rm*VsJ))zilE;ZU4Q}wL()|zOOhbxtrm)TgTKRK1&{N+NKomBVS=NzX} z_UvEB@+|h`jzf>mCq9%(d8NDN>$!!8KD&Iq_bvb5mpcu;MlsSiMY0e7RQV)b^fxv; z?vq`V(SL>uZI7AFp7Mw=FfgzsdAqwXR5C;{Onr0yYYqbg180FpWHAE+w=f7ZGR&GI z!N9=4UgGKN%Kn&xSx|)ku8E2Q0|O(wr;B5V#p$J!9lZ}b2(<3MtHv9s=<3fXn16Qu zw|0>|)o)Bia{{OIhQ7%Y4VzM86EVfabM~u4ac!0F&sJM=|F_ASpQilYqNPQkT`AbM zDRx23GZmQ!KT;Z$mZ>aKS$5>as<{f&tA+SFIXgHy8NEA`U70MHjF!&Um8eu(=I=5; zTFhRU$C7cugXR#|+*9TiA0r}@p0En8yc2V0+k~!_qV3}TdYh$goQURKJi9|@J&)!3 zD{5yvuU_1?MLk*npV9Q!Y^k@qE`ObRLHZQ`lB^4@3&OQUbxvG)`Holmx7 z`HT76-F~-sPUF@#+c)+6H`RcKxN5t1f9%cFF5I;-w}1TjhyD(I55GzKBo{h#CTsuz literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/ebwizardry/textures/items/spectral_bow_conjuring_2.png b/src/main/resources/assets/ebwizardry/textures/items/spectral_bow_conjuring_2.png new file mode 100644 index 0000000000000000000000000000000000000000..68898fde03af2f0768af2d97427c287947eca104 GIT binary patch literal 1786 zcmeAS@N?(olHy`uVBq!ia0y~yU=RRd4mJh`2Kmqb6B!s-ZL2~eN`ey06$*;-(=u~X z6-p`#QWa7wGSe6sDsF8J&n=VD$9R@(vYx$bd(l^ejf`IV zrlrO-ELZw;z|h3NL9^8{uTlCLPmxK^{Rrifv%H!& z47|8IJmy3?@CtFH9G$U1zLSgh>JiOdQ-b^^nM@5aem*1kT;!*9fuRwLR8A@_3RjShRFX)Wa=@N{+tjlH9uO!j7ZUqVg_nnHpyO$ZHFv~=~FUkPtF{F-K3mGtiU znv03K#$xL$KOK^4bIlXpa@zCOoW_j;oIR)07@GKI8?P5hzHuh^Tn(p3m&gIBrM~AD zoRyI1nd}tx<-xnwo%26E3;H9L|Iql^on`O*4W65ow(tDDr}n_D71uiti91?zn=hLu z&Lyqpv)1vo-Q>F6rT?!Vh&S4DYs1}CksuCrHKy%$+jji6E5ER(x^s)p{9LDnE2~Ns zk3M;K?t4_!qQhsVYO=N-dpnzF`b!J`mG3SH+;HgKc7a>BdREPTxvY+lueS8Ovf6v) z!8ciBmQSu0Vb;ObbL^g+j=3s0H%9Q7-JiRwL-hVD9?5y={8By1t3&LSZccybrR7c?+q|EPe`kG?^S0~XYsHnVTfWV1 zcKprA%U6=2GZ|~{x98er#kAj%@#4olF73(xAWfV$vCR9>eI;; zk(JLkR%b7j;&_;I^|_Qb^7l`_l|V2{=0p0%I*@sg-LdrJ0nkb8S@ugFWd5Gg}^ih-ui++ zySmT5kXP^etx;Te_0yZfBo<>2tPEe$TlxmD)T{3)E8#g+F>G zz4M>bzxwAZKhKw|&)0FCQAs$_{&bU~&)GvB6_%Bb-tmi{?rT5yd~NlC^mK1+xs5C5 z>7*UCzC2fHV!C7FiElYt{r|oz{c3nntS0DH5b8*2z6fU~$fiY0)njEgHo? zNW>jrZ7<;O{K&CMS4~PtQI%zDv!a8~&)9$|SzH~H&t(1kesB88-w)@z|4qFyT~q4d zF_*;!SLIgvD*3bBc(eGYLjNHp73U7u4*kz5%>KJ>q-^wF_bp>9I2 zK4?x56rTC0vtM7zzpaBqsY!ox>52Zeoj!TYk`GV6o}N)@dvW7W3FqKU z@WjCEPI}MkHz~|Bm<2w>tt$|!&NMy{xHIL;te7j-mv(-6vQSmYeD#feES@qr?!DGn4z`)?? L>gTe~DWM4fQJ!c~ literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/ebwizardry/textures/items/spectral_bow_conjuring_3.png b/src/main/resources/assets/ebwizardry/textures/items/spectral_bow_conjuring_3.png new file mode 100644 index 0000000000000000000000000000000000000000..9d276179be80fd4933308d08241c554f07fad992 GIT binary patch literal 1815 zcmeAS@N?(olHy`uVBq!ia0y~yU=RRd4mJh`2Kmqb6B!s-ZK^^dN`ey06$*;-(=u~X z6-p`#QWa7wGSe6sDsF8Jk1WzQ=lSzovxuch`oQA?=g_uxFY4jW_^j&T4e*B;(c!~e-N@Ro^97yKHD}i{q)A)+XEzK zpKJQka&cpDP48W&7oA(RKh2gmNd5hz@_^sg?pHT+Rm=!TDLK zlt*e8qw+cP4bKwGw#Q@~J*yq3?D)hl;w8s94*xy7&uBmPUpHI%YUD1Lu)GLGee>09 znLf{+nTIv9UTV&a`LXV_&6VC-g=@{*b|i@9Y`C#2_KL^%Tc5hq`%5pfC716M{{EOj zK(Wll=*htb-zUndo8HI>GrBX{v(B`Zk6~pNS^PRh(&r7z2(Z zcv1cQ0yZbcNJW<`{OpdrQ(q(-7#a6LZ>8w0 zDXmH8O?!5l^=z4tdV0bcR;I@`k`9i$PtFwOI_UdME#1tzL&<7`Tj8Y3nMQ1EhZV%9 z=H0nF^Y;XE;ltZ2itCfk`Mj!YwlrR8eP-|Tx2)NF*9afgZ(7EszU-Q|l(ZO+rr#-> z$#pif{=a%qU$kWF`@5mTa%A-if>@o#hA(Odza|c z?mpdYEY&;HoKx{J=ewktD-}2P$?Xk3zvTDzjN88gV>q&dgm=B(5Hn|H`Mt#s`#9RK zZQjzF7#sDj>q|mKszlWG>uUnyKF;ONT;A_xFIm0i`i{v?#$RsxW;-68^Cdc1dCl}mM$DsV)>#NyJM~a2_ z#oUNGW{|yZ=H8@oc3Eq`h1rf%zc|aC+p%JIRhMiPV~N{mwv9Vu-1aa}tNx*s@Jw)L z#e~xge)^Jvx2~}jG~AkWEbNwm)L*@=XK%$iDaM9weQ@i>*Yyul;~2vE^5k~B%29A54&d6jSWkAITU{0+Z6v|_Wo($6!;Ivft0vr;+w z?YGz+n>-J!H1mI<`yygxzklTKHo0R{n!oVQQoXpRbcG1?w>YKwodK%|Ec1`RTp;YNrh8u4?Nttw6j<=J>}85inlg;i)^DmCIu$V zZo8+qcE;?8I-6e?-@LrJw&8A-)tjovcRso??=3o)*t@7A)v^3e#-jFx)_k|pT}_v2 z{{QE>`l?*5LsqVd<;;uABpS7?ep{+EOp#mF9NL^yuQ>m@kYn8ACPzhv?UOSPd+rP3 zxXFK?@4klZm5b}21S?ED&%e=o4daH!ql=%|dG7JP^2g8ay{u;3yG=jE8(IEso5}fZ z0|NsCTavfC3qvJC6vNav=fCDKFfecyctjR6FmMZlFeAgPIT8#E4D2PIzOL+#IhX~7 z75x_P*I-~^jPZ1F46!)9bn;#==0Jhg{kxwX_nnrr=1xP$lAF0ANx8Wjgj41paB{KE z_C6@iv1#pE{)9)$5fZ1D2#TmGDx@8qpWtyU&2YDhqW!%`_mZB?F)n_`^XK!5$Vt+d z4!Rq3K3-gKg=wSbf>~P(JRe?G?RHx3K1t5XR_c3ll*$i+r8+nQf9 z8vJ?OGcy(+5Z$>pBIVtt7yQ0<8J8D&vUAHyGc&lWGPG$IJiW4cp(Dj52$@X9BT&Ca4P9AqL?R{e4EOFdp!eBubt1@@i^pP~;2YEM=_Gqw2q z)XBWz=WG}RZ>~KVTsrIJ6}DHM4_c+)@yl+Fn$dWG!^WWC=_Tz|PKCGra@csVv!(3_ ls%9@@a%ShxTH literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/ebwizardry/textures/items/spectral_bow_conjuring_4.png b/src/main/resources/assets/ebwizardry/textures/items/spectral_bow_conjuring_4.png new file mode 100644 index 0000000000000000000000000000000000000000..0548ae6028a7800438a3c2a56dd5c2fec3a404f7 GIT binary patch literal 1833 zcmeAS@N?(olHy`uVBq!ia0y~yU=RRd4mJh`2Kmqb6B!s-eXBwuN`ey06$*;-(=u~X z6-p`#QWa7wGSe6sDsF8JkDMl>$@AyANHI%`K-1$5`<_dm`KTVT$*g?q?p*(;tC^-O z;Sf=rnEGqKecMlVdH1AV@m|H&gpVIjs!zYzSyo@>eQo`H;|<}@Pv+&B%lPz6`)=^X z*#5BIclImt)s@?%*BC-!ZT=D!=S*!Foo4y;l)^j&{KHvF9ep~UrHK&i}etLaF zyXhi}TiLNvwQWCmi$&R({N`Ld_O-h;apvD#^*Uke;@A6F-e0TkoO|~8x$_GR%;s=D zRCPPfmuBB{x9b9T_VrW#=6^P1$=ma9lwN$)@YlWAZ;TVUp5?r{b?Q}OQloZUKWj|a z`UUG>d+ku#79seB&5V0pmc~S97WT@lDVYKBxl6e^?v*ajn7g`fy6&c3PhKeT6H zeBlC*L}AQ9sl#vbA~M#_zE(9=DJ-vLX5WLJ4@dl`|2*--`uf?662ZG%%kg32#5Ep{w9z zv7t#yh3mwpxCQcG1*J|Mdeqy&64*IOg`LmNgTwLgn!w1&yD#5bbk4?%w%0w&jnkgQ#5{b|Jtbhvkx5?bCis61%~}za>}zU%eTU-T z=!~qWoRv@gWP@Jq^X8AOezWp9<62(1x)U7E?lPHAq_f+vreAx}y7PSG;={L6&aAJj zO6N_xdYbiYk!ivF60%ZDObK%E1qmTTV|4zOoZ~xCnmFc8XfPSJh?!+ zy!@Hn)3Y7_#q!_D7N-S$H=kiVdDr1P=l9eeh&uh+<)Q0^GlwLDPcygj3Rj)cdseCT zw=DbLm4pAEWK7vsE*{{aD5KAkw^qOITkeVlmET&Dq|DxMc2@PQ=GN@mX>~t4Gb87A z?5kM;8E0fzbTrco)hnHtH?&FZU8pYgd)ekw{^k*HCOh1z>+%{I0 zvR@CZZVkA0VT)Bjddm63JJkcl)8dVnwjQ>W|7Nz}NAsM(wA5zjz!VdqJe|T6tV{`h%HfvwW`nX%%{N^}@FmtSX=G&aW)fdFQf$k0Cpq z;R*YX-`C#oeGl4Zu&d#!V7b6#+Z`XC?OeJ<(b4pqLypO&+svOEvr@GWE629oz3ueo z)AJQ)&YL&r$(PhE+MQX-?KA6p=8nk|1-QGWUr%F;7MWM8k@wE5Nn zX)%pi65A^k>OaWU`2X7S_QdH^HxloqvK+s6!G7I;w)T6Ry>nUOr|x~U|D0dgAIEO~ z8*hxaoql&_)pQFt|Gy$WOZJzqvz@ZQ&W$?MZI-aq`waNlw_uVUWhlSOl%GOt(M|L|H( z_TR?v{VgRw_@5u;_uG5O>MR2T16z`}y9+}lLlnc*H|M|RFfcH17I;J!Gca%qgD@k* ztT_@43=Hfgp1!W^k2#nHg}J9nl>K91V2t&2aSX9Iy>#+kufqW%$Lr0%9lmlQL?*{E z!0Lw2rEiK|=O$fsRrI)fzxbWyhx5w+Cfx~Swh>YDv|*VRp=8MYWldGTn&jo=h%<^8K6*Z0{P=R<;+HJj zvQ8egd&`rXY=fv_TiGo#;WU27vD+`cw?l{@5jl^;Jt+5 znCy*LF^965FKv1G_NvDAhPO2W`Jek#&)l!k<+Gc3A-jQp&DHEF`HMd4%{TlY!C1rS zd|<`yM`t?SZhg_X}0{bQR5>wyJVO-C^z`)??>gTe~DWM4f D5S(hd literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/ebwizardry/textures/items/spectral_bow_conjuring_5.png b/src/main/resources/assets/ebwizardry/textures/items/spectral_bow_conjuring_5.png new file mode 100644 index 0000000000000000000000000000000000000000..47e5608a8e911d401fbc3ad5974577eb0692983e GIT binary patch literal 1809 zcmeAS@N?(olHy`uVBq!ia0y~yU=RRd4mJh`2Kmqb6B!s-9jihjN`ey06$*;-(=u~X z6-p`#QWa7wGSe6sDsF8J51;hZjOWjD%^DUZ1KIYCr_4WmyvtLSdB5fE#`#$;TuO~; z<{Vi*|DV54{CBATr0Zfmm-&0P|H!;_L~?G%_x$ZCrFYLa@3rzTE3Q6hz!`P3f8YF% zl4a%d1-{%kz4>lS)t@7eUwo>OIn{IK#hk*A7DD&Rtj?>=t&EhPR{T#zM|}Ii_2;D= z+=>mjq~AFu6@EAFVrW!3nelj+vVqR#{qOzmRKGj3_P5i$wciiTJ$qd5e2B#B^9=tF zUEDai`uyFb7p_~iKV9Y)&)LwwpZ(pjjKZFM;nS}+Yv!L@v~KAdIX1BX&FopnML#^h z!2jB7htjkN$ExO8tl_3pIu3qQSn4*D?d#RBRShfdST0Cir*m3Nwcyb%my4AbA23wT zY82BEUB!8(=CG4?Uere|SC_n&i9Q8xGd`Y9y(jtq$u3K&yyT?qc5}AG2J2>|M$73w_K1EjRcQ zJQg&3Rq3<2c|fM)Kyr(n=ug zAX`(!D!!k>CQ9u_-+HB<&nZ9XIz8swqpQ~MYd>sud#d2r%x%{q;LK&|b>+pPe#K)m zlKkedsGd=s-{fhybc%6P+KzKG<{BzJKjhja7GA@tIxVEg^;gK+b-$#t)~tMX%vWk# z{b$`7V$oSUgWa`C->&;DSM_G)^TrryqmmsD-6aZ_Ow3;;8#+I9vG`NF@ZP?xV8htQ zhhj}HngTgxM2#`D6k_{?XY zUyrZ-xpMITlZ+|b!k-6vOtg5#aVtvK>i4zq6E@X-NmAF|Gj>+>tnLmedG_j0ocH0+ zh11PO-$#SM~bb>JSml{;lN^vqJ4{Mc%w`GQUH+ zYYJCO3mK`dsr+I0X`+9`n+vyYrxjQjh~Jc-qWeo$Aaecf?gdwN^$N9KJRuob`d~+- zU6$;PsrN;4rrb64h_`k)J#kT3`t~r3$jSE~Y&pk2MRcRZ%gED$hKaqk%7z_vpZheW zi#I8M+V<+sx%(3?>FCDZXW^Oo$MO2F{W58LMC|JWrHcCt8h0PuaI zx#L1^Ij0<+@AQi)YSWh1j344mTfckUJ`lg{<6&O={#jGE$o?;F(MsR1`SoA3(W6_Q zw)0ko-<)%&+w@J`=I;H*UXQDP%`2~8v2ccVqM>5l_MSc2XZr-cx$$mY{NU>ivyIdI zOtmf5WJ2BdnDJ}wd>xSawoY%WQfK#r5Nl>u=C9g{@ll`sUNSE}v@m9?So^=ZZgmae z<~E;O^3Un%fA~`UVc*;dSLZoYvh7MZxBl{8S>8S#k(0 zQ$PR38XDSLCJ26DnUIxsWXH#nT_i3)X0&M9l z@@Cfe`}tkvylg!!fByV1!|4CP_7j^I2fmQ$=enivMDt$mD~bJO>2)X0XK-fxV>Nog ztrl13d60pDfi20~-G!l&A&Oz@oAY0D7#J8h3p^r=85p>QL70(Y)*J~21_t&LPhVH| z#~jRpLKeoC)mAbvFa~p$|L5>mJPhW|m5xz}EDJd)b$)xrUCDNJmIdrJ3~o0ApUds= z`<)Oesa?OLc9E~;DgIp_+(PA6U*2ITytu)j;NEX3)~$gb6a|=nH5jtp&v2KGJ|j0x zJNH!Ny(!+dw=Um0U&7{g_3+`ZyEmo&6qJZNC{dM=;B_?qc3h(?Td?@yK-cVb^V3eP do!9=GDfvRa)qPRF?+gqK44$rjF6*2UngGx(S!@6R literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/ebwizardry/textures/items/spectral_bow_conjuring_6.png b/src/main/resources/assets/ebwizardry/textures/items/spectral_bow_conjuring_6.png new file mode 100644 index 0000000000000000000000000000000000000000..47731927a27781cce3241d7652e627046d605bea GIT binary patch literal 1797 zcmeAS@N?(olHy`uVBq!ia0y~yU=RRd4mJh`2Kmqb6B!s-t*SyIN`ey06$*;-(=u~X z6-p`#QWa7wGSe6sDsF8J&zw}O&hzKIW)VvZL+9fSVNcmC>t?mT`B?ESUueJ7<_Le2 zyOR>`{CWQV>Ayqj0YT!EGxRL0Ymz!uLrSj9Kc9K>`0Lwj|E^Vy_hj~mNH-Zyqq^(d&3_eE_>7ew5ZU$PR^ZC zQaN!_Gxy|9+kKzoS{oa!%@9wI9dbd~oUCq|YI^WjMH+en@ zyPNsHtbM1~HZNrN+CQ(_RpS0Ue%`oyYuh^0^Y60GBxqURzLKjQ&fmrx^66{TG36iL zFHV0IvFXw+n_#yf?eJw;QLcpQz$K1T#m=sNdxg=kO_C*-!}f#ea-D@Ob)7=rowYfh zNb*IoybI_xlzkWRB5Hfg>(Zb#HXPF$AM|`UHv9Nq^PlSH?_P|uF6rEJZzt2b4a@=t z+lqcmhY7SyE1acQxBj^8k=}ZNX$uo}WrXEy_*E9O#YKPP(dp-Sc0XDCS^bV@ntV-EN_Yos(3$JG>^YS`#=qO*B+D z%3GsHXquPaqpoQ|Sw|O%uG7A^Zo`VLt;ck?T`8KpZ0(j?f_Apwt`tvSxA%+Hp$Cm$ z+d^ zvO8;r*v_2`V*M^%1Qv)wzYSzotfUS#Dj5F;H^hIx4Ik;T4*kD zEq@y~<#&kr^hfFEz0vwKehMjTiL5_d;LWAvD}K>Vfl4Wz>Nfht!!(5 z`}}%*?eDdN|DR-Rt$HR^&ZQjav-``n8)fW`Hy3_>r+R5q%|4!>g)6Ia3cK!D+2>?F zO?Y=oD|WUu_rcGtD;J769zVUvU$R(yvF(YSn>~Y8%FGG$S1)H-_PTCv;61~ixfUgV z{2AwMynpyw(ATWp_uBpJQXb~q6UhGFu_8O`=svBYmk)YR>^I<>$$Pti&Bnw0NJAL2 z?1z7=#WvRL(#VNhmSVT)tW3|ERTotz&ssb$?^;5Gdymq|mYAugmbXi-K5S+QSzEE= z!p(F4uGC-sRFW&RbJ>@x;XUahCmbFe(Lbp1sdZxS@dSfS26jJ+pB3oN=019;ko(c* ziXU`^64;|Zub9{86Eo*HcX%8B_nSZ8Z2oa|`JxX|9Oiqb*{S?~{UiJA5AWIbz2S+? zW=q5}O5J0(TveYYzhl46)x)g~_O}x%W`5Yb$%^|{EAyvt*6VLYUsMmJ7mmwL=> zV_NY})b7A({|{egf4IZXo!Hr5YQVBrwde3!mhjESvv{xaP1UWIPG|c6yIlJ##~Z18 z`YP|9yWjeq-g&soRVhp(K_c_%5zbL zDY2GatWTdkf2@4vFW-4-cl~mvyX8zAsjM}xPuwqjUU!^-T@&lekNR!JFK?cCJt32U zfq^Z_+uensk|By=>YMXla~K#HI14-?iy0WWg+Z8+Vb&Z81_lQ95>H=O_QxE|ft+hV}lvA9nFYD!5Nx={$YK zlZMMm&FX9BGw!nsDoAcAcI4R6IhTul`F`8;B+RLJ)%C?Vr-7gMtN2~^1oaf>bd`6Y PijKk4)z4*}Q$iB}P@Y?0 literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/ebwizardry/textures/items/spectral_bow_conjuring_7.png b/src/main/resources/assets/ebwizardry/textures/items/spectral_bow_conjuring_7.png new file mode 100644 index 0000000000000000000000000000000000000000..e7ee0d92ed2c5601a653e50af9d19f2b77cfcf46 GIT binary patch literal 1786 zcmeAS@N?(olHy`uVBq!ia0y~yU=RRd4mJh`2Kmqb6B!s-9jZbiN`ey06$*;-(=u~X z6-p`#QWa7wGSe6sDsF8JkDjEg$@AyANHxn5??)Ck%HPrfKte&<1L-CX*&WWl|r|8rvw!h)BN;?03OUmJWubcN;$v=7a?U3V>i@!e4 zXzSCTaQrt5pVoT$r){%e35J$rhPBp3mc4jk5$JkP*7D`%lUD0n+Mm9-|2eEs`p+L3 ziG(j43(Jr3`rmsrZ<;7Sf6X`6wQsC>oHzY?{_fh2@EbFuzjN-1e$Qzg9rDiJDKX~~ z<4aEEslhe9cimoeZaw{}UA!=2TmOFcH_zS}J-1k`t;o1Cr6llrP#Hh7_JS|fQHPHH zaQ{*nFF8G-lXpS+hR8xw=b17W=83EbUg(*;y;mxRC(pv|bxd*H=_8v@ugeWOv@64k z&Gv2s_jBop&jPz=>u-7cEO-6H14ZgRB`m2elJoUGd;L(q?t5{Lc1h=&I~$tf^H>$` zM4VY`?bawTt1I))k9VhSj`Y?lTx&kKBT-Ce!;PwtD<0o(e43r!UwDx%*?)&{c_>3i zg7qQEPYDOqK1~#gEbHrRSllq5>HJ*&bxn+27fX$V?^Mip=-ZJhT|DDkg!o;-#akLW zUQA98Xl7xGRCGDQ&+f=G^+mFQ;V}_QuQMA}<~wz1s`{;V6a6M*QIwSS@Qmvomd;5n zt}5Oq^{S_Am=T;dS@n4gSC7~Vy&16vi>ACaG%54Uom1cK zdhhXnp4DtU+wVph3RB!93YQ#oc9Tn0y0&b7;<1@({xd75NoSvW<$mo&=g#$!%Bi`A zV&5$GZDuq4ytFCIva{RR;2Be6VH}Ubg1e8-aJ4=VEABR)EjvlcYJ*$h#LJn6Y;1=W z#MSTa*lqk>HD9gm{-d*dlh5hAs%x^`ydwCS-REyjTjRd zl&$K23$y>NZu;+eam~9EZeK5}d;MN0R63Q^ zb^DjjoU`h5+B3D%&g7P7sTV>;RIHfY4kgdcX~E>~AnOrPd`qyB2_CwC*M)L3V&bK-Mz=EyG%y{G?% zUF5UlNAZJ3UZ)TEP2YHIv7F_SGonggbDzA~68)xCZPlqI`$8nT5><~xGVrDBeI4~_ zL&5raE2m}eZrhW0Huk{W^OtriW^dR~)4=iXp!L`I6NQiK+NQIF_v|rl37N;Gx!xwv zXVnb%e{ZH$u5OFGySgA>Yl=lcOwKQ1y~Wl`_LipEpH&f7{S>Qpc2#$?vBhNoxU{U)xe z$p7BX^g4ABd7g<ubF1@r0(yv#uTS+H5f;@b-FL)*tJ?e_S=QV*S%= ze?Bhzc4b!Rj`hAhpEr3N|M#mWaL(nek5eP#ZU3&CR9^pK?>FOrcSLpfUzsfG{yL`o zLe9r+y&iE>m9qo%YUH+Qe>VQNC%D93mLnlsVO91@M!kPatv(z7lX3mQ_4?)??oAut zPT+2@S72aZU`z6LcVVbxh+>%f=KR+j1_lPs0*}aI1_o|n5N2eUHAjMhfq}im)7O># zF$c4tkkqry>AnmMjMknmjv*GOmrgeHW;PT#UT?X6?NWD5uGr`posQN#J-wzc%qM!w zHcohW=g7stg3=ui8z*NMthab2e!@M^ ze^cg`d!tcp)>*ctRo=QKe|}z=dO#_FEiXx9!>Mm!yw~F2d^kCuZ=UrBvo@vx7Bi(4 z1^x?f9$3G9%JxV9dFFH3SQO}bwJ`O(%4pbEyE|uP68nMweDa(&#{-z8CI(tt&D}qF zUDT_-YjIXP^*=}*R^K2adG-8(>q#NjqMt8)z2C^M(9vUc<^Z!{R`B_PYJaEQxBdJk zo{c?Wl6R=tD8ZA*d%xSYc1@KjMUbeJ){@q9=kT*11{3xd#2@&X81&m$U;+aJ1B0ilpUXO@ GgeCw(Mp2Fc literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/ebwizardry/textures/items/spectral_pickaxe_conjuring_0.png b/src/main/resources/assets/ebwizardry/textures/items/spectral_pickaxe_conjuring_0.png new file mode 100644 index 0000000000000000000000000000000000000000..43689fe4da8d676e86e338ca25d6c96824a8927e GIT binary patch literal 1588 zcmeAS@N?(olHy`uVBq!ia0y~yU=RRd4mJh`2Kmqb6B!s-PFICQlmsP~D-;yvr)B1( zDwI?fq$;FVWTr7NRNT569z97}ljqNKk!ltd#-_&~dTvO+`Dk7lvh(&`N$Z$cjwzqDt-O^&JFL1<>ud++q?`; z?c@D>BmKqShq@R&2vAC#_Hug zeqOztVR5BKD{r~t#vi=JqK+(+RFZpMi*q|0r%u{n^2M_3nb`aTyO*lJ$+4@dh zP@+Y>r*Gb$=Qng)=0)rdtNY%tDD?NY&uqI5qhuDpznd!F5Mq!Xd_8O$%V8#sRA25L zBJuglUstNe2u81A*xPuvX|^}!e&n8uyFe@Sbw-T9fF(+>Yrkyi>FM}t-hDFMNHsf zpb}SBfP=zm%l3c9$Qkmf!R1#pLsjP26@Z3lhJrShL7)FI#BuEED%my72Zv^{2?BSt7w+mdO`+u1jt<)+y49S+e7iw?CLA1BG|?gX<|&)6+m0B%u@t-=u`xaTb;q9P zCQtUqzUr9XpB;UcODizI9LMdT%+HY|`#km%nwdR@Fg{oMT(;-8ahZ9X`OwQ9fk^WaX*lE<|-rp3CvxY-!9|5W^v z+Z%gB)@}Q+FnNajH;FBi_7+XC+9A8G>hYe3GvBKnex>PVWNWva^=<%D>g(5fy}uYP zX)SCiS6VR7yzkl3Nq0XyR@MCW_D5rM?2ehTc79uaoVHDBy0YmuuT;XfcUKDCla0#O z2h7)Pr6lf z-Vg4J=MoKstD-;qfB5w=BhHxRfwkjoX`$|zt&$(uHh*Q1o^X4zPT2#|SJ~}LDk~5D zUT`Vx*xBpS)@4pia`OA{s+^U7vFU%O@}IYox-;t;neUxDa%PiL9|HpeTavfC3qvJC z6vNav=fCDKFfecyctjR6FmMZlFeAgPIT8#E4D2PIzOL+#IhX|n7~>wCQD$IZc;)Hh z7-Dhy=wyHYLkvyl6(tBiWr`ne%N1gZoUw%_q-6PwnB>du3AqoB@X2Drc7ZuM; zQG37lC-?u{S22f9GM%1rKzkZzqr+Oc%N$Z4C5*V%MO^-BC&bC3GtJ94Si9nIQE#Hl z!4>Mi6g|w;jTgD>VUenQ_1KE_&WTBy%SndbH&#qVUxG;ys`|I?rMea_FY zTO(tTVKXtx_RZp(fggYE`7~)#)3kD}(&`B(`)cZCY31d%s2dixvX|1B0il KpUXO@geCyQ$O)7H literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/ebwizardry/textures/items/spectral_pickaxe_conjuring_1.png b/src/main/resources/assets/ebwizardry/textures/items/spectral_pickaxe_conjuring_1.png new file mode 100644 index 0000000000000000000000000000000000000000..9f3141dbb987fc37c8b05211b70f749feed856f2 GIT binary patch literal 1593 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 literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/ebwizardry/textures/items/spectral_pickaxe_conjuring_3.png b/src/main/resources/assets/ebwizardry/textures/items/spectral_pickaxe_conjuring_3.png new file mode 100644 index 0000000000000000000000000000000000000000..1fda3e0a68bd6f71171bc4f4a062509c74c13ae8 GIT binary patch literal 1673 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 GGywpu-5XE< literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/ebwizardry/textures/items/spectral_pickaxe_conjuring_5.png b/src/main/resources/assets/ebwizardry/textures/items/spectral_pickaxe_conjuring_5.png new file mode 100644 index 0000000000000000000000000000000000000000..164c0c4509f0cf9c63737ce4d655e1ec2e9d587c GIT binary patch literal 1723 zcmeAS@N?(olHy`uVBq!ia0y~yU=RRd4mJh`2Kmqb6B!s-1*$?KN`ey06$*;-(=u~X z6-p`#QWa7wGSe6sDsEj3kDT;o1>fIv(Y-7xY@JUH+`jPL`}Eu3#>}bPS1oG0E}!cz zCD}aT+(eelU;qEfJ=2fzIVUCWlH7Ii(WjH@=LD|2%if;yw`!hvHD~^>vws^eKE1H( zuhehJ`4{EogpbVs_i5XG58J9Q8oNy7Tl3bP5jbaI+a>e9&g#9|+{&BwJB#c5rgc?+ zc)eS^;Ubfjtn@p+fQORLwfMw#JTZ!j_1Ec{r#bm^Mb-2B$Isn)#9gudOVix5%kS@P zJ#?dj?TC1fpMC51jnN!?H7r?9Jz|Eq5h+kH5IR`;GF1u4fjdJ2$ED=rmkf zn<=>cfw;oyUBY>--J%Q3H$)bMJ9nlf@O`?Xae2YMTVA4SRqu2%W@_)gy4=sAFm}n0 z%F79iwr3jz%S6{$mVD0TUR!!OYW<|7r*0A_SyEdh>+d|u%c|?X6Y1)_8D3LYT#j+?!fn3*2*d9^HI+N5bBX)^|K_ z1u}GOC~Gi$a-gC236txlLpm-80uTDPJ$+*%Zs4F;plp1gw^;Cr#`&#=?isyL5A2p+ z%Id-*KDR+iMc~9IJB7L<+DRJh;(It1k0>}gb6M_sk=$YEHOEw|TUg(5QO63EldrC1 zUs$ndm1pszCjp0?x;%X@O$j;|Vd7kR>`jlLrMTX@A3|O_L0gtg(mu5OmsHl8psmYh zNt<7v@K4vw&^J13XRy0Q>3!$^*j?YQe0EsFYyO8rnNQN{(h2kI_N&|1T;wjEzuB#Q z>&Y4MkDnZr+U2SzYI53h#+*jOZ!E`BjT#!Botzo^X`XuVWaHTqo`Mo<0%trinbp(i zc)#=Tg4w&-i|2nzYx*yi|3|PmE$I9IgmXTx_=@X4edEj4T`zl7w<%4`&u6W)MvlY< z)6LIzs{h?#xt z|M2`rsA+D!V11p&d~ugKtqC7Cm!17p^}6cm-etD}cmGE6$(r4bH6YfAaCZ+mDr|^LZB(-r(NKWhS*RVC9zBgm1epYfFYK z&HMb#Lg{zC)Z}N2`4`6swl8M%dhl%B;~fgqEzezy5bEQ-aeZ5d)yv?Z{@#!yl>K^tm8LJvNf)lyt$!cG3lCZ z`mPo0u9#=c$bZloVwc4fWciWv)U6%gQob#JSi0a+xz(Rk*K0N+F_EeA$DVyLn3lL^ z=i0e^{}jRxd3rU+Y*g20|9$AUbEd@-p10;ohmYHDjoENWDf<*(*M|)zx9yrsmWOe! zUr~2q7B7?R_X%g#zLGOoVK)0wtD-`Iv?Iff7ooc=+rEU%vx?ERwqf2X^QV!~@Lulz ztg!0t8I|%*wogJMR!nc*cJ9=srwxN5_mhRpl60?(e3z{YtoDRm(Q!} zIw5bdYsy@uxj}yKQuwvJq(Wxxo-4~wfD z(D=?<G^4$A}w$E$% z|7^cv;e5KYG5oPZvbs9(&Dm``eEIcLlZC@K zZV=rwG2MFS;a_)kj63E2*2>pQ2t<`;UaR@2zw6P(Y3&d9iL$Lb6>56yQ0esPA`Vk3 zUtQu6U-0zCl1R()%2UU#CY@SpykqCr>V|1ujlVDH&Ta1T;;|Co6v^*x*XP~hwIT3~ zruz4nE=;RUrPlG@nxQ-GYNFzcD0}<))7mZ;J*jEw35(uSxFLJX9IGg)v_~_qJ(AWH sbwB;s<-_#Ad2B^TH_g)i^D@7NJ!C`XRn{pwpb%&9boFyt=akR{0GHD@)&Kwi literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/ebwizardry/textures/items/spectral_pickaxe_conjuring_6.png b/src/main/resources/assets/ebwizardry/textures/items/spectral_pickaxe_conjuring_6.png new file mode 100644 index 0000000000000000000000000000000000000000..6d7731bf4529171ff88cfcb847c2b5d990c05d1e GIT binary patch literal 1707 zcmeAS@N?(olHy`uVBq!ia0y~yU=RRd4mJh`2Kmqb6B!s-1*<|LN`ey06$*;-(=u~X z6-p`#QWa7wGSe6sDsEj3kDjEh&hs~2G?K}w;X+YGSSovD9bbRm`3kx3eUrUH?>uEo zQRK6lbYR*4ug?wYA3W~Z`_VDziiECR+}>S1ew%)8j^0$a_xyplx#dO0{~stMZQ0Yl zQT{JaWrdGG{gbDA?|9gjT{0|*v}3DW_vV6S)k}$_?N3XNxt-th=6=ren#gIL(LXES zu%63cbSgVmsQ(^r2`99iL7`8DQl-pOC~?tY_eBYO7cm90~+HYYV|SNe8W zu-tFhx5oXWO3ubZFL`ssY_3iaV!F)t>59hX1^aG!i3;p}?RUW{Tvk6asqob+rK9KD z+k`J%=8-6jIVk1)CQoO}wX0j>mbOflcDyXuBbZiGaVGsx_`KT}B#cWsb9U9T#^kXn zB=|ggCLN{Fa_nPf#J|}7N@4SFyc>Dg4i^<4V%w~H+lBK>hi;sW@t3Br$KDmFXC7yW zY1ztrK%kjXx|7*;)1x^82m3kyq$rfXiDhIKY06Gv+mYC(puTgb*)tB^Sn)ezi?=j% z9GJ*@MWNAQ+IPl}%65uvMGqeMawxKKYG$06xVT^Om`35X6*@X`O)i3-izW%H&v)wb z4Dy<_$trcqh6RB~GlH(p*_hGxvgf9xl%;t1jvqo^Izd4fCutvA{!1!rO;GUFS+le6 zO!%j3W~ghLyEE8bqx8OWe{9vOTb~`)@XFP-2)6f_lsuWe_3*3eYcD!?zK>jd_*Tjp zecQ?nY#UFcHllv^}mTtULF9tBF!B%T+J&`Uekg7>S2T-&XB*7hNB=tz<#OmY(8*-c4dl@0NO; zX1!Q*;73ySzB|qm(h=LOM4ngJ9d3GCYQJr^(5_7{zkB>iJbX>-%AIA&ai{C9%+ePP z5H1TZ`DHq9>hqgw5C2TsY;rBeVAl1=3-;dFIA`60IpsVL4u!iv5)L@Ev`%{ZGjpcz zelrf1UWvPGd&o4ynOR9a^qfYx$QG5g@(lJ@_WP?Xx-O0@&wa32c+vcd zyi&1 zP1LuT{6|s$>x>%9BUK9)ZTtK3`N~pXGkNA+pI1gMvYo}ghrXDgyt#*Ct`U>%-?u8PPjZh2&wX0-`1sBHf7UO5rMFILg+}Dz zbNdssKUZC1{qL$3wAnUm@A0i!M`!(w%&uE|V(+xy0TQ46YEJ2wTfBafY4}+$?As6mxO=SqgU-6hR@#wS1jN2Z0_Az;p+d)+bSMpweNrYEdMI& z!^mzOhqnw23~Wi>?k)_K3{ebI-<O>_%)r1c48n{Iv*t)JFfg!}c>21s zKjvT-1HZBZhX^Ln%=x|hp&!^d8-r?{s z%nu4#S}h9u1Xw(sjjWvysUI*D&}KU%#KFn!o%qbPgyq&2@AL=0dg|}ysh^*3{o{RL zD0|d7ot_582~5gKr4nNAO-~;b7t7=6X*_>Y>hjdndEHZ8#jnSPd9OAVtzme7V6kOV z{q4iIJv_JXE9{!f)AMZ1If_RYI;qc3S|^ox5l z<>pV@ceUtIy2{hfD*2wQ6$xAC{Eqrn_RM^(>eeW$ebb)LJg`4%26K}}*yo4y{~gnJ YYDzJFHakm?fq{X+)78&qol`;+00n{{VE_OC literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/ebwizardry/textures/items/spectral_pickaxe_conjuring_7.png b/src/main/resources/assets/ebwizardry/textures/items/spectral_pickaxe_conjuring_7.png new file mode 100644 index 0000000000000000000000000000000000000000..845a98e34bc93643249ba29ea729ddb2c7543201 GIT binary patch literal 1694 zcmeAS@N?(olHy`uVBq!ia0y~yU=RRd4mJh`2Kmqb6B!s-S*k)JN`ey06$*;-(=u~X z6-p`#QWa7wGSe6sDsEj3k1SHrWA#K7z z9E$fQvzYyTAAk5ytNdh($2C_bIBoc`^NCP;$(48a^G@#iYA65gQsso%uNjb@91`DdoMOIg3aNci=}#m6rk{bZ<7oa*-c#Y;n#Jx@#a`C5J6wEOnCpObg^#7v#P zKbA$}tg}YW4(`sQ)@MRlku%%hX^pwep_1l74yZfx&x15=pdNM>weOx4gFrcTPTYL3LBrQLeg=JPtby zXU@*gXcUlQ58nSFwtr{0bhZ1M2FLvgVL1l3H~EVAZ@)3==w^rW(dlpa%Ddi5Ft|kA zJ}fC@kiguz+`-JqUFpG!2kM85#g4P`O!$811W$pokVD_680lgq-Pmt?j%w&C9P*yP zku||V;k0G{k4`^9=bPQ-$ExLPzPy@z-m!_>u0`PRnm|jhl8eU$lCR823JY8w*X$PR zJ4;yIk@K_Wl8i~qrW74pB)QBuEj{B&%npyjqtgSDE>7}V$1(ras`U$xtunoOXNRZr zuk9BWW!?%pJ=e-<86zOiSQtbx}u-Su5BZrHMX%{i!*Su}5sIiu?m>wAyZm70XiGM6#d zm$_wAW-j|^vrq1t+Y@`9MAkj9Iudkknd-A8%r>*IT{balSFNSx z#aWVP<_ekgTyHGmZRu}lC|JKYcE;7ffZf-pz1h3{+sWw9vfJP9+2bHwof7h&HS(0* z$9uE#Z>q*zJD0Wj%CosXJ6@SDH9nYV)z`YiUb#2JpCQ`x(#G|!-cvq3ej(Fp=6SLq zG1aQ(aoG&ND64Lp37gnAu}=7v`cCrBGw#@{-c|?BJ>GihMyf)+GS3-akDDA1(`I{Z zYR~mN@yYhWWfQr-kr^pFx97!OSajg(QSYCZZmilCdpT>Zv;V>@F@ZO8XRU8|5**Cc zz*FNnr!tje`Mio4gmbTdkuTfct7n*-YWgKwYl zS7TUR^3_^^2pNnEo-(YWsZPX2X0%1_lPU zByV>YhDwGghN*APf6ZZFVBjq9h%9Dc;1&j9Muu5)Bp4VN*h@TpUD+RVFbndEoC$Qf z!oa{N?djqeVsZNDtg; zj#dMXmnuu+C-}K`ggH5^o**#!S>&5zDwB9U7xOQhIkURr`##AZ?~PK~7n#ddIk3NA zwr#RJFUHhyud<@VfQ9X-6w}65J$0GfADqVf%%s_Ow!8S* z?Gw6R%gvLy^5(`RsmTp1V*WgMc=q7Bx#yDiG8}oza52sBn631ggX?dGKR>R1>(ioe zPrjM4ytSEAI&Q~(F%!)Fx%B>)jQic!gfI3lJt7<&!5Ad%WBU8@{U5w;+=&}+=5E(w QU|?YIboFyt=akR{0FlKhrvLx| literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/ebwizardry/textures/items/spectral_sword_conjuring_0.png b/src/main/resources/assets/ebwizardry/textures/items/spectral_sword_conjuring_0.png new file mode 100644 index 0000000000000000000000000000000000000000..45edef5bba5754095dc52f34a03698fe7362c240 GIT binary patch literal 1668 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 literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/ebwizardry/textures/items/spectral_sword_conjuring_2.png b/src/main/resources/assets/ebwizardry/textures/items/spectral_sword_conjuring_2.png new file mode 100644 index 0000000000000000000000000000000000000000..c49f2bf09e239580a2bad543587dc8fa37f80e86 GIT binary patch literal 1777 zcmeAS@N?(olHy`uVBq!ia0y~yU=RRd4mJh`2Kmqb6B!s-^{YZ6N`ey06$*;-(=u~X z6-p`#QWa7wGSe6sDsHU}k1opAx|yX#py}y{HM3;Td|F;9bNu7h$v?tsPO(pL z6uLXK&$ta7riiU|LS*sqw)54%oW@3F_)RiTh_N7x>2Ck z!rs$2=ZR$*_d@n-dZ*{teK@yj@BcfA=5F1|U-s^P!#siOSxl*x+q+k#rV@0Bjkn7g`fy3VFuPhKeT9I zeBmg*Zg>Fc)q3n^Bs|1L+9xyj!B1oIDM9( zMSAkipT~3roE|4=ao_(sWA~1Yn;$ohg+m#{_Ufdl5 zOFEjQR0K|ZiW9JZrJSU}-EFQUc;qiFx>_drH8TBa^(=am;_U`bxmoW3#gI))hMc z+J526mK#B*=UO?f{H^V0*?(IH#=gAqh_9X)B*F4lLd)1N?E|eD; zy*PH4y*U0;+L8T7XICGcGxN${w&Jv)@)^G;Z&zQlb&sD&9LrgqIWwZxx zZ~St7^ykH$i?`&iejw1fd$#0~GkhF6Ed4tsicgvnHA7ba^PQ^wrt!WPuBDc$mM)zz zU482}x6IDDpX+{xFi9W3`%2ERdFp=GlQr#KZ=G^)e%HLc(MM@klg{?Qtzqt`Y+R4! zKS+st)U-Ku$2Q*Mar`>hj?WI?sU!Gkx>|N(wQ=Jw(`ygTvbvw$WB5sNUYtO5zwy6_ z`JSDNY_Ch?BrbcT@A^%{bdG{#O!vD73#V23fBpAiYQq)I=ON3@rPYp2?BzZ`>(8dA zaoZ*ZwX%z!iw@Qd=*ta`bPo2C`K8m7SEyss7g_%`#wHP3E*{{GMI z&zt4#1D$tl(o~P0Rg_=4nbG+|o!OLH`8&t21q8j_Q7|uKnOMHUEa@)CZC*NaewM$f z%=_jZH*0xbxm{klNZ2&qaCcwc@O#Gg3h8QR|5?ls$W)h1XZs~vD(U&VHfQ#F^^Dcl zD+(MQ+~7!Ee0kTiS6_?HF^X*du=Ca7JI+>98^R9c{x6itxU(D`1 zb%Zy(+^eLyp35{}y>MAjlI4LZ)>DFt^RF*{AGJV@ed_`Z&eYpY?pKNz*%l?nJt{x6 zk9&3{`#k;`OLFfX4t*PC%Cq_I5#N%Q{zZ%xj}&jMURIdny*BHmli}3YIu1U|)}DA& z7xZy{!cUpddj+{C4stZNe7P@rZQdHuCv5MJI9RE_)9hPu`~Jhf9ABUAY?IoVdR2Mv z;e$JW3f|?LlD2=H;WJmmCy^X-u0z}&OM@u`0I`uNI<>YQIxhkIUgtLOv`>!LkC~3 zii2Vn?}FouO{}cZ{zdK8MdyD0`#*2>5BDEN$t_Cl$NX-k`77y&umz{Rc=7UtAlv+g zZD%r1o^(DFQQ2@PEXs&=UyotZS;eNsJt+@x&&{w|Ud3QrUF?2T{ z_2roPK%~ wFzgNse0r*?aWPl4?u!llB3bvPJ;dWR6l*)?&u?pHU|?YIboFyt=akR{09$ZJyZ`_I literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/ebwizardry/textures/items/spectral_sword_conjuring_3.png b/src/main/resources/assets/ebwizardry/textures/items/spectral_sword_conjuring_3.png new file mode 100644 index 0000000000000000000000000000000000000000..e5a4eb38945c43c79cbd77ce2fe98200b9c793da GIT binary patch literal 1791 zcmeAS@N?(olHy`uVBq!ia0y~yU=RRd4mJh`2Kmqb6B!s-t*b&JN`ey06$*;-(=u~X z6-p`#QWa7wGSe6sDsHU}kDPQ^gXiyakz$q>fu_eB!p`zO`|&wqPRXUY_g1~_I>@5( zah_PtuloOdpZWFNWqQSX6-(IeO(#%=4z#c`F4AmHVNJL*Dsv^ z(^I%pKcN2D>Bl=RRy{eQ{9;lK%cm=EE?9nkBzPpR|8k}I%QdI}oh>`pU)s6Dx32Cx zm%*%r33ChQcIwVc%u0+n&}n>Y$Gm_ZLD%_~4_-#t9Xoetm;ZyiRsJ__)*SmO$d!C} zrocP{tH&zx$=e00lHOkW^P&BF*xTE$dCQWwSh(HaecFy;Wx}~->(;K3QxofWv{mOp z*dLbK*z!ZN8;^2bkiMa_WA#Fp0w3!W!Ha#Ge`RTh&Ug`9-gRx~tBPLNu<0?eOMX;d zF5s$~#c1899g)nld$#VDFUyv$4{CYlHsdA7Ar9?(cb_djc>j*MW3tb6)lDDUMBfx$ zW=uSml4obg-EzTV#;HT)cc1m%zhQpFNMZ_W@e#Joy3sCzyMBx5&y)Ooq$+v)?#bJf z83Y`+ACO2gNMPO=ps@O!reHzO1NFm2$M1<6I4G@~DEWZx9)HoI*}FEnWu7g4^vxiM zyF;L*qe+TI;KZl62llU&Yc#mK&6R{)RJ|t2So}~>WZ^Y-Pfh)*B^6?tbxFqZmxiHB zui>&8lf8RH)HGF0HJ42(YP-a9QF66$+LM@=hmX3a1Z+7n$!lG~{8y{51Z+JvD=TkZ zq4SUJ7p`o%5p;U4Rm{rYdbTBRH!h#YUX%ObgR`52)guq(`w`Y_>^8aipQ$}3C3{UR zx$f*`>uiazy)GAg)Qv2elg|lDTtCSmbIbQ!j>`MHDS1U{lbr)Pn6p(T&vBbTWxTTQ|_xs=MTPk!_mG-m1BCPg@_ibLUpub0Hi1Gh!?hf7C9S;9It3 zK~cYz+55I7WgBa6PpEA=TB7rA!;HiSHyu~Wrk{O$;>siCy0k-LDaYf!)wbQ6_-bb@ z=Yzeb?U8P%vhglvmO0eQPa0P^QF;S=^r!o z8{ghu@6M&LKmYP(-d&QyA*{K2shf4(Sl>LgxSOIfx5VM}>tlT9`etpJ9{qcr>H2>^ z_AFJ*eJ!;v>-s9SoYK#8Slyqz4YhD><(^-_?j7(wE-|4_dO5@U3e~RvGfLko*~xF^ z&3QEYc|=Hn{Nuj9sqf7`nLe_(%fHNZ=N0|P;`^yrWui{bHEGIUc{Tg$;$5#9CuF9~ zK9=a46>5Ec#pd~!7ga~L@HbALSm?L%hgn39`&9V}8OI81_NZLgY`k`@`t-0Gu{@>d zn(T$mtzQ(**__zx)4ww6zTdnvnGaI)nN{DpvKq)=$+TT3${h3dl$h;~72$k^27Uf5 zXN&`8ocw>C^~FZh^?m#wkE9eCXwNxR<6CfE@^Fdh=n1fkB zMe=*f*{uu=jIN$8jv*GO=T6?}cPK!lZGSW;V{1U^2HA)?R==70jFMC?`FO{ng2riWv$4vOP4e`p3eQ_R@joTvc`&aU(1UW^Ao{7 zQ*Uoe@IJhG=|k0%hYu{+V8baWtg}>|L7MBB!}+aG??q48Ej#ydg73d0AxCvvSF`zs zu6MfDcp>*>^63X__NpC^c=af}+dj>JZP@{t396QdLYBWQ&-Fh0`qbyS`i|;Tu0Pmc zqZ?WC+VPFu#l40W`L9KopHFC%F(^7%A~xHjZRx4{s1pY`1Iiw}o-qHcIn$q#nPz&aGZ+{c O7(8A5T-G@yGywowyIu+a literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/ebwizardry/textures/items/spectral_sword_conjuring_4.png b/src/main/resources/assets/ebwizardry/textures/items/spectral_sword_conjuring_4.png new file mode 100644 index 0000000000000000000000000000000000000000..d040f8e86c88b0eb045e62b7ed9a91d7597f69cf GIT binary patch literal 1791 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 literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/ebwizardry/textures/items/spectral_sword_conjuring_6.png b/src/main/resources/assets/ebwizardry/textures/items/spectral_sword_conjuring_6.png new file mode 100644 index 0000000000000000000000000000000000000000..aa0b9480d5f7d85325fb7910ab9c45e4434461b5 GIT binary patch literal 1817 zcmeAS@N?(olHy`uVBq!ia0y~yU=RRd4mJh`2Kmqb6B!s--K#<(N`ey06$*;-(=u~X z6-p`#QWa7wGSe6sDsHU}kDl~IgXhn4k!qF}hJ%F_ZfAJE{g~bG=GD5oGa>J%EaqM_ zsrAH^OIsxW|C{wpzDDL}O3eh3;vO;i`L$)NlT*$=?@9Ul@0xVA@4cI6|28*w8h+Z@ z>-?Ad&BKok6?Wf5;Dy!S~ zoynl8VdC7v=1$#xkE2>AGN$WET>f|L&<2iYXA-0DJijrs`WMSR+v-E-#I}B}*68Vd zB{1J0$h!6X#@igW8_U-IdB<+Q=EnB<<~PpXygcXen{_`pmMpsH8ykJo*dnau(cg$8 zsz11AoZe@&u0_|Z;oiZtqgQ!SiyW#aE%$3x>$Nq@^0>JBAGQkfHT~)lAO38OkR-^VasJw`^O_{ceV$ zu7Xm5%jzXp9TZOgZuliQKfqbF;DcI=Ky!;ok;cTu{ffsl3Nu3l#q=E)b*P*S5>lV< z)a4oEWjXbYk@F#^zDOTG%jZEGG8|ttE$6oJTDh+1tLc@9rORezXKKuU7M-!t(_44@ zrP$|v-`;QRe!22_92@VHOCOYbEK-(Cbf39m>&eUK4IWRKnKtifnr~$7c_~}N@3z@X z*61Gl^KCMFwn2A{V#Z0&h&hdh&pCTeCo!$?Ckf54!WNyuZ3B~={j}BMm@3outUS>)EhUJR< z3nR+Z*7o{U&Yt_Z?sNqW&8f0^4+spd_zwATH#ns9NZ`FU5G;sfSnzLnZ zZqb4l_u?hpuZ3xz@ND$jQuNAvx5l;mT2D>~adWsTw)8AMu=VL1LBly_d(7CLu&&ox zT^s#j)1}!dZ~9Z-Jnq%~4qv2603lb#)Ps`bWy zhEp{xFAhdrmx|l5Vnt6+-!{3m>t%Z?nO8(B-nIIYmA;VWbE1sbq{@Q*tRETQq+85X zw_N?$rX!i@NfTdO=cT&`qrNVTnxnNwOX!?;T2=b~FwaXHcoX$ykDrr^RSKUz!~RX% z%Drx@Lvt_xxwO<^qvZVMn_q49bC^H3T5s5G-tOn?{#IB@m>hb46F*_yxYJBCJ@tA>ufi20~-G!l&A&Oz@oAY0D7#J8h3p^r=85p>QL70(Y)*J~2 z1_t&LPhVH|#~jQ8%FM3ri#Qk<7=t}s978Nl&z)rJ&Fm=RdR`~ctYv~o)4HTYuHL2p zIv?=QaN4jzpvh--?S|goqa4g(+q$=w_BSe+t%}5*;UZ4 z-n4hmiFZ8Tcq}rQ)<@kk7CtD>Ht)AV&Z?#x8a-Abhr86-W=TyG{gV;FAl8`swEOR) zB^}Dv8BDql#50%`H<*da6$|XNFcZl7AhP7c(ageYljbJ=xZtoraqR=|!@H+_yL3cK zKy$I;;+n#^7FE{OT(7LEdNl=?=+4ymyu7VMT&|=v^}tbacHzY;2Uw+~Y@T*sikPh5 nm-bG9Q8OX-Yu&9qU)dSNtDY`+vhyJW0|SGntDnm{r-UW|zyDv2 literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/ebwizardry/textures/items/spectral_sword_conjuring_7.png b/src/main/resources/assets/ebwizardry/textures/items/spectral_sword_conjuring_7.png new file mode 100644 index 0000000000000000000000000000000000000000..35273d263682c6e63fbf2e1cb905108ce7e3acb9 GIT binary patch literal 1803 zcmeAS@N?(olHy`uVBq!ia0y~yU=RRd4mJh`2Kmqb6B!s-ZL2~eN`ey06$*;-(=u~X z6-p`#QWa7wGSe6sDsHWvmN`jTlc)86ahD|%Q{$1s2<2yN#eXVwGQ)SqzAGxVKFsO4 zN#njcr_cZQ_Y?meJRexl)|}yE81=`Zut-vL>+kK}oA$hWelTvT|J!HZ4lO*n_{(p@ zZLnbmo`i}%M)(M9GLbat#-=)#x9pOiHvGax>7DVOlgQgw~FtIw@B`}%0o zYHqIc-EG1TGTBPztY2WZa>s1lE!TXr_j+|rm0q}9*~d-dmu%ngRY79fnJ)e_+umq;E!ds^^XSdR@f&j9 zl$B2^Q)_UEus$I1Ng+Y`r^CcG7V0h+0uQPmE_!}bRA7NXjI!~8W4}2pUOl@dp}ghS zt_NktLEH{3@`74c%p4nLF#mCnc<5~TFYQy>R6$2 z^3_z+jF7;qODuOjnRv*l%hTu5l%R7FCdsdQE=t-K>8<;5NOelYk_=DP@E!h7rLxup zZCy5NcJ@BSKhZf!v$kC+TFw{#>W*`N?5=NDJ~yoAwXbLqZ0C{9d?LNo`Kz&MmBRN~ zQnFc-CDzv!EpJPkn9ViorHW6Q!m}9;F=~t!TV|hGBeZ$;6E)-6GEGb;<-^)ImtRz2 zYr1o?)zQ4HyhwlN%mev_#qkr3h40>1NLSnC{4PAtf5p~4Wg`0-&T7n=6=gr+#)XC1 zWwV~o`||iw&FaS*mg};@Q)cm(%gWxdvEMHcI&(M=UvV3P1j~= zT4g<+_kGdf&l-1Izv^WNo9&Kv$$K64t@-*I`F6rih0VFVvz7cy*NbmC_{)0xx4k`YZ!Tr~pz&Qi=lmK;;g7=Q`%m;* zp8MH)Uv#az@j7AUT-S8l=Dbtm6s z-n?8UeemVM{Nw9?x$Jt}V0(7`E-(7Vn_vAlW#QJZnTZxJS|8k+mvbQlPu1h4y{FCsJLRBX=0bDxMeY)k$)RViY-jzuPS)un^i?o>k+ars2ehrwj!*7>_V9v|EkEi`S_%r7L!;CZk59fZ< zUiop&BL)Trwj^(N7lulPD2AzT&VS8eU|`@Z@Q5sCVBi)8VMc~ob0ioT7}!fZeO=if zb1(}i>F2flU&X+{=$`z05-IC(5w5$Lkv!!?f@#?ud&a}*;Y zIJ$jS*KX+TJ<7qpCPzHmQ(4TcDdY80kv$?@LQO8d$C9pZ@bvMpd0MdVr@nDlz0b)| z@5?G~#xHu_iGRDZ_)MUkIG>BP0y9Q|FHDH&Q>Xg^DCaNxn#V{{71+G zrKapVi^88@4OpknKF?ZgN8f||gp*IM7VOh)dfxSD=OUBC?o8&qsSzfPr+$8%JENKF zLxSygZN)wM1@g`5z6-+sgtf1VER0@|lz7JB<{<_H4xJeeYk$_e=Db|MRKqww@Sc^y zO~Jfkfn7I*Rz#nW@(^4hyFdEmF3EcWKQ>G-`;hkVXw^H1s$B{p$DEF_WSwspWEN(d zm-9nPR;gm0LgKSECP-9?VVDNPHb6Mw<&;$Ukuwg&| literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/ebwizardry/textures/items/upgrade_attunement.png b/src/main/resources/assets/ebwizardry/textures/items/upgrade_attunement.png index bfaad40150515cb9ac107992e48dca8a5b0487f3..01e46ac036816a59d82cfedee4b0cfe00b097fe6 100644 GIT binary patch literal 5741 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 P0L8DTtDnm{r-UW|*NXKo diff --git a/src/main/resources/assets/ebwizardry/textures/items/upgrade_blast.png b/src/main/resources/assets/ebwizardry/textures/items/upgrade_blast.png index d3e98d96c77d072b33fc491c61f579c330ad05b3..3c3254f8b962f85330c3d2513a00795d9e925445 100644 GIT binary patch literal 5553 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 T^1c}i3=9mOu6{1-oD!M#kW$BxNm%dKDDPM$9@ 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 delta 401 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 delta 361 zcmcbmJ%@RMvH$~HlDE4H!%c>N4FBK%6K9xQCn8sWpPQY>T0i=b+II#9Momu_#}JFt zdnem_GaE{@*B4H_q&YjK;FO95*P`y`FVp0HFy7g9?}@m;Z^ka~?U!8HUnVKWzEaT$ z+VHy3nN4|%^TR#*1z+DT@bvYse*TEN(fh>bC)4fO|Afz#jb&!|#jC~tvg~^8cj+f8 ztx8q_J0t{O)|Z*9|D2bmTXW-g&gLG2(;Ugh2XFWkt==5Ef7D}f+u;?@7Wm=NS#c(5-S^Oa9jo^;Ywa4W2+1G4)d)SGCf#JDKkQYNkP?ycY zeAO0)=Xazh2OW}Vc51v-l%*|MT4tx^ls+wf;L9wn%kU VKFeu5!oa}5;OXk;vd$@?2>@aVqFDd{ diff --git a/src/main/resources/assets/ebwizardry/textures/items/upgrade_melee.png b/src/main/resources/assets/ebwizardry/textures/items/upgrade_melee.png new file mode 100644 index 0000000000000000000000000000000000000000..671c09faa258b9282dff1ed6bc9d6b1d9e52cdab GIT binary patch literal 5965 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 literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/ebwizardry/textures/items/upgrade_range.png b/src/main/resources/assets/ebwizardry/textures/items/upgrade_range.png index b7a21cec78ccef18bf8a917ba03fe019ed5f14a1..1f9f08d9c7408cbaed384af58af3f03e7739a4bb 100644 GIT binary patch literal 5613 zcmeAS@N?(olHy`uVBq!ia0y~yU=RRd4mJh`2Kmqb6B!s-mQ;mAlmsP~D-;yvr)B1( zDwI?fq$;FVWTr7NRNPt{c5~um3!cC3BGOEZ_a1&&GmFRUPp!?8ZFh@qzl+?gGf9A> zp~AxD?S1>X{|@@!U@^MJE;=DOwYsF zH<2e>VSx8KDXQ&a<5zkd&X51F070hlHW!=!6(~vjkqfO<}Q%Z}sFmSA% z`>lbElVwBC#t!*>rX-EXT;9m+xnIq0WK6z%&f@i)&v{o?JlSe~uj=_;e!E{HB?brC z#A`Sd+eB2erWi=aei3o*F;vy?6_{IK)u_BwCo+9KAX>)-goNOEj-j$+AUl`KYsF^I(#vAS zj1>!)n(Umkr_#Ra+=Vy0)Us-?@0k+Py+E@zSH?-|;Ero8Vl^=ePhDmHF8q}mm@ZNG z?iR=Ke%(`7BaS@}cG@@9Y+6pTiQTiUY%9&=FUB3~i|WlV_{?Efr*dwp_PM!RxVV=e zX<8(2Sj@7Ji=Xs_(G1rM2d>m2%{3H-n9OUp=n~9Wpy2yDcE; z&`iDd_(@rRjJ|Qp3JR%~Y(LER^`-T5ZsnI&+t>B}IT^9*;?HG;*Nu zrLSbyHvKD#JXD{5(RNzvsbi;@xYmkGn2Ll{TV79Z_Ih1w_*J{GyYX=JBL3eGF3)`T z>p^1fS@XZIPi=c2=q}HCf#3M=tJMz=8T|V4`RUs8v!;>0WrfRwK%ybv!En1KTiQLcr~ z$Sv^oh3n2MhK6Etey)B+Vu8M)o`HUDE{cxg64x?>eOPrAhg24%>IbD3=a&{Gr@EG< z=9MTTTUwA)T8wOGX>lq@2<+~hlr;T{T!_ucdfYvI1K@f|35XD0kxdm_ySiJ)_92`(qF8Rr&AX7YDY?VL`uu92K z&P=faGfmS{jMEZL&2`O_QVn%Yl8udZlZ;YLbWP1nk`faQQ!JB>%#n=p%quQQ%u7xM z8C8*6pqH7MVwIF?Y?+j3n51ivn3||-l4_EoYhjd{q-$iFVwsj|nw(;sl7?i2e^F+7 zW?o_rva3KwrDUd98JMP-B^#$2=^7@PS?ZdYTO{iynVFdDS|nSTC8wICm|0qwfsFzM ztd(Pcr>&Bao&iE6ASbaTEx#z&Rw+C)FD1Xc7$FssnVTA1k_ZYmLsL^T6EkB|V`CE| zQwvKYgrcz2qTN0tJ{N;S|mF-)?wNHH@pG)jUbdARAt z`DrEPiAAZ7>8W`owo2}qxdq^OR?vVZGfh<2lxL)Z(vX3nrLKXAu8~EEp{bRrg_WtX z5+t@2Z1h1TBh0rppt8f)*9tj2Y(Qm;l_w~{1(y~STzEgKIHRjRpw|P>n)M3{8Esv_e5))Dn`ycQm+0gNvjPAW89P>KY9$l0twa#iOZ< zYQe>Y=qjh?rPwN!E7{w{C_B7kU|?WN@^*J&2x16gaJH^JtH8j(z**oCS?00J7()(@|o zIJ)wD!T)=rY;D@pAHI^5kdT-mAt52*m1HXU@g~>hKi}R;v#qFV`+Qx_@DQ&8OPXIs zO2zMQyv@`46uSO{lt*x6#@Q4zJLgm}_*JHe8@!ugIdMT+|CgF6H#P-ZbW^x*dQZl3)6``XzhE@~EL?zU!TW@bLAIgxdmP$HuX$D0|J6B9o^yUo)U zRrKF5=+WK9zdJU`TB;f;SJ)LEOvH$~HlDE4H0~q{t-d#U=y@*`>Ll#L9R^3;(>d!GSFfQ?QaSX9Iy?3&` zM|7abvHI;Ck1kvc*mB|ELjF4;GD;pE$_o&|2EVkQ-pzp3eDQd*AZ=9A^L2&l7bSz8PJ5 zRDX^0OLqO+)%Ei7Gt%rfxn@?#3Mz_q+xjRxbe>kSG-W(4J;5_Sca?fIh%Gm8%dsjv{)k~ams0y~d*UI+%&8*PJ zAN_R`vUM3^=T11e=Wy<|Rr-+)tg9yGCP*do^gS*)r!ceJq9S>v+cwYo0?AVj8Sj|Z zpLWcC%O7@HUZmSKYwIi#E><^T&8vGqH($=`D0(qx^FO2W?B_e{&;0zlUBIN7(M?#> zzHH~E%-I;2|AGg(V+-YswbnRAnSorljcmIBsUtc#r rQ~AU01zYpD_q}+z@Z0ix8;}2I=+WLiBgG-#2o#l`u6{1-oD!Mo?E+TW;h#=hXN2 zaSU#}0#@GJEX&x=TZ9#UIG{THVztfMU~82^uQxTHlHa_Lxz||U_ilr6<>|ZO8Yhmd z6?kuOtB9|E<7|$*8_Obpo^F58JLC3!-m<;nZ}+afn=0QJvSjbd(_zmzy4V+#6i2xT z|6x966zvq8vytHoml^*Sr#Uy6-kzJMo&N4lTKtX!uKBY?zg!c0z07Csjg-?WNBfW6 z<$AI5iAavfhGz=fmh0PG_buLgsB5aW^JSwR!?c?0FCIT;mr1> z-h+24oVZ&G?$2oJe4kSyZ2qh*f}QPfOXS9bIen>*IBI%z%`3|;a37l-`S4uOc1DMm zt;};0+1Y$j#4R=nX17XOX#F_(;f_^4zrg{;8>g-u>@602^1vh^_l)4YU1m2_-Le=3 z8QEPOc=-fQe6mxhJEEPW!QNgY;?&{T)Fx6?a`Cu8@)V1r5Ha<*CKtg#&q-HTUSAOC z8anw|%4BCQZcVj?OEj0x*_hGxvgf9xl%@Q)f_D2ug8Y_WJlyp-=0Eb**ywR_lGnOz zySg67CyTC%3O?H_?X>czSX9oXEla0aC#~K6uKLAB@9Xob>>_WksY~sBKjZgI(|c=p zkNvqaSvy;xJI3dOhk9ZG+p#t2271kmEL&vfNT$Ajn~+zKHtFa>4zV?b5>Gq=ZxFFB?``qp9Yp&X8cg<$$4Yn{aU8lU!abf1R zS?<2SO8x7zA8cI6H|g1i<~Y?% zr~6d*Jn#971Fq~m?3e7h^Wh&p%Y{DIj6w_lPP+6;W|7Dev9I^SzVGu(zAJk2-<)aH z3pCd+UbH-y*>zvsg%2MW{aGV!H_iP-%Kg7{^7a+HKj&NZ;`z&E^B9iqRA0YLcDA13 zQ#Fwc_WAb{lfABnUGv`aYyO!-%S;5{y^HWJ%~yT8)P=t+wlaUigGrP3hHMsV2S$fH~iCu-U?jXF7THz;1|b5d4{FJ7w5*`IymS1p|I1pJ-gDTRZYBe zU(@JI+SbaOmuFvn=DBg_GH)Z}$N#3f8`rPjrS|TExz{;=(e`tbCV&1jCA7Zx;!d8t zsLNtbU-#YGqhnSQpIdkP^68GlqB%dO-JJSMq@XH@&HmlX^1dB?-U*BTGvw{$jM={3 z?id3DLn77^E3=>^8B}7~cAn*J2;gaYKlhN}FXt`!vbVd<`QOQV3b(c}%#ZmVys7tr z5a)3x?HBRa!d?|_NUO+*&{4Zl>@jgpP5HjVM}N;=^@+*IT;#TI^D%n{1_9&Dkcg59 zUmvUF{9L`nl>DSry^7od1`x2ZuP8`N&Q2{+NJ>r5%(GQ`zk9!uLS~AsQn;zFfp39x zYDT68?tx|+54XF*A_NkwjfYek8^k%57Qu7Q!R zk)=Me{)*fJUthTHykcl5CgDOF2NaCynYjgE9U#@n zDpQi->IzDWa=>a*lJ!$_Qgc)DN{aOj^$bxwRFPW%*MQYKV8g)yW#y8eTnaM9)5TT^ zxdnQenJHF@DXC^ACT1qONd}2#x+az>#<~_MW+}RcX-TGOCT5lvX_kga zM)((Hrf23Q<{-NYWK>FKij|3>X_AGRnT2k$QBta|i9xclu7!bVl5U!%X`+RBs+mDb zk{Q@2P{3L_26);k8R;1yL;`XWOVaX-a&48uGxJjN%Zm|GA(^?U!6k{HU^6r|H8U|Y zHa9XfH#aghGesy0OD!tS%+CXvYG|Mbu_`6m$}PVrH?hQ4DKj@QJypLTFCDC-BDcWG zxhOTUB)=#mKR?G-3FIgRBRxX{aAr`j0VQkKiV`cI{NzMXb^t3*O|b*#1aN+HN=(-W zb8YnTDaJ4UEy*NLuq&%@G)iFIauf$f#Ju|le9M1|G&}62Gs=hoU6_kby3@vpHOmvMbLJZBU z3=FJ{jg=s=tw2lf8JMM*nHi_1=$a*)8t9rNrAi;uEKiY9A zK*WMv-0Zk)^ud)hsKSPX1*pQLC5C1$T3Vr?Flq@&;X4{!qrpW|2#}&6g&~L`h{4&q_N)Q}0|RG)M`SSr z1Gg{;GcwGYBf-GHz+U3%>&pI^MTVb=@vqtpCk6&aE>9Q75R22v2@3=al!~Wq+x=fX zEV<;VpW6;bxiGK)$+e-9A*CgpS$k@q8XbOgcDrO;-H*cs|86O}iLtSkx{lz^GiucNJua+GE3Z1oXmGv z|JiqmS+bJ?7Acm9{q{P^x-t;@~6IYN>X=lD+(zi_xA;%tE#gZ|450qaPc QBcMSSPgg&ebxsLQ09L7+aR2}S delta 396 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 g+VXT< delta 341 zcmaE<+rd0RS%85p$=lt9A(Wwy!A`mA!qdrJqH^{3IYot)xU;jJ*%=rZMLk^{Lo7}w zCrDg*aPCSa%T7i#URGIskgXEt&$ziyV0xFUBp@kipd0}D!$B$*EyI9xxoX=(Gr_Eg!! z>m!3D@7W6_Rn#OhwkcM`e)w%G&CJZqe0cTwNj&D3Hzf1^9pZ5pD`7mAypJbcWxkPJ z)u|8j|4ubIeDl~}9{nTt3}U9%9XznQR{Ai*n!w^`4}&Y7EU-MC*v&cTKx!yM^ZO+8 yOOuW6RKCAw{O9lQ{u*W#3rooz{~wgAGDOyw?ejiW>cYUlz~JfX=d#Wzp$Pz7p`MTc diff --git a/src/main/resources/assets/ebwizardry/textures/items/wand_basic_lightning.png b/src/main/resources/assets/ebwizardry/textures/items/wand_basic_lightning.png deleted file mode 100644 index 7fae895e27b5df0a5b8f7d5eab2d08b371a7009b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 363 zcmeAS@N?(olHy`uVBq!ia0y~yU=RRd4mJh`2Kmqb6B!s7*pj^6T^JY`{xdkbG5njt zz`(#+;1OBOz`!jG!i)^F=14FwFtC?+`ns||ViV_-kiJy;U@8Lx!w*jv#}JFt$q5St z3?{Aq`0w!X|N3z|&mC~-Qu8;y_@7_S_GkUGLrecpUw<#<#*S2NW^T<{*=o7TJIY@3 z9e&(@U-I9^4TgK33#r^=U}Ixzi)HUO-1GbRL4}1H#|s|56K><(%iE(O`Qgb!=Cd@|eOnFKyBPr>Yi`d@&W=*Ij~E zlrLNT|N4Z-|NM)r7VJD55&Ixh?brOq#>PgG*$*`h6&fDe@4k}F#_p_mX|Almfe-Rb zJO1CkVIc6dM4~}`iFLQDgv9y+0|SE^)stmzY;0_7($Z`@dfodbOmk-ZvZ#dnkd{IQ Q0|Nttr>mdKI;Vst0MCGs&j0`b diff --git a/src/main/resources/assets/ebwizardry/textures/items/wand_basic_necromancy.png b/src/main/resources/assets/ebwizardry/textures/items/wand_basic_necromancy.png deleted file mode 100644 index fb7f48b2aa8a284c75f1f739ef3e05959d08f485..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 361 zcmeAS@N?(olHy`uVBq!ia0y~yU=RRd4mJh`2Kmqb6B!s7*pj^6T^JY`{xdkbG5njt zz`(#+;1OBOz`!jG!i)^F=14FwFtC?+`ns||ViV_-Fq^(?&jSVqhHsuOjv*GOw@$YA zc1jdER==J_E$>om#s$Oh>DG4-e$D$H{ex3#k^hBj<^=^A!cry~S_P&pT>lg9YPS! z_zC=)H)sCckAnJ@@_HM-^{zhGYI#9mN!i(oIiGg^O-gcSSRr<2%Wjp`mTWU_mwi)i z+o%3Ds`FXyqqN00kEKKj{F)ci$9;!?+PNjWex*JRS@m?$is}#VPwp3b)3wO6%(q8L zrG8S-`l(-T1h)KHq2cJD_GNC&#AR!h&wN(g5V%yjLE(Vvx2j$If7vR(7vJtV`TQLN P0|SGntDnm{r-UW|9w3`O diff --git a/src/main/resources/assets/ebwizardry/textures/items/wand_basic.png b/src/main/resources/assets/ebwizardry/textures/items/wand_novice.png similarity index 100% rename from src/main/resources/assets/ebwizardry/textures/items/wand_basic.png rename to src/main/resources/assets/ebwizardry/textures/items/wand_novice.png diff --git a/src/main/resources/assets/ebwizardry/textures/items/wand_basic_earth.png b/src/main/resources/assets/ebwizardry/textures/items/wand_novice_earth.png similarity index 100% rename from src/main/resources/assets/ebwizardry/textures/items/wand_basic_earth.png rename to src/main/resources/assets/ebwizardry/textures/items/wand_novice_earth.png diff --git a/src/main/resources/assets/ebwizardry/textures/items/wand_basic_fire.png b/src/main/resources/assets/ebwizardry/textures/items/wand_novice_fire.png similarity index 100% rename from src/main/resources/assets/ebwizardry/textures/items/wand_basic_fire.png rename to src/main/resources/assets/ebwizardry/textures/items/wand_novice_fire.png diff --git a/src/main/resources/assets/ebwizardry/textures/items/wand_basic_healing.png b/src/main/resources/assets/ebwizardry/textures/items/wand_novice_healing.png similarity index 100% rename from src/main/resources/assets/ebwizardry/textures/items/wand_basic_healing.png rename to src/main/resources/assets/ebwizardry/textures/items/wand_novice_healing.png diff --git a/src/main/resources/assets/ebwizardry/textures/items/wand_basic_ice.png b/src/main/resources/assets/ebwizardry/textures/items/wand_novice_ice.png similarity index 100% rename from src/main/resources/assets/ebwizardry/textures/items/wand_basic_ice.png rename to src/main/resources/assets/ebwizardry/textures/items/wand_novice_ice.png diff --git a/src/main/resources/assets/ebwizardry/textures/items/wand_novice_lightning.png b/src/main/resources/assets/ebwizardry/textures/items/wand_novice_lightning.png new file mode 100644 index 0000000000000000000000000000000000000000..3da8db4807299c6914ec4c1b925b92f414d3ae78 GIT binary patch literal 502 zcmeAS@N?(olHy`uVBq!ia0y~yU=RRd4mJh`2Kmqb6B!s7*pj^6T^RZp^ci-~Fuxbd zz`(#+;1OBOz`!jG!i)^F=14FwFtC?+`ns||VwDv%XPT!b;ljYcAe$KyQR1ARo12o-U3d7N?g^-tEQgDABtAq~0V6eF@m0?6#1wCL zq%|#er@b476$Ftw{1fIO8l)AS*K%`w%paZ>B$L$r?1%= z*4&m}7bo+r%iZRwal^7_3WCK?BaB?ste@YVn&ZpR%gIxyz1Xe6=iH~ZR~zPT-=FNW zT*>t5oTJu?j0tz|uKubpx9h|TL527Ymb;5vimrVu;C~t7;^)hA;^4joAz4Yampf-@ zGtLUU#&Bz2!iky*RlnI6e~c3|lh?dCYsHTFS*()s?$-pSEbE-~)oPD~{`12f$@UKd zHkn?OeRH7f-j%w=nU6HZ_^n(P?EdT?v;U!V4`X-rq>o#5LBa3o>gTe~DWM4fFyY37 literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/ebwizardry/textures/items/wand_novice_necromancy.png b/src/main/resources/assets/ebwizardry/textures/items/wand_novice_necromancy.png new file mode 100644 index 0000000000000000000000000000000000000000..f13ac75ff8583c0277508940096ea8b866cbcf5b GIT binary patch literal 496 zcmeAS@N?(olHy`uVBq!ia0y~yU=RRd4mJh`2Kmqb6B!s7*pj^6T^RZp^ci-~Fuxbd zz`(#+;1OBOz`!jG!i)^F=14FwFtC?+`ns||VwDv%l~gO;ti`~ZX`i#W z4&7szI6>FkoNqBiTwPUmw-CesAJ zR0BC_js=O!7HfP)Y=R5ZPtNIAN~bL0H`uaq&tumZUnbjI)6{JA u%){0%{w7^IS26kFA>BFiX3CfSZR5XmVuJ96Kgaig0^ZZr&t;ucLK6Ua0>$V6 literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/ebwizardry/textures/items/wand_basic_sorcery.png b/src/main/resources/assets/ebwizardry/textures/items/wand_novice_sorcery.png similarity index 100% rename from src/main/resources/assets/ebwizardry/textures/items/wand_basic_sorcery.png rename to src/main/resources/assets/ebwizardry/textures/items/wand_novice_sorcery.png diff --git a/src/main/resources/assets/ebwizardry/textures/particle/flame_0_0.png b/src/main/resources/assets/ebwizardry/textures/particle/flame_0_0.png new file mode 100644 index 0000000000000000000000000000000000000000..78375f2e66fe466a5ceea3018d32c9b45729d830 GIT binary patch literal 1695 zcmeAS@N?(olHy`uVBq!ia0y~yU=RRd4mJh`2Kmqb6B!s-m8(J`N`ey06$*;-(=u~X z6-p`#QWa7wGSe6sDsHU}kDR8h&G#o=bT3Pb#Pq{Uitq7N{gmbLtkSr@Dtf)JwPLE` z5)Q>ntNwqN5Bz^Hl}9o)w!^M+ec{cN$tNXT_O81+dE4iG@?T6VCawP5+}LsPbJdsH z*Xbwj+A7}A)jwY(`f8i-_JyZEnVm>ZZ9aId`?kPr)#ZQJT$(rit+U1N(}}YzPOU$0 z#?bRjA!V^odQ$Ih`PBwC4~|II9+_*wqq@cL+m6S-q^wKZ^dHQ<$X#ZYZ)xwmaLawJ zf2@mj)xVpT2`?1Cwr=YDx(;9VzZJF#>X#OI#9vH(-8d!OdWH5B%cdm8DcrpMVjoH+ z+HVR)xpaswFy9b)VbvlRwhZpbtSO!=&hHCq?Y>sRyrb9f>W3+=2j=_CU2@~1hYy3T zZ=>vC(KUugp8aqtzH4%QwaCUISj)CC`dLi ze|LdNQAIk~{Nr3-+b6ws3eyfQm~G(BGNUw7t!uIM_KHtuE)?I=+IwlP(`_~e!E0p& zZ4x{g{%=l9<~zos^g!aEf7|o6wVDYHbBueZG)SlM7cG*^PWD@{GJ8&B(iAa)hZ|g( zRvctwio9m^#D9aJMUoH-1aOi*^0j{RbI zL?ZaiNfkHF;*-l41o>z_?Qu2sNk4P$!ik+T4jmN>ui;dk7Ea^7t#urDMx0r6*n8t4{I56>;X zW1O<@@}B)WF}vv7`U>OuGlH9U{bw)E3fMlg`uSV#YfB-E<5)(1|s5ZNU z|JBD=l8wC&EtZ7E-wz4cHqV7?lbUzD(nbrrU2F3zFNbB>gc(P+^FPkmeRh@2@z%-< zWu3q8|6Xx#?w`5+ukN1Iuep-XvG?bi9-iPQMXxjhjH`N?6?`O|+<%pXtopg+{;vtu zvp1`1&t^%}=RWEy`etJpcXsTpnR3^JyiPaYS|~kt*OSI=rvhaoIk(SdO%Rt@bebz> z$EF_@$JfLq-uvQVTqeUly>;6}W*hTkclDnxW34P%lIpp7T0x8H+Mm<1cZwPBj9u|d zI<&QRPlBwp^C$O+?qcaMrGwoE84FHN<*jM4)LoJ7@h{>->e>{Km_1AG-TQIeGWKR* zzh21C7X3E85N7U*pHl)E^8ErmE@@o7A29Q)^RtqavwDmFF>1cs^RZtv)N!@_8~t*h zYqu|Mkad+5%I?n#veuu)_*wq1e)zWp>rT7Eyw#T1IDUN(^3-3l>-oIA6<%lbZ}0nQ zyL*1?&Sm>}Jaxl1xWD&#?VY!Hhw%06`@gR-H80YNWBtazGT-N2)CBW0nqK=DH-v|a0EpVD*LnRggDguHZDSZnN9`@AagbkFqDvkSLdG8=zf zYPM3nY~QD!?Ru;8YyT}g{c7|1`(N*D-nS_@qIBo=?f+D2cTM*{y*lUU{2f~QXN4x- zdo42aq{Ob`)uS zn6KLFshFWCSk5i)ARs93bg3iEuDNS#Lbj%6EraeGof<}EGqYLe4yhe<>X^#X<90o% ztm{b0&C7RYo|gT0STgU@%MyoK%NE>z+oW^aVV~}o^=uE;-e;FC{+w`Z$|{$jl1tvN zm7lD5J>MZOB>TaiuS-?f|2{OY`0 z-9P18UpfBh;KdiSUmE|op6TjT{Ybwj`xno#?H`xzWZ%Z8ua=kolJ6fwmXgo+?&UXX R7#J8BJYD@<);T3K0RWF+C~^P* literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/ebwizardry/textures/particle/flame_0_1.png b/src/main/resources/assets/ebwizardry/textures/particle/flame_0_1.png new file mode 100644 index 0000000000000000000000000000000000000000..6b3bdae284bcf73600f7d2b23a228b578043bea8 GIT binary patch literal 1719 zcmeAS@N?(olHy`uVBq!ia0y~yU=RRd4mJh`2Kmqb6B!s-O{+p8N`ey06$*;-(=u~X z6-p`#QWa7wGSe6sDsHU}&#qF|(pop2=s{+|JC1 z>{#U0(f8{AKcTPucGsfT&gqv4;*gS`9!J*SA>e$@?8NVHF_7D7?*gf}~`%buW`S&Ap&)xQuUm0MP z)BfSe#ck66Ez2h_RKL1zrv0A@O?|&Uem*eQBYEP!u<5Z3!H#cTW4&kET8IUB7DrrA zPHDK(Qx?N1p4=(A#C%0$L1^lvjS0~`#%EKMm!01>i>u>Y8TYPGvO4zU`2BrS9`{Ny|4Z`*7S_K@W^O#N<}_E}o}It<} zHG{^XJ8}s;j*PNAmBKxJ*W8j1C_B&Rc`|K|Zoq+x{Mms_xgAVL60M&dn~||>{nxUY zfl&%A$Hh7)ut{?ySw5d=f6=f=qxzFy<@@ITd9|M`0}2kd3nWRHYPomm{gO!PkqJKI z^X5kJgA->ui#K%!9ID~cTy;cq=^VpMw--GZCFLx|qgU*Bz*9ARiGS(U>jBA6 zXJzGW3q1TSf1&Hu9ZRR}e(ACF-LCfwkDs&ss&m3rvG9?qhsZRQpDVV7{#`MvGU(mj zthCi;BE^^W@2xs0^H}syPtl|Hw16{K%ts#wFmUF!r_JguF4HhKxqLDyxPtp?kNhJO zW0B^jb<(eo%Dl~cdhgY;J-;XBeJek;Qt|Hpg>$4X<_PqbF6C$+;8xuDKb)WVbA%Miyh8h&6Z&(yd+?KY5C%y zv+92@9lLW|MmKV&3P-i8M%}K2{;jtoUVl3GEK$!eQ*njtzBgA>`_p#IT%S0#;jRqF z?h^vB*ABI6c|NE<`)cMh-F}nT#|jHvGiF;}C@#KpxF|1bg8T8PX7!Kv(tWnMr)IOR3N#6 z(Z$*>6$-spPnSkL?Be>ExB92>rg@nq@s}4HHO7|KY~TC+_}kwnr4n?*jS|Z_<3f&2 zma00Ic|PX-5$`HhXZ|afJ!LfK%wOfeoxR~v-T4;ro2HWmUwzeClvkX1@MGbm!u4l1 zR_s`n`|dW+)TNgS{cDShr?>BU>8Dd+zJHBhtmnP=tAgLIvl3<9eYDx<&^>k0(5`nX zp30sL8rGcKjZYRGn>Oi;d0*8>@0RapqZ9XY=y4T&uzq;gTyeF&VZHFCUqYXipO~+` zb$HXhGSMm1t-ZgQylHv2cJg|g_1}-I`Zl+6YSm6-{iE9QbHtXdS6q2tR@lCEMV!Gu zMVGIpz3h`le^jo^*mEgVaem}393m?3> z#Y^|!+U)Il%iG*#HhrD_KI&EVnwnm3-Guu7*XpYT<6I~I;^z_f*!5?hK|ccn16z`} zy9+}lLlnc*H|M|RFfcH17I;J!Gca%qgD@k*tT_@43=Hfgp1!W^k2wTI1(X=)bsAj;KYUTw44Nj!Qo< zY+7`2!(6A$(yb|>MxCjWN9W#5`MdH==DV{ecmAyVyxTHx_g%I^nP$J`%#&0YZ_c`4 z|F&_t32S%qh5Bpi%$2t4 z^Upq0UaQz#_g(Uhj)~W~1uJs&|Nq~)XXB*VGAxrbvVWZYZ~Wt8CLhPaCmX&l&$X1S pxqqztFYkt3m49BBP0Rbhs?OoZdUxVkQw9bG22WQ%mvv4FO#qc1IQ9Sl literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/ebwizardry/textures/particle/flame_0_2.png b/src/main/resources/assets/ebwizardry/textures/particle/flame_0_2.png new file mode 100644 index 0000000000000000000000000000000000000000..7bb1ee5384b38ff40e4f66b4273cb79cc794ec89 GIT binary patch literal 1741 zcmeAS@N?(olHy`uVBq!ia0y~yU=RRd4mJh`2Kmqb6B!s-J*q+?N`ey06$*;-(=u~X z6-p`#QWa7wGSe6sDsHU}&)oDyjpxt$;3pgn5&egkt-7Od+<&vg`OkZF<5OoCMu<6; zcpEwYoxi{J-=X6YxhHlB)P9P4m^|56Em`2|uQhSn*6V+}#WwR7S@H9@^vt`y_I{G+{oZH@3KwQf%Azn zY2F!v(Q6p?HlA$?^Hk4m*p{(+_PMB%`L$O?^`b8GJ}^5LayVFwvEHb3Qj+`SB&HXc zEM+|58`$h_$i#n%F+cltRbRx;%nT{s0UGQQ0G;D5_d#mFf+cQqP;|7M-gUk108sdj4M3^S%6aS60Ya+<4H$uXtpFQ=d$3$;IOW z$v%ealO~;s;ZC8q}%Pzcn<>tlrKe?Uzr+)8D_?e3f-u+MLV=JA#v;3Z2;@YP_-5z>gIB}?PWs+l}aQ>#w zAB*JH&)c}sP)2{{)$8U{Urq0GIr}K$qVq$IZTosWg2S?G)HZM9i$7NVHt4O?27zO( zl?7#;zvV4G`1$|eaIC8MQS#yJquqzy+B7feE$_QzqN_dSpTTqv*~ZI(i=WM{dhPr! zw`Xq3Y?iQ>n*#2HIF^}~p1HPb%jUXB?~+;0;npRO#U@W%@cqY%zKWLHXSpUNH!H4M z)5{$$CO^M=ne@4{y(Y=WyB}=2U{=)d{Me5CzFE7jEmG9=j+)x?*wHt8-_t0*HI?s8 zO6&9Q`zTsE-tv6-+cEl^Ha3;)ZO%KLD^mXL>znHMsFsx+DRbDr zHRqb{7g@I_(N9paYRR{*w|3q9Yd58oZC$BxQTNVe!kb(Qd(h-T=|JD zd|W@m)`@RBW0838%&xPNGdj0VxyM=m=@Y&zi+;H~R{?Pg*XKx+R z_*As}=bDy>M;1_F6?LW_UTU^-}yr4+` zvP^B7{D=1o^1?iy+-GpRuk?fEL)XV!JC606cGda(TD7g5_08;GQ|127x-Y+H@q4cq z^&k7{DmLz)@8Y-Mv3|_%!!!LD*!G0KzW!Y7kNh7omS0yJAB)#rR5tu~W4(T4^1*|~ z4|jah?^^GuF;(W&B?bltwj^(N7lulPD2AzT&VS8eU|`@Z@Q5sCVBi)8VMc~ob0ioT z7}!fZeO=ifa|ntGC^63Kn#sVx$mZ$d7-DgH?PYs?=Rk?$AJ0#Xy5)FCL3D3(q>57S zN$m-Ghf+Rp{h6(LuQ@M{fqC-5G-a{Ld2HVKJd>gdgqL0^cqi)>Q8oYR$&)|l{@Hh4 z|9R)Fw`MD@W+`}1D!AAA+sSppoRWjdvzmV0u#hlJnfl0r&C+vu7%$6A<6i~eX1ZO_ z2tV-faIGUt=6mKld-gW$&U^9M`{2z~g~%Fy{=WS64pzeAE&-aod?^OjwqJuUxBqhU z_?z_Js_E0`Y)6)zpTkRqeAY}mbT)0-jal5aYgw!2s&CkTL8DFKm+1$uY5y{x-O1t2 zSbW#z08{(o>^%C33-?TWe$eABk~vu!iJKl2dhKE{}<-jaeGmwz%aFfe$! L`njxgN@xNAi)1|B literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/ebwizardry/textures/particle/flame_0_3.png b/src/main/resources/assets/ebwizardry/textures/particle/flame_0_3.png new file mode 100644 index 0000000000000000000000000000000000000000..97cabc9b3dca1bd6867d6f5cd8cf3e60885352c2 GIT binary patch literal 1769 zcmeAS@N?(olHy`uVBq!ia0y~yU=RRd4mJh`2Kmqb6B!s-Gpa%&N`ey06$*;-(=u~X z6-p`#QWa7wGSe6sDsHU}k1V@m!Sm<2<}(hKgI_J~e2B|4I6nW8(#Eyhgw-W4PSfCE zYSdx~S^e)lf8hTI2FEf|V>|3B*B9PMnS64F%ig|H)!gTm_g`dxa$NV0olWW3)az^C zN83BUJI8%6ukxox_`*EvLg`&P`OP+AW;1g3?%>@RS#;~W*4yu!YB|&Y7tc`3d-{AY zFT-L>j++{nXGT1Jb6ksu-=grC=_4PRHlbrPs^`qS`~1er>R$}+=h<$!TzUGZvWVC3 zwGZSaaxHhB-#DAYHez?!zYhwPvR__*Y?|xQtyJqeeJy)X+}j1~0-o`7u?BpqIr}>C zQuC{h*Akq{N=LXZNZ-(r2n|$X-qNaLdP?QW^Q}Rx-PcN(cTC)Q^}`g`1M_|6F1cao z;lp6-+bDZjbdBMWXWv?%?aEviu9@`I?SctQvPoqP&)1nB{Ey{&q%6^!*k>O0;dBp6 zi*)nO!ZtAu#hWvBb-tH*rJDbRdm|6q-4;uw18Ytj1a-|tu zB5og)OfpztyHVNSNrRVSce2?9}Duhoar{G|_K$3@|d!N~^ z7s(xl%VtdW>=Ao5$=`A5jG$AJ-Dxw$K;6hbAuwY-J8U+jLCr zUW)L?_PRamdJY^b$q9NLbw6ZPyp>Sr(T!pJt{=G zZ}z>3%ij6_NaLC+JY}wk9sjLM?>ehG`&Z(&vpIC~)M<|nF4f=J`)F0A%I;lPZ?&3cmV{O(=Zc5@W7U4Q zN3ugyHnHof_|vChY$<+URT$zq8y@!ETsD1SkK5tD7SY@5IzK&%xZxI)VEFA>VQ2B0 zS1B=c2?v{)xJML3-`lZy-{FT3C{C08a?%N=*|4sVFboU#lrrg?bY_iCfHIH6zxt+|a zYPfbwA8%Lx#9h77M|<=iPu`UGy!)Zp{;ciqd1J-g&Y#;K^wlNz`UgG!3T>&=UEdj zE@>)Yl#pTSTy@06f@PUB3#UYaFh{FWT6hlgs_H9q=AZn2&fM~1f&oLJOtXovbKQg! z$t*9QrnC4*vRzAyN;uUL=sjsc$ON0?ZyhFRD>tovzu-=$$-$qGolRK+&HgZLm(PE& zPfTie`dWtz+$^o)>h9)(Dczo~awgfARr#lhKbtz`dy)RHpS@MGCUN(*l{BW*-zrWh zvo=q(4Zjz`S^1rhXL{U$k6FtX#Y^b-Z2RQ=@!Ps4jiwhHZ0vWk|1bNMT(WonakcLW rHPY+-%MU#J=bCBVJ$L1t2jVlh-1uw09Z6+iU|{fc^>bP0l+XkKmzPj$ literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/ebwizardry/textures/particle/flame_0_4.png b/src/main/resources/assets/ebwizardry/textures/particle/flame_0_4.png new file mode 100644 index 0000000000000000000000000000000000000000..c24c08d41fa697a16a548b3dd8c1dd7b3431997a GIT binary patch literal 1748 zcmeAS@N?(olHy`uVBq!ia0y~yU=RRd4mJh`2Kmqb6B!s-<(nPDvY- zT0&G$hW))Czv$n=<57>NJQk?^6!-Y?ByY21!LJ`J(-z;|vrf8JZ{LZl{|-C3%y_xu zYwgSQ6F+YW+?h0eeUa#^O~TU`UjAg{@i?XX=%wz{0ymxWuI=^8jxXC@aIOE4$;PSk zzw0sd921xnx^1#z?`rww0yYa=B#Vz+4Uq7XNPb(W`sn+Om3wO%wuke-DTyok#npPL zPV)!5n|Iz1+cM#W?Agyx#{cVB)V!}g??&eqjZ6J6Hhp$DwOaIwtqRNW@3swXZT5dM~BQQpEn}L)qFCRh2NgcO@CkeVX^yDhl8wqb}a(VT$Vv46BqX@ z9-EQmXC@dWp+3LK%W&xwW4^Nnb2nN$D?d--77gF=L&!^K<&&;2E7ui$HN6rMeD8w=*-Ymx?XY|I`R))tp9TBNfVHyh7=lMy7gMpEvHiLnH8^E&C% zNoM8Z#qyQGZ~k?d|CTMz3iw`cu$-;5duRB)dmFBOs#$bFB_rhFfsn}yHg;~m=~i>G zzkjB{jflSXD~8v_r@rEs?QCoDT-|;sEa$I*lCSm3!r5nz8SZO&erx3|-h{vi@kIx3 zYQD2C3b3{Lv$6Tr!-tm-ig&N)i4HwsLNZ{T>N#|MyW)_&%J+E`LFH80ZX?O z9-h=IxQAnoShnqxn|JyICqJ8%?XKJtEyH6o>-AczAVE2E^%dQ%%`b|M=!AII)JSiu z>dtwszUgCMPW%~@TI*%gHA8l0aYjd7F5I>_%4|j@>&#vIm9}#WUYR9g!yvaXw(D)c zo0DHQ9nAR2az)DV;=E6DE^OZD#;UgeNzN>4_tU2lF zZGGc;&m_AqF(T`tZ(X_7C*q=C`dt33Y{XCLuq&CVIcr`p_ltzazj)OA$7f~Soy#X} z+2Ye~7YW^MwYn}F75hu|)Y*+2dI}Ua=6$Z{C|(o3?%~>R9P6rIWhyJGK4Z5yyZ)|i zjOlvugwT+w&(>R9Te!4c>*cKtU#jf)i->b^`iAGrW8S{XonK{G z^=(q$^hr_oWY^W5_|{$i>fOEj72mrq?hd;W7iSlCU)<(Lg#4P`y>+IKuf4O4vgh@x zsXTad^Dn&y`>);~w|-y$=hvB851tC=YrL}Wv$T)4mp+ruz`($kS{;Y;^12s1*CkE zl9NTRcgzfUYjJj``g8Ad<^R9WTXFq$qeY+NtYr)D`L;Q^OqloWVC}TVrzbTH(vEa| za(?&3Ft6#F+uk*@hu(VHH+^p3oh5T+(?RPURn?5Ppz^%XX= Rk_-$C44$rjF6*2UngI7nLVW-L literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/ebwizardry/textures/particle/flame_0_5.png b/src/main/resources/assets/ebwizardry/textures/particle/flame_0_5.png new file mode 100644 index 0000000000000000000000000000000000000000..47c0b845c1aa007f99709062da4610b240b99b98 GIT binary patch literal 1680 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 literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/ebwizardry/textures/particle/flame_1_1.png b/src/main/resources/assets/ebwizardry/textures/particle/flame_1_1.png new file mode 100644 index 0000000000000000000000000000000000000000..d7c637d10b4bda608fbd93015172ab8d0430dd74 GIT binary patch literal 1737 zcmeAS@N?(olHy`uVBq!ia0y~yU=RRd4mJh`2Kmqb6B!s-9jihjN`ey06$*;-(=u~X z6-p`#QWa7wGSe6sDsHU}k1l$n!Sgp=bTdl}!@;78u)DHnK0W_n@UEnM((EfUx(;SV zdOY_y6!`YOeeB=n(+`5Kd49N9-Fw^rUOB|0RG*Sp`} zR@Zdru71bePk#c}Ey=M?l-{M2-)vK67Ll`e1MkMjqFd*+-hH1`%aQ(nqmQur&!0EB z4y@pFGCO6Wc5TP+jogQs`{o$1-|0-%NbK2qe6Ho5<9>6W3Rk3mZJFyAeNKL1z^#1N z|1B4%O|I_0>++&=YxZ+~dzXugZ-=Oi4vSK*%VN-BMt#9CGtizyuq zQX&E;HeFM!Kf?ATpy`ChlYtrlmusCt}BlZ$6#Gq2tc1;rML zAd`s~55;^54B;_6Hf2L*)616a!X`nd)QY#=Or5XVE>o=KF+ZtWd!GlV>a-Bwr(K`c z@9SE%@YpOV(crM_cgwEVPM52C^K!$s$iF9~Yz@DgW^ajA z-8@^MJ4P*Ii?F!`bMi4EiRlL!gl_SiD^bWkn~+zqY_VgY1@pBNyhU2P#||vWO^I24 z`0m*|)Awkm*B_bvv&YhO#c%r=!OgqQ-qFs_k64{KPs4^&D%8T@>Ya->7F=*LQtUO( zJZtN2KRvXZZ@NkO>l0Ro{g!K9j>*`2tNV~&=&6khDqlTet31g+&AIB%?KSIz`w8!Is}C}U{Qmg4 z^4+30Mz=0bu{xQ0u%+w9N!Kh*9*Kfa3qqn}y=z_W=^tISWlG(XsduaF?e@rjauK=7 z`a>_#xv^)f$&$3!y;o{vdi z03Z8-H_xF}t6?S96ZgLGf(y;_Hv6P4B9*4vG|$D%|O9KD{;Y zU0m^F>+g@Irfp}eIcjU#@qFf0Ki$c)(}OoZK60~9?46x_<=x*4oePT9uT8t8HL+#! z!#vsWN!%+gmbVMvYKl`#gH(cdm%5`Lne9 zRd-Hp;l{YB(jB{h-?^a9DptOKUEAxq9gSrSDgX9| z+41W9>IXVkw&f|CHyzSn^8R)At@ZCMqWB_yTmOuEES|vW`u3J5pDY6d1B0ilpUXO@ GgeCy+GdXks literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/ebwizardry/textures/particle/flame_1_2.png b/src/main/resources/assets/ebwizardry/textures/particle/flame_1_2.png new file mode 100644 index 0000000000000000000000000000000000000000..55be8e7a0812a0e6d1615062d4bfca1d9e00d748 GIT binary patch literal 1729 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 literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/ebwizardry/textures/particle/flame_1_4.png b/src/main/resources/assets/ebwizardry/textures/particle/flame_1_4.png new file mode 100644 index 0000000000000000000000000000000000000000..45f97bedb78e681fb0eaec290fecb9f79d00bdc7 GIT binary patch literal 1762 zcmeAS@N?(olHy`uVBq!ia0y~yU=RRd4mJh`2Kmqb6B!s-Q>#KEN`ey06$*;-(=u~X z6-p`#QWa7wGSe6sDsHU}%ii=_hwsmMtu#&!MV8YKBTcPmJoQgDICrx0?#}y1L}zO_ zb-bIl;pP9I-wpmBI&S&tSog6BP8)vwcry94gv)Nb*PhqnzyCdaubIEB_+Np6;k-R{ zZTtQjzxm`7u>bAT#dkCA7Cz!Dalgk{x$cd@jk-eir0s9E)X(1XJoW#kxqnmlI>|i$ zem{=UO<3Zlfx~{JZAjJZ_Q=S>oV+jW?sI2W2SKp^ZTBA8#Y(o{;4c- ztnID9J%d|ilh$wCEl`#GHty$P`ND{;>*tHVIhIk_v#)G=Ekn@3H@2dt{5q$}u_<~Jd)c+0 zJYB{x@mNaUy@#w$896>r4}ITtraSKq_eLJJr%jeg%{QlsF5_K-;I$jo}w48o;UMi zltaq`7m+Iq8XTs5XZpLM|3ZM6SiXx&hu0Jp%YqM%P8?Ec{ija73N=}gb!CZV(U-ua z4yj}xL-pwrx;{Z3SwTLUPkUUAozl;o`*33CjzdSqH5X=ds!okjod0U|m4L0sW@Y8A zD|G(3{lb+kH-b*jwOVqecDmfIZ#RO^Ge=3={Fxxw)@O0)MElmWuiUS_=-oL#a`D+) zDQDvAer;ge{7SYd&3fWVNr~cl2X^?eDP)*iZl1WOeDcndGky7775Uao^eK|^J$7Kh z`zI+E9==O_=YFr}$Nx_A@3O^dLErx;ob!2QRy@D*chlBs>xEnOo6T2G{M>dc z#on{;ix;=;_qebp^~ZJ2S=)K+RUo@Q|p#zE8H^8*023L z>plN{o3nBmC$;aKnBu0Rz9_!ts>PB2E^9Qm{RM@ax$e;{H^3 zF+S_D)Z5vI`l5F(_kQO1lHt}9Hj}eo&Q7h*yUrK*#q!?nut}|xmOMO^%e$$dkKxOL zcvroilqJ*LE`D||&fY2~v`t&yvwF|1-mJxfzP20MY7W2ZpK?oikNBD&+`UrU-EMAo z_Ue@uE!n8}l;y(H3!Sf;}DyY@;{{?{lxc1`$u zLD@EK+r1?Vg8gnpRNKtH$?5X{lEMY?@`>&`g;NgZzR}>dGqqjiy*WeO?r-5S?%U>F zRWYB~0(ZP(E{i-Q;hFKoUD{SJS99+vkKnssrM9-Zd#s(QD)Hj8=K6cb^=`b_`a5`r zXk{DM#*2Z(EZO;^7^CS?y}jB zm-+Wx%Rh6m;PIh5J{NxL-v4x2@WV>SXBFNHL$*wezkc7i@K53NUvpi~Ox$(%=QKXo z@Za5RcD84g`KlLpO+9{-f$ziC2KWA&Pd8Ug?^`!F?boy9mwUtKJ=H(IQGedE>CEZj z0oyHB{MpVP>aV@n<_7=w+j({8&fT!L=c_++ZqKss{+o>Jr<`4XQ%vLc*>6A3EZSmPzp$Z%O`qH~NJ9l@smDBRl_o-gCz5&FwvI-V^@UGcIFsUMnlru#ka) zfi20~-G!l&A&Oz@oAY0D7#J8h3p^r=85p>QL70(Y)*J~21_t&LPhVH|#~gy90_ufd z>ckir82)*>IEGl9UVGWli#br>*vI=`4wE`uU5+Gezv}gcp^Ee9G2@P{H!2xfwfPq$ zEbNVlIPP|drFwSk76HL48Z1X6-b5EF-$+?r`8lo4{QplmVa{unbxg)*)jF;p@4mvY z>90wXMW5re)Pyq~Vb*(gvtI6S*9t=#e#$l;&aLrZt|EqcE4B?W50{7Ug@pku6O_WL;M5IM68I( lx$nAVVs=SY$Xl~I=4XBmk@cC8X$%Yu44$rjF6*2UngDWlTT1`{ literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/ebwizardry/textures/particle/flame_1_5.png b/src/main/resources/assets/ebwizardry/textures/particle/flame_1_5.png new file mode 100644 index 0000000000000000000000000000000000000000..00758eeaf01429aa51b17e061ce8ea9d5090d822 GIT binary patch literal 1671 zcmeAS@N?(olHy`uVBq!ia0y~yU=RRd4mJh`2Kmqb6B!s-#j8RhN`ey06$*;-(=u~X z6-p`#QWa7wGSe6sDsHU}kKXoJgXd4W=w=obf&Ql-Y?hZBoSx5=JZHz`FK5pjc`l{H z9T>v-aP_VG`*;1~woiLIMN~ef#P4zX;@&wIIDh?+)y=ei|Jrf>T=m_z^d;1qugUbU z)BVq~JBE2r?6*HT;rrHDB(hp5uWv{@bLNH4{tZl$c5k-K3ypa^sW#%=FXOtl8|S{K zzjkyJmEhIRYwJ07w>OeUU`B?}tp;mJ`#A-@`wrioWqxPn-MtgHSDU{pi7NZ-(|Re- za)-40X}?dicAvc9yS4b)a`A)N>*eeD?|hAOe*ZQib`zhEM2p8Ao$PIkrjiMw2^a@I9;yE8Ez z3&^|kkkxU8zF+DmYyGbi%zrsXFtes!lG$)z$!9?&?%18F%g(XYEn0iYeb?mm+6)?p z?l2joENCc8X_3i1|EBXma)TY`iJKAU0vcR)OnP_u!lTmzl02ub zUU}o+)zI}>D>g23<6U_rXY#XI`3sLuvnpCUJ8yT%^;&-0Z(Bm6SJ|z0Gk;j4Crbl%e4K2?W&g4tc<$v0iW@Tj7Y7n9<`6xuH%hB<6 z$I{E!-UYo|oagl>eAh?or&lJt`yb%P`*K>*{@34}w$6IinY7FyS)9*r>r0KCf(*q% zkHZ9(D-P?9=UB|Y~>)y9rYGK#USlwk@o}9tdD?Vil zlT@>D+2hBpFBo2&?*CZ1yTYCK)swF$1>3#CJe0PIq?Ek9F>9?{>|Wn1D*(#}shx1NUjhiQKeVAC;;-%)ZY zt6b}<_D8uLM*2ll+}#&)-Q4A>nYgiu>6+^PRDC^Ht=X@>zcb&u{?9sr%}2ZsSlpeQ z`|$C)bGjR6Ipp^LyD+i&mRh95$6t6ILt zUsySR($7D&hsr01@0Ts#Vwdz`{XOT6>oRMPR&e|9-*-)SIBI`ax&FY?xca8res5df zOTT~oxb#XsOwDPg%wLmt3=9lxN#5=*43!K~3{&5n|C+Ac<7zn&cML%(bL5-#NzbY%NxCz9R-ekyzeUZd?~;$KIeHn2N-F|6x;E~xF7V%Q(r>G=we|ga z`x!2x&C}C2?3(JgD(F!-4?p*W)X16q?Fq-GT(sJ?pP75^y0#*RPg8WmG?o_4dp?n) z>xuN7J2B07f2HYuNie8m_I{~T@&8wk%Y{nWsmsfDhly2O(D%Gn{_Mc<$ILIDWvVpo zeJZ-4zI0)b&eZLPkNxZwlbGA*7${Q6F)1yvXn~sGgfFYupC|tRBKK$I7wMmG|1&=l rzEZy?cHQ>(MmKeAt*rZY_u7X&wq<-09d?<4fq}u()z4*}Q$iB}2zVnO literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/ebwizardry/textures/particle/flame_1_6.png b/src/main/resources/assets/ebwizardry/textures/particle/flame_1_6.png new file mode 100644 index 0000000000000000000000000000000000000000..86f65667db928fdfbe92b07ef7ca1f687381cf49 GIT binary patch literal 1671 zcmeAS@N?(olHy`uVBq!ia0y~yU=RRd4mJh`2Kmqb6B!s-#j8RhN`ey06$*;-(=u~X z6-p`#QWa7wGSe6sDsHU}&)xJ`gXhnA&2JnWigta6)34r1=-~%WZvs$AoRmmIczsvCNXat!>`4f!6Mdr zuZ}s-TeYC?A=6cfw9OkY%rQUrlZ*9C4ClNyfu3c3+r9T1{X4sr`Kw*fbdUD4q6IT2 zHZ&MckuI-r6nNDgJoC>vZ`&umbpq2CF7TPfEH%|%csk_Wn8m~DaU>*2_LhNlhwzyh(#bZy@ygE(7H@Ij zI4JgU0-H2PQl$0?`F!Rg4bJXRrAJ4+Cup49xY=(`@x5NDsW#QGk6OR4{cv&lfrD(E zdOrl5cr<67&`1=D{i4+-k?b|YM6u-13zq&Vn@-Njo%UwadBx*%xGpWfp>$L<-l%cC1tuKXtVFE?0v0b(XUQyJ$JY4<+|T;Rc|s^Zwsjn>&-h=8`e85 z%h}NS@1LboXYS2c%$Oo9Im^*7nX~KnLI$B*JZDQ3vd;$OWh`5KaG3z}RgX4{sclIC z7tD+f+VgPwqUtF)RL; zS-4nfPe1=->9c)5o=wi*DeM3E^21>6z8XK{wl6Ll+xIBna(*hb>&D(?A7+2Eojkj8 zN|d8pyvXz9uPtZpr?izUOLEiNCO&idG?DJzK|5P)ZRQ_VZM;}<%XjMJ3p*aJ4tXxL z@qVyH_*+lDX)0xp{Z>zIe$L=ze%4h?SL@o1&GzwkqE|gD$k9vsc{|EKO#5p9n~rJx zj*?4Rxl0~~;Z{4GMyC z!nF&e*nb@o-r{tIdwV05&nK*#Pu!vlJ>AJYk$AUc!81qUFG@%OXKRBYWuxy zeJ}m~@#E4f`+!`hS+BKUD=;uHuqAoByD(HTL@`W#bN*`%0|NtRfk$L90|U1(2s1Lw znj^u$z`$PO>Fdh=m_txhKy#W;upk2i!$(gS#}JFtYcFrqV+j;td+`30*>3GF(blA8 zOQ&Yovd%rl+!0k0*WmJ$(L=;!QNVh)Z6BFt%?#-9*q|bvBx)?2rZQ`9eet`W=l6d9 z^L@XiW9Pxo!V&jggkIUv!}#ehkBTSLCmZ%)HJ8^P-ie(l-E}tV$6On=&!?^__+Iwl z+Vp|7Z~giM-~88pNLU(RB(b-t^`1$^?>`+&7JN3+346P3Q?l$|r8RkH8@{(!U+}G- zDDp-}ukr5b&r$BPzsApq&2D^nk|QNj%-u0V=&`M@Dl6Y9=Jczopr0N=GJoB#j- literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/ebwizardry/textures/particle/flame_1_7.png b/src/main/resources/assets/ebwizardry/textures/particle/flame_1_7.png new file mode 100644 index 0000000000000000000000000000000000000000..83d962c69bca660ee5c7a6d7f3346d4b4a564b47 GIT binary patch literal 1667 zcmeAS@N?(olHy`uVBq!ia0y~yU=RRd4mJh`2Kmqb6B!s-#j8RhN`ey06$*;-(=u~X z6-p`#QWa7wGSe6sDsHU}&)xJ`gXhnA&2JnWigta6)34r1=-~%WZvs$AoRmmIczsvCNXat!>`4f!6Mdr zuZ}s-TeYC?A=6cfw9OkY%rQUrlZ*9C4ClNyfu3c3+r9T1{X4sr`Kw*fbdUD4q6IT2 zHZ&MckuI-r6nNDgJoC>vZ`&umbpq2CF7TPfEH%|%csk_Wn8m~DaU>*2_LhNlhwzyh(#bZy@ygE(7H@Ij zI4JgU0-H2PQl$0?`F!Rg4bJXRrAJ4+Cup49xY=(`@x5NDsW#QGk6OR4{cv&lfrD(E zdOrl5cr<67&`1=D{i4+-k?b|YM6u-13zq&Vn@-Njo%UwadBx*%xGpWfp>$L<-l%cC1tuKXtVFE?0v0b(XUQyJ$JY4<+|T;Rc|s^Zwsjn>&-h=8`e85 z%h}NS@1LboXYS2c%$Oo9Im^*7nX~KnLI$B*JZDQ3vd;$OWh`5KaG3z}RgX4{sclIC z7tD+f+VgPwqUtF)RL; zS-4nfPe1=->9c)5o=wi*DeM3E^21>6z8XK{wl6Ll+xIBna(*hb>&D(?A7+2Eojkj8 zN|d8pyvXz9uPtZpr?izUOLEiNCO&idG?DJzK|5P)ZRQ_VZM;}<%XjMJ3p*aJ4tXxL z@qVyH_*+lDX)0xp{Z>zIe$L=ze%4h?SL@o1&GzwkqE|gD$k9vsc{|EKO#5p9n~rJx zj*?4Rxl0~~;Z{4GMyC z!nF&e*nb@o-r{tIdwV05&nK*#Pu!vlJ>AJYk$AUc!81qUFG@%OXKRBYWuxy zeJ}m~@#E4f`+!`hS+BKUD=;uHuqAoByD(HTL@`W#bN*`%0|NtRfk$L90|U1(2s1Lw znj^u$z`$PO>Fdh=m_txhKy#W;upk2i!&^@m#}JFtYcFrqb8!@5dytyCw(bh-z zriCr~DpI1wuaI@Il2K?XyF%cF4yV0R7b_Ug?p-J_F~QS}<>=n--McTo`Ez!r@$)l( z{{NXQ9I~UTilsZdGf<?yJMR=Y=9I3(wy-j5--t`e4aD`+e-r)^i*G{QA%RNc+Y9 qjqi)_BN`ey06$*;-(=u~X z6-p`#QWa7wGSe6sDsHU}i=OmagXeF$=w_Cd3cdE}tKRXY{VcAy;b-kxo_Br5k%UN& z!akKXzxLO={B1rhVRUMjK<%fv$D2;7O*ZVPie0Uq`@GivMe+yNb?3y{l-$n0zW9CZ ze8uwXEeYHA)J$C+uzl_hUfF5e9p$v8dA7yfX}h6g`8Iv(w>>%X+cy7~S=Jf+^Is10 zfebz;vr{E%*LM8g$aR?6Z_Y*cJDrCEoTQWccc*@qvM%Mze=v8kbeUDYWqqqt=6=yX zyo+_!zf0}zywJNf`Ki8s(sf7sIQ|=*TQn|Rf4AwY!>QGKS0-y0vm9m8sPy}s!C2p3 zI74@#YtBZdFKlMqQK3^#FytzF_Zo42y&1l$;Nq-2hV6#Sq~>kn_%V6qWD#qrPR<3( zH8&*hXfl=SnX~UgjQQEGTCQvEaLj5;=uzw6zATQj{<5F5l5$CBiOt5Q_%s*ZI}&Gl zt+zOEoIG~Lw5a^gK{MTzvSNh=IeonQmSOcsH|KUhLUwsD9y!={X%kFYb;4kBJOf z6C4yyN45XpG*fEZl$<`b_}uOXi@f!!zg@F_U;AOP+tULF*~Du&6x&3Ko@6ZUwri6} z?y{VDL?cn}r$|Vb=F&MEGumGE+?15E6c65U<58FX!XuNs)^W_wTD^K-n^g9yoimT| zzPw+ujRM>c4f1|wU(n@!upPjR8FdA&%U~T&BflG?;{tVy_Imr zZ*RdywnC0}PN}Cyc+VY}v61E2;RFW8T()$pNn6tl%q=dTRM4EmnEiy!vX?D6;X;{_ z--{>jlHNt%o3gq7=}^4hGfgL#{xIa5a(d0F;+Pri zx$Qgt@9lqe^W^=XE9T9udAPXF>BY(P)RY-Y(}Ud`XYIaj!EmTWv82V{ed#R!Un}`{ zZnuoyw8=B!+lGKUA&z}py(3;Ze*W0ePJ~LY`^H|^G2OBP!6*W9RwBz^EJ6ja`{4ygitx}zHXx6ow(_3Y_XWrop z`P;h6Nlrh)J;|evJG(INu$RilScbfvn;QKS{kUIAO|sYhu_??*MNcj$U;oeJIqTl6 zaA#jtlNZk;yMj&Z!zaB(4EN?N5?B(rYX1VG*RIb>PR)vS`^y}3r}DA9_Nu0^`%l8} zF1aJDn!kH%p)IpR;jM`md3MzAZZ0~)FXZ)QXRz=yh2vEh^*#03cRin{x54Yo_9N~A z`m1GE-p+}=X`kR}y#dI) zZB|;_mQT0;8u9nZr{!|1-^cu0`F!4XZw=)`vFkWC{^R*wlFOU^lgC>7-<`0hOCuLW z?2edyP@>GjWVPz2<$AVXUY$H1ziY+3nmEOyy<=Fh=3zZ5>d=Hu3!d-Tfn zs#naD>_7R{%2&*|3w1pJ?0{3g~YhDwGghN*APf6ZZFVBjq9h%9Dc;1&j9 zMuu5)Bp4VN*h@TpUD+RV2#N}5@w+muW?*3W>FMGaVsU!y>GykTj!)>2mAUa)FtiF_N8&`5BmJH|r;Ga&wmyCuBZO2vWPuvL&d!IG;Im*}ctk zs{dD?`}zNm`Ejnp0u09s89EkmFkCNXJYmIQca!PEL=}dZtLGUk7N*R}Qd_H1_J%o4 z_PqU}H=)@KHhb6eXnI`AXLvT-pW)uNNwZrIeVhK|V-c4_(ZgAR2``=hNq;w*nf>*_ zF-XSh@1{y%SdA?tqconHPjcWS0FFfcH9y85}Sb4q9e E0Q3t9FDxGwEea3 ztMQX}vjpBuo1VUttMqo~?F)&O(oZ&SI+*bKXl}>ZNtf%wGS8p>mT3L^eBvyNsqfF5 zG4woBNLlQYp47Wrezk$kgCml)N9J1asBSU*wj@V5wG8C zALL8qTJHRQ!?z`GjjXo)-i}4hb$jGC2xkT^S${Y6b>o!q>fqyH&p5hR13t}pc9H2H z-(!Plr|ug`tS@+T#I~%`n8|<(^D)>P?SY5NsL`c}d zKRDrd0c*C6gk|l*oq4lfhjvBm6g1&IDB&xY@4Hv{-?F)FE^aS`URETr?myEZwZm|R zba_Ujz@*-lvwxghCilqAUf^`X1>YIUW;047)w&jIZ>#up=0fo;t-XilI^AYt5WH4a z&?do?;s55uWWHl8N)IFs`nNrATdSGSFvqxeN`rJ7f6*ez>}07Sb4*@40%_k==x{25F z7#K~z8t>GpIyFYn?rKwe2sy;+&=xQ4S^R6VZA#dDJXHM7;{*Iew~xju67*;@%` z{Pq@XWGm!o=ahPSg!kNm85>!S9Zq0i%wTHT^T@Uk9qt%~e#Gg6d zR(xmwJ#eqpPiy(Bt0(8zT+!#)`(sTHPwuV35lk$nW=W-)DRkm>-&H(%WJ6Dkdvx7yNOuW8|hotR2F~=`*^XV1!4qevyf0A88FTCphvugH~ z>P1g-x0|g?XVCDoHk!rwUA{b^?}wvPr(Jp0A(R@{Dzo2&??#_A7FZ zcf~8R7G-Vo78TvqTKx0-x~{M4v7P!GvhQCAdH3{+-WF!N=NImZ&J&HE>zM7l^U%If zmv6;dKPp;s_NKY-zO4MUaMBTF;aQQN-U%1IJ+=GBH1R1%V!|%1bJJ}rQ(bAFwT}6S z#k)mTJIcAAN*#UeFLJl~E3}rzbvkROeb{*CZR<}zw;JDg$)MEF^CpT$E|!yB z+Fw55p~u>%{d29VzaBdsZ@Kbb#ZPVZtKtDl8F4|cl4q>4_g?vaZ*aZGm+kjf&R73a z{r+CUmt{;_r=RcHl_@NewLJV=|IWJW_piyF-c+ZV`SI!JXDq)Tv(>$r9@Y1^eE+^g zUitZ)dH=bO<=ZC9v

    ahfh9Q$~`qfJ*u>Sofi4-7(r zft5@*-CoOH@ZRF(_>@t@LxoE}!FBPbxlWsfTT?=fI#VT&o>_C|M&2`%@Arz|?fkEQ z|0M6Pzjhpl1&$Q*EYe_lxlE_tkY&9mQ`qxo2dB(3jGe%x+PooFNxbmy+=(AwT1JE#XV$!`+qy@JqpE8id7@3URu z%cWByO`iN$zAyMCo!__Zz_D{TkKDhxqbXip-e)G$-%Z~b7#J8lUHx3vIVCg!0J6t7 A+W-In literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/ebwizardry/textures/particle/flame_2_2.png b/src/main/resources/assets/ebwizardry/textures/particle/flame_2_2.png new file mode 100644 index 0000000000000000000000000000000000000000..d6163a6e22ce541f7e3a1f5aff7ef27bce3e8384 GIT binary patch literal 1694 zcmeAS@N?(olHy`uVBq!ia0y~yU=RRd4mJh`2Kmqb6B!s-wW~rRN`ey06$*;-(=u~X z6-p`#QWa7wGSe6sDsHU}kDT^ajpt9gXe5(UN1|oV^Az^Tx~_vi`0lQ6Kk~&iVp{78 zA)&Rm?CZP0 zE0`3eQ>BEn@7$fy`jFAx?*;R_BXt@Jdp91wYgFGe*XpqNhjTAjt>U3|C(tf6ci2UiOQo?WuNyFM;h zuC*a~M}ukG4Vn0ibJEXiTA9+;vG_V0xJ^DjeVLumzh$z{d;2e_UV50oy8jG^!w$n4 z(&ZVA0&0JSrW+&)(N!jUifbm!R^e{qRk8op!l`r8Z&hwdQoI4-kJ0} zJbdq}g~w(|nYILN_MMfzuT?DiRmawIcgtR``z=@X=H-TMk+o^PaWj4!XK#s=?zy@0 zdHywpZ~u%OmFJ##z|$k?op6VrP2fUW!7}E^Y_{TNV_9CaR*4O6MkiL9NH8~Vn>f+0 zefR90_Mes=`PX6oS+Y1Q;CsEna<vJl?AKGj7 zR2@5XtUzSt)#>J3!xxal2hxb1ScIn_jR+ZBvuITjuVwt4xm1th`Xx zdHZ~A$a}wk=iI-(d%|w_%Dm-XP1rL2U=>X>l@&XydYK-m^XyZskuthkb18qX|Jrlw ztAotSX6)5TnW=Rn`K#EpO%%})gqz1aP9+o2D{E>Kb*^5 zF82+q+=%f{as?q zY2R)4&5jnEfBSS*r;zI@-!h=CT0ip>212iw>)TPi}m8%!$+3NE{yBWc4o0H7>f>u zyVcC5H#bPH<7WFh*Y-mu*ZrIYk2YrUPgySN%z5;SV)~o4@0f%BF{kf|$yzbz#_P%d zK6Hm%s=e73;J-@uc))$TC(pe5|MhilDR*6do8zrWu(X!d{i)mDYZkL` zy2F1Scl557SrK#a!QLtH)ywxC|8o7_O84(|&+o3f|Ek;hcp}ID4Ogvqz2e*X?(Mnb zud0u)SYQ2h?codNe}c*v{>ZP(y|&}=49TneBOX{yV%V`sgMop8Ey>&6g`tumiec)T z^Ivlq7#KJUJR*x37`TN&n2}-D90>*n2KEw9Usv|W9D^k>?qRy@xGVNBoQYm&yCR)4AL7z_!Tml!kWwl4l>_}>YmEJVWWVK&RU&Zr>fbp zIxRO=aCcqYI%Ca-?v&=s!ZP@YYrFg}U3TA8ey^Hp&{wh{bRU_`WZ<@&z z$L(8VP96wb``B*6|5tC#UhLUto)R#r{?}^NjV7E=4&SU4F`DTYci`l)1q;Jhh<7FS z?%6B%ZEvB(j&FVdQ&MBb@0KwWQGXMYp literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/ebwizardry/textures/particle/flame_2_3.png b/src/main/resources/assets/ebwizardry/textures/particle/flame_2_3.png new file mode 100644 index 0000000000000000000000000000000000000000..1d8e5c96f3e270f886c4b8b5491328432d151b2a GIT binary patch literal 1564 zcmeAS@N?(olHy`uVBq!ia0y~yU=RRd4mJh`2Kmqb6B!s-HdTd0lmsP~D-;yvr)B1( zDwI?fq$;FVWTr7NRNT567CmjX1<#-BT4|goJ{4Qm%_}Z1m~Nk%!&6ymb@#JzA(NY6 z&`vM0fWN<&U$pnAtr(Gy7iu=Ok-2^RlRVjTtQIlGC^O z{pZ+inO{(K>+;&UG4l%l@RYdBV_cdZHp9o>p1D)1Y~FQ|XSIRx(~RpMeG@qS^Iw$p zgg~C2MINDvHw(7db~7}xbXru)M8=dKdQsfHSgi7#?An*ImDy#-?}{yt&0D$PtRH*z z@rzqFSDw3j?!w$G_h+;1H>hoowHJRErM+*fRhalz*5GN+7WFNCV{D-oV0mMM1fPBL z&fD$>K13w3y=2W&>+z9^XncEY7Pos|%=hAFJRMP?tQlS_*Q9K(ydWQP&-G$$K``GZ zktQoIqY&X4R}USkzPI7|={FO18rX;`OT4$b$6J;5=VU}<)a#|E_xwC6TCg&%q2c1x z*X|XL0(p~zH-FyEzw64`GQqF~3vOn9i%7V0iDM$q{H?0H&oS9=&b;NebF;QFgN9Qc zvw==P!e*T|-NkZKlG*y@ez_=wFA8m9%IVSa;l0%n(eXI+d~dbP`+cWYB)Vlc3a~{V zag@qY=vcbd@vp_(KI_@6?O4?7ocDnjJ1?KJcs=K{-i{YXv-9_S zJy$JX!=uF!HG|X4g3GQ&KzWi|OWzLbL(0dNOj4Qav+1Pje5WqSr;|&~Zl+DI<+BtE zU6SxyJX%IH-l=n{w%5v6S*zBr`z4i?vtp~7ulePi;SvH}s zyI$TsKX=u^H+KY^s;v!UjWw2;I2T?Qb#Pq0?&h<|?5k5>&&qX743=QMdZVO}tNiGK z1?$%MJYITt<(=ufCSH_(xhzi8J$BcBC(Bote4omdRxgU`{4MNS*7!^B&78bT7jDc7 z4XmuW*nd27!v?#z{3{F3@#|$oo2xag-SY6hjkocp8t=K^Hoctow@WHgx`wrXo3YN( z+IcR!a@u#+^-Yv>{Kung+f>t3Se@{K(b#j_x5#h)=T(+oVP3cY&{|{1n;Xs@zERWn zdyCb|IQ`;JBJVwNWR6|Z%FwV{z59Rs+?V$*%#m)K6?W;0r}qrbEl+mz6uy{ZwlHXV z=-lj+>Ian9rDU4zTheu}K;xtg!`21rI=dxTeh@O)bm?5SWW=gzv(8PjzCP*N-E}3TzGu%pg{9#E_O4#*7t}Rvx$oca z@ilPz*EjN!E1gSoWXi9tp1bM6RsVp^>Q4ge0?n(fyl3w|pRYTwBiYU?G+YY@s1mL zv*c+6~aLhiYy%k}w}nXmWwvX^zwaaZOW?+Y)gA9=)U zbYcI~`8KEIF9nq_FfgzsdAqwXR5C;{Onr0yYYqbg180FpWHAE+w=f7ZGR&GI!N9=4 zUgGKN%Kn%`P*gy>!pX>%fq~(*r;B5V#p$h=ZM}{p2pszupQ0Paeb7y3(xFREEE~VD zByC<>{^2pxJxAN-CayBEYqvV?-aBx_?Vua)jvW%+=8+x&vyZI2m)`d9=lRnT)&NY14F(vr&?)HgkHFcGT6qXl+PjIeV; literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/ebwizardry/textures/particle/flame_2_4.png b/src/main/resources/assets/ebwizardry/textures/particle/flame_2_4.png new file mode 100644 index 0000000000000000000000000000000000000000..2aaa59bd1e4cdaa006ef07cbf883545d72e35d60 GIT binary patch literal 1633 zcmeAS@N?(olHy`uVBq!ia0y~yU=RRd4mJh`2Kmqb6B!s-zE*`qlmsP~D-;yvr)B1( zDwI?fq$;FVWTr7NRNT569(l=Fou}rxh$WL#$5V?np*tP>=BLd(`Y*TM`>ED0GZ(Dfyli7*Gn-3loeJ*Ke#W{=st3vg(lEa^2_d8dJ)m z585Vfd8)F0<7^Jwjb#;e6%Q7F`}J>U;`M6Yz1vN9r^rqy%JP3ToDwXI@=Q_;%elud-77RPOGgq#kDvt&Prq0Zn#Wh-X?}0i!~>USWA^Y zcJvQTI9|Y*&9l)mdErZQzxq}toA9P(iV}-YJ`N6E-?Be*`NDhduY_I}B(?51gv(BR^udi5ahW@gKSJohV(U%q0RG)-bDs|&}p z4tCQB2Zhs7j{hp8CpddXtPv7ak85)A?3-KqXwK)nD=VJdjMl$b`M$Z|j+M{Mqu^k> zK$6Er7dOtyFBXLx9+3!cy3BH!GhaPp$rRsbIh#|a*Ya6D3z=YdR7`W-4m^GrZ?YOd>>*4oIC;Sbiyihv$}? zo7LPqv1e+Z_;&sk%zq|ZoE7jr-e5Uf>Fk~MmDLBMe2d*5dR~ZVWez?o+q%|zvd;nW zuN7Z=I(r}9SQ5ssoPC42P~6V6JI{Mv(c`>RKNsw)T)0hl{jG08e*B$l9-LltX60>- zvx#YPB663$?X9@_ykWom`d>01#6RAv`dY?xbZ7Xz`(Iz(WnQ;c_F`N0mR#!ci|$P?GK-AyDI9v`OYWHlba463i)(& zQop+Tjnbv>hlK9D`1Cnz zk)86-V&|&mnTJ;{PWk)4^Mz~c%IwF1-#=;Wwn@sK`Z{*|>+H4PH?5w}qxEK6y-e^v zpHJe2D}Nn-_^`Ziu*pj^6T^K4Eq8O&WIsY|> zfq{Xuz$3Dlfq`2Xgc%uT&5>YWU|=ut^mS!_%poW$pz};^`8);&hPR$Bjv*GOw_e__ z#}X)V{Nwqlp*pQD%3U)LF?YC3`OUIu;TOJtdm73=2xu?7pm}AnU~dJpwUkq{XGd@7 zotd3;Z)6?Md}sUp-=zEB=gbjiYi9JA#BzgEnd3QA&$h?Kb>BGUx|woxbebfC-B#$C zo^-r*rKc|Yy}$Cwr`7FV9m3;r*x3zxt8C$^$r^+ZF4cWKU4O#zopr E01Yh|rvLx| literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/ebwizardry/textures/particle/flame_2_5.png b/src/main/resources/assets/ebwizardry/textures/particle/flame_2_5.png new file mode 100644 index 0000000000000000000000000000000000000000..25185d969cf1c9cf78de293c9304d5b99454baf1 GIT binary patch literal 1605 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 A@Bjb+ literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/ebwizardry/textures/particle/flame_3_0.png b/src/main/resources/assets/ebwizardry/textures/particle/flame_3_0.png new file mode 100644 index 0000000000000000000000000000000000000000..7be866f0b2fc3d8864f408b10a2f1a759ed49cad GIT binary patch literal 1683 zcmeAS@N?(olHy`uVBq!ia0y~yU=RRd4mJh`2Kmqb6B!s-rK>_BN`ey06$*;-(=u~X z6-p`#QWa7wGSe6sDsHU}i=OmagXeF$=w_Cd3cdE}tKRXY{VcAy;b-kxo_Br5k%UN& z!akKXzxLO={B1rhVRUMjK<%fv$D2;7O*ZVPie0Uq`@GivMe+yNb?3y{l-$n0zW9CZ ze8uwXEeYHA)J$C+uzl_hUfF5e9p$v8dA7yfX}h6g`8Iv(w>>%X+cy7~S=Jf+^Is10 zfebz;vr{E%*LM8g$aR?6Z_Y*cJDrCEoTQWccgt3--w^!#1KT~zU5U#-Px~CMG38tI z!TSccii*~6oXv4J!aD5VC#5pkFOR=A%=PG2s(q^$&A(*Nt=U%FjNAis8YVqA=@Fz1HRm0Y*?4fxX`?`y*o{Xgr?<_!9QIQ5oyaXShK>!} znvIVnI8-OO&nq!d6JR{fQDzaL$)@!Dy`S%~+h>LF$>bCqY!^uKP;~Dz+w~&3 z!*JP*$(}tz&nEdhE}ao{O0qj`#<>}D7fviTZ0*)v_e01_XXTTw4=cCrdX>Fm zJ@)1bw|KTdd%=tafqr)$@bpM}C)n_?30z1kSf(7A%~srOJeOzEA;}GHc@r*Y7_hPB zsy}Y=d#Cqo-&0@9-{E^^mY-Sac=!LoIZ{`0pUtbRJ{WcSv&%!z3nvaWu1s@G6wcq& z`D3Bn`gt2S8p^a^dG&fS*Qsmb6PwnYyfocIr_cZHwe5Q{wN2-R8ArCuKhD^FW|htH z*2)WI9l!7YUNLX(pSk_7Zk`mkd!^nouO`f`O|!_dRAj}@>Rx6A9|UgRr;cwg^!mwua)^E!A{)rLeKuu@!Gh1QdgO{FSrPquFmdv3PIMd&u`gK65*KSZ8wS+Gv==jA5-Y*pt+j}*UtJ7j-}iF)M*l|Gg5|gR`1kj#5j1acgakOYvL2=4R>@dxfKO&Hrs&q?Pg2 zx9+O%DcitL+oGkf8#9P3mz6x*@O!(phWj6dg)Z~0O%wTw)`p%)eb~`7`P|UB zS*l%IySGaAB(^(mj#8?Bb;)`CyqZ5tyI-9=9=~hFy{R+J-JhI3BY$QUztR488zx+e z^r>CD+)m-A^7|{_8^7-?e|6mX?@wo!6S?6VmhIi=*7r%5@#%`Xf0b>z0|UcPPZ!4!i_>c-Z}dA9Akwy9N<2ZK z&`|c)L3RUyq!~3#ms_uv3(WM4k?dT|&%ivpSwDf3o4ceqA@gxUklJOIEkW(Y`OKlq z?rok^{lEI$&;NhSk8>RsU^rgL(6NYv;d&|K2`dh}n@k@jsxZV{JhEml8hawlGN3^YK>J4;Mc1R8P3fKecJMH)9<0N$#r` ztlwz9KPZ3XI*;SBckWkbeO$1kSHFKd!<`cM|9Q&`S@(PI^zxUvQ!|Z$fq}u()z4*} HQ$iB}Qi&{G literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/ebwizardry/textures/particle/flame_3_1.png b/src/main/resources/assets/ebwizardry/textures/particle/flame_3_1.png new file mode 100644 index 0000000000000000000000000000000000000000..ae440af708e4907a580675392dc4ccd9c0034675 GIT binary patch literal 1730 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 literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/ebwizardry/textures/particle/flame_3_3.png b/src/main/resources/assets/ebwizardry/textures/particle/flame_3_3.png new file mode 100644 index 0000000000000000000000000000000000000000..ce76fcc23c83736c6d98570d14b439974dfb8087 GIT binary patch literal 1593 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 literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/ebwizardry/textures/particle/ice_0.png b/src/main/resources/assets/ebwizardry/textures/particle/ice_0.png index 531b56b52021c306c017a547365e2f140b1d819b..d8e719bab58e70bcfb8fe2b81236e624fc59814f 100644 GIT binary patch literal 1649 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 delta 198 zcmcc2b(7J!Gr-TCmrII^fq{Y7)59f*fq{VoggMw47#NQ5@9Sn@U|>t~c6VWz4uU*E zFWyeBWs$3Y#KO-l&HFI(UnK(rLz<_HV~E7%?$NrstN2I(JdOeqcfq|33)78&qol`;+0Cz@F Ae*gdg diff --git a/src/main/resources/assets/ebwizardry/textures/particle/ice_3.png b/src/main/resources/assets/ebwizardry/textures/particle/ice_3.png index b12745e939ce781a0af09df2ee45a53061b1dcf9..85a339fd4f1930d6c25d0898cfdce6029f96e623 100644 GIT binary patch literal 1213 zcmeAS@N?(olHy`uVBq!ia0y~yU=RRd4mJh`2Kmqb6B!to&s2p(lmsP~D-;yvr)B1( zDwI?fq$;FVWTr7NRNQ(yJ-6ts8c*B*&0TtoiY-Tqe$08vx9iWogg*bGN%v-|{k;6r z_K4fGRK+hGZ+3jVKL7IH#`q6*J2kR2mp}Q~ZTT!fVaEQtaDTgZpLc%Xe>nHvU2~?8 zo_Xs}oAlK-#?9l;u=({X?)?^7`!X3@8~OG-MCqJlZ6Y#x8jB;7~$Re{s}e1EmLNSoc2kS#z2r_atX};xC)>cVh9A%Dwe>et!Dm zXRX#8|KkdKpS*bCX?OnaxeMG|kDqv-ccqg5qhfh++3ez&&Dw^F!6)Z>+AiCqDiOA1 z()VOe-$IU*ySj@dm))4~g>RPVTFX-+6W)4Gv=W_VQg(lZ;t>fqhh5Gbx*x7dUYhTG zJK#~4Ni&mw`2yh`jZ)6C?;#8}eD>qgo#&^-XKr6?8U9kJa(8j- zjzd}wEgMg)HD1He^6ccwH-FweyLY9xo_U&MK-nx_VV#B@u^|i7b3Z;ivq4yX?*3DA zx5%@52p$t-apqyN6XaI?B-JFO*w1FiI+49^VG~1Vi(g(7Z!wb$cXp1=;w`z&E#AFr zSru5kT^iZAIW{DTT*R6{_zn4c!W2s7Ea zw*6a2#gdXob8ay76-8-B%bYs=$ocKQ+4CZgi^Xcrc`p#PdvnnIm5X$r_UM})l;5Wu zz0c*%g3_2ppTECd|LxZEq88^Bz3pa8uTB<`y76k;wcySBmZtevTwM3S_WR54SN0v~ zIPOu-_iJhCwz!AltdAF#3$@1`nKi#kcy%Rv-`#({8IOxXI;;O?{oKQO_U^`7W0UgZ z-_Bl$xq7;{sCv~;E++jA=?@=1Epbf?zIFUl$y4`f|8>^QPrd&v`0g*hwMRZKD_9b< zkp11SlRS6%b^qP(`^VlVG2iru`i;N5y?gg%_U5-uW?*1oOY(MiVW?z?Vwn2o{MQ@? z1_sUokH}&M25w;xW@MN(M}mQYfxX1j*OmP-hoGo{akk#7Yz78~B2O2`5R22v2@`g`Ha51l?fP*^ zq3*TfbAJ7K2h!#IySiikPro_o2_W$F`Qpjk-|p;U+$j0#dDVM|J%&e3W=+y$XSmlW WyDB_?a~1;w1B0ilpUXO@geCw&sYBQR delta 171 zcmdnXxu4OvGr-TCmrII^fq{Y7)59f*fq{VoggMw47#NQ5@9Sn@U|>t~c6VWz4uU*E zFWye(W|7N##KO-l&HFI(UnK(rgO8_+V~E7%-|3B0J{lE5)GbgCt|MUCv z|6}{-^W?|xY3bg0Kw`Pw{@?fi{o`c5-}#wm&7YbXT;J~OI(XpwBUR_UFVdQ&MBb@0Aff)WB>pF diff --git a/src/main/resources/assets/ebwizardry/textures/particle/ice_4.png b/src/main/resources/assets/ebwizardry/textures/particle/ice_4.png index 389abbd7b66592b6bdfc8712edbc5ffb7c927abc..0bf02ea58c40661c78e17b63a7795485cd6f5cda 100644 GIT binary patch literal 1591 zcmeAS@N?(olHy`uVBq!ia0y~yU=RRd4mJh`2Kmqb6B!s-u2h9YlmsP~D-;yvr)B1( zDwI?fq$;FVWTr7NRNPt{esiLZCeNSaU8anlbDkBrtzpmpr{*45ySMVXi6QG+u}LSU zxb$ZI|9ktY{f`ZNev+@7yU%6T_?S!-7IR#GewOF#pLgQFY^|8I`ZKe$%8b<7(%jeT zC*JNoI9vDp`J$(%w+U}sc>0r>#$n^+jb9I$sqA^OW&i3O-&H>s%=xQcH_PJG`un}? z5?7rx*6iTyJa(B^zllS|>yXR`m5bYe_?*@AJ<_&Xl^>5qzu)uyp!@tL7U7(NgY5!I z9upTYXubJjQMlm|iQuNoESEWV3!4O;nxi^9XY*;hc9~)=kNHVmy6b)jdFiYyn%ebg z{kp19=U!9OERUsWvvSw{6pPAPseFA`$>rSgyWcM)`?qgB`^q@`%b`2h*IZ1?HAq`F zZ+~R-jo+tPddrg7(-V4l8w>3v9GpHs@L@Mwz0Al7$WScwcfA_C1g1UDek-bawTM zZzj`s92U=B{CVH2Gc$uT>asJxT+sBT8^}(VoE#_vuLGiy065)MK zAEy4>C6lVH8f&-G-{8ZxQkexip08rfEVBwI-hM`RV!?J@2Gd>FA{H2`?n}9*zg6PA zq}9=#TU<@=^gKNAcWF_`Wus;}(X*+6VHS&RZd*@4hBS(r09MP(Am?lZrA6Bx=)1@Ez-{kFP^Af{%qRR;FWi7dc5AQ^Yq69 zUf-Tv=4Ax}*S9@ZQ=gF&-V*pdq)yf4tJq`twiWl1{y28{UMdpede`uMQDC|2g>xG< z&dxpXSV{X-?EW3^(mIySTTy&8n|IL$5kIF7Q5QU&H(PA`GNElv_@yb20xz+@;m?$~ zmiOoKrK7TwOZ9xtl*>J9<*^RsyO1mXEp}6({-ee#@m9}6a?@93`7wO%|8=i@TRY#M zGS7!a@mJ%0pFdXKb8O@4czcr_vHNE(ZBq@6|GroMR@~y{FRo5m`srS)-v1hf&!vtv zN$)S}wX2pqt^4`vSHV=92TS+8Joazr!u5}L)Cbjzv&ZfEkiYAf{6?3TmmT9ao@8KP zU`z6LcVVbxh+>%f=KR+j1_lPs0*}aI1_o|n5N2eUHAjMhfq}im)7O>#F^8b2fXP=c z`x6Wd3{N~=978Nl@4am6#T+Pd^y7VQ;Q*%qwFzoR&uHCgni^fiJnh}#Yll>CWTq+` zFA-SuLr_-o@q~24BT7mdlD21SZ7RP1eg81#nnx9Z?C7T3TA zozo7H(;npAblI`)S;8Ju4ujR&8_a!nD{`zp-1Wq6cEgrPH;Z}q8)|k4C;a)qBsbgD zT`uITwZ;1R2d_p)Z=S$1Bcz+7b@{jFH+5II@2-Dx&~yD3z|J=av>$)~xHhchyeV^3e8<{fo8--Cc`*e0dyS_K-Q6GpOL!;j@Aa3=9mO Lu6{1-oD!M<_8tQO literal 289 zcmeAS@N?(olHy`uVBq!ia0y~yVBi2@4mJh`h9ms@x)~T4*pj^6T^Oc=AWzVXw+svn zoCO|{#S9GG!XV7ZFl&wk0|NtliKnkC`y&>9ZfV|!ng1#o7#P-hx;TbNT+Z#c=3@+$ zXx(ou`AASv`J&GgEs?0`jZD8c@ciB&V5N0eKiI?OSh9zN`S);zSwB|=&zV!hzHfz= zE6e@~DxQUoE&-u?zRT>nTsdvko_S|Bi!d-NC@nElD~elwU3ahBnt#u&bv n@rch|t@+{oFc+@)J&Y9%K|#}hxkfWEFfe$!`njxgN@xNAz;kHb diff --git a/src/main/resources/assets/ebwizardry/textures/particle/ice_5.png b/src/main/resources/assets/ebwizardry/textures/particle/ice_5.png index e1bdc75dbac565c8c5d94de7eebc45df46b89b4f..8749f94dfb3988cdd66e9473c38d136bf67b56a6 100644 GIT binary patch literal 1498 zcmeAS@N?(olHy`uVBq!ia0y~yU=RRd4mJh`2Kmqb6B!s-rdEYSlmsP~D-;yvr)B1( zDwI?fq$;FVWTr7NRNQ(S7P(19o#)SU5j!VOC!OPoy&rgMYSg_io_;-ZJGQ-r}u`+$CSJ~blgqa(vjo(uQfCEtmpqeUdpXsRs1hu11O=L%SR3C z{^!~rSi!Y)!$UO{@p*Y~lsX(1shnZ-7qag$XnXS^mM<}Xvu?}RPh71# z@0bFW-E`UAFi7h3e>=s;?WS7+bHjo~n7!fZ1#2X_>a; z;flX4mE0VylkD}rYiFKiOfHD|kXCMIH;9>c#Asgsh9FE}Un zC4{*wf-6FJ#m^&7#rG|~Ym00sR*f(^DCsMAzwPIeKQjwuzS?$z(AnlG9j8yuUt?OFt! zyJT41XSj*)?NmHAL&(gxVD1L1gGx)!L~c4eEB2e^lNrH|KSiRq?0Dp@v2n?%P_0}0 zcfIoEHNAFa#lk7Ga&N_a*4=U=$bD_;%Wc`^cfVgq_HW;M_LX+_mt%LnM=m~lE8&cv z_5TFktoQliCVj%Pa~ch|u^juGz`%O8d9(I}tu`~H=fqCDC~_*Hw`4+arU4sUuJSd% z_TB8o_n)3!@i%(U$L%wWn|H+@oFjQ9_u0Nr-x{~hde*BndBMe2=F8qzd}b0`CRi*f zRR8-W=ikca`rV7?-4>dBq)6La)_D1aFJ3uqV%%Dhsv$Q_)4HcK$LGvf;xhWY_V2fx zx|9ufukCYLdMR&dadq{SeX~{`W!mn1e6CIMeirkKBF3J*+rQOLyLLy!cU#b_z}qH& z7tTJEt|2D0rEG%`U(d07Y42vF&J{d<G z^f$U@zMB&AB%!Tk`ex=RkNCN6->)vceekyIZb^&067SDDZMD?(1=amE?&}A~E6>z? zymV9d?ynZs>L)_@E5i0$ZT)%k>AIYoYmfAQ<0@6Xx#!Bi75jz4cva^lzYXz;pSrfk z_|LM;>raY%A1ruI({#^39Fn`as`IAF~L=Sv@{biQ@-olET zUsqJb?_SJXwYc2ti`W@u_5C&v^mg@bnY-?+`gxc4wbqxNWmDUwpEWM~yWyAqnP+bU z4s12MyJAX#g(r8fhwl6zyFYlpp0)6DtwY+L$u_^{?!EUn?r?iu{oJ$9?H|mU{#j&p zZOMmsQ!jiixRX4G{kHxtmw)A7?iaRPUzzcbMeoI_lil13oeT^NY)RhkE)10nQ4CYx zod24`z`(#+;1OBOz`!jG!i)^F=14FwFtC?+`ns||<`5JWF!}0be}aL5;h3k3V~EA+ zx0h_am=i@>A3o<6bUewSWmcwlAV?sGP5i;EI}OnjMZR5|rm5PZXw=!FV4>#IbMbtV zh)JuM@P>~e+jq?Qd{6#g)WhvcGVRh2VLTBE=zmptmn|Aj{-acG6)j*rM zXV+eilQnFg)@GR>*Y9PBoVK=O!3p-OvHpJbe9ZfV|!ng1#o7#Jpax;TbNTwdDe$kh}e z!tlIXkVW!}Z4_JMY=8C_KCuf{ABo?R|8`TEqT(@g!NP?eX*aVcvv;If8}R(``d8-} zAev;P&A{gnAbP3WIl5Sicfo6h0^hXAp5|Cw0 zr{lWWjn3nrUarvSD)64Y;am9MCZ-#2%7xS{qq6@!Xa2I=rC=M2r5XbR1B0ilpUXO@ GgeCx)zFGhP diff --git a/src/main/resources/assets/ebwizardry/textures/particle/ice_6.png b/src/main/resources/assets/ebwizardry/textures/particle/ice_6.png index c597f4151ffab8cc5bb129c233b3b641eab0c5f8..881ed9a89e133b763477b862fb553ca6b775a995 100644 GIT binary patch literal 1177 zcmeAS@N?(olHy`uVBq!ia0y~yU=RRd4mJh`2Kmqb6B!tomsEvBlmsP~D-;yvr)B1( zDwI?fq$;FVWTr7NRNQ(yJ-XR;Q?fsi)`wkj# zR^6PwQ2sy9?s^-6yBnu}FB5*RH#%yw3~Swfu+UZo^r97r(#S#2uhDWAln^&1{zAOq$!J z77Az4NOgSC)Y$IY)fs|m?yVYwR`h{^U>*V^vb*5vNX8N zxUDQHB(S0JNU(zROl856kPjzM%sE=f$oOfV^h`!GCB}j&&+k;IUHX)I{&vq=Rt1~5 zi5w;sjSQzP`+s%%1v=mCE?Rz?BtoDMSbc!Po7ab=KWCe$_amqUNu93lDRkd zcipr-@psbfkMH6OAJ3m?EPPk{#LUij6Mj#;&3+{+E?y+E;aRkW=~kl+8xJnbPCNT~ z_LrykYRnJ3cliI`VeyhZIcNED7CirULEzekYY)H3H_Z%B+049GVfOlL6R-P+bymI; zytmb_`dwK2+U?n!Zr^JD@}*PKr!LS-ZNG-<=a(WG?@jk|P1<>8@0-AWx2k=Cp)+l# z_tdP4P2Spcwm6d0`eE)7zKZDXv(d`ccmL(+?>#2FY=Pe=quH6~OJ@hmTHd|)ZH?>F z$w{$w`Sx17B{JNbB*^%|Yo3=9lxN#5=*43!K~ z3{&5n|C+0dKYu_){bL+^{uRJIGj`uVEkKeFo-odq*4o2PwtM>CooE2}*6Zd&v pdf?dx=Fq9ZfU-Xg!P9R7#KV}T^vIsE+;1}u(J62 z^KN~Lov_jKv-|D;m)qB#Xb5%uc$=Lk{@=gU2LV&kGpsj>=W%iODE|F={r}bH-wbPh je{F8;?rrYsV`F$IBXu?4vh+p<1_lOCS3j3^P6;G8Zk>8<_{=P}A+tRIH`^kiz3ljhBIX9~&;``qR>yJ&odpF*| zrzz^(@f+Lg8)M~VgKm6#eDht<-NGF9T}tm8jNH>qw#|R*aA^75Z<|l=j_1r@w%LAC zSjX+3UoBNSE{eD%9*^~~c~{t{bi!ei$dxv0&slyNn`H~bC-!eGF8}PhXZP1dbM!(;>kSKmBRJnVrQ=E;s z!lfBcp2@~BI3;JV^1dH>XLjl1`wgN3S5!AAHXW5u?{I#(aa&5E*pHR`=jNZD8+4md zLGW0ZiZc_F-6RdyPo0*6j_%C!o6bZs$tyUlx^seegJ5SvvdwX~`7WoYPxUwM6Ke>_ znaE;t!=XX6De3Q$ga~I>*XH1>D?EKSPt!1T=`~ztael=lmDVMi%ckf&4e`;L5w#^H z?WWf=9g9OI$LGXsn^UYQu|=W8@jX+25TD%>j&`|^9__L}HAGJ@Z(C)0EoAMpC@J&I z8~=2-J(;!jj@RR+R;Hx}b8-ixjpb8IB{DRT@~&PM&Gb)u_Jn{`o`0upjo&V@qz56-el6c2+z9qBoROiVDWT);8Okte0yCCaT>Vt%4=k15Wo>{+~ zp8b6{<38rU@0oj*r(eyfdr))d+OZX~*NR^pot}DBI>)r@YSqrtr>ph9-7#x>TE?>S z_`6qoN;Y23DV3>e{j)r(s=s{8v+GxuS-J z+tubjAL?yT9HTW?MO`D44(-fQpnc9dqv zA3AZoTd4g?U3F2+HYv9)mRpO%f}fp^`M;Uf(#y_0Kk>uiuFXGW?zHXt#d4nJa0`PlBg3pY5)2Fs>?NMQuI!IF1Vsf*n|%4>7#J9eJzX3_EKa|@w2|{r07J_| z{q+JW6V$jpo^2>zT_Wia?wLHTps`_rlSh_}lBfS6s delta 163 zcmeC;+|Fp+8Q|y6%O%Cdz`(%k>ERN@z`(!(!W?W23=Bv3_jNNcFt8HQ#KO-l%~z4I{xAargNvt&V~E7%FVdQ&MBb@0LU&qXaE2J diff --git a/src/main/resources/assets/ebwizardry/textures/particle/leaf_0.png b/src/main/resources/assets/ebwizardry/textures/particle/leaf_0.png index 6c1dabf2c8c5534f2ed11fe1485825402b5fb788..0260459d7b778fb7399a76734eb52b1fa101beda 100644 GIT binary patch literal 1274 zcmeAS@N?(olHy`uVBq!ia0y~yU=RRd4mJh`2Kmqb6B!tozgC4rlmsP~D-;yvr)B1( zDwI?fq$;FVWTr7NRNT5dJ$lk-4W8Efkw>*)i1DP8NAd&`0sa&Jw3I-Nhtc6!C-b>F3`^MAkF^f}U$&z4?}Ss!rZ)YJzjTM|qx<7VwN{^x1U{MF8D`iWz~+E0!y zUN-TVg894;OaiaGgXjJ_mp1R!F}p@lfh(HDN7y#s{U$K`(&B9?MPffzmL7ZO-s}|1 zs33SPOvRar>DpwC%1w=y0*=Qy>?CJywz%ie5VCX9%LL^|jOw2vq>Gt+ot3O+O?OTBZD<;G zh0W0X@1bU?Gm0{b88PZsGa4nVnLZkDELc!!uzBK~$Buahn>!0N3Vtek%NA(yCMmp- z+E`|F)Aq#Q39|#gN8kCOU6i)qH(ycOg6JprcHRwGU0JvI1dEB^!wXlujvr-f7c)L? zvv2ah9p>}deynGIwT_oN|0s7>PT%6AriQYMZG2cC9N)oy`{UC+XI`8&{ITUev**-3 z`Ys!z%Tr>?-D^J1S$1yA^SJIUU$&Tko@v4Fd*-~0q^P}3^MW<~FK@m-yl&m^+DVe% zc0B!&nf5Ha@UM<>@se+uY2I(vxu+?eo$qb7-+djc{k6V3Q6IVIc=@*9^jPE_=rM8X z23^}+`}Id{FNB+_nLgQFustew%30CJHzs@z*VuOF?Vp`iXT2-yE}XZzbuVa#XIF{p z)TKX)mwyzvXQTb!Grw%nSKhn4KCxFU9_7s6dHLLtJ+J=Uc7Ggl)Fx-;=d+=o%tHBs zez4w>n{7OQYhDwGghN*APf6ZZFVBjq9h%9Dc z;5!Jyj5{V~zhz)xU@!6Xb!C6dAt)+fChZdUgn@yf&C|s(#Nu>vf<(rF4n2i zK=0H!5LK}H7hfFn42@DoZoS#@@fBymf*&6p{m;Y0!}IIcubwTXjJwXh53Bug{=k6) z1urkDvVp+XFwr%MPPXC;X7g;8bUPg5w%eeAF=EB&#zkXkBf9V)2&y64@9bWbP0l+XkKt=nLY literal 196 zcmeAS@N?(olHy`uVBq!ia0y~yVBi2@4mJh`h9ms@x)~T4*pj^6T^Rm@;DWu&Co?cG za29w(7BevL9Ry*<9TT(PGB7Z(mw5WRvOi*H=eE{Yo_Ugifq@~=)5S4F;&O6=g4hZ1 z6Gkhxu1e@IKB#ij^`>N8e8t&Dju!7*9-wC2;Jzd)vYy85}Sb4q9e0OjaIJOBUy diff --git a/src/main/resources/assets/ebwizardry/textures/particle/leaf_1.png b/src/main/resources/assets/ebwizardry/textures/particle/leaf_1.png index 990fba4b9a20f30668c5755e564f7cc141052754..52f737ab721eeda14986f3f57fd65603a3e1e46b 100644 GIT binary patch literal 1155 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 Cqyzx~ delta 164 zcmX@iv4hdLGr-TCmrII^fq{Y7)59f*fq{VoggMw47#NQ5@9Sn@U|>t~c6VX;4}uH! zE}uMk0kd5CBX)LfYa@sGOK&nTFt~cUIEF}EUV7#r=K%&DCWp5UX)kif52Cj#Z||I_GT{juJHr_smBh3OPkwIPJy~VjX2JI_UQG%JJ@S4|&ye%LNAH#j|?Tg~sN->zLje~r?u z<`_kYP1+%Ep?Ue=&zooYYcy6#sXNwwsXKh!RXq2Q!}h?>zX3URdAcFaueUcpyo?!`=fb1rDFJCbOz@a)Ge`!Af6IXt=I_=_cXr%jtH zztmuMJm0@17dK6|xt^z0vZ(CzpAQOGm5;jazPI|@y>C}lpD&zZo*lS-=@~&8<0Vfl z&n{;D!+9)mTgS49B*u+gvn1C_bfqjTQ+J;#RGPI}KO|t$=Ce+D*|{5Sa=Csk))nrO z?%lgx-Q<2DcZB&8mESCfsAa8yqxJqws zTpoB#!F=5ZCV^Mp!83oIOS5}3`z><>o8wF)ZLt~K_OzdH`o8z*WaGpBX6f7hW(2Iz zW>9g;b2L1nu%R+Z(LZ{FnSi4^>-?5ey4JHD8(eZ!FCT2X$=r8qqI5BnZ@hMy`Qxih z0*B<E(m({N7E!)3ZaraP#^TGaKLePcUY_t5p8 z^~<;SYRnJ(*9$m*Zhpbx)?;usMH6Py5}Eji$$cEZp?{&XPO6&mP`<|Lsnd{Y;+z?GF}*XQg{z++1VZ zc6{qB{qB!W+@Dhoi22tCz;<`{v~3^r@byWL*I1noHAW0 zcG@+qTCJ0t@7eeS&Rl%w(6v}gF`v4bTTA}cWZr-MpY2ya`yqd^Kh4?ySaqd$J?Yob z@L*tIU`z6LcVVbxh+>%f=KR+j1_lPs0*}aI1_r)^Ak4U9V)k1G1_t&LPhVH|#~gy9 zf(&P${<2|UU`X+FaSX9I{dVF;-Ub66mh&BzlR7tX$R=N?77;7R+QpN!N@OA9LKl;o z%$vV1OYZC2V{2l}KBG-|$8P2)b7oie1nv?z<3HP(gJDJ1=Ii$l#uj^d9uv5-KQ8zB klv>e-RO??>KbX}wX{hJk;W;>qfq{X+)78&qol`;+0O2SPT>t<8 delta 171 zcmaFBv7gbnGr-TCmrII^fq{Y7)59f*fq{VoggMw47#NQ5@9Sn@U|>t~c6VX;4}uH! zE}uMk53^j}BX)LfYa@sGOK&nTF!*@7IEF}EUfa8ox50sjS(eS~+u~%NS8G0TTbRl= z&(IRu^WwnMxw_2pPC;hQo~yJN99(XEQoAb~Tjeon(vmYF#jn@@ek3z{?eE6=BE~&8 Xb*%SaJ?+H6z`)??>gTe~DWM4ffK)ut diff --git a/src/main/resources/assets/ebwizardry/textures/particle/leaf_13.png b/src/main/resources/assets/ebwizardry/textures/particle/leaf_13.png index 85124935f27096f74edcb5c5cc4186127f47e40d..ea5d76f241e6761baa0e7c8464931a0d250aa47d 100644 GIT binary patch literal 1074 zcmeAS@N?(olHy`uVBq!ia0y~yU=RRd4mJh`2Kmqb6B!toqpCt8N`ey06$*;-(=u~X z6-p`#QWa7wGSe6sDsH`<9=qwb0#EDxNZ08JoGeL}f6kS#$JX)BurT+V^-b;j!pkdX zO6Z(+vYW5anQ6bT{4+26(FZ+~7uZ$pe^_wQ)lcHZHu-A**|VRQZj5C!FDt&2Fhi$m zcl@tye}vx@)hg^rJ-@w7_*BX+i`i__f>nh|9v~@bHJ(DUxTKH&s4TZ^T>Rj zET{WGS)%=>(yT|K+#R78&SV@7P-(k0S0>c!%F46*0vx;gq@DB9^m3N_D%L+STDarl zieiR&Sq|;FjHcYi@;figF+cZ{OEYa9i@zGn;*%e*oKb$P{g&g(Z;jYRzWi$^i1*KO zlWM+WahTg-g}!gIxvl}b(u)-jCQq=8J}$}P(V{(*&+J;&fk3(9$1@!+Pj4+Z-X_){ z@Oq<1iH^d7BEJCpgPK_youcV3N4y25YMhLIzo+7TvwU?3m)Q=5gY5z)M>*i|52AnywgP??^Q9m zM?bCK#}>Tx*eog2DM7`)v+@^acI%d2iQ0a*^yR+xb++G10-{6mS6=MAQ=GMB1#eQ` zuU2i-8O}Re7Hph*B7rUG4abqg3Jp!q4(0?G^|9|fnA6?ks>qY2!tA%yk%uK#d72;l zZtb1R@AT~OFMJ$7(U|#e_yl9-yGrHf-!g8U^~}6$Zo@GxnOS+;l9QXAFCUq8to+jH zy_Mz%;>A{^KfiuK#_a6NxqHr3SH@g6c>lEU?b+}b#y)90w_>B-I(|A|{9maz%Iy8~ zPhPTLm%P=RUMp6dUnS&TZ#%Wpe){q&c9T!fzjm=XX4e#x<3AL4d^eM_nt5*T(Yo)_ z({IjRZn)w5JRj2!kE;y*TYnyLGSPSbz4pd;j{h3QpYzndOYWU_FD!9 z2KEw9Usv|W9D<^PjJqD4TE)P?5b5dS7-Dhy?Zkte2Ml zV5$xAZ=U$zfw4=AlGEz?-0&QKRfczb4rxpms<$h%Ua!$e4pg1Ql8{!mEy3)(>+^7p jV-i)`t3##iZ{LyLF8%ZBgZPUK3=9mOu6{1-oD!Mt~c6VX;4}uH! zE}uMkCbL}fBX)LfYa@sGOK&nTFgSX;IEF}EUV7>v=K%vAmV?$Fwm}zHdE{k$7P6?6 z+@s$q{c_2>XB>=wJ{lj7@}49j$h6@t|BS*1PyVjdDw{L&TB&};4w;yhoTZfv3=9mO Lu6{1-oD!M<7z{V5 diff --git a/src/main/resources/assets/ebwizardry/textures/particle/leaf_14.png b/src/main/resources/assets/ebwizardry/textures/particle/leaf_14.png index 50a9fc7007a62c3b58da8b13bd85d7ecf9a1e544..c9812cb6c1456a203d6778e326e8818a032a4f19 100644 GIT binary patch literal 1084 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 Z?R7J{*JH20l7WGN!PC{xWt~$(697gPQjq`v diff --git a/src/main/resources/assets/ebwizardry/textures/particle/leaf_2.png b/src/main/resources/assets/ebwizardry/textures/particle/leaf_2.png index f9804dc0e507f82f055dd65a0faeb2335b3b8a26..94dca3bc6c752ffe4c4cca6b614c1f218e783681 100644 GIT binary patch literal 1165 zcmeAS@N?(olHy`uVBq!ia0y~yU=RRd4mJh`2Kmqb6B!toXH|tnlmsP~D-;yvr)B1( zDwI?fq$;FVWTr7NRNQ(yJ-Xb^y7nh=cIWi zFPQfD()YLX6R-bfKA2lwxn*`h`J5fhca`2Z7*(g4Y>U6s*uro9Hhc27;+uOV&;9$l z>F~D4*S_9j?YJoNv4yu>aihiWo81b`o|6LI=Xf3}ahjRizqxDQwR3aMc2}goUNraY zZN2^=iPzhk_h)Q*yJY>=Xs*~5cdP1l1b%t*$aA-0l+0rJ#i!3XYvzAjkmnq!Ya!;L z`P#5w=tJ<9!&;oGNgbj`q%y>&WN8RGzjf@BN|m}29=lS>_4r&xbK~%7sofLo3u6QB z=$KeA_!}=c9OUSm@XS~|>hH3v@k=}ANgtfdc`&1JkI3g!Kc*J3NhSNmDoOjVogjYR zve!gyXJwms!-X5OUR^2|{hW61hIs-jOX*1&!vi^|1s7@DeLhX+9FzUlb2pMR12U`` zRGjX2rFb|Ts1j23H#1;YdLeO8UAb87I4g_CROy+FW=e7eO6T`|^jYxq^r?2qXl@6M zX&wwxItmAh{0!@xx@R~`zCI=y`c=v#>(ZN}*6Z*6e(+pwYBP(t$qxZ19?d5j7hQYp z+9Z;@EDMEl5@*$LsU4jXbnb=pFl5&>fdO}nSW{M>h%kc&C1HV zvn27S`TeHMjZ3Flm-;Myx2x>FbHD9Z8-wd@Jmw`o1l?pZpG>~B?3YKc-V?iJZnJNx zJewB3Be>bJC7NT_?M}Zmg=2jVHa<)2dC(iuuf&MJMeq-ogcPEX^Vby7Nsq^{bb(Gy$h~=s#<)4$t3*Yl`E$X9Aj&jGd^x} z-!p#Q*>dJT@-O=NO}ajZ2kTUtojw2L^G*l(CxzxS=bwDO*g^UD>r*eUo7{^yv%B!o zchg^IWB9s%*6FQ(7Wkfh-oe5E8|B|N(lN8V4$n@w`F5#USkeAFLOF%&_u8*GtLo+-EnohK~JtN6a|#(6Kh^V{REJqzbspSt_njX(VpIsOUG;d&VS_k!5`w!fPX z&Ggs!8MPxltLjNy_Fm@m-)2mjP}cH8^5vQHIyav?9R6y{qyNKc2k*MD|4N6qZ~eJ& z?l;2=(=Y$bH``{ff8l^S&%Y0|>KVW9IJnp@;CUhg0|Q%EYH&dP?C}E!4jkB^S$MiWWqN?USi*z9uliTiuyNe)KiIx2 e(cl9E!&zmi(w2R8+ZY%a7(8A5T-G@yGywpgfF}h2 delta 174 zcmeC>Jj7_+8Q|y6%O%Cdz`(%k>ERN@z`(!(!W?W23=Bv3_jNNcFt8cWU%p6u`TAATut%8ZX}SQ<)AR}Y6OLx8%A62CA@sb0 X;cc=s7bm-dG01FBS3j3^P6LK|bX~-)_IvTw~zUp)~}sq@1*v1l=sGMvHrB} z^k$KF9JdwsWNdl6WPbK`k*bB?%syZ46KbWvv>4;uoN!wSn&@?~lbEwgoI~?x5AQ6tvmM>W z?4WdJtw$RROP|9ckry3jCURIw{YXhU_h@GW!^$FM^8;=w41FKxNS}9!+P9`=*2gSH zj-z6o4$ZtQ5%;uTsaHAkroNGWA7Yvja(RiR#|KAe4#P9$A$>x%S0s{p#DdSLJ@eI# zFxi}9StzvUkV&gZ?4~I}=Vq8FmmIq+DQ79J7gTdm$V(?I=%nb=;M%KFS!=?A&-TtX z$@wo9RdO~eYiF>#X6gN{?Q*-nUis{>mRGXw1&1=9bmo)pTg!g=^v0d2_3bs=>UlV?0@zG1aW228!q&7;`1OMB zyUll|-rbI z{+EBTp3mfi;N&~?TY2~0k~<%`hk=2CEy>&6g`tumiec)T^Ivlq7#KJUJR*x382Ao? zFyoGi*>4#b7}!fZeO=ifa|ntGnCCd>6)`X{Bzd|xhFF|VPLMEq@aSmwfBm>UKjdTQ zbOtp`7JB~q|Np-|Gc)tyrQXveK;X;QuNzk_y}_!}B61)`LE_Z;0|yQq_)z!N-D)R8 znz5q8--w2zre|0yXBSCq{5dyEPlA<)hvCXf`KPs+>y;T87#KWV{an^LB{Ts5R)6>g delta 147 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 BY(@Y8 delta 210 zcmZqWddg_r8Q|y6%O%Cdz`(%k>ERN@z`(!(!W?W23=Bv3_jNNcFt8Yby977~7&+XmK+2SDL+MlE+Ez#8}aW2RBTOzko znbAbE$JMGcxPGsEAlYl6lk=dL?~eSPi5(G7Y@E!un>hE*oVhCQq0*s^vU{faC#i8W ztm-P}YjBTW*7*Gwt3u0xE&Vsow|30gwhg7ekl@6vX9yH0R2-~D#}-sNY{O7G@OKREZUjJ<)6 z*xtMOwbB1L%Xa#4bI?Gs7+eEOjMm5iI7^RDNGy=c6Z`gFJaEx}hYyYH?3cJJGA?{kZT?yYIxWphgA zpyA>vWqzMC7~>CGoDsVy(jVclrYX%$yG_Y()!mbUOI_yPdc!Tcgn9}H|N~^ zw$^dsItC5FYho(SVk~C$vATQL8Dh?G~-QAxp%LN2OapRQT!-~0XGxa8C(UOkTwiY&Z_ zDqCNLT*(f&x2SU+j5^Z2ML zqPua)sjFc*|6gSrgl4Z<8Q45!R`#VDZr|vfmCo6B%dRi|Ew}62jmwU?fqR#`@jtO! z?$&)v;n}kI9YM{OE#4eb$2)n_6pr;d*zhn3nDD2~o>Xjef;TNXC5J09Kv}Xti#JK( zh1A9ps~fQ=Yfqi+_$_4quVaqni+?PZ#us#p()0XRTs66`QN|>-yWmR6W?6P=nOSPr zOzwH!e|OfO`Ok5ttfLDN>3+rEgO5?G!azq=xN0`ghjuL4MFY?ZYv(MKMMG+kU)0 z^QgR7H2QI(-23UfE1s$ByyB;H<=d`=XHWN?$)8ZM^Y?v$3#WVToqh7TXWxXA6E9Z( z-m>=&!|qLw--S*1%e>JjZtD^yfX6UxHq$*x6}5TzM@m|DDPfzxo$%-R^E-iOlJi zpML7kAKBma{8v7n*O*n$_*?PT1doP=%NQ6K*pj^6T^K4Eq8O&WIsY|>fq{Xuz$3Dl zfr0NJ2s7@OnEjT4fq}im)7O>#F^8b2fMxe@=TZg+hIUUE#}JFt$q5n}2RM>B+CCW@ z7#J9Q@ce8DqHX4Un4!TuW5qM3pG=W!xGuyNeSCEEKMxNN&#zybCYUY0y=3`vcWH5hMcfCRB=4$8boBP7F7cIE pa9m#}^-#l#MvdH{M+cZ0gcfUU4(vO!kb!}L!PC{xWt~$(695v;LoxsW literal 223 zcmeAS@N?(olHy`uVBq!ia0y~yVBi2@4mJh`h9ms@x)~T4*pj^6T^Rm@;DWu&Co?cG za29w(7BevL9Ry*<9TT(PGB7Z(mw5WRvOi*H=e9OjH}S|<1_p*4PZ!4!iOaobH}W1b zU~svZ?lM=yRjcKOLfXtJ_Zod~H0QpN%@91rw5*6h({?X3Gp;|rdsnbmpw~|+shosa%dU#lP0eN1T)H9d$(-ySL!M&(W3MyH?LxfO Wq)jKxxy``9z~JfX=d#Wzp$P!TUr{~) diff --git a/src/main/resources/assets/ebwizardry/textures/particle/leaf_7.png b/src/main/resources/assets/ebwizardry/textures/particle/leaf_7.png index e0a4a7962ed6d8055cdbec20dda86f05ce4e7ed8..2a444fe13b95484dd8708f739d2017ac32ff80e9 100644 GIT binary patch literal 1269 zcmeAS@N?(olHy`uVBq!ia0y~yU=RRd4mJh`2Kmqb6B!toZ&rmwlmsP~D-;yvr)B1( zDwI?fq$;FVWTr7NRNQ(xJ-X<#8Bgo|on3m43>Qr$mjR-_j&&gwVR(lwu)cRYWu_F#l3SbaNhoR^Zk~am9hM{*M2^l*QYO` zb};sv`}Jw{O|kZD6}#X3Tz&V)rbjKJFT^TYrx+S9-u&kfm&%^onYOcc98>+BY598n zQ_*ej;^)p^+b$6*=zpU?coJ{8d75B~LZHw)#&99~ITzgSKU^jBE<3&No#&p#<(Klj zPwT}mHJBaE_io9>O_T3k&(kVdR5ttPX>s2^O}$%RZ~r^RnD5RvLZk%|SzF zubGEsW*wiu=zV&32BWu*LYSlRVo~Rb5?SS&LNo)Ho4s%43fgij`5I0mQM%vHhnZ=PAc>!w|!sK6D?;sZ>Vr+pWQe7SgAN|D%)muY9W<@0_j zWo>Yo5j~NIlOw0k<>bX@Gi?P+cpgliVA=hYhiS>FsXpw|g6tNJ$L~ly&iu9MQ{J(Q zOafiHj~dyeIX0{bz0$v((R5146{*nDSEde$Mj!G0CZWDqdf;eqa0H;&O$9 zY`l6u1e|y@i$r7+rDDIRwMis<%`j0cIrM_1e~MB1Nwe&-o6jdC`>{R^&bj!gOMl^! zNm}76Z~VI&nxC~|<1#nirB`w;Kbw`m@aQzFthL_TV|Tya*DhCWwL*7Q{K|`+cfMcA z2$VkZ=F4aKD+%BJi8UQ7T+}Stu~Ajvdou&qEcVU16Smr%;7yB8$>B;3P?jyw;!RS> zklt8kb)$B|?`g9Gf4krLA!uoQ;V+w|@de$Y@VxRBS559~7%}$7TA18j@;IT{nY+_j z>iv@G@1Nae_`lWR?zW2$W9BS)mL{Lye>v8xu-Kt|o3wnL;@pWB*Dq<#In$l_CFicC z@|BDC-iuh(RqqwM^`O^u^3m?k9T#VQJ9=`rl;n^O-TmRfdz*B}@0touqWOcFL05%GWP_S}Aj8r<~r?fR{;+ z%D$SFx7TYeoS&!g`S96V%f;t~{=JX8$v^ebd*wgox&K%tI3L+AzS(e)fq{W7$=lt9 zp^_nrVd|UnUvn537&r?&B8wRq_zr?Fvf<(rF4sWM@4q~nU3l1f(c{O9jv!-rw{eS5R2?-x&zdzjJ&%9g1nwgoI z`S99T)>jG{xqAvUTq f=qM{QKZDJ2jm2gEw}~?_Ffe$!`njxgN@xNAPxMck delta 213 zcmey$`GV27Gr-TCmrII^fq{Y7)59f*fq{VoggMw47#NQ5@9Sn@U|>t~c6VX;4}uH! zE}uMEf<>y*5`t6nn(`xr`pFJU5CbqHfg!Y2B+Qw|B{lgVbU-o-_?}(}XPJ6lZzgKHp zbw96uy_Z{HF~_4wvl!i*yy5r5H=a1)Hv5A1x)kSfr`O5-t0QXH&9!V7|9I}A>uz1$ z-Fv4W%Bi#b(d~BH?^Dd~g%?_HZTxgsJlB4D#f5cS7p=Yev*cu@#?!M^D;@_P&ik6O+z!mfz|YN9DYdj!FuC6mn7Z`gF}&|K9Hhza^(O@#=YeP-NjXRN49} zXt*DZt)ui7~Tb8Ox)E!Ux)(oy!R>>a*T?E~mR^kpP?NB);VV>TFHx zguE9|zT0~zI?wIS^c^3yi$eP!MGwk@p{Q-UUq4jRchC+ z-1ofy?yNuapW}_U{w;92Y-tkDsl1iH;{3I+`TWIsnJH6>E*=is_OMgD#X8;i>`m3% zQt{8z@=pHMF)#Lhw|l4RTK5Hq!@ie9{<>K7cJ=4ui{~!f{>SI^tMoOKKCVu)(5PGW zW9pn6LfbXX&WO62+4`LivEOp%JDc9bb(1&E{i$$LEWh&0p?8%mv-3DF``j=oJiEKQ z=zGhj(z)$Zw<~@V|McESVg1UKO*ikm81t{%E3mdDe9y9@Hm<)Ezbq?t%Usj@Mdz0D z#_EG|Y5RpQ>=Ai9b5TBvY4GIf_vTMKyXWrre67b?i+}ojG%pv~y}d$pp5#fPJG;et z{<$4Jl;k&0Ub%ku^qHN1ZS;$8rprJ7`scyAXE!s0FQtD|x1V#2n7-Dhy>LgpP zLkow~U<($;FrYz;w^?3pUw?mRmkG5^~a;Uj#U~Qj& zU;2lsOQ@)Wi%Ph`{qqbNv&9;UqL>Qq+c9eVGLoo#&&Z*u(NL_X*t~c6VX;4}uH! zE}uNvhDEOa5j#7#wc*WaUy>OZ7&<&%977~7x1QU}%VfyY_V7A~rmoX2UV)|Rj#Ek^ zpDajaJi_MLF2VY8Qr~=Dql2N#io7aT`|HU`{!>XyQ&OtCG0*%=t{P9{^^b>@p8IGX z-E;e0ULwbqm5du$0z$La{-}F(`&xTwxTj|6!YN65We>kdXtNrGx`s0D()brKTWb2> it1-QXUE21)nT}8O+OuZEDisC>1_n=8KbLh*2~7YrRaY7S diff --git a/src/main/resources/assets/ebwizardry/textures/particle/leaf_9.png b/src/main/resources/assets/ebwizardry/textures/particle/leaf_9.png index 29c3868df82e4a2dcbcd9235e337ca9ca7694a57..ff4824f14c9150f8df3ac18572c717b480b5c2dd 100644 GIT binary patch literal 1309 zcmeAS@N?(olHy`uVBq!ia0y~yU=RRd4mJh`2Kmqb6B!toe^!M=lmsP~D-;yvr)B1( zDwI?fq$;FVWTr7NRNT5cJ-XSttX znT2sHo>MPqzhz%v{)<~adyo2Z#a~bM9z3o(J;zOb*5A$dZ|Zv|5Rh375%f;_IRxQbX`{KpEj`A;YTZ}7j zK8@rusxOcAIdi2y5*Aw$| zW(M5JxRc8;&uc;Q(uP?Fa{6N`&dq*S)2f`dj>rEr$Fa$ey%%dg_P-^#;(Oq(Giq{C ziu%@BQkgtOkGb?29_}-_y7GO_mjLr;jB6Se_{~%nn{jqq`;95@x2jIwe89g~d2>E5 zUny&Y%Z%uWJlq@-=NG-X$&$@%T+;Jk^2D8@>E;3nq0uv~Zgf-}=qx+aYuLDaedzAl zgu1-&uPro?oq&|6{SZXu^XgHhHHG#a0>B zT`Mjg7fALoRG-b_K0|Fj)6yA1rz9t*wVacf`*7mtH1nHxmd(C@NNoF-r%j(U*JXTE zoe~jr@@m-18~?6ecQCycQvA3rC~IBjXWcC~f=UUSUlF^Sp7qD+ zU2)c)6}(A#zgn$LXE^U@eNZ^(MFLyWHN%c}M+Vkhc4Oh2mewbD)6^n!xVA1hX7wOM z?uf$$(`~nYCX}mx*EA3MuABEwxyafd+Yc`@(K`=Z_YYfbH|?;bnnE~oqUTGFiB!Ch`yH<`aBRK=w=*=~QD zXt%@rk-qMNWlyhWdwXx!IVvCa=1`{Vl;4+{bf&%#RIKxSs$Y_IEt(+$VU6u96nh@iwqASr_w4VU^Y*+t$Q`$>(mrcq zdgRyFvHTy?D=(IRzv5mgc>n9}Gq2B1HVgjq?)1jZac{+U*`(^-7k)3d)%L%Z<*!#9 zd;H$jEdSGf@8ziK2+xC7G@O*jDg@J*AEy>&6g`tumiec)T^Ivlq7#KJU zJR*x382Ao?FyoGi*>4#b7}!fZeO=ifa|ntGSf_qfiezA5SnBEG7-Dhy=%l^8hYSQ- z_d9!N3bvX%Oc86o5LCr{grRYo=N!I^8`yiT>&z0GLflJ(gd_ux1jQ9!ySe=P&zA{V zowC=Si!!`j&bpvTl;QkiYwH!OxD2%2Hr&x=D3E49kXjwe@V+)*Vd<6Ci#eYiKDM|n z^W4Q0m!ljhGhXSt2VXW}Xc1VF!}jct{@2TUr@i}I!Ss7~2ZuvXU@<@c_Pr(Fmq;A^ b@{8%^UJIq1m3t~c6VX;4}uH! zE}uNvf<>OZ7#ciX977~7_xA4OWik|TnSar1-2p`<#}={H04}E^ z0>LNC+dNjZ?3Z+BUzf00ann}GJsC@OK451|D2_C~+BrjM{paPgCv9O^(eLFm@%6i9 zZM#=bIdtLD`ODD^k1d!c6u+Bwt>F8gTe~DWM4fwpv$# diff --git a/src/main/resources/assets/ebwizardry/textures/particle/path.png b/src/main/resources/assets/ebwizardry/textures/particle/path.png index ab02959d3e63be575b4578308088016b0a6d462e..1e6c9d72fe89240a49dd1aecd26bf04954a39397 100644 GIT binary patch literal 1046 zcmeAS@N?(olHy`uVBq!ia0y~yU=RRd4mJh`2Kmqb6B!to1*<|LN`ey06$*;-(=u~X z6-p`#QWa7wGSe6sDsH`<7C7y;0*~weNZ08Jo*bP|6PTZuu*cTPw^XRj+mgQQt-F1a zP_wAwgIGzSTmA2CYYw|w9uv4~^K^drS^J-v{hX?OPIGxH zvKVBiF<)UxvwQATe8=Xv^$Eiw)e0j;3E#fyLh~g5FPYO=CBM>p%g>df&yFf*8}vHn z-Fe8WaAo>3tFLoa_ne;nRyKmsajucISj4u!VoBjur*&t}VXfPBbi>_CbJwh6n81;& zt>(Q|6Z6e7vsuR_=G(_fH*u$$Y$^EL-+tVt>$1ucNQy zgSQ6keHJBUx+JLEH#+Ouo~L0}MQgqLW2;|X+xtAuFRS~Nvgxh~zimyUuCQ&i`1__; z>P*^q0h4XQvS%E6lpA;OGI?akoiST3Q8_{S%(gQXno}HmOAf3w>1a&IIdbb|%6GSS z+wU|T(=U7+KardH?tTSvwq368l((y2$(pI&<>T;JS7uh;rHvcE9%+@8e{+0$)P@Zg zW!kT#zy7e5@2>rO@=z`($kp z%*@Se*60{BvmD4UV+;Af?e#x3At50lCFRfQ0|yQqIO3p~@aO-3`!jBG8oInomtMGH z*L=x;;TQ2$I~rI|o;R31ci|S%S+|k{s`RJqb2b&g41k9cO4sNznO;>RE_v5@>m!GCn#MB-qy63fq{X+)78&qol`;+01-UavH$=8 delta 200 zcmbQnahuV&Gr-TCmrII^fq{Y7)59f*fq{VoggMw47#NQ5@9Sn@U|>t~c6VXe#n8>5 z|Fkvf)8qhVx%!8!aw3N6f|E-07#J8bJY5_^Brdm}-^hC?fT!gl|EDjjd>CdgN#&fj z^emT2h<_93ic2!A(-xf8pPMo_cW!Qv;>jsX)Mt9zo@8m)N}E&o>1nI_J>Fnb{fMlD zqrClXakIJC)!i}dE6cc{Rs8q!^-tUGD!<+PlTq@fgWckkqFD^w3=9mOu6{1-oD!M< Dgoa5e diff --git a/src/main/resources/assets/ebwizardry/textures/particle/snow_0.png b/src/main/resources/assets/ebwizardry/textures/particle/snow_0.png index 53ed7b630ce95cdff80e074c99115bc77c646b83..9ed0fc9295d595d237c45b6b37762b6bd5d7a4b4 100644 GIT binary patch literal 991 zcmeAS@N?(olHy`uVBq!ia0y~yU=RRd4mJh`2Kmqb6B!to4XZ*TN`ey06$*;-(=u~X z6-p`#QWa7wGSe6sDsH`obD)3ym;@DUFI{A0zF;lL_h-{q_{Aov0-%M_{Xa3h$s>@%mwg2(?!MS&O@diGO zwHCI^_Wk94Q&j8tc$@t9vgM`6H_E<{sbuFVPCJ(H`zD{rkCf$q-+ZcDe`NO4H~w$6 zTb9dy`Dm$iB!ekA;kfOAzUo<iS*+6Vc|(lK_}n3&Yix=t-wa% zsb_D?vL77Bc15`v>uhX_U_Q&d*6P%efa-uHZmn!zuZFMkFf2+xarVsA!Bubm)% zp2CPd(L40@#4?R*A#NC z8B`A4X-d&(Xz&+l5voiLQ+ko{Ab5gh`w4cA2^{7{%sEaT4aqjok6C-2p5E%8CZo%s zsF*nU#vO+S(ZvhuOr)|_cuaWVqSD#rIc<_tmuHaItY?y;CK(|Ym#kVA+0ELmHqGa( zPV~t+%zXwYHCLaWR;kbM}`# z^2hyS?`)8-`yTebPPac>>YedV8}2V*a@X(Gs?E<{kpHak?OpHBwH*JwZ|*wZ@^j}6 z{p{yz{tSYWT@K^xN&@C-%4ezy18; z|Hgmbjcos{4*uWt&VRDnmIG2dGy51A7}%1$-CY;_2(k{+L5hRFFC3&FVG=1_pgk7sn8b)5$3g%>V!Y|KEQmJtZY2 zx2@MwJdmdKI;Vst0JZMM A5C8xG delta 120 zcmcc5-ot3z8Q|y6%O%Cdz`(%k>ERN@z`(!)!W?W23=Atj&Z}c!U|>t~c6VX;4}uH! zE}uNPfLYG^5j&eWr^a7i)5Q!743eHMjv*Y^lM@mW5`O&u|G%D1qM>jDR}w43(OLW- V)$V#-XJBAp@O1TaS?83{1OS1TB(MMg diff --git a/src/main/resources/assets/ebwizardry/textures/particle/snow_1.png b/src/main/resources/assets/ebwizardry/textures/particle/snow_1.png index 6d792d6d11ca3f2695fac0ac7f7baa3356611d33..6fd9ea9c006c079b20c46fd9835803c00b8bd684 100644 GIT binary patch literal 990 zcmeAS@N?(olHy`uVBq!ia0y~yU=RRd4mJh`2Kmqb6B!to^{PT5N`ey06$*;-(=u~X z6-p`#QWa7wGSe6sDsH`<9$0iofv4@hrE7nK3d;Iuv_U^ui!jWbFMY*j?Lq@DIGDK^LzvrpZvITXZW%8TY^`758UN)?_5k`oDG-2 zWr-)pB;y#IYM+Lr*QFQdzdE*`QCne!@!2+3vHh|_voG!4mQp14V=bxLC^PgY%x@m|~(l(jIkTh}yu=hVKa*O#2H%T>R+R;;hS)%EK{Dcgy^=Sb;hHAl>- zd+EpfY)YPx$u?oxGY&n>jTKTX0T*m$R4x{%m>_+oCT)+%sReFU4??7lI2f2Dy)D_a zd-CrovoC)Lzw<-6C~v{;ra96t#CCqa6Bn>LwQlhV7L$92CI;)vN=wh-lK!_rci+3E zwH2>R3fIOfUf#9aZJBs^FVF1VZp$|8c02ZgwX(D4zlM9g!sjcy&p-ZCDe=9$(Ei=s z@6QU~-&Os*bH%3g_xsHI>pA~Vf4MU|MQ-xnwNXXaPsGIC{PcJ3?O5f{tNQlc_%Hrz zdn=25YMXla~K#HI14-?iy0XB4ude` z@%$Aj3=9nHC7!;n?2kDFMFp8d-mGq8U|=xxba4!^IGz0G|NsB>Y$^v%oH)^OMqTCn z5eG$y3TBCmtQERN@z`(!)!W?W23=Atj&Z}c!U|>t~c6VX;4}uH! zE}uL(ms!sG5j&eWr+ERZMHmAEgQTa6V+hCfgQxBP=B~&lRRN*X2W#dSTkkkMU)*Vqn)zFk(s%1; z7GxzxPHT~K47y(T_wL>J9|2t#Sp&Og^)+&6`C}elA*G`ux zfBQu8x=$%H5lrIs!sTD!KccpdbNr_I{y z<@0R8WDC(VrF|`l5lM_2xn^0r6;A00eCyY!mHO(+GM$hKNe_-`m>Y|K3r^Rle`K_< z#c;)DCjZg}hxawiYM<2~lX1+~I8M>|iPwgdCgWK$@@>`2{+zUs`Dzz6J!A9YuoKvjs*)V4Q}^1J#fr3xGj_%%+V}$vLQHAfcfBsj-{6m zzH@u$o#%JR`_2#JqPzvw?3U&ibc^;ES39kJ_Othq`htzz?!M;t3pX5G5Se!RvGvQH zZ+`EewIgr7UA5<~;>tUh3f`Z5K6CN(Pdhxn&#TGntDAA$cUS(=-+cczXYYDeDfHiW zS8?T>BmaGN6<7Y@_<#M<+|!SD*M4!Dy{kN@|GdoKjNN}4lb<}(%qYnA8$>5 zQt$ph(_MDI(+B(2zu9vdR^Q9h-MyQEfq^Z_+uensk|By=>YMXla~K#HI14-?iy0XB z4ude`@%$Aj3=9nHC7!;n?2kDFMFm+-b=avgFfbT-x;TbdoK8-0VE+IA|Ns6o=_x5G zDF>KmNNBJy=QAkpn$MZ#z&-h)0Ndi12_gmt1`G_kM|i~M{J-qVz`(%Z>FVdQ&MBb@ E03qtyo&W#< delta 125 zcmaFNK9SM5Gr-TCmrII^fq{Y7)59f*fq{VqggMw47#LQ5oL9%dz`&N|?e4edQ|9?H3MuN*j10y4&1*;D* aFsL$e|60ktehUKw1B0ilpUXO@geCw!h$Zd- diff --git a/src/main/resources/assets/ebwizardry/textures/particle/snow_3.png b/src/main/resources/assets/ebwizardry/textures/particle/snow_3.png index 3f6a9c9103abc094a04fe70802c66ac51a0f2892..dd08a3cb42715f8f780a60a1c42db7313ec5423a 100644 GIT binary patch literal 961 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 delta 288 zcmey!y_w0lGr-TCmrII^fq{Y7)59f*fq{VoggMw47#NQ5@9Sn@U|>t~c6VX;4}uH! zE}uO4G>csQBX)Lf3u~b~zkLi03ROT zh-iIcJ$)(urT-WCXX09FyVT5*+h;6XCL6vh`Ti`mFDtmk`M!H;wyt|UV_9d^YRl(O z-u>)cf4a4Ob~KAZOTu9TkL~1&*VP6Mf1}99X=X) zCa+`~mrGqp)Lfuu@Hv+IZ0Y5g^%IhwdVNT7GMFX9e>O(4{?fa~D*2_}DPQMlzjzeb zFv0Lduk{{=mS3k<&i^_0tj(3)S_W-}7wNM^rO%YzcFvi%FUwmky>b5bb2s+h(Yz+g zpn2$)T#|>w0X8B3#+;NsmlKPd{M(Aej!Sb)_#ShzWP>1Q!(y9j$L4rko^Ja-%_fTB zkoN(_i-ipgr!D(`b@~N5-|Q|wRxMxi<<;c#j!oQlEdqxt+@5M&bd`7R2~6&abe&tp zD-~**={JX^-(bE|ms+NmX1dNSL967lHurPV`I~m0%}?x}otJr<^=WX-N7X42Tb4}H z4qs{U&-6;hs%s&|i`#;-*8LQV%DEMET6XKTrMur%zu1`VZ+m~G?yB=wUO2p~&f2nq zH!1JeQT;4~;}zVFj|(5M8w(`6E6A}kikR@Hg`KpNd%|WsTcZ7t@rsG^1zNmG3NNHK zzAs7t?)ok|@7V7DM|$HY8Z+NjKQXg0Z=!Ya?ge3=YZjkiG4XqNV&&96c4?VeY1eG- zd0wx*@24lL-(q$B;K=Jnq8Sv)zkI* z;NDr$mjfp+{FAnK+GkIbRc|y-wbcH}4s5>V?lRL`XVGzymd9zgzRAe2-n?^hWs7i} zm0sA7o5vrx`~PTA$a!nrq!V}Zn}zQ7?bC|$`GSuvelvIJ&myB#W%-MneIVNo(D4XFQioc>rpE{b@04NWbvn)Uw9W6&+O+iyMI1Y-E@7` z=WNaEQ~xq+e!rZ*{?u!aApia~$&s_XS?ph&4LlS1Q2xY0pU;Ap(=C6=vkU!UJ5+z> zS^VCs7hT_MdLzofz`&N|?e4-*$q>ab_09ROISdR8oCO|{#S9GG!XV7ZFl&wk0|Ntl ziKnkC`(qA4Q9;(d{d}7l7#LQ0x;TbdoIW~vBj;fQ5tsY?jXo0&F=jJ}Mjeh-+pv7I zxQDv##6$NS1b8ByR*L*-wUVysf4)zbR;zld#~x3;k=9IFs$E|i)2_*i7-y!2AO z!wSb$PV8+LSjDp`IqgEJ?Csb$`HK6W>|Oq1@2=*eiN7W1{1ZQSo!>yh(Pi^)ZD9rm O1_n=8KbLh*2~7aZtUrkW delta 220 zcmaFD`JU0ZGr-TCmrII^fq{Y7)59f*fq{VoggMw47#NQ5@9Sn@U|>t~c6VX;4}uH! zE}uO47qeXbBX)Lf3u~b~zkLi03^krEjv*44Tl+V1G8>9G&tHF%MN?)2d%?rNO;6@4 z%w2Br;~ZOC!U-WSVfpKKwN)EcekgMqPgXhCa{c?^+zW?x= ztwPBn4qlyxY%^xwiA}!~o3?E6?ybkTcJ7YKUZWe$!PsD#F8^ZhW;30+tHr1PVVK1e WE|XpJuZ)3#fx*+&&t;ucLK6Ub-%&sS diff --git a/src/main/resources/assets/ebwizardry/textures/particle/sparkle_10.png b/src/main/resources/assets/ebwizardry/textures/particle/sparkle_10.png index 74f32788da2b72f23b01d0955fe02483a98940b2..0aa5da0231bfbf118d76b86f5d71d4bdeed233c7 100644 GIT binary patch literal 904 zcmeAS@N?(olHy`uVBq!ia0y~yU=RRd4mJh`2Kmqb6B!to-dBZ0lmsP~D-;yvr)B1( zDwI?fq$;FVWTr7NRNQ(yJ+Mexk*DpxrEC9&NdiL06BB2?6LaC?+fOl3w;rvze!A@KotuY$vL05+ zc=~Bp-_!Vn>$e%YPw%^byZNf<@$d!NPecQbo#{FE>9eTEkEG>aHWW{B}+g_sHJv9bT(w?0%%H{iMe4SIZ&uK1i zMHGYVG_EWrVwWX?Crmzdh5>>uGfzyHbfj# zFwd%BQ?y%?JFqOKkJrHF>KjgHU4L z(IgLt1aB3uPP1e)r57(A1aByscEXxtf|fa#Y>tc21B?EhhQ~5~ZTfVyXEm!rh!9_A zKQl{&q1LD4i?!{d76r*ny+T0RC$Qu#*D0!XYOng74Kg+@6H|D>XUO= z!)H93qMLHwa(a^|x085}-Up4;=ds^*yq;HfyY_tbN{{(ctFMKutvb8aB=1tepXe;H zS=;ZNa%2yB+0icda>L>NnkjuTuP-HEpSP>@{m$u=Z!N0w@0B}I>(?u`)ltXKes^H= z%{Nj_$4VD9OLi2h2yAy`;5^%W^O=Y;e^K+zX_D3SDEo|5~HdORiFcdGOJS8O$^4@_Z_T3(Q`%k%hAw)Vr^)sp)?>+iJf=l#I- zh3gAH+pFKZFJJzQL70(Y)*J~21_t&LPhVH|#~gy9 zf?T==!b%Jb3{svhjv*GOlM^IZn4DfU3<&xrJU|`_&^l%AcU|`??VGcG128JX2`??tz7}%1$-CY>|gW!U_ z%O_9PW0o_0#Lmub$#}MMnJ)tagRrNIV~E7%4W739Te~8eggQ>iym>+#Gewt4$+Ygq}8|0CJOlgrffch^p9 z>WLTr{*0kQXj*w|&0Mzf>+dX3Oin$L`&(+x5m~%BL-SrPilp5+AW?zKwZy zk!fF7;SAk{t}+`PzHrTwj#Bi~3D~{)@u`{C+i!~Naa{BiKB24R`euvkiTO)>H1bT| z2{kMideNb~AT4p4ve>-e%XY>;?3k;ayv$(E$0rq8Urzm)TxRjAc8T8R&i1elZ#O2T z9>=^GLvDv1`o5*Ftfg(A^j0!tI|eL2BglRx?RIR=sqc3-P2POe#4j*g)epME055sx=zRlQmHy!qCmUp~G5PxdW4)_qIi z*|R+b%h`%K%*Aa^b@HVtsP#G8@GyB~NS^UYd7d&s`izf|jfmEQV^$ABI8Fco`S zvtjq--;<79Q0x>@UCc zdSCMN$t$1Ov}-)tte$*z{&dxUlb>h%=eKWCTDaXg(pEP5_~!mHPPKf$n=dP_zT10m z@nX?9p63m-r%ir&dfqcBl?x}&iusG3EIrm}@NHgg9nXwol6t4Uh&-7sX($`}WM_xq zmU+4>w)Bft1?9}up4y%8Zq>ujFPFQCcdl!?vOwLt)4%w|qFWZPT^EW=mU+#XIU#rV zj$IM|t^^l9cYm8z$@p>7fiE*FW-XRKc6puqZx^9PnOc?33zyv|aftnj6pD3SY<~Je zVC##sMkOJNRhxNaLp%0Gw*6a__W$kcN9GbQjw{YF{{1#!TIZQ|r(f~buYSyC|F3wt zK34RItkS1bybKHsY)RhkE)10nQ4CYxod24`z`(#+;1OBOz`!jG!i)^F=14FwFtC?+ z`ns||<`5JWWK(I2=VV}DnCR)^7-Dhy?qo$iW<>#4dEcuQEK>c?IAW6gkE>cRNuB5X z5Rv6|$ZYMRlWM=O?D+qTU&GErlkq~7G(%K2tANu3X@0Z7;toSThWC4!UhL&(5Da9n ze9l-P)BbDy!8!Dsc%zmKd`)Qc5H*1zu4rD`_8T0U)x-nE@-Lx m_mx9-?e6k|pYc29i95TvE}olz#)5%?fx*+&&t;ucLK6UYrZk%X delta 221 zcmX@f`GL{6Gr-TCmrII^fq{Y7)59f*fq{VoggMw47#NQ5@9Sn@U|>t~c6VX;4}uH! zE}uO42eVxLBX)Lf3u~b~zkLi047Hvvjv*44Tl*IZIvesh&$s9K&hl`ca&=Ybnu!7Z z339KRzI~7S!dj|s>-i(&oM+m!Ri`8#Z`;XmXK&T}8IpU;@9h2I>&BA3cGaq=>`)hj z=QZXjX>*HDonbIAK4&>~CTqdURa>s5yyrb|Z}zoWD^}GQzEg-ZS5x|DcH(lk`(B1; Y*}kt&rkwuEz`(%Z>FVdQ&MBb@0I}0qlmGw# diff --git a/src/main/resources/assets/ebwizardry/textures/particle/sparkle_3.png b/src/main/resources/assets/ebwizardry/textures/particle/sparkle_3.png index dcad491026950949fcfa231909b87b177548aa79..ae54b361085eed8234f316170d6a6c6f31f18cc5 100644 GIT binary patch literal 1154 zcmeAS@N?(olHy`uVBq!ia0y~yU=RRd4mJh`2Kmqb6B!totE)mHN`ey06$*;-(=u~X z6-p`#QWa7wGSe6sDsH`<9zE%`22b1l$fG)po!v)@45qKz+`ReEPsJlIZ@i42w0tF} zXtQYKpBKVAZg1INzw0Nv{I;B4{zZmIGd_MiseVpk#oih{+erKMuaCvCmzQn+f55=< z%ex}!+n>&FXur+;XnO7L?b4dsed`>qpU_?)ZEVbT+CN<3xVZJ&>dDuNZ`Mbg`(-s# zvF!Qdz2Yj1*(7A8^ZMo-HSLR(5!vy?sOsp{IXvoHEa#O~&avLi&wui^d;6W6d)~aW z6Fqk9sQ|xaR2f%)vAJ={g0i_k-?ayQ*Yw-@dT-YIx0`moQ8p4i8+D~rvzX;L@5++T z8#~l~u=S*FYgrbN&jJARtC?mUC7iqPg?oznV1{Cvz7jKo^E;M zzW5xI&D93J-Aq}0Y4^5Xm}7qSCzod0Iu?I5mc=JOUO1!t*f^K}%5RNWrPbBz7IeEa zIvrCmU-yAY;Fb3B#AoGZpBLu6Vc)>Va@c2cQsd3M=>pLUqH}kiym?SRBLB_OJD#t& z8blJ`F&I8^IN(;)s1%tfrt~E6pt`fA^?7NI0FIcGB^wI$nEF1=kUr1h8_!o`_&9^H z_XG_kEzeC>U!_b| zt;o7G$HG!3QSqpXTBes~y3Z^@tH&>S`sbM6yYp=OhNHe_cP~xjKDGRZke5!-mL-$4 z!^1cJ&0dqV>RL$g;$R0?TdQ7?zddkn@d}l&nwUBer0QFHR1OxDc!8* z8T0Fk7PDIjW6gHrRVXlxN37>BacaHcfpe@yZV}W`FxGD<=!tj zUVGn9PgcLh@|dPw)#7WRmbNSAAN#Y${Lii#E06ARJoD!4afuV(&Cg#cx#INm)8wBu zzMZ%9Rc20Ksw4h+$`p1MpYp0X+Q*uMZ-2V@sNZhc5#dvl7qF}N&vHxM?<&k>yIM2b zI;h&<{>e{o#VnV<&3Wm$@1pVaZ+y0AXFvb)C*IxuQpt<6(cA2*KHt(Tv2HnYI;gMx zzi^OW`Zxc0k@$V;XSkK#ojSG0@r-%?#Q1OjUpmOve|}(}@>zd(;Q1;3d(_k!7#P@+ zyxmB=1wJ~3$iX04q5QOV{? zHM>KowS$)@gG17xhGxt&zrMLr<}Z5U7svD`9^K>ruhdl zWg@0BeChCv Qfq{X+)78&qol`;+02L<@mjD0& delta 196 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 bj*4^gSWl};m$}Zsz`)??>gTe~DWM4fZ^e*a delta 224 zcmX@l^_kJQGr-TCmrII^fq{Y7)59f*fq{VoggMw47#NQ5@9Sn@U|>t~c6VX;4}uH! zE}uL(l0~lm5j#7#CBv?|X}1{|7#ciX977~7FFj+(b=W|_<>LN*%^a^no}SZe_M4D* ze&bw61;-7nf$1KZX04n{OrBh=XFGSoa`!5x1*@LS`TH@7VFrT}hfs1!`FDxM?E)>e z_Sf!Ts=xF4%-VCu4}adfaMcV+hO}d;>tb$uW%p)AhaHo+SFJ2AIPu=@9>YCToV+^! b*D|cG@Lnm!!~ULufq}u()z4*}Q$iB}&;nTN diff --git a/src/main/resources/assets/ebwizardry/textures/particle/sparkle_6.png b/src/main/resources/assets/ebwizardry/textures/particle/sparkle_6.png index 985abad9b3f3b1f30b61af0c918e354d43ca32eb..357138bacd7f652175cc4cc9ed96ce420c126421 100644 GIT binary patch literal 1183 zcmeAS@N?(olHy`uVBq!ia0y~yU=RRd4mJh`2Kmqb6B!to7gmKtlmsP~D-;yvr)B1( zDwI?fq$;FVWTr7NRNQ(yJ$lk>4W739kw6#%I&(>%UoRYx~D^=FJRulGHZt5fu+tdU)7B`~K3>m~Z^cH}6X_ zJ}Oyr_dA>6szaJ@c5t3-%avHop*2B8viQifBW?o6w($SYetRb~?uhl;?y~5(y2@#X zauZowy4_Cu|BBkZ@9pH;Ogg{^DxP*Yia@}tom?dR5yeXjh@h+U*RFKVHl9B+pa z+s=)yA`JoYvtC^(=lg!a{5Eq0qvKp7_c;moz9}DFSMpwW<{Z|-U6tEq-};4xGkLUZ z6+Jqk;eeRO6sFu`IW89roBZ9L>dY$_PzYW3#Og)|%YjatYsU=TjHgZIH_y{$SSVC5 z@kk*fWVn3J2MF6(c0RugFQdccp2jtM|0UF7l>r8HUG1 ziXW-$XwBq08Plb?bk4>Mw^u!jjg^Y-RZhSAepmb5Z#$OTif{4%=<2NzmgK1#zAmWn z=kI8%Vx@qWkF%O~IY zy$jCs`@4O|$M+|8Hoj9ov9mF6;_nl0S+~x5F6^qdpiq?0*Zk#tHr)2wKM&A{ZAzR z>RsZO-1E>W;G~(a&6T2kl_&4^=${L_ocQRz^YnsU&zXyMwC?IR|1Pxn*SYkqnWkZO z)oWM!6sI5jFZlg;+~0eD>KFY_Qaae}Q}mxfW7;m`j6E}#FfcH%C3(BMFjO)`F-(1P z{%Z~c0|RG)M`SSr1Gg{;GcwGYBf-GHz+U3%>&pI^Lr_$Z*7hl++Fe^o%y0K(UqW&SP_iG(yD!ySfathn+X#3Oc(5TmzuA5 ucI0)Pa6?WQ!@d46hFRHr&+_{n5a*Indf^pba*Kh1fx*+&&t;ucLK6Vy9ViU| delta 162 zcmbQwxsB1dGr-TCmrII^fq{Y7)59f*fq{VoggMw47#NQ5@9Sn@U|>t~c6VX;4}uH! zE}uO40kd4{BX)LfONL!_({3{`FgSaEiPy4f9{m9`HM~@wJuw`Jd{A*ZuGRRV!fq{X+)78&q Iol`;+04>Nmw*UYD diff --git a/src/main/resources/assets/ebwizardry/textures/particle/sparkle_7.png b/src/main/resources/assets/ebwizardry/textures/particle/sparkle_7.png index 041dccff698923a24832b1cb31102bcee0665f01..f126d0458f9681d3509612f46cdbfb158cff28a6 100644 GIT binary patch literal 1146 zcmeAS@N?(olHy`uVBq!ia0y~yU=RRd4mJh`2Kmqb6B!to8>&JgN`ey06$*;-(=u~X z6-p`#QWa7wGSe6sDsH`<9y{%^22bn#NLPJE&p#bc8ybt#*f;;#m+)xH+*Pk$s_0){ zez@~sm(G#DEbENk-ml;Fvyp#kO7G`DXRd>f9#8U~V;Hcz{@c7Yv#*yX=QmHjD`Riq z(-imZ_JwKnZFld>cjVnXeKYUTwns0xO1k$jotiPzFrsc36X*M~sPAfPpKtoTVb0g7 z7S1x~u2+jIx_vd^lFoBVD&$QTb7Y&OvN$}(^HG7*?8lk@^Rv_Y9=h&HF1dK_S?cu7 zBFEaE3g}7cTK_!1bv9S*io0oce<%DlJlb5gH~j71x2sRVuOl2_}|tvwoiW;bYD8)y`}BiB}6nKRpU; z@JOB@9bUo6@pb9S`M=Jk*P6uXvJ=bn6`^WpO~$=%bfkM3e} zP&)H=A`d6W4TndX6MD}~Wb>+Um6eg+N1sPdOA15?BUp_PI zxb@4I_x4CV_%F61eebDj!GFx=RQlUJckq8w`2OtW$}dH$q>S0lwswbW|IB(=dnF|5 z%IvGXechAKidY}dTH5(8?QYda^Uv$6GWYgN7jNr(Tes~=+13}c^qmiuZJu;<@|tar z*VaVu-L{oyV%Xj3N^@__Sg%sK#fIzW#iY8)pQdk3x;Oc}+>6c{x$aXob6o!~U9roq z#c2KWP0N$w&ZoXVJKO9($CpdX>KD6d^L~z!`+o0jRp*1w02-)1>*XD)+;-t}JLEtRv2 zHJ7S-HWXiN-*o74mwmej7>kfFfodE?l($?w0h*B_A8U!%3sWa4Qr1_lNO MPgg&ebxsLQ0O*h=%m4rY delta 171 zcmeyxv7gbnGr-TCmrII^fq{Y7)59f*fq{VoggMw47#NQ5@9Sn@U|>t~c6VX;4}uH! zE}uMkKeJrkBX)LfONL!_({3{`F!*@7IEF}EUfa8yw;_OsIhXBJ(V9bSGc__b5*gDh zq%<7XJ3i7n{mK28Q`)C*%c2>&I2fb0g?`>>KRcAwA=EHRXo0rLz71>NP0Rgzn$sj& XYw~r!Q~wwk7#KWV{an^LB{Ts5Xihs~ diff --git a/src/main/resources/assets/ebwizardry/textures/particle/sparkle_8.png b/src/main/resources/assets/ebwizardry/textures/particle/sparkle_8.png index 4da926fee2b7a92ee7c16d2ac6b767a545be1197..e81ac0dbf9f26405678aa6b508b957b2f51dd81d 100644 GIT binary patch literal 1491 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 d`SB0_ZWJG%e? delta 161 zcmdnTxs}nlGr-TCmrII^fq{Y7)59f*fq{VoggMw47#NQ5@9Sn@U|>t~c6VX;4}uH! zE}uM^okcF?5j#7#CBv?|X}1{|7@Ry^977~7CnqSdq}lB~z2W24;5nas`X&Aw+Wh;~ znfUm#JCC@2+@Jo14X-bYxB2_eH`Lfu^*`RKKX`4!VUh zFfecyctjR6Fz_7&Va6R3v)?i>FtC?+`ns||W@cpIF*_j6vW9_yWwob^V@SoVw{vgj zy;0zCeVp;{|Mc&bmaA?B>fN}}qLS@7^_CiAa*o1{!#dmyDB#Va|Mr`wS9Y0le63w? zc51@rJA19Zz1noFXpLi@wQxxDl-FxdPde3EB7~%CkBqJ3xzb6;Ua#_ticb)nwwA&F zKvC7|sJW~!4&BpVnQXh#hn;DKgNLf^>T6bOA}(JP*lBt9-S@B4YMST&zsX>{uIqJn z06Qbp!~^ELHh*}1STsUT;^JN1(%Rj#*YTVFUn|j=s_h`GeP~+Cg&E5?-P|})Z-M8j zEpgld4`y}g9GZ6U;Khz<>;L>%wMyhcFT-uub(>QaeHZ?@su@vQci=V&P@HQTa_S+6B+%>QxYPQLi&r`gpxvJ1XS zZq#9Y@$OW#eqICHZpWWG2A{o3H#ggPMs4ksdVkC8zsT9+k*6+tu%3Q7+bV){+pnJ& zFNJd^x0X%2Jv+I9m0jbu;lVSGSEud!-gkG?wFe#VIA_mxuDtBq{OZNli`>%wF1xc8 zuM|D13CWywlu5)SS5-qXsk2M##+-dR?&rVPlso#@Ie1&zUq8VQ@=k^J;&7+Sxr<%n zoYpM<7&==$(XOvepIu+dds2{*&S}-zmaM^>xKpnzo;%&@^rdI_Y;}J!uKhm8_VM2Z zZpABVbq(xw>zOBR+mgHL&pS)&8{HnNs~EiHb|&$zlR{ra*ZvB{g8XMJMc#5C7S z>Sh0_4Z`#7&+z|H`Q9L^yJgMis+S5gu107V^ap2GJ^sl!EtAoC@pitMZBN+G+`9aP z-R1an51W0eUTYSdbo;9s5D_Aav z2i4k&RsPuT|8POjL$1>-sebz}6!Pwn+-+y|;qJB1%xjVba_2hbPnS(l2{RDqTZN#~1(SnsH8hNaK z*qS;nGUa*u)4{d-bY;~grLXHf7uOtn*Z20vHdd==8GnL~@b207W~G6$!KI-8X_fPZ z&wkU3saj^?Kj#pWSkSgZ(m&TMuL-?ozL|;d^$D*DJDlqdXcw5z`OMsOxo^3+Nrc?> zlGuqVrLGf<=g0?`DuqV|PrGyY8k=$7F&Qq-W}oo#f{D}qG~Bx^yQkfx!mZNOro5^H z{^# z#l>zqlS$+L>2qvu&z3JR+r8p~Xm#qFOWU^dsGeBRQg!MRvr$!n$KidaKi8Q>JNB*i;K3gv-3J^upxK$;fD^>QfDml z3=|0ob)EP8#jd_Z8c!j>U;nD#5`i{K_aY$GRcu*x8I6| zhD!3a>rD3+xxG!$>BHZ@zO$C?*|Wz$uK(rNsyXM=A6Yyrv6}eYa{vDQ8MBU^Jsg=e~PL*8u`qQspr%J4ruFGDe;pF8hz!EX-=+&#DTn)=IdDxgw zZF1po3=Q3}?)3BL>fgVA_t5NoEOFR?LBJ{Dw%J@i_NULEvo{#sQeG5-Y(r#lLm)4<;O_+wbl< zsb$wXL8l4JGz(>vmp=LVbLP#Qwso&FW*s|xn3-Yr*|x(E9YRA_tm>+$ub;jwQ|P$i z?YClw4PJcz-I91BZS%s*FAZe)DyyrL?dAuEie}Dw^xG~q@?Z6%`}gH{t$Vyn?`+y+ zoAZ(Dub+8d{K&$Mqw)2wAN%}6Lw(eQyB7V}e)VUK+hvnQ8jCK!+z_?)L#=#hsD7E* zY~EF?9$E0EMsB+Q{-X`Qrs|`YFFlVH_N-cUrL;Fu!lKVPP(*xd_tB=f_3eu^JTw_C z=AZ9zQ=U?`+jsFrhwG&wp{nPLA6ck*3NhIUeOBYN&}EZ}L60isrloF-TmO?^ ZxnSDr#qw^q85kHCJYD@<);T3K0RV98jdcJ3 literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/ebwizardry/textures/particle/vine_leaf_0.png b/src/main/resources/assets/ebwizardry/textures/particle/vine_leaf_0.png new file mode 100644 index 0000000000000000000000000000000000000000..2eb6fd3b1c4c2d0de9c9326cc71c7b8cd751d5bb GIT binary patch literal 1272 zcmeAS@N?(olHy`uVBq!ia0y~yU=RRd4mJh`2Kmqb6B!topH_uLlmsP~D-;yvr)B1( zDwI?fq$;FVWTr7NRNT5cJ+|z#22b1j$fG)piY!T%Gv*hkv2XrUdGLnkoGo)r?w@Tr zmcZIlA>SB#`QOjov-f`}oYwqN$aIN-j-B1lCq`0P-_OTQ{`z@W-kXaR8)koIXBS@l z?629DtM-TWwliMT|NSk)e4~#2E*aT*)1Bpvtxdx0WBYErEsOfDwzlx*ecklh+uQD3 z`@8)0-hP3_Tz@tiuQS|u)U+p3La^XbPgJ35-(ulYIp?+aUOPAEYqT?Vo<7$f zBq1HvUT`tvre|EXx#+F{>$JKb3$GP-slTmSf2;a-`1IO_po42%WxZ$WmfTTLJ)g*^ z`bazDc%)EQQYY&Xt&BX4qXA0nTdgZsO<5T{yL4fbz}{@WBJ1Z}k28Z$%#WEF@JHiH zEX%wshvS8erfoOpZoDwZ{OnII&9rqb^ZFk2s2%qQtbxC_S{=T*#Vmh-& z%TCsV3f;Ch9dtxaxII@AED8B=vg6Lia%qkU9jjBUZWyp12sD3oY=+0?^}^d{7j9u_ zDL9~ZabqLH>1xM+F6&P$)X}-u;W0r&%d_aggXR{2B#HEpKAGAn5=lK$!Dmjr3N^_H zxw^!1=MjrTDy<^Em!<@rn_+Ue^w^6YIm`UK$7l05wd&^WTB<9)#Q&qKm&V2nPu1}7 zok_p12P|G06@0c=Drn_THQg;Ywk(}yU9`6Ndu-K);u%x(>>mz=9#{Hvz=sCOysec%4R6=rFTw= z)y=ynYEPf-sPCTryK9c*i+?PZ#us#p&fkd(SY2rsSivNq}UKf>@>a9&O?O{zT@<))@`Qc2ZS!Sw?mwMv8T9O9iRFhUwo!kqgZD)RFW!@V`sf zV-7)4LGCDXh3{yN^978NlADwK=<>bi2rmnO{IAT?={oQx1-vquXg;h<|-P?0B zXwO0IBf>|Vg5Ed_TsgYlOW~-2XFzCh=;OmZKa3t7ouJh6K}KNWGL~e0FHMFeQ&!zO z!;?@O!*w9FI`_$e$;EX$1un4S3=E#GelF{r5}E*?3t)Hv literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/ebwizardry/textures/particle/vine_leaf_1.png b/src/main/resources/assets/ebwizardry/textures/particle/vine_leaf_1.png new file mode 100644 index 0000000000000000000000000000000000000000..e68d7c8007d3d7ae44a054456144028094654503 GIT binary patch literal 1246 zcmeAS@N?(olHy`uVBq!ia0y~yU=RRd4mJh`2Kmqb6B!tok5+|5lmsP~D-;yvr)B1( zDwI?fq$;FVWTr7NRNT577Cr5?2G5`CT4|gdigKq9+ML^IJ>#i=W9Q|Km*>7a_jlF= z2_5d0D}*er{QGHLP*wN3@6_u1akoFb~e&SCor?FBt&#G0RqhbwH{J@>lpQd9li{HG)LZ(F;e zw7z6tIb%wQtIfug*&8Hc{+>{BQ1CSR)uHVz;g?Ztv;NN3@>G_`D<7}CX#6<;mf(u-fxFJA$;B{Emo?>; zaNb$iD$eq7pT*Ua?{mH^%sa!L$jbFo#6J*Irisbl;WUD}O!Af6pv3S@K)@)Wr#Tn&nsDc4nELH}CRkJfy8renFW>7KC6C@*zhF1%ub9cM6xYiAE#FvlY+Zlz+}Zj55VvGp z|J%z=e+-R&O*$^GuvmIa`NWH>Cza+ZerUsa>`t{fR z)}LIN7?|tjfBWv4)l5tbyU%YwAsi4t@5mS3qx%@U8eXk$sQO-7@?=5w+`oJ`f9s!M zZMoS<^SH_ka=k9AqEBpwj^(N7lulPD2AzT&VS8eU|`@Z@Q5sC zVBk9l!i+m6X1`@%U|=ut^mS!_%poW$$Q@;_yoG^*VV0+hV~EA+qm%aX9x@Pcix((u z$xv2Q+ps;6-_0RX!Fq<4Pw_nlfn1?Y4Vo7`6Y97uj;ubnN!7mgyP}e(i;%q0LvJqG zD~BxE57d}y=gChCX@cA<5e@=dYyxH|F+n=oUsZ6iCd}NNmq02dYzHeju|D1`@R;Shdj^Q>21_lOC LS3j3^P6}S&~gEZFs+W{FuB^`c>@`y@`C*VIAG>*A#jV-m!4z zZV8B=ajWya%q#DEFZ7RaNo)~**1+y#m9MsGsq*%ePdXPi-_qDSmF?#)9tNc!+c?@- zcrx6RPEP!GW*&zH+lR>lmfa6|*iJ;PTVl0Cuuwt$!-rnmdCT;o?;Xj|RXEh;Jh3Iv zLE*GS_n(hy3hk3bv!`sm7Mb7NYi3z^Eb{rB^2P3|`u8ec&;4%q<3;dHZF7HU3tZ4^I6mTPTjhtPok#h?RvZJw_Mem%=FxiRp+JV&Zs^srF)GnIqlWY zX48(n`)4k===bIUPtQh0gLmxA9vO0TUOF86kdRlfOnI?}PP6Hz<~d%?h6Wi@8{cjz zE;sl-$vpM!_KL^pXI47i-Jjsc`%0`h{GQx~u*)@zPpD*sJUkHM?Vj8m^r*r9%j4sl zw=CcOEpl&g#p}iSi7W0OEj;ro{G*KB>P4G%wr=08axPWRvnx8O^r|zHkEw2;zhK3y zJ(g#-dRQNcPuu!3^|9agD8KNxyLYy4%Y7wdweo|{`lG&UU!;A@@Q$e7`|hQ{c9ryB zOMi7A?OznSyujVoclxd`Gs-_-T4vI1-K4E;k-m#x`tM;UuD3mny3Y$97x!H)o|GG{ zqAVAl_w4kv6DzOC-qqWpnzF8FO>Tizy74rN%e`ix9P9`glfE?RhQ=XcNK-HWD7{v|M%c~bk?rH`dQCGM=daQVwpmk%F5 zoc_MpFIsM|m)YNa$8$GZsbAYJuzR1v`p#qd(YOAtk*h1^uv_ur{q|qn$Lrs&E}DL6 zBLf2iTavfC3qvJC6vNav=fCDKFfecyctjR6Fz_7&Va6R3v)?i>FtC?+`ns||<`5JW zUXV`A_jY0>zk9ckTtaQ_8 ziI;Xq?y8L*V!i<`lYXq0y^(nT&s_agtELDs2tE|&%~-iG#9z&G5rhANNf~?Ou1YPc zWO3Ma(n_i0aRg(JAw$Lcm07GiWZyFx-1TSBSm%0Nu4eaxz2Oa)AL%fxKD|l3Y5L9k z*BoE!yqk&IYkJ~7sAve72H&3bfbruEOP4+) S3uOid1_n=8KbLh*2~7aOpM`Az literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/ebwizardry/textures/particle/vine_leaf_3.png b/src/main/resources/assets/ebwizardry/textures/particle/vine_leaf_3.png new file mode 100644 index 0000000000000000000000000000000000000000..2304504f0f26f666b7e0b3045bfa71c1078e99fa GIT binary patch literal 1195 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 a_BFk`r_5Fj3t(ViVDNPHb6Mw<&;$S)#=C|9 delta 2189 zcmZ3jJwtGUayNrZ*TE7&r?&B8wRqxP?KOkzv*x2?hoR_7YED zSN8in(juyYUn~yQFfeeadb&7xXkJ-S~eT(ot6?YWh&*6sUV;(yF|+i|(}1oe%s zE-9LvLQNCYf3SBf@0c&}kM9wqqF^1vo`#kQ2fP-sB)zF`sYt7NzjMd(<-1p}FSVTA zo_D)2t%7&?m7vhACFfR^UW-c4|M`?(`RRWPnFEjiZSQ}W<2;X<;e|{(Lyn1Ty7Zy; z|7I&HjxYeFe|y?jPNrub zGsBL3q91;r=iSD=tbWmp7>7SaiIEK(*fz2~PATkv5X$+QwJ7vY$i$cf%~~B!djlWq ze{bs$ulxA-0qe1|muL4bdwh7d*v17bgH}W~wJC@l(Grr#u{;pU9CP;JEX71!l?)M% zRfr`b6$?W-OIFN#YyopY5IVOPf_~ zuBDb(@D`J>*&Z(p779(#Is8w;@xmEl7sh2N9!VP8xXx5-+MO(%bof*AQ6??@jE9oU z^*d4zzIfCvE5ZG7ujK3eZ5ysmc=n5H+Zzt^FwHGpQ*NnVTes%&oe0Gomlef7?mX~P zTqh!Q#i_}wW3||Xfa$jwg%7;{H+6nJi-MBGZh@Ja4XZiU$rSCdefY~i{_r*L9g`ME zhK&zBYCWF{?)X}S+*$#eiKxd zU#LIf!R&4+)b>63P?kr@J)_s>PNeTDxX8)YlfWaPp1@+*m&5h;{T0qE#_w|SAAVis zUG@Ch2G@-EsN=4T7k7%@ijMvweE!+h(=)1EN|v3x^;EPdaMkP3YjOETmZv76=H@P>XY?y_b~;!gv?A{ox5tOX8T;b zsb5XCp7-LZf1UAb)u7d0H(8VaNs8f6ZNdcUpVly38JmlL;Y`)qi$s<&)+ zYko_N&E}(CxxJMUi{mu~+-A>Ny=`X7{EHdeFRn~Zz43JZ_VSZzoa*0_}JJ!Rn8*~I16KB3xcpTmYcKc)@GbaGzsoYOj{@%L}b9hrcCBk?hD`Vr@$z^?cn*P z=juz2#2CvhtDccGceVJr%O~?beK^PW`QL=UcbPB!n^Q95!hPw<{+ohxGI)CAVVT|YZ~7`d-m%J*FJ^Y+#e`RVFCXyrdQCN7AFCK= zuk`L)N44{@y@FC_XUg^Z-zt#cpU)^bH8q7x!$TlYW3A8)rS)Rl3$i$_76-Sh*gY?{ ze-c=CM&V`Q{~v053;V6-%J#7t8wIOtt}!U)wYn?0_^;;WbDBIIT!k{1HMUN8T3?pI zHbY=>+sVo90&6$j-tU|FR%&w28TC&c`Z@EbvD`Ve%Vy@A4T^%>t><4>NHDWYdhf?> z@8{uWJn699&ohgwx_GB^CESn~@N(IFhh_bX3MVUr8BUYAr#UxJt&v9+@xgA;em`-V$@bF6gLhIiW%WA%Cw_hwK zG`qNd$&Y^>?cb|r*r-b{&5{3_vHt3hSNHU8nkdg-I^nk}gC*~QVu4qV&n#c*+pDRW9vB&mTTVBIo{T`A|j>ACVg7f zmFl9ollp>xEpBnTJK^YQ%VO8RnR)@tb(JB%T2pg4)#hq0dm#2dwaedzy?mF--=K=Hj5Fobg6r`jOCnFLng2-1J7Dvf{!i(}^BF#T+u0&L_s}HP16nsj#Ou$` znw-91@-mSMBCM-?3Subg@V0TgTRpvw|%bEz@9E!irMkc08I#0WS8a4!9O)h^Ua!z&@cJ3guEVb3D(7`=?wn+a diff --git a/src/main/resources/assets/ebwizardry/textures/spells/arcane_lock.png b/src/main/resources/assets/ebwizardry/textures/spells/arcane_lock.png new file mode 100644 index 0000000000000000000000000000000000000000..6df7d7d8e75c4476108400e8807c33c7adf4eb3e GIT binary patch literal 5300 zcmeAS@N?(olHy`uVBq!ia0y~yU{C;I4mJh`hT^KKFANO4x>X?&B|(Yh3I#>^X_+~x z3MG{VsS2qTnQ06R6}Q&TNH0^i6l(eZSfrYzqFCm}_it>~fBrJ*1ZMT7ExX=v*L4$* zk6TKL%GrO{?fZYS*DD^)NzyXiK1a8H!v*5_{KR>?i(flmA+>Y5++>VWBR^(>e?^n|oJcxgO_w(H?&v(l0 z&w2h+{#3TQym|e9IqriIos$nr?{DUwmV8a8QM5(O>V4y4exEZlYtF0mDQ=mcoPJM! zKkNIyFQeb&)SqjQcTUWy%R6yD>C2q*m(Oq9<*1FF_D5J#`~C8_&%QX+2!|+7t>z9+fjRe z`D`7-UvIhJ-}9G$w^OPszb-CdQQW&9Og5)mxXgsFFfIREt^4lW?RPboL(}5=toJ4x z92c&ym^t6?pZWUl4$n2VoxAy~PxSRCC56)hMOH=P4Ld#`F}eHW-t?b`q<^#CU}$>T zwsX_LyyMv&6Yr>RKXlZxAb!)u8{&6kBhNFmbnF!FE@WiMDO23}Cg*u;fF(^&cV9oGQIM5}?t8`sU<`t)-k>=7l zUaM9vo#)(V`E-u=G`FupUOFqE1bOMM{UVjMX63V}thH;uJ&SfY6m)v+jIikJy~dg8 zFV0<_Yh5K@*COaHRXHWlUAoq3zGV8W%4w15vul5fioM+bNh|H@)v)_{&P!#>Z&gl@ zEx-Nuz*b>Do0m_5{cPWUG0);(wSUpGeTv_&uh_|Mswnop_NlO`-}Fz0EtBV{B(f#h zSqbPnF*sExrmgP2$ZeUJCcQ{>61(YimUBf;JS>mP>}0yVuv07pJ}R$UXYx+nj}=pX(IXgn1XFIGQ8%6|YK#i!XCln9eyZ&9shh^05x<;7OH% z57zp9y!ec*R#EzutWJEPHv&=3_Vgyxfmg_g=mev3~Chu0W{`D(CNp-L;+l@Y{*FrbpvPRkE#L3(Hb|xBFoEP%?=ArRy)l`Lu7#Dq&{z|iR%-u^i-kNq*ecQ#$6OIdbrcb;6O z>?qd}bZeJffbNo>^NuG>1xN z&pe%LH?!p|i=~-Fviv1%ml@Ow+TL(F#BfXIfqPQGu?|Ta7NsSb!uRdI$X;-@bo4No zeJxUa1&`tFYm=kqFI~S%c~|hltNcAm(VSD{ysNj(ecgC4@W!#!UF@s*mOt29aqHuL zOF?nH_pQg+l#+gXBpOPyD6aID$m@+-W}hSObU5AlUH;M4@0r9E6J@epKFrCx-OSU! z^?TH`oC{B5Zx~hOxO;zOIC96`HF*Z3yVK=Ay&7kjb!%@=HGMk4s+>u>;hf*Z7pd#_ z{!(K2blpYKcU~Vyxk2OdlW!%tg7hc4Z>>miuqcpt!1N$vYQQV*)q7>)ZYSTBej%*b zwExbVG@)rlE6Y!Z%zr(3t?=j4OaFwo2^A|9-Q2a;yvyXEYFmg9m%;o1j;7Q5#SY!b zo%ZN6?`CTMh@3BpI3{=O-s%NUcDqO1`m#~JMr+}WDTcBuCy3OaS(s(7 z%9T+hXXEg&Y1X_XVaDNEynZI$+xxSUty5oGFHaf7Ej zNx+nIircwM87(R?Itxw;DV;8pi58J#P29a}?y-Uc2c~)kh~L?KYJY9b{t`E#Uo)Bc zYbJDE-7Vy@?1+O2_Zv^Xv}<$sJeaYzd!4K4X3vaU6DL(X@R@x>kn>e*cxrU<^_9EA z%9QR-_0(3b6nMBwS1~7~vo0@4;Ory+sIaAZ>qJjppL8v7q8CT#b%%RPU9)(dgl(5J zyb|eOSj8Q1dhUWF1(Pa@%rre`-Bx{g?)%fSxHHncQ6l>@CjL>^h_qyoSf|{vHKNek zHY=1@8{GBzf-5thDXg<2Vd2j?+3RMQ>3ssl0?f14H?wzvzZP%*UL-%xSY|Q&=RJNuIx6~eBIoP?t zXXe=krrN46spp&y8^5`Ad2yihSO1qm-CO3|wmf0q)Q!R-{R$aLv>f=ZHOs& z=&W(|&g=ebtfp$LMU!Ptl}M~#(xB=!AtGl@ZH%Sk)s-9FcmEWf{E1cgGn*@4?~~*m zp~acUe|FZV@Kj0pc$~bkvnZWi<(Ny0;&g@kX8nol9$j$Ql-c%*(X_AL)Z2JVpiA?;P7N2;xqDph#^39Ud+;jTMcmy`=i2dKX zRrF)qv`Z&SH}NDg&-xO5K_M*et;W4|2^>>`Cd|9m_Ad95tmgDT({Az${yp<$hEt#8 zR+T9^0bbMBOq2StLTy2;*tAJ^zb=;5o2{$ay!6N_z0y~az7zhay>*_krS{4v!zDcl z3G+*@v&m0iZQ>}Bt8>UK^#0%+qFy+?B}X{-&i5ze_~PJEp`>I!u4AFw|I8O zWEX8^nbT0v(tcyvr^VStQHs49+j^&MGnDDwyz5P9v{|feZRL~d%{}89I3IAz8XLKZX#ZvLInubGV3xw^`@(a4o+xE(XkMu!v_aSR z*2#-&?_QfHFmS49nkqCV95VXV(YM#R=1N(>uPNU`POa^0 zo}%A-b=3zU?pqn*W^JrH+7?MH+Ic5w<<5&56D%_#%ipkVlKnHk&bg+xH7=skePuJp zPRsJ`eQ__!4@&rI{EB?Y`0sJEs!YSnsSBU-to&#ZYJVs>@!RQ(4-F=J2k*B|ytD0Q zeEq`@S1;*j>0CNg^sdyN)BD@`@8z$i{Qh_K&)28-|7ZQ1-oC%i)IPp0fBl@zvwoVF zmE=cNO^s${U|?WN@^*J&_|Fi)5Mc6wc{>9G180FpWHAE+w=f7ZGR&GI!N9=4UgGKN z%Kn&HT!2+w$k0TEfq|XF)5S3);_%Vwr~75XMUT~g54-zn-Mg3XB&~xc=qjd)o>A)h zGs|$3j%rbW(8Ls(1lCBFpY{%dMwJrXS_q?faOzB{;;MsQE?8L^+oenP3 zgidl>+g=U58~Xj^qE*#$a_O1tLRN)^U$u;{{XXY?jcT8~C-eW~qRcgRd;Uw5o$oGX zV2H2DWW2FeU~_fchux{V|uuwIt!cgpu*ivWkF<{o#m>r19^C{75Plq%_Od+FYk z=NArh-`O*DJu`#FhY64FYBvcS(%Jc4u0en)HgNH`dy~C9l~|lOOadzX-8oncGT+U& zyZ-+B&j*irG*#`b?%X=^<4tIp?vXv^p?O|btQQ$~IbC4;74*qLWMitmwgF2G^fjR>Z9JHt^!Q!Vjt&3etNdhnPE@e zLnh&D$xPp6rp{|STO1;yn>iY{>fRQ}zrMJ0%A1_+l?J{y@4nn{;q9efQT_M#`L&wr z|8)mf_LcHA1Z!&_DLfSUR~7FmDiECWbgg#y2gQV@ z^hdVWEUSWo?r<|4h>^J**tIX{O~&@h())Hl-t4c5m?qPk922W?L%_mP>gvzXGu_RV zF&qjk@^Sn9R8-f$xqG_Pdo@q5;?>f2p7%!`+`T46UGrGn5u$13)i~wD2XhN4_kzc4 zg{xTuUFIy?b7S4rx7(wfCkeOlbdojlY1{N*KU9@c6`*8M3okXje_RR7qA8}stb3Xg{K zFP=G%dC|pB3NF5yLOqE=Q#Vv~exLhzr~1CL<&$UF&->32r9035i|z)gf4|JniLjpb z3XEiSN?2a((y^Y+VexB*x>aq8S9mN=FVS)2ICib*mH+dMQY)L!PbM!Ak)LDj9w{R8 zd0t_l!}8`bJ{Mu;w6Bc<0^4S?KGt!rjyG0dsbdzHb2#Iy_4a(@lf`O}4bQhQJU`!D zY@^DuOK0J#6>7o;Z0Wizjrb?9p{v@VBZbDuH|k_nuUr9r?_UT zJg_}}>+LSt*$dRWW%j5?a33p3vsot5Z}`|SQ08-7_jG!9ca477hmWQiJjdjF9_}oY?s4?w3@X~SO5nh! zMrNCAUH$dzCP^NSnirh=f#bH=LV-o|B7%%Q&6{Sp<SC9YKvS}}_XC;rv3pM3kZ6l4);=u}COXqFQ=RzCnWOv-R`W^YCE<-`qxvo zy*IaU9KY8*r9(jA+{06w=6yUiLE72g)8b=4_t&2n-5s;*zMfRSvr_Bb6jkT7CwmfS zJYSO;yIbY?3aQOi=XED+GFuYlb;@n;^48!=|LfIU&m)Z6&Pe?7`gm!n_mQBW2=6o# z=iFDX7Ynv-?U}2b-I9Li$dqWEzdQ#Xw)1GuSKYjCZi|CE2ba7-g;%mfwSStfa`x+u zYfXhT_NJ%k-pp{x;}L#-!QtiwyLn}ilm8qkf41#AbL6y(@4u&uga)f~&k!)UH@W42 z1_e_HeR;LhEWKWZc_>XvMa%&!kQ7cuiy1jFh@49{ePxk*##TSo+WaU{#|2rx+`+d!dZ(rYky?wLd{(JlXe>&gaUpM=^ zyv=l`{fA#?-#h;GNv=DlBL zd;aT>RO|Ep8tdoQ-1+mlT8AZBRgW$I51(Gdz0GNyYZSIz_$gcQy|HuWq#rUrmwo^C z`^L=g$K?-J*Z&fX@!12@-t2S2Zyzs; zUbp-4x4*V`Q#vo^$NzZy_she$)eC<-d(Nu*>S>?;fz3WE78p9}a!mgob!YDOyFZt$ zKC?%ryy|#DpL$*8%=@u_wAX)kc;2z=+|6HoqOU(GDV!E4s(P-+Q24wvbJxec`k!0P zzj1G1WVy^+oZ5W1@4A5UPXD~t?&1ggQWkI2-?e+wJVp+|Vs){{OdL0OHpZ51tB9YY z+$UONrTty;7bBCN>i#*F3Bpcnb6%O6pBE{A|Mld4J!M^niB5d186FA;x(pA_7t)q_ zrMV;{$jfqSNU*nUyG-#Z%jr73uT-Z*1f5(uB`WHr>6M7!vs1CRX)NwD`_*D+e9q*v&gOGwzdvc~T&jN>dS=z?wfpY2 zd0D^P@>y^9yKTQ4v(@KRTspaYPSvfK`B&sZ_Ah=`r||vwikkz&TS+6;_rsZb9*j*PRb}> zfAyaKxw_{9#czwtr8vBqzmrtmm@N6<*`p?EfP;*r<96ONZ*AAb!VfPrKeXx2|KUpZqr2ox!7W-JuCl z&QiIe*QFl^ZJn&<|dr(_g+Tl0;fmwo0}FPowj$%4#b+b_TT{KfY3hZgmp0bBn> zCVFqLoq4m`bFcGL4#C;ktZYF=QC=5jWt6aN&==g=AJ%bOC1di{qU(__&+ODzG_bjS zTRWpAQ|@}Zn2&=O--YUF`&Qj6Uy=7vlZ9=;%i75T8-E$P-B(L}7PWWjp365(cOSXt zEamyq>BwKF)ax@gPcVM6^4oSXlhocklj9#IH`|CCJ=$SIMxHd!4zS0{>p&nUp z+W$xw=cM@w^^01~40#pTGE1kyQB7OEETh>$*mauYl^JU-%%pZvHO)t%T*KspB-Q8+wpMfCP^Y2a5YeRIqWsBlpD+>s+Ds~qX|CZb=ol+Y2q}U-} zLPK|Z3wPpdA^j_k4->y`STN;6?3^R5jSAs!_P*zNVzY6&e8wHOoL7Zyhbodb7Rn!b zq*-wI?Z>L+7pDHRp5xb}^i#Oqd0T^2b^6<-J$D?}=)AwQP4}&+&}Z|a3AzGHE}T$) z)KODb!L+SK?550tjTM(tu2mm-ck7a*vcpuz7V}6Z{aYt_`P9r8oA|j_g=nz;Pc#;k zK5{gaN9MzK%LCJ+m!)3beM9ze&IHRft1>3fpIy-XVBhwKQ2~<<3(eo;nt6B0uIR%P zQU!mcgy(4<^Ie#*E0{fC(`DyfI@5f=_tbuy=F}3pHt+t8i%vlaPvlk$RJSmzc<|>=xYEP;H$y4zdv(KJg&8*tEcTy? zyPJD0?3>cs-%q0YPH8EuDyS9j@!HV+C01b4dS`z>O^v71Cce^Lk#@aLvOZ9pDNpR7 zCYQ^k6%!kts&xm2Zb)JY3tqO4GsE2e`^V(SBHm++2k)J7j`^nT@1I@SVq=ssQLj+0 zsPEm18m_w^XUq#t-@DcHP)^;#w@VhzUsGSozUx5ekL44)D9Fm^S^q0VjE@|$W_TUzFH zvU*A!3)*>Lfvoxr?J(#6g}#<+SBNh<_xfC%W|;zWsmH&ZM@L*f$aE%sRPf-oapSDm zv+2l=rF-O0Cb4p)vc9Xh#*%%?mxaN=T)TXV`L50br#f^v4UAotwK+LvoY$HbQQYCw zbs;WM%;>zpGtWssQj%KOV_zQ2ZQ(NBzE8zx&NrUlvs+FcnXp0WrN~U-RTJZ`dI<)L zMDXpKT+__RYS_8z&+gQAxpj5Z!Yg$c(`&`P&cBv)r>JI+@#}LT2Sj=DAF}C&Mjz=2 zI_4U5KFjJ1dz7S<|FYU?eFi#AC4IaXE+m-tZ_d7##4nMnZ*0wTJ`iT`K`QP z6?)#}xz2hn_;;ei$pyi)bW``7%@KIi%gp$A<4sp-t+kxZtXw&3H6x;*D8BW4xxlHx zudT*(+q($n6QMRw7CXwmT_At+rt?!p)qItc0ZTdU7E0HsCaScH$h`8kxau|Y??l(; zoARX$Wr7+RoyLteAu6xfmv~=EITcrOVA_+%5B(44CW#%K@HDCVksRCpO()`?>g;ye z6{DbjUQ~5?i$~71t0q2k=ay(z-hJ01yMc8J`@-)bQqEoi*F7iIdx?GBw?>;;}b2&J^PV;*e5NMXMZSUtmR-Yr` zev@Q4Tx5g~2Ay2R63bb6VFpL{wWglM*LwN(2>O2PJatIievgZxR$E`I?#*kj72B*S`Iy=464=Ix=k!uosXjtfRxSFe8(wz#=v?#oT5x2cI)DmcyS=ZOxnpRwNekHCsW zHWK@vF|J4rWvhD=%6`D3GE+XY^{EC&gXKleSzb%k*J@O!>;DmK{Sh#glihEP_T{Nk zEwS0tH%~YE%+l9VaAAqWxAs#HUS|9>Sb1a8#gN>{FHQZjZ#l(6!#+4KER~v&#JhuY zn$hQZeri2wWx-YR6bn~B_2Jnc%F3iNNjd22%H44!HXq1mU^BQ0|#zVKSm$t%=g zV(@nBt~V^ZpFEJ8`l4FA$eT&m%RI$J}VaH0jQdk{ZjE+yAVd<$uJ~ znmb5A_ED+#qKk$hvDn=_XP`}r*dREzuwPGyI8V^NzzOzjJqxVc? zZg`79Ul04|i6_~;h4>BEM+Z$hp7Z8-{!R5FfA1rIpPQA;=?zHiUp`Trb&}p~X^(?k z6O~p+b(if}t82pjwPnKI-E-9*cHeJ3AMncSpR;_&UTxBi$vu+RHw5o;w(ydQDIXPb|Lrd#U&1o%> z3Tu{KfyZv?-sI3-?GV|WBP=U2E%t8zzxIQdBul15vzusjHSX=2I{k5j-RpIH+ZY$; z&d3eK!aFDUIv&-LvYvyV$Y-f!TvT~dQXMCIJ}AN-bT^{Z8iCw}zlHjtU&o3XOs zM0eEmgoI5U_hyJ}wOGX0*M84zrL5bmX;T!Nf|efF`0>Q|;ysClN|S{?{&1al`XI`j(>JR@xa9OhlF=jdn{=7>YuuG)n5IBjJl^9ny_tiI`}PAJ_>y1MEL>6RO(Ul||sURe-)ROx8GYCtjPS%wzv zC5xk!y7e%ngu6Saw@Pg%qT)S2Kb&uFy{(7o^ z>ct&DBWKmNN?LtRRoN2ue8$%a>K!kS?_9R;^5qv5H~#$iH+}!C{hvQvU;k|Xj^BIt z7V+_J-TLgl^k%npf!9(%{b9BwZ+91lX&~tSefA#)1_sUokH}&M25w;xW@MN(M}mQY zfxX1j*OmP-vpBz&;p67mPzDCh7Ec$)kch)ar)L&~K9xLP|332lyy|=>A)!sm2h9=$ zB3ZY-SP-`MTtw8?u-lSLgRQQWP1&`j}{pl{rW2{!)QNnY)o(AaWUa;QedO}R~^Q;oC zv)2`*Z+%>T_0jwLhf=-sSezH%mtLB$a`fOje@Vae9V=GO+;&Y&>(wNi-Jd+~y}94D zo^e-G0IO5Dz%GXsO%5t2)L$y8yFF|R<85(@Z9N%r@1Kl>tyiv^PS|!#;%Jh?$qQ58rMc*CTJunA)~s1S-j;`L{&(Si0khVj0D-oy z0G54f0Vb^tX-U~~b2U$jUKTl}bgY$OYhmNmcdGa5B-f=2URGxL!r{J}_s-kdl`k5% zdaUor=XzuDqs{4*gn)J%9#^yY;9(jk2$?^*5e{f&CY*Kf3e#+F_YuHqGy=87sc`J?9K{`?$2few)KT zmstmencrAmJG!r1S|Vao!?wNd5mjGwf}^uJef%fn%xap)qvUj}HJ2k{dHamWt0$H{ zk;{wyF1(73=a!K110VjW3(dsbZ{IM#=6dYRW}Tfq*RF*--}814KIX8J$BG;{NWRST?3+oWb5 z*c$UC!qSsjD{I-NXUnecDfslhrs7Y$%#EF**_Yk4ezkL)o#%Q`JJFk;QK7cRKWI~~ zQCVXzv-QkLT%T6Ye*gUG-+V=Hz3$TAheTv98>OsGtSi2)e8qqLVb0$sX4fvqOD$1< zlN5b;$>q$r-Mz?0w{_fD}spsY%sPJK^;GFtSS()L@zpwTdqNgv-ef@ONu_`gO=LK&Mz2CGg zne}DKEc0o$2OB1(SHCh&aZHM<<6D-cjWw;ui5W^(@dk(+XxmiaqdwFln!332(cU^Z4AWc&sf0M1;-?+IhWyu5UYgqbR>-je~+nqX3hpgGSR& zzki36df1smGz+_!EBnsO^!wM$>$7&v5*?X`9;;?w-m57jIeFPaj=kwYCHlF?@9dd+ z)AX#1kf7JD^Ais-#I`z`NN1hlsGqaDEx=c@s#3r-Yf)Rtl?8oCS(AeW40xA?UTe_x zOf6>k(RKLFw8$H)j&BSx|C=oNDrJhB`N@@E6!wOnSKd*mZLIaW`hdhSibE-lx44nQj^#<$>7|$RrmaiW-i&fb!tI?bN9>) zLt)dL1#MqWGSv2b_`ol}FsVwkk1u%|Ys2c@KKU7n5}cR9Ws(*cbgh4F!Xh+9)6p+l z`AdDZ=EVJZX;r1V6EzL5Oz=Bdyz{RIyZ61_lO^@vEz`+LnAUzFneoa5L&*j0i45D; zSF$hGak!`T>AmaPHM@#bmAJ&OZ&mPZo!n{{WaO?Pv`8_|@rKFEVq>2ByXSoPEM2kd zTY8JuA`M2~``9!i{tM8S6y7O=7>X8 zjmT=d2UQl$l||~8@BI3t74-M-jG(0_R~*pZX`_5^wt#W&^cIc>qB8r+e;Gc@|Ic`c z{b;~(-C0I?4z`*bWAh&^(PNmv+Wycd?T$2yk4P-*@#C_aHvBIB(%)w=OLCc2jAKBS zNc-nIpAMd%x%HpesrZ|XnyP{K9mHZ&P9C0acgeo|<&U1YV`s3^er8>NgwB1KQnr|^leKZ=b~Qj zn|k*uCBh$7KW5nUvnTFGvo$-1I1-@JL^zum4;{9-@| zt77A%_A^s7zNJ^*s_Wh=t6k7#wsev0#BlTMT+oc@)pNefE~eX-4@859Y0&zIS@{ z8|yFDcba%L1*zu0tq+b_TG)erp#ZF|1UPFoSmz`(%Z M>FVdQ&MBb@0Q9sSE&u=k delta 2386 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 TU)*N~1_lOCS3j3^P6e zU|`@Z@Q5sCVBi)8VMc~ob0ioT7}!fZeO=ifamoqmDHgCa9b{nONc41Z42d{=bb4k_ zY^vrQhaiN(v;JwdiGB<=9H>`FIZr(-+|%59#Ovi6^;hSN)B!{>j+|a z(c&b1$4N)}=?)IIWS#_rMFC2jiOCKvIU*n1>!%8|L|?aZ*IZ|1e%RJ*e@$TNK|#mY zPgtc478xi>1ZJc*K2BV!{6?c+_G{u&r8Nq@Q%@;4Nx{$FThF{R}`m>8y zxh}0pdL&`6AY>8O$0Sy(`1^a8$X2UNG@R~zBEsxg>A~-w-}yHdUCr88dp(_F+T0G~ zO>?62_f536ua*9HDf9>PVT+k^Ira`W`KG;X(y05jXzvV%=PDDYsNCAb(5I2)`9ws& zmuqvv?mq>;^`_}bK4OpGGq)f`wg1oC(ocVzYaaLc3+hGsO^`p-U-dC4v+6hd23!8r zzx+%J3JER_A(I-C7P=<7H0Cb;)4(e}r=RN*!;~!EFdp85`?=N(ZVvJA{t?^2yUA>gf1@DE3hX>((?b$<%( znVua}`LVUfPxR*BTNcmPTTT@IRTQ%$O>}qM{Dk|jljm$M(p1-zet7nf$-L)@mV9U3 zm|GLyddv-4S}4P$)Da=Uc*JQ+t9+ZramSr<8&i{8CFl4Yd6CoF`}%xp&aM;d{>vo2 zeI*=mYjWye&(l9I-%$B4H$NrklR=_Z%3aCq8S~a($lB(x-NHKFN{%tpeA<#HQ#J|S zUM46#%k4r^vishOz0DSX4_oZCNuDZUF8Z)dako47npn#-1$t+9T~*((KH%Xr{yAqe zK612Pl99ewE|u@+vp|~H&tHB~NT$MUGnTYH88>XRngx5jl61Fmuj{tZyTNygd&41} zygJU=`Fr|`ug!7FpK@?pZW6QcRIB^pi|p>qW4v>R!B4M$^6SHIWuMIdJnQWA zb?KFMNd~eL{C|E~V&fNm>G;2umT_}+KHqEX*z!6-)Ad%lW$8->ecv-ic4lsiV^UPt z2d**^lbZOneMLx11tVMY4m9LHsK&AlZ^g>&oPS(5<0n02b(dkY}i=T zt13C4J$`P==b4AUq&wMt`M3Fo*{@TN!eVC4e6;cH?ZCJh8V@RBJ~wXd>FIe;QMafe zHTkz)t?gc(=hY|M{xvbNJ(JQ^I~Dq`u3*+nWz%cCZf|NNZF{(kBl`H)wSQuMqtS1@rN`aAT-bY&$TqJ7r+d{l zUzO_rm)tYwdC^(P(~=(5clM+StmU2j+5N_+FP}}k+E<>NE-tK)mzd=H@&ZeQSzx@} z)vN`pQGL5DS_twpW6 zyZ?KoE<50P_^;2NnDt-*(A1fp=VGs&e_UVF74*^I zNx!0k(u#LH9x;3p7iR5zlsM&a)9b``$yr{ipBG(y@X2)bji0BaH7*~&ZdWGQoH>7c z`tu*x-hUUGA!dKmu)$R&norV z%y(8z`n>I2+4?#`^Xbp6ug4zqn37hr?aW<%+t$Ui?|eB}JY(LxXAh6dJ%8{oGV5sM zv-IT|a{BB-FNJ@n-kNrP%i0cxB$Fd+RhqXx`(x~v_Iuv*f}+1QpWC!0&!t*e1V8!A zZ_{?kaQ@#DN4LBx-DdYE`pX$bsi%^UPT72YWwX}p?++FimdkP{nNGS)IilKeF~MZn z%_CPwmp+^;E&{cKwGJo~Xp%|D~`i?4fXY%%O)X zJ@@VYn!bh4|B{y9;@6=id;3(|!Zu&rmin!*=)jh@TRbLlU*dCAw~_F<<08ehs%zz$ zkJlOv-`$;5;go4snQ+@|)zmDfqJ2HB{aC~x!^{iRD^}J;+F50^wMsM=j zwA-pDnuKIUJx;ku_GX%1oNAeIMPs^`=L`dlz_)*1HgFxWQe4LCb@I{GHJdl)+!EN3 z>i=_vy~|FSV;5>QnVtp}DmuDut@gMb*X4I$>E&+^%B#`FchV*(tl%C`im;U|?YIboFyt=akR{0LzLooB#j- literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/ebwizardry/textures/spells/combustion_rune.png b/src/main/resources/assets/ebwizardry/textures/spells/combustion_rune.png new file mode 100644 index 0000000000000000000000000000000000000000..5d883ec8392685b0577b14aba852808af9cd217f GIT binary patch literal 6199 zcmeAS@N?(olHy`uVBq!ia0y~yU{C;I4mJh`hT^KKFANO)tExgGN`ey06$*;-(=u~X z6-p`#QWa7wGSe6sDsHWvky)g?Td?K-V-Y*2WZefA5y~~p^7rGLt{Bbw*qz>fRMP8i zPSVOVr%pB9{{QQF;r|EfX5MWFfub<>NcIr;g!B*MYnhO0{s+*c_Bt0*GVteF(bJa_~o$r61 z-&j1q{vXG^=kfMQ-@knS`y*T9PVhbcDe{I@_rL!n41ap$Fe&n{uST;=&0qVn7T>TaV6ik-D4I|dUj6dn7cqlSN~1% z{}CL|Yzx;sxExv8p~)lg!Lt47UB=lG+z+lS*!i>X=kJ^o4@;#p89RKsBrZ&FXqXz* zWngbxWhxZoPWXsoNtW zZ|ThJty`~IPcCbFSF`)G%X{S>i%TaK^GKI&xv2hSX6CcVWoNB!ztLW^!{dMGw4I^h z(Y3#Mr+993=5kLs#p1Ia#$vQ+u{)Pgdxk0d(P8V365oNo$dY!@790v zPsn`w<@(m>AO0sS9l!r~ILEomylDU9Z|qmX_KT{Qza|q=Cy}ZmT1>>G+mwCe*L$JjH9QM;&-0SitoA%H`KohPP^GwrWbsS!S1E- z>3|$F?K_jsKEE`7Y1&1uM-vNn@4hDa@#0Y)FR|V$GZPKePagkLy}|IG4a*7PJvoi< zr)>IsXWA|eqi1E(5*%eKC8ut`sk=79Kc?8I_CCY8uQys%kKVk=@t|#@h@X(wHdlv} zEl%qc|0;hucs=dy>g$ykx*qHHZW4OXa7>M1^%obGWOd2O{_Zz@OS)ViMNYnKrqDZK z{^tbkX*W+@PB(7ibv)P6UexDtX!_c@(-wTMT*aQTo<(M5_swP#UAA|doj2X`_bU%7 z>#<`=HQ1IHV$v+r=ad`u?pQ&#{qDJ*46&ULg(SY7jOg7vZ|^IY$ThkvjyByq>Zvg8 z*GkcOIx1Ob&mJgrlv;5hSo(?rSEZWK)Xmes*&Y4XYxZXD>KnT+3RuiwmfYc1rxLJR ziigqtN)mPM(tt7EuT<^3ft#7$T$t8~rhGyAp!5%j?gw^9XQ!kxL13XX^NSXY!x)PM=prZ&vWXn*VLvHys|y z-yBa&iwwoPCP^^f%GrCKBZRr=u#t=Vd+ELNORaDFRs|eWVh%QalHz(v%J<|-T_sbu zt#Z#dxH>9E3KsJ+zE#NIw6m+-zwb!Wgb+3vl}+tenpV5ng|S>LeNIJnnPI7 z^mJyR#|}w_sxzy1vGTEQJIA|np-k{wLlgZe!uOQ}(wa(U6;-T@lw?y{8?%6Q)*Swm z$F9BE(iGn+x$2y@r-A^J62nTSnYZ{K6&nBF#B%6s#|gW}Gl~z^%(Q8{Ig{&@{OX|Z zJwX~eH-kAvE>CDrNnSAd(oSC+cjpd|yhm3TFp907tROZw%;@qb0W){~Jsy+pp71|X zH1TPC$I{s`_5#%xgi3brcDj)evMY7Y5{H6}28KR?srzyhWz)rb_8o4ql`LHB^Y($D zo{smw1(r(D*0Y*7f>h$r(29b$QAA z6S#kEcTml_;PXMa_vVD69~xditjkX<3Vu0x&27j;8?^wD_|7hA^gg-J&`@XCJ)7oFUiCMzk7C;D=x zbMdF7?FpazOjv%LN(!CBHPwBZZFO@*hD4-RRX{D1Ug0CB*;;xUiHq+{)Y!bIW!-`m zE`7iHIXgehkurGtv%{(_I&HUUrhM9ZZb>y2d(EXe*WNb0J0bUI;Wnl`lRI+l2gO!8 zK8c^K^@*|X$Z6xG-|0)v^x3`(`e;76&iAJy@6sLN5rRkAqT*LD>=LfIexv=O(%#Kl z*NRIggl?YTXWmfZ;3RZ9Q0AOdR_@kqE3?986?Mccx4SsWqgZo>hsD+>Hd>tR>zW&; zb?jd}Wx=8oTyJ*?@&DSu-*zs_y}@P1*Gm(_eHv9P4k#tbME2%s6qn^n3r?P%(7Z13 zkl(Xf_0r7!s;Y+>6=UmUySSK!2cm05=z&)(b^e>sNjT>Jz^ zMQJzBmjRhNoEvIH0~sdGaPc(^HgjCtI_ZsIiUpJ7wU(*X&SKB=C+y8t4RV`ysB(wk zkqo8d6-DY(=Fgsz;am3XYS}}pi+TccuPFb#`hS$UCC0+UR?6kJNqUzOJH^z%eD%gwN5EBYkTGuL+=m$X=%KJm?~ zgpQUIYo2n-ZAjC8z147X@}(mtZ(XFXzX@Sn(J`;&-KXoZRnkkAm`H5DUU~F$*PUaY zf;9<7tra>yZ$*@dJlN1^Amp1QfB(s4d%LT*4?pI*f7Ve^CR{aLT5`FHtZ9;pZV{PV}EpbMVRWxkv8|_(cGaq^r9;%SA zv()N>f3onKstJ>9c??QbuPG`z#;MQze*LLNe(AS2N@v}tyW9%>SbQOaweWt6i^qz5 z=U1KHM|Eb}$=|p8&VRJ#yJzE(C3=N->m%l_P`%@(z3Q**sU)@ttNj{TXE`muu{JMI z(ys12GFho%a_JnW&3E4mHfm{iUG-Zao%d?BSZ^v%R!-8nBWWR9FUDN74|{f~a+eXq zv{^2hNy49Z_jC3yy}uyXe*dn0Tuv39c`MJp>uYhjmwD_~v9x8CvzNH(qY3|3?DBAa zZM0B!rnI7QlBeV{tM>+<+g^QnS-E44hoaSNF3y>6vfe#%3u*c&!@A_qM1%ZoYLP2% z>uk~9#=j}#s_KKRP*sh!r{iV3met6RDf8%UW4)t4!0p7ZHA?PdDMo&HXmfb3TclaGSblqEg$E%a6MI<9CLYepsl-KG*&E zz2|Zpe`?Onn#Dgkrra->bz9O6>%Hu?N^n7Z?n|)5;#hKNC47n z#INuE;^hwCdk)848`WfG4j;EFz0#x+yD7L{-O{puwpFiOmS(8*O7X83-X;E7AM%`K zepkgWHl`!85@kF}+GuEWCH=U1P0eYA3pNBr?^7whDV?xHaMe`op zNi{wV;o2x7)Lg%%Qti2O`qc|6IxiOc33Jc6?p^G1`}#-EnMw;LGbWc-OzYTr?dPon zYL~Aa*qSY{>3D+iPfoe+g~y!cJuw0 zD7|V6Ng?YvoM=>SQVywMu!F{ew*~@%!i)k>mG`#FpnNlZvN3_&^x9XQqM$zmYH6?RJPdgsn_(%SF z>GJ1~H`T>mTE0i`ZvX4=hQB-?9eZy0>;8_C`sXhTe=ba(^zHPaed{mR?*Dh|zU6A$ z{@>>2d1)WSenwU?FfgzsdAqwXOl7EJC}KG17RtcDz**oCS`{r-K?xtXVDGHx|;nPS4a zmT8*SDGxS{xP}iQi?`(ac4tQAUS77om%lbI`O=jiQM0ctv-8Ma)+Ea9At`v|l&grq z!j9l$M&}C7%`E<@SN-+j?{hPanYUP5-n@Tv`qpc4*?+IQmi35Ct#r=&5dY=ZZ-!hY zt?TQ~{(mPYcOd<;Rr|~{zr_yx;eYm-^zzGczeU(6Y-VEU@mG~d$heUFvEjol zL4$J-S0{xyitc~y#JJ&Sc`!>l51+>;$z+dDU%i$dYS!jvs4<($u%Yayg1CCtW+sUT z`wTiNlj$JL#2X-pO8FnsFid%Zh`mluP)yE6zP!85EGZ@Ic$5$2Bagy#;Q)S;kb} z;&uAq#c2jlIFogkCh-_2Wm>vt=>C0bbk(bM`u~fMPL@7g!;mYjFLxp??!?xImhO@- zOugm@=NX=QTkAS);T(S+rBinko0l~gmnNRFH2cmWDyp|^+WBDji;hPnvR1V?Ea6hR zZl!o&-QqR}ce+Ex#xSbl`ZZ~C=h?;jd_TR*ywTBzeFI;tK z+rKGZN^kNde%U+?m{WAMiiKg-pPvaw`uEMW-IL5Td;gvA)C*e9Zac4rPZOQ8`PSjJ zo~QWbGZ{X7lkCsZnPZpAsOa|MZRW=0%|$QQJl3Btp(d1AYnZBJc1KGr@c7lDnOlMm zt}45ba*OH5P66fvR)KBIPeYt70-G5Zzxm-d**RT@WkXr1(?JdC>ql~8gaZvueYoDp zU|0I#OR{F_V~cA7dMY0#ypPD7GRdmxj-~av`v)ue*8a9hZDgOk@&R+LoXzI~*(Mz^ z8M{Pr07Z=yu3Yk~M<2UDXBc?2A3$cKK(t`trLAXu1^qney=F zTEp{u=csB6I&|2qLh6{S;f~zp#XzJ&sPR~d$6+i)a~W1qN|fQ9`yeGaB8*F zUdF~|^?j2!90=ZKCpUS?hGLO_+x!(8rhd0N<`=z9&r8z4;9bk4K(BjuPTc(1D6ll8 zg^`=HVAZ^pR%J82;_qw6%n*5{Tk)s5Z?^juH=_N=_sI&n7W~tCb4z>f?$hDR zYOWY9(c9Ga%8nY^60@vL8n^1?XLnBW`#tq=dTmRbHU zqv8R(rmDX1vWx{cPn=`=A$IIs#Tt1ZjgBCL4LVPL6&~pLpwCk-*`7aT;nPzA69m;x zOjK%m-{`*W-J~2o)!EfdFE&;l;!3C}_x3){nOGT+?{^m9DlI1VGH~h>rJ@jgMu-~6c4Hg{=*S4uGlzr~@&fiE_ z=4(f2MrNAZ@x8TOcz~Wnc}*FVX{Qm z$|A*}v^k%;15aF;(U7TW^QIO+cf#jb+`6R?@1jCjul*z+~?8i=r54GGV#aNJbtADrtGj3t^510Z_155wJm?i zo7=PB+86kHarM+^RDO&(@#PGUrsP`f&Vp%cJba(eKJZkn;DGqK!V{5V$4|9g2>kZo z@v;wh^5(B~zUh73FG|X<;&VaU>4?_m_dj*EY95t*`29cUj;QsU7iq-wwQihN!0DKC zO!<_rfjXbdu?DS$hCa+I9?vljnYF>J;La26^|9Y>6ic>=TZl!yO%W}svyUe+B%*s-F^|NQx6Nt})@7%GMJJo*V zXeIvkm}tK@^x*qfHC3ll(?U93ZcLS`c`#XD>kIdtnfLz%w66Bc(3<1ZTJ`Q_?*3P4 z|1Pgp)$_X&@oDM3olFcdv%vb&v_j#o6L0Di>0$N z-$i>)zoqYY<(b*Ox9@i7UM$_6vbQc+%lt*n*6h!2v4znB`Tq|6&%QYG`l|E!C-XHf d@E)sY6g;^sy3n%yIRgU&gQu&X%Q~loCIIPV#-;!O literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/ebwizardry/textures/spells/conjure_axe.png b/src/main/resources/assets/ebwizardry/textures/spells/conjure_axe.png new file mode 100644 index 0000000000000000000000000000000000000000..1a50b0e488c7e1b8fabff07456b18d1c2fdc2fca GIT binary patch literal 4557 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 literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/ebwizardry/textures/spells/conjure_shovel.png b/src/main/resources/assets/ebwizardry/textures/spells/conjure_shovel.png new file mode 100644 index 0000000000000000000000000000000000000000..4d3314933e92cca6108fa60a80804a1e0e8ec960 GIT binary patch literal 4317 zcmeAS@N?(olHy`uVBq!ia0y~yU{C;I4mJh`hT^KKFANM^sZ}8nB|(Yh3I#>^X_+~x z3MG{VsS2qTnQ06R6}Q$-kKA_0g3smu&aOBn^@0dKi@BGrUp)QJs=EK+Q>}1*{oJKT zrf4WB2{7FKciq1KH+%iY>n}E439HhaxBpIY|0&PU=kI@(t=V_{xA^_}JN}uyv#aai zQQddBIPzQdej~m4{8#?;^}m0-?p*o2Z+>6?eMml(lD}>H-tSw>7m3XO_#tlhKfC2W zy)EAV51H>#cjwRN(sd0RTMmlE-qBP!zwt)2khX`e=J6AT%Y<@WEWVf9Ed7!F=Fah# z{ts&B{B4J7}DL!1p?*5;*?P_s(@B7XK29xFK>wQA$>O3#zuIMuIRxm;8rc)4Zkk%B)F-aFpE{a$Nqa&He)`LP2j z$6mHn=aSelCx z^H^5Y*#z@&&cEd~{rQpFN1H$Q-*Jw8&*E@ock9s>7Uq2lZvvXu8(tGQu<>C3rcX19 zWDEpc9&x=p;HxB@m2>glS!2^X)r*g$OJp~4c&di3cPPmZf9-TU=kXyrt_pFgj{&_FlJ~Da7HThtc&BBJ~5_Fz1JiaR7 zaN(lGXWb_U-@f4 zquA~4={xe3zge@r^IbisE1Y&Zd}Vp_#@zG2E4TN}yqzMZ+r9FzZ1$?FO^!CZg994o=%5;{GXc4TmygO||)2i{A6upHz$@IqGKF1)OLye|k2{zpCW%j&zf> ziBhj8Sv^-L@4_-%h@o7%nGOguM+SRLXb_8>GYpuJS%W9DjDINGsj6Lh_ z?33M1*=MSrt&xZqxZ=UFhWn&0L;oFnjsw+GdN;bxlDWcp>T!xx?}?MA+B*`9CdhSF zB~OzM($}4|x_NoT%|lb3tK8q==3aSCYT;*2*?Lvw{)5dcCvz(~PT%gz{CCpbNpF7D z1b?_D`BLS`n?Ffw-x|M~EOLFuTQ6I2Yo)JB6B8-~UrTICzrWOW%@l9JHFsz1-9P7* z;Oj+IW}7;$`$c;2x4P(cufBFlW}8?m`j>^J1M%$>x) zDB`{9-6_%H{~0^Ew;9+rIId+opnUvWhDh}(7ojt2IzHXmvFBUvIoIlkr&wn0Sn~4X zmfy3~doSF!X^=U8;G)E9uD_^bYxXIuX zbRaS^{Yhx$tw{_r(VZ}ZAjT20$;v3=J&Qzw}9c3x%W&a2#9 z3m#=WoiOqCH0Nb2SXZ_*{;IlvIG2TcM&X0F-lNg4P6v7kb8J-cFFce`w9g?lXs(%& zak1czgCD%CIdZLdn4&d&%A(Zo*PrXHDptNNlDcNzGp@%;$-g@|yQh{0`^BhVOXx^_ zwPGogMkc@PbAyU5&gNJNg@b-?$`%;DW4@m}QE;>7o(DPRvwXOsO<5~l47^7njW3E(201kBfGVev!{7=M7@cJ^5Kr#om$~@dRK|1TX_4)XMfJuz0YHG zTU3kl>Pw|nifT2jg36uG@1-PiX=tDLpx-)G;Myi0>m`34tBI>~>irH|Q@7gEPR&uS zH%HFUzBu#y1-2Oz6P;%E3-|1Clx$Zt)m4=F%~&S&ktI%`P^(4g_?A@%nK~z5)pzcd z(U}&kr1E&?;ua&dbI#pPkp~nbub%tpxUqLa#uZqJqyGn3-%LYHcdOW-q*Qwt##Do&rxDM%Ddt%!aDCWl;meEnm)Vq_t~?B3x9o34xYW# z*3Np3%A=*lZR{GScLl_7wZ6K!{=Uf!UD3{d%?zO zXr9PX5mYUCQY3BHjh6efnpav&nIF2e;ZK9wiyKdtzpXQTlB@dA<+S{(u5*2PYJZp1 zIcFrEbz15g^<}B?ruj{q*%gFOigMXI&RN-Hy3FUg)Zv{kW{PXp?z|Vb!y;m8&ee-n z3WuMSC564!$zLbQ#1+XGrZHF9cD?(#kKdT(*Y<3VOFL{I*^#xrgXxmva(%BE?Ut$& zFHUDr_`9v(+SwH*U*{GUzbp8{d$=lr#n#PZ`5IpvX%|)5-0X<^v3%$F%&sz@G&w5! zS#GvO@}jRTrrAM$>rEDX$^OB}erv0hNSo#Un@@Np51+LAInhfn+mJ`~_p*zd6!Z1w z%$)BSagE!@;muvIrTnv%epsvST=}dk%p$y^bxOW*+ImIv7xvq>7W_TfE%tQ5LU#Qd zPnnkA{A*G7-Z)z5p3I4DlGQp_*F{!kPvgAyJVj}XQOVP8lUure2NI>r($7AYzC8Ke zy(Z)R_2=ULeSZI=eEamJ+jseHy&{+$UcI|@mTl-kuc&RS^7by>I+tJb2tO=2K~NR5$mhVvO42os+%!LpsvDAKm_c?Aw;NC9mu5{n9;U_S$x{aPZQvF-gCt zRybd}@A>QPxw`?UBdh-R{*?E$xN)-Z{^mo9J16d z+a~sHdbr7zijUjWthmI?)?41aI!%4e?KgFno6BuCUbuQMkKvEiTAx^x4Km_7<~)Z&%!0mpv(Y$zs!@sd`1K-}GH%j(=j=_DXKY6|0=y{>0|( z&OM&X!oHojw$bouu5ZmoB{v_JrQ4n#7UyN_|FmYk%CBSd9OuV&e*H1c;S<~IeJ;Nb zoLszK>?Zq$1)ZXoF2AiU+Z43>x#FMGa5^?zGbl(+o(nXKgKesvm+t57m-C3^;hZm=|ZF%S7mB08#P*UN=Wg#qr zE0=kjJ5AoQ>*b?4bQE{HO}+B-E(yHRY@ij!x2-<|pWan9pM zGiO>C+Xvk_!Y()O;nTT4|DXT=XMXXy6DO0Ipa0*Xbl|x8d%O0<(wm$a9!!?DW%w@B zDRWog-YRGUepyOG|{^K=&yT5XsI~;FuXzT0kWgHAOFYh(o z{})^Eopr}d#y9?pPAFJZFbE!<$ja&8$DV2-Q}l3ta>&&8xnbH}um2pjbywQ|yM0}Q z-sBncyJgdsG(BLn(U`(`szaQSzsu$9eo^MvuV3%5-v2Lq^Mra;R(JCh)kAkD?*9GA zy<_J0uww51rV!O59qkPrN*psD*E%_!n1AwM=ZUTkZq{cP_1~xR^Ryq9*?DeCVET@Y z2Y(%73ljH;UDV8F8=~CIwbpxy)Vrg!J^@8y5jGKk+@Y|CC=?!#EF!X?rr z-W4|SYteyRL#M#B&pREAYHm4RR%|Hm{Q7Xh$7^EuZXaZs);N8-<_u{e(XKi9Yn4L; zWv93ZIt3~S39#f>$1v*|UwURK`p!epZg#_oN$QK7yl#dFZV6e!3!>K11 zzu(6w!^Btk^5grYOApe1nnkE7rna09N|1~>)zKkvx?{Bgr)-o~R4QwUz(uVOFItUj zew>=!G35bk|KFdwdUao;Bi<-#taw(;xahZVMA^!Y29D^6Cj~w`6zsm`)Pv)C zHs{^f@8cD6WD;nQOS|vR`k~qTV_reId+0`m2Yjh6%}S{%S40=;O+PUI>Eiiu4qIG& z8d&BTF>c?J%lEFjL&qfWDl6kvo@J|ARw*25GFZ{s%vk8RK=0zJ2l?m!HL{#jQN11!yE9QT=@;Gfm&dI0Syc}GL-iEa*Et0yhNa2cUqQMNo6`k45f7YzJ zu<60X?fwN{zw+<+f2FYC`NHY@PCk8Xf8-Y5>s_pzh3CUJ`~F^@z&B52^QQ$Fkq&|r zHo3g+GSJ{GbzH%`kSAx~XPNN$`su&pDkf>4|I@Vo&p#gV{{Ir$LO#`dUT#>{YUg-+ z@n(gWm+p!5xG6I@abyTyw7C7Xp(3Mq$Fy<@9*(OG?&sz{dv){sj{mK~F_s^_*Z9WN zJW9>El{8r_JF4cE({<KhJEnOG}hLyGHzTIH)r?PM=>Vm)&dPd1K4@2baZe*@f>q zH{qPX>4wGr`8qvy?!xD~kMCK_b?6AsnrHFr=RQ3s9{=c5@cD#XCEs5%AIrK;Wqp3< z?9f~2))yn{xv%IlU&w*b;&o>N%2gznw3OS5_t*Cx|6jp*eDlRyeDk+hep=R^d1}+_ z#ccPY`Bs>_J^tu5_vZ8l9VKyt=5?o?-7Y^+OyH=mdJ|D+SsGz{beZnHyN`1Fx7g;b zY4ASv`GL`gMy?KyNkVeTdNLO$Y>PfqnbvkBQu=N6np~ru%UpNy-D*)e{CsK&XHBKP z_C|G9hHKwF0u|COeBU{r`C6#}^Q7mdFRb?D7R{a)yIH11@m%AB@;$7d)m*%GOknS} zObB#XZlRD?aXodCrsFK{ybi6!7hgDh__?$Fz_Y!w@Bi<(`ZczReY~lFEI$@7`DK1G_!nu!V;D+3!5I_4W22 zf1dNb4}I`>_PLYE%nbMboGw{-D#>Pcv(7TDy~>TLA9lXEzV3e1+yl@4_dV}Px# literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/ebwizardry/textures/spells/containment.png b/src/main/resources/assets/ebwizardry/textures/spells/containment.png new file mode 100644 index 0000000000000000000000000000000000000000..029eb68eb854a6450004c4bde0e9e74d5e854538 GIT binary patch literal 4994 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 QU|?YIboFyt=akR{0L){vp8x;= literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/ebwizardry/textures/spells/curse_of_enfeeblement.png b/src/main/resources/assets/ebwizardry/textures/spells/curse_of_enfeeblement.png new file mode 100644 index 0000000000000000000000000000000000000000..2515ec506127ef198b850afd75ad4753e458b890 GIT binary patch literal 1726 zcmeAS@N?(olHy`uVBq!ia0y~yU{C;I4mJh`hT^KKFANL}Y)RhkE)4$}3>g>`I}aaX zU|`@Z@Q5sCVBi)8VMc~ob0ioT7}!fZeO=ifa`Ff$NGY8<_>6&p&D+z(F(l&f(d&2n z@1%;de>h)R_j%LhckfDWdwFZKPMrQjDBIPihpDr}P%+M<=i}2;E!zJX5ARPhdDU9= zRJB~q?T7-`L6M-AhSnf4u~XY}zSlncE~B5e?QZULY2Obj{%OyC`aYZU{P*8^pKI0R z>I)|P>%Z8zeSOUz(>XRG*SQ;xo=z@ETKM?M!Vm4~hu7xbIIu{|xYfZYex_$1*KEOQ zr=OHBVhPeb`jKZT=lXTEFK)-bczg2m)oSsWh^W1B40ryoTzCKP;uAjV**}WjMxDBr zv{LDC4DbEx-zQz$eDPJv3%8A(j;B{@#D%(Q@`d-ML>x}%>oFM zes;v^`1|?UDa+Pma_dV}2Wo3?`q9)keM{VArEcA$M^o0eS#J`QOqpnU=33H>qfyKJ z+IBV<8~wZ*zis`&{q0SY+mpo4#H`Bf@lSuO5jXLk1kW1PwFL%U?~b(vAKDf$x%BGA zs2;BLEQ`rU_y4+j)Fap7&XU$_jz9l)wk-)^n<^YRXQgbri0#7%3D*|z^7kE{o4b&A zdl|n(3H!a^J*!`&B~Li&f4q17RX5kONpp5jnf&M1%a3PS-yCsj%fB+Oee>%{U-IY3 z%Lqi?xofoIVV2nEtv^zDeRb;sc5O3xci~5z*)?U87aaY)UB8bBM?HJiCTBe1Wg3^0 zN6w>|5Z_HXoBFmttgtp(ml}?XBIZZVB&_;~l~*NXd(Y4MTE#b)H|_PZ@Y)xtYnu*t zxyxQjyB^)TZOP-Qn`P~8oU@I3@y1X8<--cIbq{=B8n3dy^`R~IarU0x(k1)sZdyI> za*e(|Pyg|D3yIBD7ccfdlD(=?*0)ohDL5{xrQExsJVuve{ml>0);$UMxNYLP?|YSV zC9}(I-u%K-M*)JhCSa^V)~;MlE#HcF7%|$f5Mx0xwzl?+LvDMie)B7 zmu%QBdsg?po4s3sC%P{0a?i0hJ6^rCSQL?8Rn>aj$R_y(@5|=cSsaOu_hZ|pow1O; zy6aWZl9@h%6;;`1OP$aBbvd!w*SoEER@f5Ot6c_p$K_`Iy4lpX(Rs(CNxGd2_gVAw zex2KyrBW*)GnFr;RPRQ>cUjhIfeDjCm&fmz@=|!Km8y>BF{k*fuXoZi4tGi3Nk6w} zpR(%NwAVAf1gwqvvzGJm*;3mxk1z3B-MHLl>FQ+k@ywO(Ejn|j?wfS=?ICNyUpK#2 zw%7QTdLCzQ?Fdog*(CL#pr~Tc+uc@r+Pe(8{!BNyr<=GrM7;U?Cads6{l{MRS{3NocVQ#_qh=B_eXdGhnc zsG0Y^{*$>{CenZ9)z$|`{W6k^idMN0vA9hCB++3Mr8Z>9!WZ}3uettp6jyz_&w9;#f@^=pX)#uz_@6B+X84%+&@ptLL z>+fZLzW#ZS@9U-wYpOP#d@VQcWz7aF-zc@Kvlyn$`dTX8C2r8-;eGK|PLfk0r>5=4 zxy`@tcZ985H)HFU+hLbeY}uVyWYUbI6dQ(LX|&73_` z`Zqj2dOEq^-r_^|^02bIQHKiZG_v2#j9VRi|Hk87!D;1DIy(f`YD}J8s-mAURjBUU z3r6v2VRNm_s*RcQ<30QBEg1IKWED4^I(2Hw=778zO4qZxUZ0vLV(_yjpI2ISZ%~wf zP5Pt{hc4Zdc6{^4`rgVHkGtkNS()e6-1#Wq7<<54JttI-fq{X+)78&qol`;+00?JY AR{#J2 literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/ebwizardry/textures/spells/curse_of_undeath.png b/src/main/resources/assets/ebwizardry/textures/spells/curse_of_undeath.png new file mode 100644 index 0000000000000000000000000000000000000000..d36d96f3c24e4aea85566cba10421d43d0120e71 GIT binary patch literal 1990 zcmeAS@N?(olHy`uVBq!ia0y~yU{C;I4mJh`hT^KKFANL}Y)RhkE(~)RTp0duSK0la zfq{Xuz$3Dlfq`2Xgc%uT&5>YWU|=ut^mS!_$SuIYuh8|`f{%fLJ=oL5F(l&f)akeT zWx@rI)rT%${(RH+n_t&m|90zR?+uH-w>OHE8XqTcG6o7UKH?P+aHCgX1Hk(^z^F1giNpFqc8>{f5ZDyl{qvM^6UB(+(#nv6Y zz$+jg<8Y-w{0^^Up>YettDfGTf@e~{zB^bm)c_zukwg>x0%lk=8?O`C8!C}|O(M^!)I$Br+^nlJ z@60c({FlFEW#CsuK6$G%C${M=7CyFYuHV*Y3)u2jxR=acob0MrY43WCLC~F5#8GvU zo}yde)dL~5*2e9Fm|A(()8RjU|IRly zH1*S6Iq}ki*YUsj=GT6!eD%`8y=?9R>-~q`z5UI}D{+_8lgW`=WQ)VLo_*`DI6bNr zYU)t3XqwETs1Xw6p>=Lq?P8l<#rFO()(7qF_nbVfzyH)$>+Xtq#-?UR9x_{3zWJz| zla=%6jbS!>$S7JRy0X;Ja1uObQD^lG9hdZuXFGky)~b1 zvFCrhJbC}}t1rLxpWC`SW>;Bz+TzVxj{4YeNw!T29b)&6 z>V_^|3?9~UUrKu&n43D|45kov1skHV?WFPpAB}O_wdb5`v)@3x^Y z*cv6+DIg%&%}zLa zb~n#A&gSq1O&uF<$y0-5L8U1z&DAWp-L3by`1A)oQMuXM>4DXx5#5mdCB%?>+fr$%oDJ z|4fko|3c*b|HncJZ*CZ#yuRUDTdwudGp3mj3KPWc! z+#aWO54`k*CTjFVFEsHu)4U`{!89YV$+n8uqD{1Kg7b5;njh~{{a$-+^L?NC?v=0J z+1P}lD(1@TGxpy}emHI8u0<&`lUg5syHxZf^rA_FYE1&1>&{Xq#rZDqy z?2fvNKQF)izT%{N2Gh*)pB85>zUJCHZ^N!tH?p4e?Y{7;B-yOv$bP2BMuL+TIUGMW zX+@h}Tg98_XOuG1oTfFebNJ4-=7pEe62&9SxgRw>W!gDOS*K(g_cQmyi<&Z?xI|W8 z^UzQ%a^x-44N|o$HjYUuH4)r!pkkl3FxXr`rsBFrCAK&LmCw+5ke>=PFy0)TF`VsN|>kJi7 zzorVLFWh?L{fsF}4NXT<13MSra9F>*)>2!hJg!PnYR=w^k>>VZma_Inwtpt9toRTa zHre#9M8#%(y=>b0PT`M>K^YTj4;Tk!RN-}C>hSMT}r+h{5nF)%PN Nc)I$ztaD0e0sx@{s$~EG literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/ebwizardry/textures/spells/disintegration.png b/src/main/resources/assets/ebwizardry/textures/spells/disintegration.png new file mode 100644 index 0000000000000000000000000000000000000000..0039d680a1c768c84cfafc2dcb97e48482da9078 GIT binary patch literal 2076 zcmeAS@N?(olHy`uVBq!ia0y~yU{C;I4mJh`hT^KKFANL}Y)RhkE)4$}UNao6ombk+ zz`(#+;1OBOz`!jG!i)^F=14FwFtC?+`ns||~ySecODGiQGnwveQL|rfwk#$%T6#donLi;w&giGyeTmL&;UT(Mb zqDk$_%u7o=vnPAyWMudF=B|3Af8dzl*4CzmKQkH~XY90p_Rk`Hz1^E?ePg5At=5(| zpTCy5^Ua{*{Xv^F zwzQ50;Q)u{XZ>1EXfjz`{V-pvV}a6?)1qeU&+8w!S@c>VeYw_kPKG;wTW8#t6+FZ9 zelx=xTP=o0mNMBpoE9o)o)v1jJQ56?Qz78!5_u{9(cZ_RJ}voo=Eg6mn10~Y!H(yB zT4{3cjhU7mzjeTmA)oP%LYDhG0~xn9UMh*PM;^Nfh#qLRX!}+D^V=(~=&-9lO@B&r z_V93|$r-R1ybpZwuPlv+@5|Pc5)&QvMmaWkv~c*VI9>8=WZBe_^yufgTT^VeOYW4d zelVSVH_MjKpY8;5R+>2*h%j@jB=sEJ7k9--$w)@7J$=FUBbW9Gv6_D3V%_@g^5X>y z0!ogBy9dp?aY4y^AN$UF{qr^1zk9hn$~6T9IJ2{kImG9Shp;}{c12LKlWXZdrL$2} zZ*X=>O>}z1a`=YrtWRgZ+PT#IuY2?0@{;9hV(JP)S-b~4qpKPtc)!XS`YSzLEa4H- zanvKEQ|1U)r&Oo#oT|Kd&e?9gceWj$IQRF15AriA|LVusXm2RVNaRY1i*{w2$hEQU zyNkl|3E>@QCQm+>EFw~rr1SFa!Ub-IO>*gXOp|QNW5@t9lum1TQ0oL8=Z#Sg>&T!k4%)hBvU#6z*%@vmUaSh@6TE4+XEjkvK z_rw$*xD;ru_^zU75xuCPNdz)CH;&iQ7ng30*{ogq|&Ep?U6)woQbn#O`j$dYl zqUwqZpC(9kYcF6@a@rcB7Tm$!bw%5kO}M@P;j)D@vcsR9;O<$gd2prnm%5*JH+IVZ zetiBzdjH2;^$+H19&PBE@O>KR%F?t9$!_fjAnZSwb-MN`ve`&g~#6vl)?bmAl5SNZ$TEZna5Y4+wruVNV9 z*ysvxD*Gb))3#~;@&l#nBCLjU9OrXAF4sAzrMtpxXJ*a>-*mmg^RvYA9$ResnYiSa zxkWkG{rwXcyWdkcet5sw>9TWHV%|3E2U$D4gfo|?ByuhK$>njI(R|ID#1#UDMW-2B z8<}opY$#3P%e&ik_oIQ;N2PoImn|wMhTF|a`>gf&hic+BF5Tcg#!)ksO&@0MycVi3 zd4Y%8|Ha%B0xYJ^oN_g}S!efawUna1UmJ~gtnEMacK3$Q?Vk2lU44BQBq9#AYA&58 zKJSKb)b?qPm$gs->Rmlm>fSo{xw9HxJ<@bAnbYxM21nt!gk4UC)0b~~SGMj*_Qw74 zO9JfN_fAdL_kAGWLv^XfPE3GWD7$>^rjayRJEHQl$;K|6Ff@3GuhyI?r`Otbh=X8Rvi w`R1>FI$Ldj%(wV_c1efJ{Ma9Rj@L78_#ApQl}DhAfq{X+)78&qol`;+0Nh%}lmGw# literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/ebwizardry/textures/spells/divination.png b/src/main/resources/assets/ebwizardry/textures/spells/divination.png new file mode 100644 index 0000000000000000000000000000000000000000..bf5999c6f1f99cb4ac90e164e745542098979653 GIT binary patch literal 5844 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 L`njxgN@xNA61g21 literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/ebwizardry/textures/spells/dragon_fireball.png b/src/main/resources/assets/ebwizardry/textures/spells/dragon_fireball.png new file mode 100644 index 0000000000000000000000000000000000000000..3baa68e86fe0f774e376b543aeb50bba68e3fd8c GIT binary patch literal 5692 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 HP6(_s0 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

    1bHXwF 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 literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/ebwizardry/textures/spells/fire_breath.png b/src/main/resources/assets/ebwizardry/textures/spells/fire_breath.png new file mode 100644 index 0000000000000000000000000000000000000000..0e0ee447f6b111b7989f950fb424d1eaec4fd416 GIT binary patch literal 1938 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 diff --git a/src/main/resources/assets/ebwizardry/textures/spells/forest_of_thorns.png b/src/main/resources/assets/ebwizardry/textures/spells/forest_of_thorns.png new file mode 100644 index 0000000000000000000000000000000000000000..16fbe282c1fdf5c40d22608d4308735e69cd278d GIT binary patch literal 2579 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

    SbXLg+mpIAfwzn`xEs1Bd5N5y{7~cC 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 E0Eu@du>b%7 literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/ebwizardry/textures/spells/grapple.png b/src/main/resources/assets/ebwizardry/textures/spells/grapple.png new file mode 100644 index 0000000000000000000000000000000000000000..da78b69b20629acaa3e2f4ea385647180a60e011 GIT binary patch literal 6134 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 literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/ebwizardry/textures/spells/greater_telekinesis.png b/src/main/resources/assets/ebwizardry/textures/spells/greater_telekinesis.png new file mode 100644 index 0000000000000000000000000000000000000000..190a4cc16d190f740fa32775048c6a89de00b5e4 GIT binary patch literal 2461 zcmeAS@N?(olHy`uVBq!ia0y~yU{C;I4mJh`hT^KKFANL}Y)RhkE)1Rw1q>7GBfX9? zFfecyctjR6FmMZlFeAgPIT8#E4D2PIzOL*Kxg^E-*z*)w?=UcMYI(XihD01bIz4+$ zYHH>2`uA1WcVCP9U6(e$*yj10okm7YN<1Ro?k`&UM140-T;VIaY>L||x7!xSye{QS zm}corb9%)ttP;0KW$D`oEUPrqgf<+z#d3vb8YBDpnKNt8%`E;_yMFKWr+a@So@br$ z(`Wt@->|T2r#_$lzjM!d<#+ewE&s`%Ww*Fn{a12UX(1!Sf~!{pPejRk!d7o0!)Sv~$~`u*8y z5s~t-3=9>w^^Pu9-}caoX-WMz51Y_~S-r(#p=&0q8ye{(+jbU+X|g8n^txlo93*%( zO>&N1-v<#Vho$>k7t6Lj*O9-q_m9@m^UOMDfBgA<`u4%e4?J7c3+Ek*>edP=^bwfn zzwjD^;)JC}LDwc&IsTk<^I6!fa}!b}>jWOGWU}B6Q~o>Q*EFWT->mN2-h1-RcDX)V z#x>S2s!m!0Lh3dx>K{WorpQhGsp@sK!z+27&bo&y8A8`AI@2;UtMh1XbY`g1rwvEC z_gC>rif!;yI>X}s>qSb-2N90KLLnxbd%GK7CG~#X(0tCgC4|M%BSb5B-IW^~tIeM} zx$F#D6tjBKxGi9DS9{JZ9zwb%>e3jwlhGyr0=o^k!a*ICCaZB!d_DE;?+dC%@{gH8>U)#C0t||8Bfyn0C ze=NtOzU}?aY@w)d_D8?F{6pFL8s^r^(p&sA&8~-i4Cy#6`!s86#e)L1{Sk~d{Wh|f zGxwhPv(EO4mZ;QMtCbxV`|O?_{hGRN*VDNoQx92qzR;;IJGXJqrKP54B0E^7E{)WZ z-!)nJe&vkl`=!QeGbi+_^RV;1)sbMF*Z;stsOq_#R`>M9r%GEsyjZ(-QBy=%5=B-yBMqt)}b z+_Jw4%N!Y7%+H3bd@;xFXhyQ|Yn}X?w#O6Jd_3InUEb!zaO*SyGG6t9n1DU+p73siT&DY&58Sz zIGooQ_Oxqi=@eYOW@WwY>W}H?x-U6vpBlA z6tx&-$H zP0w?QXm?O(QQ=^!(cE||q1An*fI*M!WRvCX4?g|uSj=BPZT7!c@;~3_*9-FBsQ z@qcvZUe;c+mp4W(K8DqaV~wfATFL(75!nHDQ*64^b&l6(*cbKBF=7J-lkI?G|gPtYURSoQa$>X*Q73Y z2TwCUZjt@6Pi@O?=SOku_F9kKw|X=BD1OpO+$`Z9MfQ8equ1XHf5+cBcI=nb z(d;^S5CHksq*aC>u*6?ZW8_<&;0*0skdyp&+{8L$MvVZ zm>;R?EnG4!p_I){`42-&|Axul@osC^J$oR!y5>1+;{+~$t(NsGLb4m2)%zx1d-Aen zvbMVBl+_X0lE)2qUbDzPC)eHOmGW58qIA&%>?Nj!t4{!P^ zKKSY~?E8JG?115$a>o-dH$3t!XVt8Iq;m9`=CK!>!%v&2SXj&M^sy`LJ1lv2VRrbr w)Bn7LpKp6y?6Q9PT;`AQzaM?wcAq(8$<)e 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 literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/ebwizardry/textures/spells/guardian_beam.png b/src/main/resources/assets/ebwizardry/textures/spells/guardian_beam.png new file mode 100644 index 0000000000000000000000000000000000000000..30eef9ce2fa4f753a86460d29d47aa6ffc8702ec GIT binary patch literal 5882 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 hA_d#A_d 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 N!PC{xWt~$(69Bb1ReJyc delta 2176 zcmbQE-y=9dxt@V7$=lt9!G%GVA&2Eu#4-j32F?PH$YKTtZeb8+WSBKaf`Ng7y~NYk zmHh!HpNI$#cZSI(1_lmEPZ!6Kh{H>#*Z0JPiXOLres1>Mxi{y|ysLZnUxS%~6pyNe zt8n0^5bsQlr8f?_)k!S;(jK|g_3{KRLocVEf6me@F1PBLT6H3FG6FYpoLXI6tzTSTX;l^3O$v7pHaF^K^7x^Z#bb{h;7#Nu6_&a*|cs((1k3M>-GBc#(QJ zcL%ddEW4lV1U`la<@%`%EYEmSXId+~sqy9Tm0&iIJ*>so@Tx&TP{mD4sMTv`M!cfM zw!@Q(iyA(h@8V}WXP-U6+5NR(!;#PD=UqH}KE8X8Pfxp$q%o7mi3qMhE|*0P9WFNn zd@>BIdY%=s^fU(TJaReTLPKz!z5VfrSu^I%nCkP4C+f|g%}jdGO55!%w(b%kuA@ zZ0|iCwsy(YjG*E*Y+MfmHP7a>*Qx=62IC1v{^iR-C{%k%QdULHU}+UdV9y`;yrucx!P^4 zRNN~pm&^mi%u870dHPd^?uH+)%jc(N z)y+N?Gd(`<#=)-L`45i9+j{5k6Q3FwD|3l+`>eEB6)j7ixCbAPKIOhy{9n)OxX!fP z_@kOnC1v(JRsD5t_Q8PqnUTkTNow&J7!*%<7-c_yU%KYzH%iMxenl4E&-!-f2Lt!| z9Ua@=3(mSxeD&z6`i4|L1ye!CcE#SX$(q$&uJOBD(vQ#g`tDx7{&`L*+bf^el;l5* z8s{CfpInr`KYd^I#op=0so@#Be3@ix8rpkHrY4@s(@JvC|FA)tZ)a5F()*IBKej|Z z@veOnReilZ?BI=UzE{$J{KzC?IAG^$G#q(b~ z!L;|h>!MAJE}9{1Yhv2AM(;bz-2XPg@cGBMhZ^ka>J{}xP32j_dnQ^Ru~+N+u=8$s z(US{;@9yrLDjU7ccv~6IY1Y8G_4ogKFa(}$n)Jd=SU6CJL0Imzd~CDbyTtR~GbN^H zEj;HPFSY#QZI}HoFX&Xg+4X99#b%XMkCGB*w<&)d6|@vnk8e|cEGas*ol&-Bhv{_P z`#%)Tb7GGF%08ws*X+dm{Z@X7aWfx2b`^UYd-TCarskiHY1g`Jj=x^BJI!?V^?QBw z(Z!rKyjCtQD=hicS21~8aj_gP)8L=FI7G1Z8`GVt$!Yd{8={q6inS*iD_z`ay{$Q->rn#dmV-Z}?sI=& zp6{RcgK7OIvGw==GF4qV{QcI)kD8lWb>{E9;4S2d~_d4Yt z)y(HFnTV&<7wGy{&)e{R+40QtZ3lRhii|E!u8@~%>8tRR*&d`Qd3qIJB8MCIF4+g6 z(KZ`D#qHZv&C`%>X46!j*SY*!|K^m_S5wrT#B%q}^4_;os9|sTUH{#;RC2O=@>ksS zOEF=*T*|VkN+qA~cANM;v7Q;{)~XYYRF8_Z<@=3kF_QoIIE>2c^P`ur? zuX=~ywqO#Khk91@#rT<0ay&`L{BPFArUAb^Up~{SRUH{C~>D@=^z12rN%Z zE}8!Eh@#IQ^Qi5UI)z#f9x?2Y2oRAFZVGG3J7Mkp?bFBQ)0sBZe7^p0gMUTdyjbb& zMaI#L75^`#Z|Dy#vUYxS?pdGwsgr5_lqD+DCGKz8a$w=& z(r4#i**l6Jw|z8gq7B3M_vMRM-0(ZYJGbnN!i;ThMp{q5tjMy;o#heoz4Q3p#QDn( zOnPVGSaNCJKSAc?<($n<|)I#z`)??>gTe~DWM4f D^X_+~x z3MG{VsS2qTnQ06R6}Q&T%$_8@Q?TX#V-Y*1d#p0-=Q-{lIR1UQZ&sSgrFU)RwmcKx zq%re`q@|{Az4P<@{`J4b>sS7KQ?xOxdhNXZcZ&O)_0R7A7dQXl^XGqmcE6u*@$coH z-#-+Kv_8&^YyY}uz5E>g`OG@|&!3-v-a7hy<*n*P-}&v;e0FVq_if+0z3N^cOYQdb z$JX~t|2$oG@BgH|WuG2DdVl;T$1%M*J{ONpcKWm@{I2T8rYn~{e%Z~7kC0kFG3eBu z=U>=27R$%)XMO+p_Vyb;KibW&<7@r=wbt>k*y8U$1M1{=t2@Pqi`c#YbD4kjuebaE z)pp+9yZdf++-~WeLMvb0oBeC!)aTOTeoiyzB~G3Gas7w8^TMBBz41utg|vzK`ln9( z6KC9;aF|c|PQkqMqGH}>KDsi( zUb$0$&&T)%UxkQy2IgiKe`@zw;Ud3f~_}a$;hPch*|S zmTwrvab#oT`Glv2Pc0l3rU;c6i01^YYPh`U-B}6l^IJC_xt_U%Rl#f3$%Zx-rZsc8 z|7^VT;DW}=lyI+=N4>Q7_RPv!xAa<8sFbNru$Z{wfbyS_TFB(YNtb9 z>+iCZDmmd}i|*tK4ljpGRCse;OJVyY1Gi>^D0utNks%`>gDC zZND&Ih}F+2!Toc~eo2b2yIb;EcYECKx8JPo0;(7PGR}G^T~yx}Rk2v@$fx4DwTq5r zZk7*bIq4~wrXW_#P$cJVI;T2kYf%2XWQSXOBe_zXSB5!loB1cc|G&h$ ze-D53KYXWu+<3>Ad8Yo2OjY`tOnF!HnM&6spWZslX}9Jcz36Sha~DrzoBn-=cAySJ zsPmcALyrAxwq7-)d{MWw@A9rU*<>uElZsf6A`qpUY@<_YW6SkIh&vukQ z{ekmqw##$BHJ7GKnLX55oiDxewo;z-qP(D@s}{QVw(89;_$*@KUUeqfW%`ylx3qZ^ z(|Z~6md;z)HPbn7>JAYllh2(;x;k$#*`%=rrGypmFA(5rtonQ9_?cNc=g*$vTOs;s zaaGG7nH$A<8!W;Tw>ST>F$+9#`J2-5V>jB4lykX$Q!$islM|a=c-_uf{<_qx!zE^A zQrE8wevdlHcUke@k*sW+hdn_X`(`LS-)!=MS*h%Fg4owzTMTA;O3X2EuXl}j|883I zew*k*Rk_^Pf1ho2+h(#dBJz;=_grJ$*K^-5H%#6CYtq7`wMUmfe$y9rJTN4^YKqpA zi~7yS+k6BU_;o#241SaRyG}c-DTdLKX=Z}1b(({MyE?{m&!6QSX!;+Z7p7WvH0+x;>Kcze|JuNJag%% znQK=7PrAL|Tge$x*LVFan9zO7$~q^f$al8QEvB_zdJdUR@76Byo;_Eu->gP`eRFts z!kPB;2`tx_K9RqyA=L5xrOQmQ#SWZv0U>`ul`Ok&|KDlq(n5oh>zQZjD*xvolS$;=*CyiE*+g zTTE86UEAP!=2C=c*Xd2?mK-WxWxmQ-zWuIc<{l9hhbsG38^!Wv=XhwWIoc$1!BuJQ zb%PaAD~{`j2`+Ry=2-Q^pMB>m)|7R#R=nDk^4QU1QDsY;$(tklYkKX)UQW`D`^5YC zYn@f};(L?dd2mm8^Hixz@^GREU&s@ke|uY67)nJ1uFjNWd-*{i^`y?yrxrfG?T*a5 zDpuC~>+}|OKlJMy%hyodc|8sri|qn4LTVTNP$*fvSnP|hWX0d2tWeuWUQhB8ciUX* zTG#gV*P9h}J1=ybR~_#Duc(xhvisys;~kw^l1t~rZJ(jBVcJRkdoMlb-DBDv*SdK@ zDYviKtO*S|bN;1tKi&~A>+~_xB<)?hm{!b4?T$DZ)}@!=#5q-qE9Qn^xW`E*12ear zpJ!X64H{E(Z+SX+#!p?o*e2v?{M9{aojS$B#VejBF7f7IiktG4v2TXy;)ji43jZDY z53TDu!s=t*b|OeAP2^l6-_08;cdVXk+~E#hn03G7;^C!LFO840{;vME^LDbL;{ADl zCowi;^k^CRJz=@DFK-2(w(G)8yjg0~MIX9;KK;&af{gddS@CxHMs<5Rw{agYdthWJ z!rYg{TE*fZFa0*d^i=PLwa@n+h?B~^`_<%Gi`x0=FILai)NNVlZP+Js)^U;G42{m)l)6!#?}Ck=S1+Ep#%rg%b)O{HRSj2%X89K#=07{7wz9-_ zh}_)o8dt(M`@p}lqtPLGuPrUUf6Uvlc$KQ-K0v}^XMX^(#2{Iyi~_D89s&6k!P-Mp5uuvz8P zgvC=?XJ2F6_~+0+#eE)ZtoICCM3U}%sqFAqCi3_a`OqjpN+2{Fq=Rux#5Lj;I3w0?(<%o4~uGi_ev<6vpb-D16SpukR!_qI_%XG>N08{FyB=X za`Rl^DaV=-FyZYkhMPz7!fz&h3hSG^r*)3R=asd09Iwvqu5Oag{3S# z#krLs?-kZwV0xr*N8rgM<0EQ;hV$CQt}0t^zZ4SGR+Y|m+o)1osiW|Se4x8_Q|768 zljko8VwU6GVqw{pr5Y{cB!@?+ds06Mpsai`SdG z29qNqZKifOeQ$iS`_auqKB1Lv>Fa;#N-nlOVy>*p{%*s$O+PDt_@1A(DQMom*}_3h zD?|>+s~Y)pI@okxur5|O*CH3c`I&IvQ^_y3tKLoDFv-SIcV$MQL3pcFLn_5? z2}JLScs0ePZ=rD?8|y)y4R0n2Uvr$c@^jbItF?iFYbJ@VY1k^(b2{)*{x88RcbD+W zDadB;=#0PWdScPXT&0UEk9K)+JpX#-1IHO8Bpj#j0(blusy za^jJhmoK?R%~$1j-p%)H%j!E?NsTXg=ka-&tUFa_B^tFvZi2P;xoJs^-biHExGYL zeDaQIhr9lKd&rf?(Cn4Xn49l>mFIu?7gc-JL?@3ItIas_CvA$BRG8eLv}KFO!pk{A z$5$;^%*qJ$4pnQ?u~ljpwVPqqB0XJ5H8`eub?Svq^I+~9lG~P_osg=O(DUBcIAcpw zsmPYtNrwVvvzV=%njbrBr%cxZ@szbJ+HBMQnzT*!cven9opK8` z7n~QfeEWj^Q*uh084UQNoIkAgdeyyQvfcK#CDX2La1COSSXkasB{b0_jE~KGk$dza zZcW#guz9x(d|!r`x34<%;N2Jb8D9?0J+gG2jk}{y*ZIX~?s!a6w+WhB71?odbKIY} z&u-H_&E0nL3;pj1eXRYn(>-(k%E+1pzV)w;_Jl0^7<1mK=*s5V^2fJmRXzFT^X2Q0 zeED7VMn7IJ{QY{h{kHOtk$3-!@Aqbp_>mE2!@$76mgMd3!Z3&7Kf{wRUdfLb7#KJU zJR*x37`TN&n2}-D90>*n2KEw9Usv|WOk4~~8n^4_1u-yia(KEphD01bIz4+r$WhVb z^>@GDt33ba&Fs6Wg1t6PNj+UhR1~~2uLzu;WR#F3#C;-*B}U`P-Uc0o2u8um6V5dX zQ4+c=rf!`YDsF2-F0d$fD7-rK?oD=CS=l|~@AuBNPi#&6nR9M>^xfF)=l}mX|MK#G zv0%5|qW|45GtSz*znaI?u~3Y`!TSiyf?W~I)iiEYdK}*-dg?X1?SWmXn^)%F=`avZ zNMmR;n8UHMIaled$qh@E1ubnCN(7{wI3C5my<=q&{NVX6#iJ%$k4}8PNUCt-!NzM^ zWp!a~y1W-;6S5arpOkVe_!+n^setuhaMPFY3pz6d`uUYr;TDqFDp4ke$cfG%L8eS#M74PGJa8-Q%u_9K1bxKp7F(@+5zNvl9 zF#T3ai#o?Xt}O}ncMf_rEfo#6SUi6oK_ffrx|7c6kg#YQ@oMWMRV+?sGoTBOLNNfsUIHN+datJ$k6colDCEA zs|WL}^O6r9vlo2br*J9IMT_Sohmo-IwX1zbn>lVjdiYWG`PGKG&K}%vV)k{!xN_u6 zDg|_IU&HnA(?Uy!=^tKv3xDCYWW~x?$Co;PivIHczI^&~T{LIa;GTH0VOq+!RbSW4u@{bhp;ME@e(3G9zS-^@o}c|bAtGZ| z@8JR=9o@&rQky-$xXjqQX^NnpIp6Zh?s9WHj3&C=h+GsKs}uWKMMCdQj!cXs%SCQR zhJ|bX2znpQys<$xnx!)7B~O&q;hZ}krDh#=kkXr@r~lvX;u&6N?dp2{kFR)Si&*vF z|8A(SEt?atVrqy|UvAWu|NqR_-2P~kvZo`2uZ2OVm7!(X!X+$>K@DDMf{eWmg@U}d z?;ZJ2QQ*PPHT%(m*{|wEp9I}isZwItvc2sCI}^{FaG&fG&Q>`KCs`J?o%|*K|ID?g z#R8|E&7Q0tv0=wXeTEYCLk}G-YBk!~9~LOj&8td^)M3?27tEV};QjZ&tNW*|UjI+A z^I38Q^U*!l|GCv{c6YDumrXppS^whYyN+gp2T!TI@Qcvke3&ukXTQDws?Cy1u5IV% zXlI|p_+iQihr22*+6^W#9%mCyFZzAshQ(ZYp8YMW+v1O%IL$usbynh!15&3}uVV0s zF_dY@{O=PX)meCDn4Z{rPB4B>Gh$39i^e>x_;p0VKi z)cYI0=bC@)DtdE{@1EsHR^j}=mbNQplIx5n{g?TtpJsK=p1=0cmH7MT+~w;Id=+2X zp|^fsu&i&@wO9O*nJ-@_dugo55yy~rZ&+iJUdxz(Xx$v?x z8uZIK{{LriX0dyOMXizd^}NLAuh|VuCZq{jPk!|A>uiCrW%*o7Hchy(rZ&x7`?dO} zANxM;DDBB(=zJ{b(Dk=%_9;z{ko@+hdj9Ubf10AIj&ZxbD?GNFckQ)|!q0DZR!)j}F_tsd zme=)}2gICc5b#*p{Lt01StH%>(8KfbMYVp7bDd{oKANjIX`)|=&YnE=G_|8$sohmC zzsvob(igD8Jn8riLxwAFL-w%EO-DH~0KXlzM*FCF9(_xd9ri z+gLT0tefb!T*Cfa)V_>YFPt|gzmeGVoBvDQ`5Te~rMufFz36;!Sy%0TrSRR2BEeGE z5|14gc+av>??8jdg4YQa8%)K!U#o9UK5zZyONsaeo-bDR*JYBAKaj9q*3jwSw|zs_ zZM|K)cW*3;bWm*3IPoWvVV3aOhptx49EY11zCN-jaF*ZPw11n9HF2D8u(%Gg_+06q zAGvj*=FP&#`-L;J)9#)6dS=gaF###B@~5-!{j7R$_gT@D?JN&9Q{P?jTvPcj^w~Av z2Wy+zcc$G)jVV7n)kJSrck&wvGm+e7dEYNIm7JM*zaj8S|Fmy@r@CYI{JJ)K&c9D0 z@#dz9H>EVso<3*FJ@J&%&9bKT-_I>tsaxmA>(Lv^ot9KlWAo*N+L8d9ZFRzq^ZO5b z8U1n(-(2u9D9l7}VV{j~=j;0mm4%l6{Ul$!#P-|@DShks`~KmtHLGsxG${_tb5d0{>9L6y+&X13kAGa3=L9cBRf{=(f0j-S;gvbF)LAdtA=mWq zs=YNgg;XzzF57GDV=+%{(zX@<-&RQd+c7g|$;@}t)}K(V4wyD`e~pRwrGiCgWRzwn z9OOOe#I|IrnhlTOIwSq~zzEc%mA;Gy9F{o^RK`dmKwv*=#16 zdO?aykbC>3%b$3)B+q7Zr`FznX}n^~scb%Nc8OM3i&bWATP|hnR7rU}!Pmj8_tesj zmpqd$8m!ILt*LmSalEho48&9Q(6zOopxFfu+8c6lh)8eZS|dtN@dqr_3KbHo0r;jf@>)E|$3s>r%Yw(iy z&Hd=akUlS!;r9P||H8Do{&1gs>YSk`z?3*MAzkp)x&Eco_9x^B>j*DA^JmtkiAwwL y|0%R%n04zBLo35MpPK1qY#nv~j+E#AXTE)0?0yJuZ4?6o1B0ilpUXO@geCy6zMVW%->crwn>TkR;}I9Jz@Ai>MVuW$QobEin~WA1cCx0JY~m5w#DANi zNmO8>t5~6Ls6s{gL-&&*-Z8E|JyrNQR-|*#=IB(v5z;0ULg==*!ifa-F}bfmi!k z!1WE1iE0PVFfb)r2nMm=cA1sAp_s#glXu}u1(OzmBfD?ys0~=AaPDh!cVs$BI|No|hd^sE%)XNdlw0+9W%kLjw zRG;tuip}+4(v&9k`)9vgh_4T5nzg{8^i|E(JB}I%8Zp@+Fl5I=8RkdiZIfrNi_OAI^!t^jgBf_V-H2*N2-9R+`uT{p zLhntEOpGMU#coE1g=_u@dLLbRe~WN5OJ&YapIO#cH}||&n044eN^g#yeq4P+{rs#) z%M_>D*6Vrgv8v|Zdwjp0rKiRfCoRF_X1cHH{!5#^xy3E1uQZievB5==VPU3*relN1 zf=Q7s4$1*BE`R&38`#LnTxveF%;LqeO`B%CvJ-t0Bq($@k>OU96VHoaAMX>+yDmGa z7C+&c+GA*;oO zVm7~YR`#h)hliK-D4I6scE3+9K3q~~@TNM(_zjm^jOB!w zaO1;lR|4WfSsfm&s!wF_*9x%NFSC5jwKErkb#>OU$N7!_>ywr}{`2{T zyU*XRvNa$6Ro|)b?8;E8j^k`ecxTPO*vm892VXt%FF`PGWGj4yFnXL*Z9 zoArf_A9l^1F;ir9n9jR}_p9F|-*R3!uSYi7jX7XVT|Lme9xF$v{fJ2c>tDdjnnM-lS#B&UXJ|w)b+L$rr*yZ$y z4T}~k9Nw&OZu^`1+wIlYZsk`r@6JvydiBKf&|2R!@p~sme!s)!;_UU_-iU2(UY|Er-&I<&$z$8RN3WSTXXe!R&cDtalzjG3 zq=cM2zugvAO_BbbJ5Cp#Kb|qE=hsF4$SoH`@>s%rIbO(X|{OB|8-Y+*4BUfQ+_Y-=Kd!*$Wom!wOqIB)1Q~77}6)7g`b*FrNyX5?WOIqtK*T^J@ z)SEp#QD?Yhs@rK*Md|h&rcIe4dc9Nqgu2TvUAlGVx4Zv`nUtOZlCoE6aFlH_jI}=m)EnT=HhiQ|i*u64CPqrgUiGS+snLc$zL@w~z zP;}!a&kaK>t6Lr=CeC^%mmM!}2s$!3GU)Ey6(#lROLhtF6p4sz*(7iyA(BJnR9MEW zJv+4W_@2x2`v1`_{b$xVDagR)0pF(se}iv)dSfT_Q167Q;J59cyo?>PG_>2#EIr_( zJf$;)D>d5VQ?t9*$vyKcGje(_@4w`poV`cjz|C~Y1LyWH-#@iW>AzFaPk~w7Ee;WC zHzHd$ef}SG+B)7~8|SpnfV4XQn;sLtZ%#_J4*Y Y&t%j~8CcIVFfcH9y85}Sb4q9e0EbR^J^%m! diff --git a/src/main/resources/assets/ebwizardry/textures/spells/mine.png b/src/main/resources/assets/ebwizardry/textures/spells/mine.png new file mode 100644 index 0000000000000000000000000000000000000000..ff5ae76e7e2e1ca0233b48fc4e721e3b864dcf6a GIT binary patch literal 1575 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 AsQ>@~ literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/ebwizardry/textures/spells/paralysis.png b/src/main/resources/assets/ebwizardry/textures/spells/paralysis.png new file mode 100644 index 0000000000000000000000000000000000000000..d79ef576b4c5262210d4d212c72cd310d7d83e32 GIT binary patch literal 2420 zcmeAS@N?(olHy`uVBq!ia0y~yU{C;I4mJh`hT^KKFANL}Y)RhkE({C|ZVWY7o|j88 zFfecyctjR6FmMZlFeAgPIT8#E4D2PIzOL+#*rmiIw4$$n?Pp-%Wb|}#42d{=bb98R z(5s@y>$Be%pR@gbxBC8(Y9@Y3ua!MqM~%W|HdNg=7 zu<;~lM@TO&=rGh^oa3zNILEbf!s)b`h9-7L&n;Q#`^I*TJtKp`J88Ravuh8(ab3$? zBete^LG7F$FBA^^^bA?V7s8ML4{4q6%Qt(y3I)8yyZHS#3$_j6rXA6W34<$2`-nQV(}K^ICVNN5$UM$&&1mmTG7y}>p(!4C)hI(ghi49B!pCPk ze7%?LPH|5RF}AwwG$HR8e{jo7t2v@cPd^?!=Xb3BcF|MTm7BcH1g`IER}z4-IVZ+Wy*oO#>bfW($y2^KAtE3@38!{xMSVl|8>Z|ox5j$ zA^Wa=?tYt6sx)No0GYl>U7onyf9_i=yqyPw}bv59y7=SS7IKOXsX{dT%g z^y%!^WuGp!@3yQj(Ehw^{^|SS^{0;S=KJ*VpYoYsZ?$6#*4Xc#VLI`v_3e*`tsc2_ zc>j2yz2ZkYgM$N;fCFpBd1Z0e5^<%j(8KeTE$6H?c>C~ZMB}^_U4^sG^ObH|ytnz~ zVzvz>clmNm7g_gwu;tfndSCscwA5uEzg6QjhS!o=qHUL*8We;UY*CxZwUS#{g}J{d zWa;jJWkH%v-5bv>+~Vxnw5c<4=hg#rG!JWvb!UhNhs|nS%R6PYq4)K-Dn8eOIgA!q zIb?4rl5v>J5FnuO!KOsw!ksGz4ppy9zS(xy=Ib@JI*U{d|MPSE3cK1unl?vENt&)` zW!!t|%Q=;uU(e?^nMSPMc(a?BiL%G6>~7um6g_+OIse1>*X0w>E!mNI$|G-fncl+pjSi;U*8E#DxAMIHa_#s> zGjFed^j4Q$!gzzZmuB17_q~@Gy?#FU61e%}ONJ&5$CV6kIrlwZJmtcSRgc&Fs_JRJ ze(mkT@Y-3{%ln`G3%_2*$%bq33J^$HnyGN`~l#g5A=KJvC67Lxq+m55<=bdCkihf4% zTAbv*cT!8|3HKHAElh34LMC;)eLEa+e6IJkO_}-ZM^`unWhW(XyvntBwo{c?>N38( zrBc$HmTHwcdZNhNmpAlL|sZmL4(I-|u+3q1a-M{>KMzI(;NB9opln zt@*6T=I1Z1f7_Cnb$K-xtx^ov`|P^T$+GQy|C1f>yFS`fT#aDz|M=?F+mf#(moMLJ zTpP0S*rFcm$?QCjL{0mg2X^c*wX`AY5yMt4crwCPbrSAG%StkF=p&&x! zq)XFA=G!-_R?Pk#|EqyDy!Y{<#M+22=iE*$Raz(1*emdO!eplc8_ua5UMzwErxxX~ zrY752UT9n{>Un0^@y(-6k@uyFSIg$;OE$L8h3?h9VEgywTUy(et(R`y zaM22NR|`G6G#>Stdk*IwB7 zvpX!PW7Qn<75tw5ffiXYoE^4@U6!~MC~d7gckG5&<9(f|W3kuICcIr&_O1NcjZN#B z-&Wo!ILNW>?fayEYdCqbP8OW~p*Tg$aAnJR|9QX6H>=M%ENmWs=Jo3B2A{2+Kl-#7 z37(4RDPCUT0IDb1cgen&%{h|AzudWG#1a}Cfb|inM^5wJOso~LzGZkcFJ^1Ykx;Q1El8dD zp{`muta`-)zUdx|guZInANkpN>%gO*8gGpg9yqwL%e*?Z$fxJ9(^9X6%cZlmC9<=t zonnr%$O1NbvU1)#`G~ zXO=*@Lf6Gx{kKIhonIXqvhld_9jj*BRiBeNpU-jLIg4w{<}?4}&VFUCTJA4@GRykW zolb_f=hqngCcd|0TGan4q$<*cF&LZKlhz^-r}p|i=7_~6E2*Y^>*iaJ7(7ZR`2JXUuJv$ z>yK2+^YI$%r`Fv0^Z9v%$1$%tJokRc#%z$;oW|)Q5cR_GeQ8cy`lniXODneDX64WR zep~)z@BP11tZ&c%{P1{)#O(RfpZqPW&h7qE`!26-pW73=^nVYXipy@Sw~sF>Key`n zo9nNt&ZKC~P7jp#-uZsVM8~8Z{i$)S`;YuCiti0i?VP+s|ANe(Wrb%eH`T_JoGvZD zv+w`%*)0-(zqS6q=P&xHCTP+3v~ppQ`vv`c}N2v-W+A;B;|DPUjOZPsB1jIyd=p$>-|$XWaR3#1oh~ zmd$>4ifOm(dPTRQ`FFU)pC70_>6RQ{Ql4tdJVEK1AIoDVjvH^Bif-O~R9o0*6ZYYy z%RA>U%q%fpb(X~k)LM8fu4d=W(|mXD_2l}wZcz+Mff}qC8VU!x3=hs1(w2Fpxg;aV z%W`T+u(xfyOz|np={miyRHsA)om@I4D(a=_m5AW8Tdzb#zdgIXp=If`Xv4MJu2rR9 zI(K32a_jOhc7HgO`%FG*EbcS=)naFS&g8Ss=5uDhKWXcns(%`KX4UGo`|h@RS-;!z zS#S5dZND3{)#p@PI=OsK)vcHLSL8zKUC#b(x${1-m_N%&=icvA>REI2o+fjsTY4Vi zIZ{)i5ZA)c^6k)>F!9CWMTgFq`3I`-XX$aydDP7pHo?Y_8{^7I# zT$ai&{>h(^bo{RHT|4jof^EOvYCL3Gq7~woYr%1Q+nMusYR^QdFaEMe;?~{bt=}ha zzHfOX=J%bu;dZ+%jmwv8ODd{9cVShfy+GJ%Rf|=MPbbCbDBsv$|L^aPpY7-O%bVB# zw&7oXZP78$0EgouHV@Kbg;ylMGx9xq@T%~g*W0v$c)9lPa*Pw)&1?8fWA(u|doD3t zzjl1l>8P(~uYHNQb$83Vy9-vUJ+uv%_!4wKSZ;++{LbfD&tI7K^GKWhaqOtDa$ex) zP^Thz)|~nI^*3wumfn25Z+_G!ZP|HwEBh`kdSCiHPM;Y2NwehBf|deP=l@eAFG@e3Wp~|9Aft4@i*LbI-CvLVEY~;* zhOJ`wwO#1BZ_K30fu4f1K8ZD*JoS6gghv0xDn{;Cw}wAEaW!b&l$kfGQ@zsIx%Y2> zb|Pik9mDN6E!#IgpZWaA27wucuWlInvwpUkb}c93#cU1sttB>vehaU$TdcjZ%QAIk zYVcW2y(bM7DxsBOoej_R-Mi+h3Mf2G-8Jb3!`!er+jNTVugtmp_>9Wt!r+5PKMKAI z*m3upu4?4Eh$#gdpYT1k6g1IR>FMA;dF&@E`=8{!JC>hYelfpIgWJeSE2~TITH_7f z3sI}|3boJKI;QiVYEXW8@am(2SE7Px4^9LfIKn(f*fZPyZd>fM18ROny_+gl81n=zC&7cIs- zpA(Iyk7RB5OU!4?PGDQkA#wwdS2wU$AFIiw)bWR~)#=^uUW%zgrt_)f*k(vr>4$10SQ1fIHimg|c!DB+Qm~NGqo|P56H^{-pZt z-P5*k7v(rKEVHow+Hy;L+UYKhEFZZ0m|dF{%? zOpnuEoV~V-kB4`(FwYfxD(%F1GJ^d^rJ(jBx4NXT*Y^dyBhoMAq)5Ipzh<}8MW=#U zXG2=CtG|@n?O@H7r(BDRrk>ER(%HC7n5SgfywzDeuRY}cZoaPUHSOXVIrl}3y9+Ac zyIf|LzP;e_M~{MzB@TR5Dst~~%P(vy~eS5{)veTr;`6BPZOp~4k&liY@!J-a5gDdBS?x(9dYjV!rp86}X0z;7n~u)^cWUArt|IsAs&h+t zUrkR?+w2??-nDqW=cgU{N-GZ^ljD+%y2AY6f#}75jcqcmuHiTDoKI`s%W}=-Z1@C! zpE-dCg*u+gNpXEtkz~>6o4v^T;4A-dqvKnaFMpqN(&R7eRUiG@xh31yu6vf^H+!?U z! zwN=qRU|XW`4ZpX%@f(iopYB@u_~!%H9aW3i7L`c%=$F*#=tZxa`=s~Dk5^l7l|B}A z_y9 zv*q!`$JM3@Q*=CMR6Ve@Sy-tQcue2tg-!Ja_Z5p~ooE+OzMR#2tJ|x2UCWjQ*Q`^I z?1;4HwA!0I`SiQnDxo&>`n#s{A9K@t|ElKR=MzDnPWXkGX_`L2Ij`<)U~u21a?4lG zh1@5FA6xTg$8LM3xf@TNPVAjsZRVcSf2WjlnU}d>YVA!AUxg_<^sbp?#U7fK$6V~R z?ZW(DYuD%EZ$~hDMo1v{G<_G=Z)a53wc5Hxm~TBl&u)Hlu2uSb z=i*)Qf_~fA-s>%W!k58%Yih|h=TIsB#9N{1`+K%{Rp;oWANHQ`#ACWdp@-qg%7Ere z=IpmrQrEAy*l{rb-e&dhC3p64+>Z@^{pg``kIcE1jQjb11x=gFleNf=cgK`%Sp?WBredeYhBFLb82)=@ zcBwEhFmM)lL>4nJa0`PlBg3pY5)2Fs>?NMQuI!JQI0aY)JUep1j{H^qTNrBKZ(%V_<)ck^EEtBrqt#qw)O;cn}hCF_$N9Rmwq{a^h* z{Q2)yN2b5iW%_?yjCl>;y~?(!^D2ZH9-P|7`rt*(88812XFiBjmQPdB-f&N7siu=h zicDd~OSV&4E{nCDI4s^Pvh3L^U=xBrzM!Nqv@&qQcCK}KYa1JmuseNd5!i4{VX?$} z86&>}&qHf^DiUQD|BALLxc$QF_;-fBb4P8qRvKq6cb<}_;@apFH0Q&a^ZLQFXYIM_ zcDp0d_|cP7o>PJan9fzMF^tIWT*NY6V$C%U&E>K)I+a=kY%0a%cI0l6Pgtt{kF&!ttaTslQ8-t$$VB<9(IS(h9_KeseSBqEV&zMLUcJb;S?V0V z9F0-gua-GpmCBaUi%<$x%<7yhw0H4DEB}JN`|%d1uJiS-WAFIfq;a<6@|;Ds+<^+` zxVp+_=WX}ieR-L5>CE?M1ze3~tczxpsViHwXGuvhuUdC=$2K<+ZneoQipsCJf*gK3 z1Xk=Z^bmZz^MjhhEWzcPMtz=}dgAgKWliSJloWeDJyVp^T*lHVaLdfxbQ$|SNB)}M zXFX7?zo#WjCb~KI(TU6QJf4#zG+9{s*_@ueIIB1DxpLd=*T0<=9%HR~g1ye|0i!Eo2xmZSG%zSlmmt>(_TYC3<u=noI~UbF9a3cFfu?hD7A zC>HxvlmF-A?mYGf{q@zHlCC=*M9zzT_Uag0{v3PvV9iG=M~|MYYxws-OWp6zp`_OW z#>KX5SuT?}y28$h+m+tm=d+Fb)3=XdvBm$}-=(bH*L&aYclfz~ujliuQZ(v&dG3s& zE6+K3fhLWlKE6Ts;mp(nI9nK(OYI=93 zit!oyy`P(heSg=gTGI(0`wf&+@ z4{p}g`^y~oeZVD@=aizCwg6Mvq|0^;0vwv1k3?ErPR-EpSknA%_kI2Ym;3)dv6^r< z_C449pI?(1*4X}QfBEQ?(9Q-9rbY)2&c{L7qeVc0<~6)-K=OEc3geMaQ2i90%fe&&~V zeW#;vJ2vj;!SatRaX)`;pP+cmgm>$^;Mcs*ewA-r+O{T?`PbvzV~+)Q1y;Q0WB72n zXw_ClGu~qvYEL_i`Xcw5DNfZ_a`D<#$+6P*eEt8#MKz2U*Jqy9U2w(h*wratQ?1iMN#tY+-9OQLK)t!e(w z{-iPX;{%yrH*yhn>nA^?Q!qH$mW%+Gj)8OnL`ve7|ImpMijk& zzW;bu{N`Kh514Bdw;IeBYgXEQuFwb+Mary}Z^2tU4yyY%H~0dXMb_v5M^F zcOzm_E|$7(znpyON=WI+oQrNM?Vh@Gew}gt;r8*?d^uL8_WrrgPV|-=uMiC_@L7|X zVUilVa1~eja_P_K9VvM+PT zOX2ubn^&7tb?uI-_9eg>raP5WA z$_D0DPHq?Tg6`SQWO>hdE_g|<-uhStg^5N9Yt+s~W#pdN)H89F#kIN4q0=)%Y`5N# z$}wi$u+?d`&|zIA@^DV`l|H z&CA~RSx?;Ajn{q3!sZ=_yzUp+$@L=QwA@R&R=XNg&6g|k^q;ar%&t?-(>BU-q&YeDS zjcc*imy8Zs{>m4Zb@lRmEb3NlzTbG&@xj61^X_+~x z3MG{VsS2qTnQ06R6}Q&Th@7OnQ_$sqA(yP;MwV%h6HG7jmekm?-weHacd6uTNzt{F z&ZMY`mGk#=?D{*uUjDoOza*c7s@kU8=g9vH^42Y}yYl?&_p0yyyN>@BzZYNl?{ew) zkFF1bp4jg5`&@Vb{?5Gl{8PT{v#Z^G@O|dJ`+pcFTsbrAZEbulzsTX&yXxof z{#Lhcx&H0S|HnVwI@v$F-qxShU|OLen|Rrmj}K>cfr>{Hm zeq*t`d_Cj)$CveQ*#51x{m0W<{pokxA8xnzukYlD_j_0R*WU5Jb3)-|tJ|~CALe$`e`oE{ik{Q3FQNFutaIk_4!?gq zng0IYkJ|go=j#}@%5uF|^bxqeRmwXfF)oOu{*$`Mi%7k&h?yJO&L#hd=-&T%oAv!K zQ)f6G2GhyzILbn zuF8D^(uo)J&P?U~mcFM=;+g$cQT_81f4}j3S9$X8^sjOZ9W!o6^z<8iNRdCA{(p)< z*Y^hz50`KL)KJMI@gXg-viyPCF&<0PjJ$c8|L#fa?9ofs6-YD`HVb8BiPV(*rMYs^ z!n})(^4S#K=P{dXR!xrx+BnHubL*B%*=trto!xpRD*CPNmX6lQ(`$Ex zMQ86d&P;!C?($sgD*41C6We-iPOVtnYd7({&*ijvsn>3%#U~zh{jq*eS9IyttK08; zWG>IOe!uB;-fsCVWsf|M``JCca@p^H!rQa2&ae3yKjU}uwLh~>4X3@UeLC4xZ~CWX z4t;CGLbhbZN(ucW21oY7Zz1!81d1QM$!uJ(fg$^z%ehZUJZzW09qjx6;N9e%_D{}6 z{_@__`v2%0;nM&7&*rSCHvVp%e}BWaUuQKw3N6tPS>|seal3BD{GGpNtn_nxS!uXs z|Mjf*>d!Y6`|SL-vwFpx-xOnz7p_y!gvkm;bwRlO)X^eNmrw^`q5{b&FNx zwMyDHI?X-5El~P#_xXV618QLfHYb?0<`^Dy2x&K#<9^Z9Z>GwzH-LMkL;vfmL7H+i zi^AmuZ|*jIuW221_j+U0?~7?{hAm}le@rgBfBxm$IY#G%t0NzqoR26^&Pf%!f7ijd z^8L0~?<#-T7G2nwcWma@RZ6L{fv(#=d^yXz_>}%Jh5K{c0?M`cic^Y%v+uq5wL~+V+y1)a8#$EUUFHR=!E` zR$P6q#9)u!JNNAZlge~Tyu2(#Z%MwX$UI&>A@IBA>?tc*u5I@&d?ciu%QE5DtFwm^ zkGk(Zn&=RF{=VZc$)7B&4(}Wee=`!?VD{_Ok{pK}MpbJLD6p*kvnEMra^RYT6;=`GY#{;?5cI_d9#78GY~8X~ zT;9Q|yM7#b6!2~1o%ENhUsXiRy|4XO?`TKrGU+sh+vyM?ZOJ^6_{^n&L@?rrNPvinQ5 zn4arsesw}bH+0j<(`P%hb&Nw8Ked@J&^Zzr@wsB}?wRvpm$+|!{3`Z{|4wJ#GS2AeeHpfhsq01O6OKTUqt=_MWTFDj@4Red>2>8z z>Y7v4Gg2z-);$#A>P{88bf3AJTlT%9rf=ET9PSr>--~!-4syIG4N{queD;a&lf6ZE ze!k2z%RAD#E%cs-NSOYeosG3u7iE@l&p+pBRQKai`9Z6U$iK6`y$oT!{q7!!eSbvoz>n=I&s1n<2(5La&wpjB>A=_1%8duT9 zb3}atZTt?*b)3b)99N#x8>*pEb=d5Ba5m!%_a~Dci%gR?=3?fSyfJxD<1FHQChU@dXSIVO_o=Zdn9j3s$iazQ^Auq_dvxRz5_jNwew#*$=)l7~Ti-S4(`70tSI`GV|| z996HLi3^k*^-ewh?YD2W%}1}?#4YVyj5GV$V}7mR@!>q?&a{jpa(-Wrq^a)I(4r!* z{f@48vyQCvwqWQlxuA3{F;#BEv;PUQJ5QKO33?DD5+0$ zXnZ7aa?7opDXUHdU&+5$Utel$awBXqrlP{|$o!j4J zm%8w+^#$L?8yBRG`5T_%s8D*HuuOPX!4iYyVugO&iGIp~Ud)HA_Fj0yE!nvF`1&>L ze2*t`2(9Hl@7sH0>NV!6r!JZ*+g}X7yJJddu=GVvmmD2F1+$}EzvmR(3@+-`nmMb1 zeM(LaaW6}GNB^{(~$uY9+7_Tmy16|X`& zpHP;VH$|7djE;ntL}^-T7_XafSjjhdf-&Eb$FIG3HaV&-ayybGlciR>#ZS=B(%NC_ zFR9Gc65m47ZFo=T^zRZWpFL0S;TzXn_tH5p4LI%d-uk6}UN*NzWAg7@CY7_60qWc2 zG)+o$PRusSt$&*vQL3VTrgHK5lQTmseKj6>NV;upQ}aG*?>X^POpyNh(n%b~2jw!9 z_#bs$nqM2hKJ95h-iz~!9Q_Gur5k?7o;n=b;hY62A_9F}1yX zIABt3^v4w@`>tAc@+@WVx){BIdtUa-7xQY?#D5S|ZM_?FVC#hEx)Telo_-g%c-zEm z<}Z6YQpPJPr^Bsn$CC0X&sMz&t?)Dbe?U6iv~%)2)k&{4c29H+SU0~_rRYvnyWZam zTMGoeqOP6$9&qL5?nUx?FTZ^hcy#ND{fQ{vzz&fEkGHW(useFYvg9mt>S}vjwy?&t zA=Y&@W8ZsWn?0P-Yi93!o6UJsW@Xa(FSV<8v`Zu}PqxVl_ptYtkDIz=!j#1qsv1`( z8_88|ZH|MK%|yM@!u{R2Z=>aj54^pk70Y} z`81Ws9BbKe4T?*SsC4EB|WAmD+trZcY9$HNU4z z$#Lt?mVZ7`>b!0<@+Ekl{-1Pdou?I&EUJvQt0o+yr2 zGFmrTXCIBauvSp?=bV_7PhT}>HXS``yo@K>Bk0!bI(LQl=lyFq-v3oQxMI$-y?Og@ zCmr~{)7W3_ug(A4%iqnn`SbP4-`3ss+rrOTs;oW!SA25U!^aaFR{UpRU|>t~c6VVY zW?0Jbe``Zv8Uq6ZXMsm#F#`j)FbFd;%$g&?z`(#>;_2(k{+L}@M29a^Z`BJ126lH( z7srr@!$+sb_r!*Z9;?rOTYK*B<)7gb?3XT_YbfNB!^6d5a!r6k@TseCyum~l?nV(I zLy4o}wMK5W23nblYdJZSDlYy=@abt`$n*;4RO!96!a`hNR_4Ou=V#_xf1k7Ye4O1I z>+%_X^FOMXe}7YZe&_w|*S24?x<8TmxAn3AA3rd>|6*UmxBGd@WQGH~Pct^GE~_d# z&$-{0^P<&^tp-MCj3(rK7Au@=FU&ZV?Zywj6nl6(rjZpJ{&5!0fH!!qDj9!lERq#ha$;A-?&*nKLr=c30g) ze>{7h;(e_2@sm|^=iT4CNVq^n-L3zkS`_zWy@{HOwsw|u8ugwGxwW|4Q+%?SnstXy zq7n0^=8W70r{BDhN&7H6`KHR>Xq6kb)0O-M(~i7ww33iLBjYxE=1j3R|2;=HTeY=qMX=tzfT9=?tj)<|A*mI z$I(dGa-e%sSGC%8VT?(IprV9zjyO-#o`CDk3>Fqbu?%Ro9=b8 zUTj{|%f9ZvVf$=n4bx4#m|in$T;Gr+d3eH9DT!DI2B8N#F1Z%T?fINp<$ZkOwBuJC zmpu^qsMna?bl-Y=f82kOOQ$x({JgdJ^qtGU*zRfnp8rFbCwyZf1>CqD^7nCbD z+UPEA^=O-@zIHD2bDhWVaZdu&r>sCAq~oqw+)Fe4D*a zA_wOvXSMB|Biw)I@N4^85xu=N)zVH({?6*oNBfNzOzt?EdCKG2MjwIDBb+HrcV#|u z?fi7&dV1kn8$owNK_xen8{a>tFIbasoRuX+an|924z2HZ>t-BXD(o>&b?w}wSzpAL zPq0=gev_;JK`q~L`Pu3AwUX7(+FhnET;$T6(dOpRbAx3~gd-dCjweh^N=-}h7E5X? zYh@<;D5NU5dcIru_@HL_odQ;^u9XR|Ivsl2%mg=kJQh*>^z(Rq|J-W+uB~quTa->s zum~}q<$WyNW7h%ozf0fF%-7#wew$ftQSl6}i#^+`bCYB@>{1F-J^$x~K_ydBx9jZcghzhS>Gngarhrd$OmDYkFYEd* zZp&|$pH=-4*7v?brz$Dq#^+Acf1ium=k4pA$~%S8%{1(q0Fy;?z~M`l75n=|vIES; zl_%I8{c-%~>HO5fpDHCq>vra;%fI(YR*UF4vdZzSMcFEcGYbsAZJKV*{$J@D<0`gO zQcldl1<%XpyL5lP@tf6X&BTkYMhk>GaxaM4{5!?SSNDu#_qunJN{!ZZnk;l&JuCeG zP5VE+zf0~|BZj<%d{r6+M|Gu|1lJj{aB0Pa(+OOWDUxUy1$NRs3lN}+fXcEC9$&+Z| zbV_QWlS;j%I)8bO=-USD+Khxhkad}+Dj7N7EbiG@+);R9qU|i_NF(=OE^v3Xe4q3RV&;zTiUfSGS&K1C}!ydY!}a&_(=y01y&0%De*c@mJ$By z+7%$WM9pnN7RRLqw;qly6`ywg-uZuzopr04~4C@c;k- delta 1985 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 D0|!Q} literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/ebwizardry/textures/spells/remove_curse.png b/src/main/resources/assets/ebwizardry/textures/spells/remove_curse.png new file mode 100644 index 0000000000000000000000000000000000000000..c5b3f15dfce8d5aae8048bc625b3a43e7a8b4e49 GIT binary patch literal 2459 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 literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/ebwizardry/textures/spells/resurrection.png b/src/main/resources/assets/ebwizardry/textures/spells/resurrection.png new file mode 100644 index 0000000000000000000000000000000000000000..8d8a9cdbd7e1605911230e1cd9fe07220730f92f GIT binary patch literal 2254 zcmeAS@N?(olHy`uVBq!ia0y~yU{C;I4mJh`hT^KKFANL}Y)RhkE({C|D;WMWYei@= zFfecyctjR6FmMZlFeAgPIT8#E4D2PIzOL+#I2gtBtWKF2Uu0n5i1u`G42d{=^!m>H zv~bDeAK%}6zi-d?t+vVMh0-_iEO208)nsDit!L=);F!YX;>s=LyJU+=M_ZT2!bJ-f zH5vspFeSMQw07heJKMKPi45$g^n%b+rDep(Mr4L%Rk4=b+7rnx$wdN z9~lkheRdUx!&L9FGrW=c#*lMu)>^L*yX&oMK4@qfL@_i8Fa^#@n5*h5Q~8kL@V|S4 zxz~+(r~!?6Tx_w}*{Z{`PUjpU=IiWjGLgyY2pamp3{Nry2yg0aIBnhc3H;- zL8g+!4iP#5L6g?5HH_PTBAT7^_SLhW8`gRil=E{eSflnuw(yNaRfd~s2mqX zm(|L9rk{CUJVnMp?b*cF@{hKL$0uIZ`|-H%*{Nfa4V%04cvK2q!lrm!ywsC*%darA zxcTA^w?&?tm=u{}cc;AIJ^Y|^jw7SEx%tc6(>&)YE`9vuh~S^DMN!GWZ!O;QbA5Qn znl#b2&zw^#Pfc*OSSr!0U1OhWqW5yzygfRSy;&*(>8fGbQ#d441sHq8B35V4nw2OK zaVD#2gUdw4AC}?UVGVbqfZ=SzB7gr=?i1%D~+oG<0N$1&f z``@gU4=rx&cHccmLE?g!5KG5}%X-WIJUMQEbeF_ZllZ^C!aI`OKQv0`|Czh!%nC2} z+pZbmhu-zFGydMa{^P`c+q3V^+6P}1t*bnB0bG$X<=)0SG1&xoJuivcu!nx$j zm(y*lR&_jS*&~yv+OkizPsRA*M4>f-9EuyF1P(Ru$R66RA$g+Pkn!kV7iHfrZ|+rx z6l>axG`ly)PEeheXSy)@-NwqFR?gX;muGqCXX@E?ZRT?F7m-{erlD#WrMUEvWG8>) zLiV*x=RA74FWw5AW;*$??WwBCO51Gp?wxWTMI0m%I38tG;J^@^|_opFkr4RnD_NxIVv>yT`t3+hMo96P}-3 zgf&kd?dFYKQ^?lSVlgSDbI}ReQrU^BY-@RgvRz)xkh_;=X`N8~TX;#P+pK5Lg*T`z zlr)c+zIlfH#d2>aiH^rY*}B<}yE-ElOjVHX7B1%|M@yy-^eqm#$2&4>5_@s+G91pyzd_sy*}ga zPf@+Q302RxUlF%Eb@8pe!J2QHv)p%nKbK$e;#2y$`Hfdk^2Od4Zo7QC-CJqOCW+(= zQOyj}Pd%PaI3(oCdG44*ctVcPq^mcUxOw!3i7j#2ZTR-&ZH|{3Zr4}p+cdrpFIj!^ zC(EXqGanD?O7Lww8MB%fF6uuQIV<*gae0B>p{Vw5;U(t;oth?S zOnoGtFTi#oYU7MOec$J47-i_5R~O)jcrCGu@BY1Iv+ufSu{Rife0fMwVX4z5mHc%N z7D*&4_t^S+d+-J&Ju*y;c(C_~i=^bAxno}3bpQN@<;ah5= z&~fS277L~pClBX2VN0&E>3LnamKfXO;P63!iKlppUw{>piI@A4%HEJ!HxJq=wtQxI z&(1Ng%urctosmwya?67J=`%E(IXVSinFwkMR;=mXsF(QoRdUR)58@2}->qV6aq{ZD z*0>F`0<$%Bc}iCytQXW`=PDbwdK`_5^0Uq#BEPfO{?&zFZz z8LU~x!5Fx)F{Dp`Nx$YjYu>$?bMp`XHh#2y|F=|zeg7Zv3pgqI_VLScynn?k-EYJB zS0vF*L1kgQz&m+|_x{~K<%Gp~?kfJxI>kS~TCU<><0FPg|4M37m47?5U;Zsn`|U9M c-#_fld-XGvz2CoOU|?YIboFyt=akR{0Lk?YjQ{`u literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/ebwizardry/textures/spells/reversal.png b/src/main/resources/assets/ebwizardry/textures/spells/reversal.png new file mode 100644 index 0000000000000000000000000000000000000000..71f0cb9559690f04ebc9669be9c303d5b068336f GIT binary patch literal 5726 zcmeAS@N?(olHy`uVBq!ia0y~yU{C;I4mJh`hT^KKFANO4VO1d!B|(Yh3I#>^X_+~x z3MG{VsS2qTnQ06R6}Q&T%-r;NhhWS9$0Bx28%3r)PU!u>TT@fd`BL}p=VN^5e`wAU zQWRp*+PrDgmAwD2=O6#uygy^*u9T(ErhPsfpS7~}T>Gy*|Ki^N^ZZ`%|IlykbM=zt z^W$0Cl-_?Vo%Q|quX8(U?*?3|uK8p2?o`eB;QPXR_y3q-@akmMt>3$T&C_VRzN3Er z?r;0nFVDYS`M>+=*2(?d_4fX)2|CFJY~p2KK0ciBb;=2@r0%)jPZ+wa?|%2ZjM-yJy-T`hEPy z+|92ne{bDA&uHSQcY9a%uf5|RW5JQSXM1W~YyGk3Me)7isoj$o=*yW`_&%S_@ABct zlj-mO{iwaae7=rht1Q=hMW09OHcEMCB*q0yiu>2X#B=&6mzMAqrNa-4b^qCIzx&)b zzVg$j7)hJSmG6EWKK<9^M|j+P;kk=%RQ{XD>7I_xd%hb-W-u;ivz=Ytwf{OB_xi*otO`2MA{yFU7}reU`8Orx zVSqWy$(fPclCIABDpP!FTCrZF)Kzbtl@TYGPKk15Yowr+lN7*CK<9>EeuUz)~@A9_y)%q1b?@#!Be#KAoEGM12uTP0*@l5|@ z*gAdA3-JwSsBlNeVNz@t6HkFN;6%*Zt0% zrT;m%e@H)J>G=J>!#U1f=0){K-m+f_+b^mb*D$5E>!mRNp>6W>&TsxbW2Il(%Sywo z`;)hRpIm&ya#_spJGLR`{?3`Hy=HAn-FeCA()s2`u4Z-4%h?cfX1UR$&-dT|-*flx z+28j0<^R9d6xL%g2hJ}c0}Iiykb~BbKSESuRH&h-dyA1WS3ZFT|M=0ME>fq z#u=hV6L&AtR!Cd?ebE;7--b~I-K~n>#lr7==+8g>F0CN(t9Se7@@6Qt=~PvF@4*|L;;6w^ z?X>ywF|~%|4OgnB2b0d23Fj393HfT5GZGdWOrD>(dlYXd5~F$T-Pqduq47fI<8t zr5ep?M_+XW-)Fn8%WKh-^j7kk($d#4sVQw2#b3%uWmvGKORZoneSJbYJkh{FFx&aV zJ`RRr)_oZ+E9YLQnzL_?5nqZ7m*dLniKThMSESC_J!w87bjtMPsbepv6uBK})A#;c+w*`eW-fEP1Q>m*kL}sM?uD1nDKSZ( z4ZDq)b>w_37itJiGdtn3?X_&q{jEG7@)D$apLlgmnN+#f*t|jBu*}!GB~qtB~r zdsVo+w!bY(`qyB!An2C2LV<2iy5=^OtLu^#*Db!9ENJ#6wAALs-20{1qD_P3`pi$U zWr-Zwztzk4$V1JR&1-|%TefnTHE;OBJ5|tHUVCe6!op=Q7^C*>w%%8EC$jQr(Vd82 zYE#>U*GMhdA+5`&ZpCVMisk5*6-XRDipGGU$D}HBRX%{{#tK7Uvhrq{434E z5!#tA6Q3ml{9hVMw|3^oSn{uM2r4)du(SPW%kyOu_q)G}_cpjb zp^hnCSg76eYV!KZfM2Q|hqafUelp8Wxca4EP7hQ)|4Uz4qSbk;LbRV9Y zlVy5YFmhF%ySBBX$_^E^iia(aWpcGxJe?B`w1wt{-m-tuYk%nMk%{#Q-{*A5FRRvc z3_t#L^3q$&wF(lpUsx{0Z=%MsTqR8@N+TnDp7up`WsVcv*_ChJsjc!-ygbQ)>6%68yeq@grBf?5iPM0USCKWw z){C*#Y~_+9E4fzBRi!tS?+71a@z-lvrnK0*+r~NV2J>u}G~qjoo0r^ID3V~DIxRM} zT4HhE!@>fckVrGVOYOezoh1(Lbv9G>){v4hU)wO-zLVqp8-SQ=)E_%=LLElCGz4VO6UM&jhcXag&b=@mTLrs;*9S&^d5>-7P0Qk@oV9YGLMb zA8VXW)J=CyxLnFSF}=0m^)!{0`7(d*a;!Miv?^uxrPLVZ+!?#QT>MtDG)OpQWv#mR z$yMW7z!i<67TNF>iS`~_4<4F!=S1IvZL!~V7ioUlWKrvLck+pEb*5IApIvlM`FrFC zgJD<6qmYZI`Q66s`FkNfag)9Gv-G1qB|Q&h*JUjdOnr<<*y*MYqIdmYYnOa8-y&l2=-p?bV4TERpZleLL@=_C@!^$JoVQHM3rw z|Cpsb-ttT@=8&Og0fsLJY$WwxbfiPOF7BHkY+pRjv9NpnGO@YaYm^Vcnl zGgW6ZRor57X-d&gJ&wo~e7cE=eQyesz6ZQzn#+7vfot1`GWPVgy-Vk<6jWuo>9YNk z;<aC6*WM49Q78WD1ONIBnVb8nqQ04# zCQHpbx2ZEI$z|_R`5KY3$aekT7v*<+_cgi`Z7j#sHn&ma*WQOVT4o`oCnj96tx8?p z#UHvf*7)XCiEnDxeZ)EYtr(q5ADZNI==jO2ZJGA@_JofCljhkZZjC*WTKX}kc~ixO zsH}xo&W8T|aWOvmRJx9Qm_yIy4i3)=zq&;XiiC=uU0-$K!~(N9R~mfyRw*dT%I{5e zdlJudjc2uCrmXk$-){a_mM59M`n&eYhFNc~-}>D>`J9^EqCXR!&tU(%?C_r_Inxd; z{ACioWy)8fB@T8sQuV7W#0-_w67Dg0^?g5hB*1@zzN2r}q0X5z_Ho)-e=V8%OZ1YQ z=lXMpuhnnR@x7q;TS>Ef?*f@a-=>wEcI0F}x&Gg>Z|yaKGeme&4?8nA#wFJ*au(oG zHc1!WZxh_oD_Hr$MQ`VcNSQyM%Kzpo@4vn9>CwB7H+@-s&3W;gq-Aewwu-DzUUA;< zRi{Tl%>|QIA%`!)?5^(~-#Pzk|NLF|&;9?j^0&2ly?tr@zpu}~72Mi!t)4kRHA!*l zgOsZb3=C{Z-tI08QyJlFfXUKc6h?`&2I@c%bp=^!bT@TlR1;6cn6fEO?f3 zCRj|8=}3P`K=*=f;u^9UM)Lfh>-U{XvgBRTpSDe>~G} zx0dBx@3{lz#`9*K{jg}y-?e`yE7dVQICHYY{$FZajL;gXf1-RF;&v@@>GAYAf6V7b zi;E6d%f)4!t4vsa?Mq!T&&if^UXV=Ol=_{A_o!8}?voA{asFmE<>S2Vp{p6M`E#&u zSfcjm{#nOmCuek7^~`RWsgbO9E@Jj~k0TF40!7|4#ZA?!5W6)?^}fOTtgtPre7aMs zdL-r*7SEAhdpODP|KvTB8RYJmA8gquQ&>DFvDnYpGW+qI%ai%md+c6wc2`Wz?d2Yy z_(BbjRQfZ7OieO)@G!c3^NnjVIbM8QMZ5PcT(7ID+Zy)fJA1@=6}E@z{F3`VJeGbVh3-YXJ9Tq{f6>Xc*C&=1JFH-1 z?a$ra{`_?%-*#2!_ZgB)4|RO_6JB2EwrQGq&8ylMbE^#_L>3mxE$>o(aK%t7F_L$K z;_N4f<8K~%bNyYK)w_a=+p=H!`5Q(=JlUv!|8V^)Wu0xNdJb7apEO)qrFg$Md(U?W zluP+|`}?Mkm&23x@1E`^yL4N~y@}Z_+I`Ot399*)n;r00x=w2I&T zk(|8lTN7VM>$JUyP>*DtaJ%E)4~ge@KT77v7|)1*axuE>^OX;*TJkgcitl|ns%^;O z|K^9K^H+_mpYi4LK$ko^p{cz7ZL;(L|z$qdSUW?qo(0f#eO5 zZTepG_I^Fi^Cx5COqJ)R*J~SY%2so5_zH-{EC}o1;dyuCa7D_Fg4a*~Wd81d@w?0Y z-48|a+`U~pZ`Yle(H+S-t+DTu{--3~IUUCjZ2uA-Cb8y==IdFP^LI=Mul;7b#&>tj zp08g2{{FpxNy|lO}V-H_cNzIro$k$7;rB zeS8bVFPj?VwYY9SQ2Fy^%H26(%w4K)pRu&EIjSy7xAM7ZxTVxZFk*ompP+)NSooC) z!=Bp`6MGVu@?0`p^i4!FBT%e+(uHnMlLd0Oj7GELkKj)q zzU|)mqOJeq^S9qGmW%eky>WPU{tchz$NBev2>J%Bk*K=%VV8c4pTo`l#rods6pc^K z=(TvhtY27_vo2zh#{X)*#goO`!`u!9u3rApS?pF9!x1KT=hNJ!2_L@xmh2b0S9JKQ z%UzL%RT7`RoZHK@XK{$X(gwYgJ06^#eR7$)h1LE8_S@g4-PH{btlBQ6(D8_qg>yxq z7O&6k(m%`N9{O*8|Lo6e{nWDS%xf%;PrSDANtRgN{^>`0eA?VUu8Lq5HcQevxATK` z_+)?oqLR9awdVIvIzTZ0Xr54Y%;CRnc^$QsXPM(O9&HBBhwB`RfIlVpqg692s z$2`T+@|CRjIYlLvq!VjW)%<333F+;4Dx9)+VuY@|oI7Q@mHO_Y zZOx3o_mzmZ&uU6Pl{zi<$Rhp1TL#bBb6mpQ4+wv7`zW+xi>&M6=v`@T%U>y9d8M)M zn{C=7zUg;Lcq`YpPn;Oq|7Jzt)WehP@Bh%{Gi5y=>TY>Qtm0T?iKzC%Ws8ywO%ALm zdop>pRn;A}_tjR)%4(`=LEbuIr#-xkg$>hmlxmmdv|oP2Co7#O$=NG-uxcr1qqFb9 zn&_e(x+mW7G(T8TFeNHD#`|#`Sm6X33jR; zn^bBoAuHMG!s{xK^5Eo=gjAJ-9St)3bsbz!bxB|FS`g^kE99gg@$}dCsCl!c3$ER| z_sXp#A@b*uWr2C`{y97MF4UPNtd(cj!6D0|eabLdu}97FS(aO{E+g;aV{M0?-=9C1 wXmYgU~*gc%bU7#J8lUHx3vIVCg!00rmSvj6}9 literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/ebwizardry/textures/spells/rupture.png b/src/main/resources/assets/ebwizardry/textures/spells/rupture.png new file mode 100644 index 0000000000000000000000000000000000000000..a976e1e9410a3bf3094914be896354e8b5c53d92 GIT binary patch literal 1846 zcmeAS@N?(olHy`uVBq!ia0y~yU{C;I4mJh`hT^KKFANL}Y)RhkE(~Ds(|LD20|NtR zfk$L90|U1(2s1Lwnj^u$z`$PO>Fdh=h*M5XoX1YUwVQ!~?XahdV@Sl|qtl~1=7x(N zum8Vy|NA*Ji=Wkb&UO*@O%B%lrKGr}OSg%CX+$^YMlT0Wua+*a=B5?;LS6g1zBWmG zJ?ee7Ilya5Q_{pHlZj!!6->B#eLd2Qru&>bGw1a7>z@+mpGisUTmP}zvbsL~{oa4s zYybaR|Mz9Fyj=br9Fn`d72m8JPz45 z=RR1ou$OtZgYU5}N6i z3*Wm9e&32XmNy2Lr%zY^#(i%k3*YIkFCHchYDpGd-$mV~%;+=_P6)a%<;9HP9mbiq zPxei2VR)|pi%sb`XUC=9-zi&EzPUdCs#3)lDj=BbqvRoCk$j-SK&`2QztbyeozQ8q zP03F_yRUh~FMi~?{Czfu2If|2(>Y=nls0h0s1{i|DynN5^e8WApCKZ{;TL;uq0p>@ zmB$52w4QriuUz~34BJO}adVE4XE$U6HOz`1s$hB$l-$F6BLIcIJN5c56Plo$6An^={qpV>mpoGgPZOib{l?Q(P!;!;?m~a~*R86GAswOBA_VY_|9=>c;%sf%7tJkNHAF=0x!$tTQqXFBJVz z&2N{`8Lkt=v4~&c;o5Z%-|29_a=3Xu+j{~FuchqisUL68WI1rsbs|sPYql+Fbz8I# z?rnO^t~qc2kvI3}EDl$SZD0CCXK7bdhsP~W2Zz>XOU~slFK8$&m2^Gv)I{&%l+Rz7 zuCS&ruQ9HxZfM`S^vJv)+bb%=*{UCK@o-NIUL^R~k0IAs%Y2q2#|qB4{pPtkHX9X= zrTj_AioS2L$M;FU{FBY{m6J=`AAERWno;?T=Wp?Dvxb&f^H;U986G|2jqdB8*BOW& zU7z-*UaIz;f1~u&i$%-7PxkhRRIT5x{r~@ktvM@rc|5;JOlVT$%%>tc!F5+!WiV@dg}PVbf_*YLvWxgF=~TlGCvi5%pQooI5O7g8zP8Dfsxz**h1` z`C0p)JGkrctmpT+cN@3M?FqZ^l~F~fp}Y2)y`j1rlMjob+=H2c_q`7Mm8v-X^I1jQ z_nEDCmh5`BW*76Lf7*TR9Xo?BGpP0)V1Le~_GHhE^>@?5kGu@Lo%zy0r|y$N@cx}! zIA2}0si_KF;Gmj*cFqEar3b23tyty4p3%l=rQpb0QD|0JWN0Kk_kAC~#@>D3rH|de z)pKrpxYBuFRfUf?YFxN>Fnzw;756`^)zYk^W&70+FPskg6r8foDn0ze@StV;_HC|D zLVuiFdt%n%l}k?qHO+HA-D6sAHBa`K6K}*mMmX>KcCg=z{`neztp5! zUSh1X*jakNaeJ}Kp8L6uB0`2O2N`ZX`}1^O%x`~P7B|+j)90`~y2<%CT6^ND&9`a` zH7~ur-&JQe^LtIw!UdQ0cZV`-UMyZ-v|`HdgHc{Bjtt-K%J2MhUXDLbG}zT)+KkS| zr7X|Wdj0PU?0>WU;qttcer@K-pMUf+6EcH?wo0ovF%D6GcU8f zDzDi8`1A{Bcdvhcu6Ip3uuJmbW~XbaO_s7n$y^;*_CH^?uWFhj%hMS3_H`~R9l9>~ zvI(_X$6H&SefnDW+g;;L#!TVU=DPPi3Ey9@`tZpmNgfFV^EoY- zuT3NQ%w&f1GIQA;eENEA8pn%o*FWaEl)v7|yX3~dM|t-DSxXKI+4YKlFaXtmp00i_ I>zopr0HTXj+W-In literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/ebwizardry/textures/spells/satiety.png b/src/main/resources/assets/ebwizardry/textures/spells/satiety.png new file mode 100644 index 0000000000000000000000000000000000000000..2e794f38d1092b241f8ad627a064b9350fb04d31 GIT binary patch literal 2450 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 literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/ebwizardry/textures/spells/shapeshift.png b/src/main/resources/assets/ebwizardry/textures/spells/shapeshift.png new file mode 100644 index 0000000000000000000000000000000000000000..8d15146739313e408c37896758fc409af629e53d GIT binary patch literal 5336 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 FngH5iBI^JE literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/ebwizardry/textures/spells/shocking_weapon.png b/src/main/resources/assets/ebwizardry/textures/spells/shocking_weapon.png new file mode 100644 index 0000000000000000000000000000000000000000..8eef6c871689a565f8e5edf428dab2a46ccbe5d0 GIT binary patch literal 5691 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 HoD!M<6JoSa literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/ebwizardry/textures/spells/shulker_bullet.png b/src/main/resources/assets/ebwizardry/textures/spells/shulker_bullet.png new file mode 100644 index 0000000000000000000000000000000000000000..9800214a49167cf63952706fb88448f10c1cc2fb GIT binary patch literal 4963 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 Wm0z(6GCT{aE+*pMG literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/ebwizardry/textures/spells/slow_time.png b/src/main/resources/assets/ebwizardry/textures/spells/slow_time.png new file mode 100644 index 0000000000000000000000000000000000000000..3534adcd2ad58e288c602cb5c50f419bd95e0468 GIT binary patch literal 2411 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 literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/ebwizardry/textures/spells/speed_time.png b/src/main/resources/assets/ebwizardry/textures/spells/speed_time.png new file mode 100644 index 0000000000000000000000000000000000000000..bb95bfad59dc5f4984e3767b6a387decc52f25cd GIT binary patch literal 2530 zcmeAS@N?(olHy`uVBq!ia0y~yU{C;I4mJh`hT^KKFANL}Y)RhkE(~`Vlo{@p>(_s0 zU|`@Z@Q5sCVBi)8VMc~ob0ioT7}!fZeO=ifadC(#u`JN2ox{MuneXZ17!q;#==A8G zxlc>m=D+_i|J(lmwKHs!tJ5|dH)}DJ=s0+zA;2kformMv1(xP4N()3ZR;*q1jcHbg znPTRmj!R1BJ5&}!zjN88HTr~N;EiDCJ!eEY*C-ha3l67sgPB&=FHGmq0R{s)Uu+_AU~ zaUyzi_ZjJn^e28~<;qiM1E%$IaZ7RHz ztb1-^zLvq&YiBI`4Q+~fX0v~p)~Ec}%uHKx`;4uot5go^&0nacqo%KMxo69CqllN6 zqu*_=DiWP)vFGEf*E)0cA|rY_9ye&cZuZqU-Nj$~XlDE={y$s^yHr1{Q4O#=`YLft z>51okiENU;o|<>?%eu^FQWcHj($IRh<8}XvYivurnc32>Nvz?qsCmM1cdKG^oR5{x z&adBQd$dW0if(#*NxS05!{ctg90IHLi{2dJ_9;!{xFhiTO2mtOEq%JeX|qb_HEZdb z>1#Z0ihjSRS>67xrqsNJT1CGi8$$R_ah*Cf>B%JN{5{j$ohTvis=g`?uPsNv&TM zArltycvAP2I~-aub{}uP-ueDpy;FsqpTNdFChTiBGgu|I2uNFQs_A(8gN2EC(E?{# zTaz73PPvjA8rr9~Xj;6NjgGLY>DZ>tai>L8X_899gzA)SjHjL+bia4H`FjnovUAU* z7p11NT+2&X*u~-=FBLw2*;l+kR{TDwR{0 zG_pC&KmV^?_g-h2xAIS)xvzU%@ZTWH)ncpe0;XN+{r`5E`b>ygw6!@*YNhPIHwS?W~ps}UgxPFtx->=$Q1qT)2?{?K*?0;+!N70UX7loAsgMyV;fRB`~Q68z4P}V zd&gG~XJ+0k-v-n!sB@C(uBpQ>M)Aa8i z)3&!e7GUAB)Z5!6lXJ$J2O6G)PA^fhFeWJMYQ| z{_?4&aZ9W%npYnVY}o(*lCjD0Wh<^)xg0cEdn;_#*0U~KIeF~ZR?O}we&UvPCCq5* zy}ti{ZqfBemUf4VU%a{3SQ4|R>d2FC-7n|a`5M@{?*5v6Eg(W% zStf>g-{fT5?oi7^+ha;j?)>xGeE#8lw-t9(&kJ*@FZSZ?)VNvnRf2tAb&Kly(+xAU zf+a+LX7z8ldnl?=U{>k#+{IDdfnohx3cj6FCmmwZxb9kJ^QFS!Mwf-$4x6#}GUt zu%R{l-Gj&9-z>Ydz@~qJoX{4hKN?H!tq?AaYI(~xJ;v;G@cB2+S7VmES7K&=s3mq- zZlmm^Fi|(pC96H^H#*e*Hu<>ma>oL{{K|=m`K|Z&B%Ie^I1v8rpZKn{z|!`ph{tWx zdW-Gusm#d;$ajy~QERMze$AsRHFIY5^T>RV6^g#(&z9oac%SRyy6(8=0Y@Z{e&X7? zk}svH^P{ZKpZUgruD!3=+A?|jLzDmJJ9B2veDL${@{HV97iP#Q=eV6IWnXdOa8_sF zhl~6%{TGGQKNM!0{?SmHkr{aZhRfMqEYGhRg!+XZbMe-D{<=X{TK>_GLkU+}_Mhpn z-`yIz!1U+)oE<5$4uLrD1_n=8 KKbLh*2~7aZoV#iO literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/ebwizardry/textures/spells/summon_creeper.png b/src/main/resources/assets/ebwizardry/textures/spells/summon_creeper.png new file mode 100644 index 0000000000000000000000000000000000000000..2a678b7507b6af0a364858fab420fe4c39e9b9fb GIT binary patch literal 5393 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

    acy2Z0*jZm@8j#-!a zQl^=4zFsA?C?~J-(Fc!kF0Q?EXSLYK7IH+Jh43Fa(s4T>Q1DUi&znW>)cTnU1Agwh za&Xb>E8?~jFF5y$G@RA_`Xy&dwc^hmY%v^HJ0hl}@mjY^&S75>KIet?)~LCU+D%tp zu;7mWzPEBpU1I#ivc%3To?nHNB)fb?8?@J2oby~3Z|^eCR#nYBgE_uGBCp*ie=U1g zxq5fow+CXM&U|4A-N*B5(V^nkD^EBb$~Y2sjNR3?5h}j98C^m8T8A~ym&YvLarb$GgcFnK zlie#`v}By?|98zcgJ+(QVr5=pleo#z8|@t8`)rmp&Q2D7+imF{C3k*1 z-1X#t{mK5{%YW0m_x~%Y|NZFv+quojW&c?p#dP}C#;jh?z`($kY!0F)*+{_H=O!i8y?8 zdUQ{0s_60h*Sp`;t}A|aW{O|N#%-OCnpK1*W$ui0>``5z|I5uoOoLPDh_}kGB!@=7%;m+F-)n#GdwN)o?eIc|35BdNH@2yY1{kx6C=ZcQ*NvW=Iu*I@pB&D}-3RtwUmHK^ zV{U_O?eWX`TNFZ*LOg`8SRJvxVtK?eBwIjAcFDzqB~=|;C6WzY`#M#Hlpfi95nFh7 zwQ=aPFUOqQ9;^B9+Xyn`Jtm1 zXjo~q5HvzS(P9;oI$X4bwiXKQ7m@gz?zoeT+9nq!px2ufO+4qhD`r zELVg71UKPHA}`M<7Tfxy^SwNG*+=+@O95Yx!ZD?5jT<|@nm9i>V7|XQ?8Cc_=?eqw zz8y%;(A@L&^ZUi?T#jBmYS1-NLa9Kqp@M&J?1>opmtPI<%5A&sw&$p&BhLff8&(<` zNix6p7urW1x|v?re@<(OAHVkgpQa&g%-{b`h&WI$SKlF_ye!b6$J*N=-+bBrmXcjJ zjwA^;e@(E`joE$n-|zixhN4a45& z-=+G=m&7^}7*`dkH)Nhy+;}9TF<1A|E?c{QbJ-6zSERoE!kwTSsPnu39

    wXbqRt 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 I&MBb@0MCRgJ^%m! diff --git a/src/main/resources/assets/ebwizardry/textures/spells/vex_swarm.png b/src/main/resources/assets/ebwizardry/textures/spells/vex_swarm.png new file mode 100644 index 0000000000000000000000000000000000000000..7bdb9189a06d1a6631e8ab3face73bb1bdc8b0d4 GIT binary patch literal 5544 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 QFfcH9y85}Sb4q9e0A}X6y8r+H literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/ebwizardry/textures/spells/ward.png b/src/main/resources/assets/ebwizardry/textures/spells/ward.png new file mode 100644 index 0000000000000000000000000000000000000000..1b8284f64b6f27cfd42e00a8ddfc5da18db5aca2 GIT binary patch literal 2304 zcmeAS@N?(olHy`uVBq!ia0y~yU{C;I4mJh`hT^KKFANL}Y)RhkE)3ro&NBS&)i+>e zU|`@Z@Q5sCVBi)8VMc~ob0ioT7}!fZeO=ifamooYnVou;vx0$vqu0~LF(l$}?{x1q zDy5>w>i>t^?#jP^yOuqzz{5kJm4kVQ1cz2)`>|eY)m=&~i@2LR4Beb#Bx7d?ct&U_ zaUA4u=`nN>-!S>Wgbx!=2)H^c2|u&l{=4k%t98HZV?(~q-D$(Kb>;Cz|L*@hSAOni z-;U4Ij6QDE=j0Grw7dR+*My*Q^}03oSq+NOYiJfeyEOUWxD0Uj#_oD`Nio#xT}{o?m-kx4F2o}ONv63m8d z3KKh)Oqp?R+m5eUJD<-vA8Y#XZm{)pMus~DJ0G6BE}{|;RL(HPNxRu$QK?&6QBu$D zgXznTw2Cb@T9e;-vD~5K$OBK!O_n#07w6Aq7TR8a?@eONIypW+6aT&I6gj6DX{25_ zl@QVwCK(yFU~6K;8e^-;J%g)Z@XT!@tFr>lju{35vL_fhMI`Wf(j;xq-_9WvJgEOl%UoZAu!`&kA;as4Ya+CgseFtx`S};ml|qVhojd7mqWj%Rqrd8-oN9&=7g?`3C(NYPEJuvug&$jtXFt&QV^4f zf;EE^$CL}T^Nf1TB<4;`W&Tv-F_VAi?|JJ#A3L3IU~9cNHY#P3ErX|zV2YE3qwV^i z=gRjVOXjyf-)a0m_5L$e4yEIMdzy=RgEXdGi)G|$e5Vztw8SO*vTUAF&&iXUCn?E) zc)L6Q@l^4+#MfV@RPAEmcS~Qf&-3R4&WfBZ6|XD5F1^0v@4D!pm*wLgeVI8~#`+&$ z)bk?}0jC5e-G9qeboF+)W7%|%CQ?fAL=#iXF=Q>q+R zdb6cDD0&BRUoC0Riu(BN;`X1f%<~d=&stpC7sjTk>ZQHqibBZx#<~q2nt?%!wyK@> z`n1M@!!hs)2TR#Y4>_(_qZ4c?YR5HvnVfjGtV>)uZA-3q@b)Dx>S37@)0BgFS`to{ z^m#C4ge$#aRTcHhS~BJCkHA@*Bo<9^Q&3dvd8KvuMbDv{z{W(&v{^@#OcDc zRAll;yD2R;rwxt;TsK`C8+W5)m!?{agU3aF>&^wQuRDEF3YF5`y>RhVx9_5p8>T27 zbYC)I_hIiZjXL7fvI?iA8mC`8llgYj{7FJBZzKgK&0VFmKcgW;N>jz@Mc%yDjv%3A z6G!(J5sr;bcPkm5|9SUhn%AOUCoj*AiQ0CRmg(ntSFF-h_j5J7X7lw@L&Tf6ElwP- zvf3XWRo?Py$;6;TQQaY32QwTplzz1MGm6&UZ;;Wms3}oUJk4|XqLdR?PWI35*8dmA z`9zu(pY!v-c#E|+_RG9PQ{Ky3QZvq``)pr+M17VrJ4BEAPf4RTPlP(`kmvn_B zm1Pd0XCrm8%UUP zEw&%I#kw{&A@}gNZ(@oOP8>%B^bFQ=-n4Z|>Y2b~$eQ%QBEN8*qxRu*MQ%rmUVZVL zSNlyqru^~N9{!%2-W~I% zRGpt;C9vyqLb^h7Ps;;NC&8w}yV?Y#)(FqB3*P+y5%ZD<7M~s&=KVVK_0Q)Q`vne! zUXMBYe!j(_l5MU%^R}(cxHaqMH_J6^H?BKa-QGWMhEnF!DZx=w6Q9S0U#wP~=xD5C z{OakPEJJl;)u#`P{N`8oUw-cQ>Dfi|ov)+g*&a0h{@)QctIE=y(=}T>=j^$pT;FWz zJ==FY@GyL^_qDdqoOA{uP1mIP^^(j?2RGeKyvfmXQlj^oMfEq6i=1V%x=tQzng8#J zdCaE&3SX0M-TWx>;o!!-ds~Zh<#)clQ}jZjq3|Pwf3}wXIe*uKl0;s`pP}Ow3njnUU*1 zv&a17p+*K>qdnWFq@LV#_t~8_u3VlIr@y%p?8I|M`|!-o>bveNbLr_5a0;)wDBS%1 zh`8-NYk|2hj{c7Q_;Ka)zS+idm5HmRZM2-T52x%oxo6hfUo5Joo6|ar#ab3bnwaGJ zdQH6YeX>aM@^2!$ojZ5@`%t|u! zl(IhMG<=?Wb=~9zUr)z|w%6%KXDTh#doKHSV)F7;duKn-vW`>Sm2m#8d+V*(0KwI+ zS0_w*zhBd%Zu|E2tFl6$-`&2Uy{w_!|LvR9gs%@5Z+rZ?y?nv0C^7ksvzGHSetdZS bKf~tO-7|k>Jt$*fU|{fc^>bP0l+XkKWyLTM literal 0 HcmV?d00001 diff --git a/src/main/resources/mcmod.info b/src/main/resources/mcmod.info index a2b20f24..4aa7d470 100644 --- a/src/main/resources/mcmod.info +++ b/src/main/resources/mcmod.info @@ -3,16 +3,13 @@ "modid" : "ebwizardry", "name" : "Electroblob's Wizardry", "version" : "4.2.0", + "mcversion" : "1.12.2", "url" : "https://minecraft.curseforge.com/projects/electroblobs-wizardry", - "credits" : "Designed, coded and textured by Electroblob. Code contributed by: Corail31, 12foo, Shadows-of-Fire. Translators: MadWrist (Spanish, Mexican Spanish), VilagVil (Russian).", - "authors" : [ + "credits" : "\nDesigned, coded and textured by Electroblob.\nCode contributed by: Corail31, 12foo, Shadows-of-Fire, Tora-B, Avatair, Aeronica.\nTranslators: MadWrist (Spanish, Mexican Spanish), VilagVil & kellixon (Russian), Hahdrim (French), lorrampi (Brazilian Portuguese), ZHENGLOC & dragon-evol (Chinese), shejery & rewi_wire (Korean).", + "authorList" : [ "Electroblob" ], "description" : "Electroblob's Wizardry adds an rpg-style system of magic spells to Minecraft with the aim of being as playable as possible. No crazy constructs, no perk trees, no complex recipes - simply find spell books, cast spells, and master the arcane!", - "logoFile" : "assets/ebwizardry/textures/gui/logo.png", - "updateUrl" : "", - "parent" : "", - "screenshots": [ - ] + "logoFile" : "assets/ebwizardry/textures/gui/logo.png" } ]

    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 OU$vDVvFfv#F#-VKJ7By3 literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/ebwizardry/sounds/flames_start.ogg b/src/main/resources/assets/ebwizardry/sounds/flames_start.ogg new file mode 100644 index 0000000000000000000000000000000000000000..40108d2cab9f186070ee3e0a9626b778518085ea GIT binary patch literal 30379 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 literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/ebwizardry/sounds/electricityb.ogg b/src/main/resources/assets/ebwizardry/sounds/lightning_ray_end.ogg similarity index 100% rename from src/main/resources/assets/ebwizardry/sounds/electricityb.ogg rename to src/main/resources/assets/ebwizardry/sounds/lightning_ray_end.ogg diff --git a/src/main/resources/assets/ebwizardry/sounds/lightning_ray_loop.ogg b/src/main/resources/assets/ebwizardry/sounds/lightning_ray_loop.ogg new file mode 100644 index 0000000000000000000000000000000000000000..041658ec474cab742a3e6f9948228d6c2378952c GIT binary patch literal 43032 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 X&Q9k4|NT27Bc>HI*Gws9W?%pS`|Cv~ literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/ebwizardry/sounds/page3.ogg b/src/main/resources/assets/ebwizardry/sounds/page3.ogg new file mode 100644 index 0000000000000000000000000000000000000000..5f3a4e82fc03b9ef61ba7d04222c990e38fde780 GIT binary patch literal 17081 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 literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/ebwizardry/sounds/pull1.ogg b/src/main/resources/assets/ebwizardry/sounds/pull1.ogg new file mode 100644 index 0000000000000000000000000000000000000000..4ce3730cbdbc14153dbb9aa9a982cf9d61defc19 GIT binary patch literal 29901 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 literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/ebwizardry/sounds/pull2.ogg b/src/main/resources/assets/ebwizardry/sounds/pull2.ogg new file mode 100644 index 0000000000000000000000000000000000000000..737809f4aa5f60d20439f7499f832d093f96fb30 GIT binary patch literal 31418 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 literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/ebwizardry/sounds/shockwave.ogg b/src/main/resources/assets/ebwizardry/sounds/shockwave.ogg new file mode 100644 index 0000000000000000000000000000000000000000..3af866c071ea1ccc44f690be3b57a8586f4222c8 GIT binary patch literal 44395 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 literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/ebwizardry/sounds/small_aura_end.ogg b/src/main/resources/assets/ebwizardry/sounds/small_aura_end.ogg new file mode 100644 index 0000000000000000000000000000000000000000..9010c3d5f2d4c414dfaeb79f5502a8d15913e951 GIT binary patch literal 59448 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